Files
UHD_Media_Tool/docs/runbook/browser.md
T

9.3 KiB
Raw Blame History

浏览器(camofox)与原站视图运行手册

对应 REQ v0.7 §4.4、§4.7.1–4.7.4;合同与 camofox OpenAPI 对照见 docs/design/browser-provider.md。 代码:packages/adapters/src/browser/**(适配器)、apps/server/src/modules/browser/**(会话/接管/能力)、 apps/web/app/components/browser/**(原站视图)。

当前状态:全部能力只对 testkit 的 mock camofox 验证过,没有连接过真实实例。界面上"画面与输入未对真实实例核验" 这个标记会一直显示,直到按第 6 节完成核验并写入 config.verified。

1. 登记浏览器服务

设置页还没有浏览器服务的表单(留给 C1 之后)。当前用 API + SQL 登记:

KEY="Authorization: Bearer <admin API Key 或 DEV_ADMIN_KEY>"
# 1) 访问凭据(camofox 的 CAMOFOX_ACCESS_KEY)存进凭证库,拿到 secret id
curl -s -XPOST localhost:4380/api/v1/secrets -H "$KEY" -H 'content-type: application/json' \
  -d '{"purpose":"other","name":"camofox-access-key","plaintext":"<CAMOFOX_ACCESS_KEY>"}'
# 2) 登记服务(secret_ref 用上一步的 id;没设访问凭据就留 null)
psql "$DATABASE_URL" -c "insert into browser_provider (name, kind, base_url, secret_ref, enabled)
  values ('camofox', 'camofox', 'http://camofox:9377', '<secret id>', true)"
# 3) 探测:读 /health 与 /openapi.json,写回 capabilities / health_status
curl -s "localhost:4380/api/v1/browser/providers?probe=true" -H "$KEY"

设置页将来要做的字段:base_url、访问凭据(写 secret_ref)、enabled、只读的能力表(supported / verified / 上游版本)、 下面的 config 可调项。

browser_provider.config 可调项(都可省略):

键 缺省 作用
verified {} 人工核验通过的能力,如 {"snapshot": true, "screenshot": true};探测永远不会把它置 true
navigationTimeoutMs 30000 单次导航超时
maxRetries 2 导航只重试超时 / 网络 / 5xx / 503;401、白名单、控制权冲突不重试
snapshotMaxBytes 524288 快照文本上限(超出截断并标 truncated)
requestTimeoutMs 30000 其它请求超时

站点域名白名单 = 站点 base_url 的主机(含子域)+ site.config.browserDomains(字符串数组,给跳转到独立下载域的站点用)。 站点限流与快照 / 实时搜索共用同一个限流器(导航、开标签页、历史导航取令牌)。

2. 会话与控制权

  • 会话按站点 / 账号隔离:profileKey = umt-site-<siteId>-acct-<accountId|anon>,同时作为 camofox userId (上游的登录状态隔离单元);browser_session.id 作 camofox sessionKey。同一 provider + profile 至多一个未关闭会话。
  • 数据库为准:服务重启后按 browser_session / browser_tab 恢复适配器内存,needsSnapshot 置 true,旧元素引用全部作废。 上游回收的标签页(404)对账标 lost,返回 409"标签页已被浏览器服务回收"。
  • 控制者:automation(Agent/任务)→ human(人工接管)→ automation 或 waiting;closed 终态。
事件 结果
接管 POST /browser/sessions/{id}/control/acquire 先把适配器控制者切到 human(新的自动化输入立即被拒),等该 profile 上进行中的请求收尾,再写 browser_control_lease(缺省 30 分钟)
他人已接管 409
交还 .../control/release 租约 released;会话回 automation(或 to: "waiting");needsSnapshot = true;待处理事项关闭
租约到期未交还 租约 expired,会话转 waiting(lease_expired),不自动从未知页面继续
Agent 快照看到验证码 / 二次认证 / Cloudflare 挑战 会话转 waiting(captcha / challenge),生成待处理事项(kind other,subject browser_session)
Agent browser.interact action=request_human 同上,原因 agent_request
站点停用 / 浏览器服务停用 下一次访问时会话关闭(site_disabled / provider_disabled)

HTTP 输入类端点(navigate / click / type / scroll / select / 开关标签页 / 带 target 的 download)只接受持有自己人工租约的调用者; 快照、截图、会话详情随时可读。截图只给原站视图,modelSafe=false 的不进模型。

3. Agent 能力

能力 类别 说明
browser.snapshot read 结构化快照(已脱敏);sessionId 或 siteId;清掉 needsSnapshot
browser.navigate execute(admin) 站点域名内;没有会话时按站点打开
browser.interact execute(admin) click / type / select / scroll / press / request_human;登录字段用 credential 由服务端注入
browser.download execute(organize.execute) 捕获下载 → 暂存 → 解析种子、匹配本地资源;不提交,提交用 download.plan / download.submit

execute 类需要持续授权(automation_grant)或审批。元素引用只来自最近一次快照:导航、点击、按键提交、控制权交接、 服务重启之后,旧的 eN 报 409 元素引用已失效…先重新读取页面。

4. 下载产物

  • 暂存:DATA_DIR/tmp/browser-downloads/<artifactId>.bin(目录 0700、文件 0600),超过 24 小时的在下一次捕获时清理。 合同里只出现引用(bytes.ref),来源地址去掉 passkey。
  • 核验:bencode 解析、infohash v1/v2、私有标记;按 source_release.infohash_v1/v2,再按下载地址 id 参数匹配本站资源。
  • 提交:HTTP POST /browser/sessions/{id}/download 带 submit 时转调 POST /acquisition-plans(同一鉴权、计划、去重、 缓存阈值、授权检查);被拒时产物照常返回,note 写拒绝原因。同一会话同一 sha256 第二次捕获标 duplicate,不再提交。
  • 浏览器没有媒体库写权限;提交链路下载的是站点适配器取到的种子,暂存文件只作核验证据。

5. 排障

现象 查
原站视图"没有启用的浏览器服务" browser_provider 是否有 enabled = true 且 kind = 'camofox' 的行
412"浏览器服务认证失败" / camofox 401 访问凭据与 CAMOFOX_ACCESS_KEY 是否一致;GET /browser/providers?probe=true
502 浏览器服务不可用 camofox /health(503 = 恢复中);容器日志
409 先接管会话再操作 界面点"接管";或租约已被他人持有 / 已过期
"连接中断" 截图请求失败;看 API 日志 component: browser 的方法 / 路径 / 状态(日志不含正文与凭据)

6. 真实实例核验清单(REQ §4.7.4)

先固定用户现有 camofox-browser 的仓库、版本(/openapi.json 的 info.version)、启动方式与认证配置,记在本节末尾。 每项通过后把对应能力写进 browser_provider.config.verified 并更新 verified_at;不通过的保持 false,界面继续标"未核验"。 不得用另一个浏览器窗口代替后宣称通过。

# 项目 做法 通过标准 对应 verified 键
1 登录保持 观众 / 馒头 / HHClub / CHD 各一账号:原站视图接管登录;闲置超过 SESSION_TIMEOUT_MS 后再 browser.snapshot 不需重新登录;过期时落到登录页、loginRequired = true,而不是空列表 sessions、persistentProfile
2 截图 / 结构化快照 列表页、详情页、登录页各取 screenshot 与 snapshot 截图格式(JSON base64 还是 image/*)、尺寸与坐标一致;快照 eN 引用可点;密码框值、Cookie、passkey 不出现;大页面 offset 分页正确 screenshot、snapshot
3 列表 / 详情提取 快照 + POST /extract(属性带 x-ref)与现有 HTTP 适配器结果对比 标题、分类、副标题、促销、做种一致,原始字段不丢 extract
4 文件下载捕获 详情页点"下载"后 POST /browser/sessions/{id}/download GET /tabs/{id}/downloads 的字段形状(filename / data / size / status)与适配器兼容;sha256 与直接 HTTP 下载一致;进暂存核验,不直写媒体库 downloadCapture
5 重启后会话 分别触发 BROWSER_IDLE_TIMEOUT_MS 回收与强制重启 camofox 容器 持久化 profile 恢复登录;旧 tabId 识别为 lost,不重放旧引用 persistentProfile、tabs
6 人与 Agent 同标签页连续操作 Agent 打开详情页 → 原站视图接管,在同一标签页点击、输入 → 交还 → Agent 重新 snapshot 人看到的是同一会话同一页面;交还后 Agent 读到人工操作后的状态;下载不重复提交 takeover、interact

本适配器依赖、但 1.17.0 OpenAPI 未写明的行为,核验时一并确认(不符就改适配器,不改合同):

  • POST /tabs/{id}/click 接受 {x, y} 视口坐标(原站视图点击);不支持时需要改走 VNC 插件或上游新增端点。
  • POST /tabs/{id}/type 不带 ref/selector 时输入到当前焦点;submit 与 README 的 pressEnter 哪个生效。
  • POST /tabs/{id}/press、/scroll、/back、/forward、/refresh 是否存在及请求体字段。
  • DELETE /tabs/{id} 的 userId 放 query 还是 body;DELETE /sessions/{userId} 是否关闭该 profile 全部标签。
  • userId 允许的字符与长度(umt-site-<uuid>-acct-<uuid>,约 90 字符)。
  • 性能:四站并发 1 / 2 / 4 会话的启动延迟、截图往返(原站视图 1.5 秒刷新是否跟得上)、内存与失败恢复时间。

核验记录(填写):

日期 仓库 / fork 版本 启动方式 / 认证 通过项 备注