feat(search): global search aggregation backend (W9-G)

- GET /search?q=&scope=all|media|releases|actions&limit=: local works (title_alias
  exact/prefix/trgm + name prefix, slot status summary), TMDB candidates (cached,
  localEntityId), cross-site releases, page/action jump list; tookMs per group
- cross-site: enabled sites via shared per-site limiter, 15s AbortSignal timeout,
  site concurrency cap 4, same-query coalescing, 30s cache; partial + failedSites;
  results upserted to source_release; inventory overlay via GET /inventory
- GET /search/releases: site/resolution/source/size/free/H&R filters, sort, cursor,
  facets; shares the cache
- POST /search/releases/{siteId}/{siteReleaseId}/plan: forwards in-process to
  POST /acquisition-plans (same auth, validation, audit, rejections)
- contracts/search.ts, runbook, tests (partial/timeout, coalesce, cache, overlay,
  filters/sort, plan)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 15:05:58 +08:00
1 parent e0c0c4f51d
commit a0946bf480
12 files changed
+1869 -1

No files matched your search

+33
View File
@@ -15,9 +15,12 @@ import * as organization from "./organization.ts";
import * as pi from "./pi.ts";
import * as policy from "./policy.ts";
import * as schedules from "./schedules.ts";
import * as search from "./search.ts";
import { GlobalSettings, GlobalSettingsUpdate } from "./settings.ts";
import * as sources from "./sources.ts";
export * from "./search.ts";
// 所有 REST 端点的路径常量与请求/响应 schema 汇总。
// path 相对 API_PREFIX,参数用 OpenAPI 风格 `{id}`(server 的 createRoute 直接使用);
// web 用 buildPath() 填参数。响应体统一套 apiResponse() 信封,这里的 response 是 data 部分。
@@ -1599,6 +1602,36 @@ export const Api = {
}),
},
// ── 全局搜索(W9-G):顶栏搜索 / 命令面板 / 资源结果页 ──
search: {
all: ep({
method: "get",
path: "/search",
scope: "read",
summary:
"全局搜索聚合:本地作品 / TMDB 候选 / 跨站资源(15s 超时、并发合并、30s 缓存、库存叠加)/ 页面与操作;每组带 tookMs",
query: search.SearchQuery,
response: search.SearchResponse,
}),
releases: ep({
method: "get",
path: "/search/releases",
scope: "read",
summary: "跨站资源结果页:站点/分辨率/来源/大小/免费/H&R 筛选、排序、游标;与 /search 共用缓存",
query: search.ReleaseSearchQuery,
response: search.ReleaseSearchPage,
}),
plan: ep({
method: "post",
path: "/search/releases/{siteId}/{siteReleaseId}/plan",
scope: "organize.execute",
summary: "从搜索结果直接下载:定位资源后走 POST /acquisition-plans 同一流程",
params: search.SearchReleaseParams,
body: search.SearchReleasePlanRequest,
response: execution.ManualAcquisitionResult,
}),
},
// ── 定时任务看板(W7-C):统一注册表 + Agent 巡检;全部只接受控制台会话 ──
schedules: {
list: ep({