refactor: 拆分大文件(contracts 端点、整理服务、浏览器纯函数、整理弹窗来源)

- contracts/src/api.ts 2733 行 → api/*.ts 13 个领域文件 + shared.ts;api.ts 按原顺序合并 Api。
  新旧对比:354 个端点内容与顺序一致,分组键与对外导出一致
- acquisition-organize/services/organize.ts 2645 行 → organize-types / -plan / -exec / -finalize / -records,
  organize.ts 保留为汇总入口,外部引用不变
- browser/service.ts 类外的纯函数(视图映射、原因文案、坐标换算、图片尺寸、出口代理)移到 session-view.ts,
  service.ts 照旧转出
- organize-wizard:来源解析 useResolvedSource 移到 source.ts,FormSelect 移到 form-select.tsx

只挪位置不改逻辑;typecheck、lint、test:all、web build、server 编译与编译产物自检通过。

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-02 17:40:43 +08:00
1 parent c9e8120fc6
commit 8bec4bad5d
26 files changed
+5906 -5696

No files matched your search

+217
View File
@@ -0,0 +1,217 @@
import { z } from "zod";
import * as browser from "../browser.ts";
import { ep } from "./shared.ts";
export const browserApi = {
// ── 浏览器(C1-E):站点浏览器会话、原站视图、人工接管;写动作需人工持有控制权(接管) ──
browser: {
providers: ep({
method: "get",
path: "/browser/providers",
scope: "admin",
summary: "浏览器服务列表(地址、凭证引用、启用、能力 supported/verified);probe=true 现场探测并写回",
query: browser.BrowserProvidersQuery,
response: z.object({ items: z.array(browser.BrowserProviderView) }),
}),
createProvider: ep({
method: "post",
path: "/browser/providers",
scope: "admin",
summary: "登记浏览器服务(camofox 地址、访问凭据存凭证库、启用)",
body: browser.BrowserProviderCreate,
response: browser.BrowserProviderView,
}),
updateProvider: ep({
method: "patch",
path: "/browser/providers/{id}",
scope: "admin",
summary: "修改浏览器服务地址、访问凭据或启用(环境变量登记的只能改启用)",
params: browser.BrowserProviderParams,
body: browser.BrowserProviderUpdate,
response: browser.BrowserProviderView,
}),
deleteProvider: ep({
method: "delete",
path: "/browser/providers/{id}",
scope: "admin",
summary: "删除浏览器服务(有未关闭会话或由环境变量登记时拒绝)",
params: browser.BrowserProviderParams,
response: z.object({ id: z.string() }),
}),
probeProvider: ep({
method: "post",
path: "/browser/providers/{id}/probe",
scope: "admin",
summary: "测试连通:探测该浏览器服务的 /health 与 /openapi.json 并写回能力",
params: browser.BrowserProviderParams,
response: browser.BrowserProviderView,
}),
sessions: ep({
method: "get",
path: "/browser/sessions",
scope: "admin",
summary: "浏览器会话列表(以数据库为准;默认只列未关闭的)",
query: browser.BrowserSessionsQuery,
response: z.object({ items: z.array(browser.BrowserSessionView) }),
}),
open: ep({
method: "post",
path: "/browser/sessions",
scope: "admin",
summary: "打开站点浏览器会话(同一站点/账号已有未关闭会话时直接返回它)",
body: browser.BrowserSessionOpen,
response: browser.BrowserSessionView,
}),
get: ep({
method: "get",
path: "/browser/sessions/{id}",
scope: "admin",
summary: "浏览器会话详情(控制者、标签页、租约、是否需重新读取页面)",
params: browser.BrowserSessionParams,
response: browser.BrowserSessionView,
}),
close: ep({
method: "delete",
path: "/browser/sessions/{id}",
scope: "admin",
summary: "关闭浏览器会话(关闭上游标签页,撤销租约)",
params: browser.BrowserSessionParams,
response: browser.BrowserSessionView,
}),
openTab: ep({
method: "post",
path: "/browser/sessions/{id}/tabs",
scope: "admin",
summary: "新建标签页并设为当前(需持有控制权)",
params: browser.BrowserSessionParams,
body: browser.BrowserTabOpen,
response: browser.BrowserSessionView,
}),
closeTab: ep({
method: "delete",
path: "/browser/sessions/{id}/tabs/{tabId}",
scope: "admin",
summary: "关闭标签页(需持有控制权)",
params: browser.BrowserTabParams,
response: browser.BrowserSessionView,
}),
navigate: ep({
method: "post",
path: "/browser/sessions/{id}/navigate",
scope: "admin",
summary: "地址栏导航或后退/前进/刷新(需持有控制权;限站点域名)",
params: browser.BrowserSessionParams,
body: browser.BrowserNavigate,
response: browser.BrowserNavigation,
}),
snapshot: ep({
method: "get",
path: "/browser/sessions/{id}/snapshot",
scope: "admin",
summary: "结构化页面快照(凭证已遮蔽)",
params: browser.BrowserSessionParams,
query: browser.BrowserSnapshotQuery,
response: browser.BrowserSnapshot,
}),
screenshot: ep({
method: "get",
path: "/browser/sessions/{id}/screenshot",
scope: "admin",
summary: "当前画面截图(base64,只给原站视图,不进模型)",
params: browser.BrowserSessionParams,
query: browser.BrowserScreenshotQuery,
response: browser.BrowserScreenshotView,
}),
click: ep({
method: "post",
path: "/browser/sessions/{id}/click",
scope: "admin",
summary: "点击(快照引用 / 选择器 / 截图坐标;需持有控制权)",
params: browser.BrowserSessionParams,
body: browser.BrowserClick,
response: browser.BrowserActionResult,
}),
type: ep({
method: "post",
path: "/browser/sessions/{id}/type",
scope: "admin",
summary: "输入文本 / 站点账号凭证 / 按键(需持有控制权;凭证由服务端注入)",
params: browser.BrowserSessionParams,
body: browser.BrowserType,
response: browser.BrowserActionResult,
}),
scroll: ep({
method: "post",
path: "/browser/sessions/{id}/scroll",
scope: "admin",
summary: "滚动页面(需持有控制权)",
params: browser.BrowserSessionParams,
body: browser.BrowserScroll,
response: browser.BrowserActionResult,
}),
select: ep({
method: "post",
path: "/browser/sessions/{id}/select",
scope: "admin",
summary: "下拉框选择(需持有控制权)",
params: browser.BrowserSessionParams,
body: browser.BrowserSelect,
response: browser.BrowserActionResult,
}),
extract: ep({
method: "post",
path: "/browser/sessions/{id}/extract",
scope: "admin",
summary: "按 JSON Schema(x-ref)提取页面字段",
params: browser.BrowserSessionParams,
body: browser.BrowserExtract,
response: browser.BrowserExtractResult,
}),
resource: ep({
method: "post",
path: "/browser/sessions/{id}/resource",
scope: "organize.execute",
summary: "解析当前原站资源详情,供独立手动下载使用",
params: browser.BrowserSessionParams,
body: browser.BrowserResourceRequest,
response: browser.BrowserResourceResult,
}),
download: ep({
method: "post",
path: "/browser/sessions/{id}/download",
scope: "organize.execute",
summary:
"捕获浏览器下载 → 后端暂存并核验 infohash、匹配本地资源;给出 submit 时经 POST /acquisition-plans 同一流程提交",
params: browser.BrowserSessionParams,
body: browser.BrowserDownload,
response: browser.BrowserDownloadResult,
}),
reconnect: ep({
method: "post",
path: "/browser/sessions/{id}/reconnect",
scope: "admin",
summary:
"浏览器服务重启后重新连接(幂等):上游上下文还在就什么都不做;否则注入账号 Cookie、新开标签页回到原地址,控制权不变;失败 503 browser_reconnect_failed",
params: browser.BrowserSessionParams,
response: browser.BrowserSessionView,
}),
acquire: ep({
method: "post",
path: "/browser/sessions/{id}/control/acquire",
scope: "admin",
summary: "人工接管:先停止该会话新的自动化输入并等进行中的操作收尾,再发放人工租约",
params: browser.BrowserSessionParams,
body: browser.BrowserControlAcquire,
response: browser.BrowserControlResult,
}),
release: ep({
method: "post",
path: "/browser/sessions/{id}/control/release",
scope: "admin",
summary: "交还控制权:智能体恢复前必须重新读取页面,旧元素引用失效",
params: browser.BrowserSessionParams,
body: browser.BrowserControlRelease,
response: browser.BrowserControlResult,
}),
},
} as const;