test(e2e): AG-3 agent quality with fake model; runbook capability list
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
41e3647f0a
commit
3f0327ad97
3 files changed
+225
-5
No files matched your search
@@ -151,3 +151,4 @@ NFO / 图片投影、身份巡检与挂载根因聚合、HTTP 失败自动切浏
|
||||
- 追加(用户 2026-09-29):对比 Webtop 与浏览器镜像合一 vs 与本体镜像合一(协调者倾向前者:同会话、生命周期隔离、安全面、镜像大小);**视觉自动化闭环**:Agent 截图(多模态喂视觉模型)→ 坐标点击/输入 → 再截图,有界步数与预算,用于登录/验证码/交互式挑战;二次验证与本人设备确认不自动过;每步证据入待处理,失败转人工接管。能力:`browser.screenshot`(图片内容)、`browser.click_at`、`browser.type_at`、`browser.solve_challenge`(有界子流程)。
|
||||
- **上游模型列表一键获取(用户 2026-09-29)**:`POST /pi/upstreams/{id}/models/refresh` 按 provider 调远程模型列表接口(OpenAI 兼容 /models、Anthropic /v1/models 等),存库带时间,UI 可搜索选择 + 手填,失败回退静态表。用户已接入 OpenCode Go 订阅,Agent 能力测试统一用 DeepSeek V4.1 Flash(视觉部分需视觉模型)。
|
||||
- **AG-3 Agent 质量(来自 AGENT-REAL 真实上游验证,2026-09-29)**:补只读能力 subscription.list / decision.list / download.inspect(task.inspect 不再接收 download_task id);`download.plan` 的 requiresApproval 按授权范围判定;测试补全带 sessionId(OpenCode 需 x-opencode-session);等待期间 token/费用显示;超预算 run 在任务页标"超预算";同根因超预算不重复建待处理;汇报 Markdown 渲染;系统提示:禁止空/单字探查查询、参数类型(externalId 字符串)、子会话预算不超父剩余、中文思考与汇报、被中断时输出中文小结;重跑 AGENT-REAL 七场景。
|
||||
- 进度(2026-09-29):除真机重跑外已完成——38 个能力(新增 3 个只读摘要,已进后台调查 / 巡检白名单);`coveringGrant` 与授权器共用;预算将尽提醒、被打断时丢弃中间过程文字;等待期间用量写回;任务页按 `business.outcome` 显示超出预算;超预算待处理按根因合并;汇报 Markdown 安全子集渲染;fake 模型 e2e 见 `apps/server/test/e2e/e15-agent-quality.test.ts`。开发库没有真实上游(只有 fake),AGENT-REAL a/e/g 真机重跑留给协调者重建用户栈后做。
|
||||
+28
-5
@@ -6,7 +6,25 @@
|
||||
|
||||
## 能力
|
||||
|
||||
启动时装配 15 个能力(`catalog.lookup`、`release.search`、`release.inspect`、`identity.resolve`、`download.plan`、`download.submit`、`download.recheck`、`organize.plan`、`organize.execute`、`task.inspect`、`task.retry`、`task.cancel`、`policy.preview`、`policy.apply`、`inventory.query`)。注册数不等于 `CAPABILITY_IDS.length` 时进程启动失败。网页搜索 `web.search` / `web.fetch` 见 [websearch.md](websearch.md)。Web(`POST /capabilities/{id}/invoke`)、Pi 工具和后台任务都走 `ctx.capabilities.invoke` 这一条路径。
|
||||
启动时装配 38 个能力,注册数不等于 `CAPABILITY_IDS.length` 时进程启动失败。Web(`POST /capabilities/{id}/invoke`)、Pi 工具和后台任务都走 `ctx.capabilities.invoke` 这一条路径。描述符在 `packages/contracts/src/capability.ts`,每条描述都带一句"何时用 / 何时不用"。
|
||||
|
||||
| 分组 | 能力 |
|
||||
|---|---|
|
||||
| 查询(read) | `catalog.lookup`、`release.search`、`release.inspect`、`inventory.query`、`subscription.list`、`decision.list`、`download.inspect`、`task.inspect`、`site.list`、`site.user_data` |
|
||||
| 计划(preview / propose) | `identity.resolve`、`download.plan`、`organize.plan`、`policy.preview` |
|
||||
| 执行(execute) | `download.submit`、`download.recheck`、`organize.execute`、`task.retry`、`task.cancel`、`policy.apply`、`site.health_check`、`site.refresh_login` |
|
||||
| 原站浏览器 | `browser.snapshot`、`browser.navigate`、`browser.interact`、`browser.download`、`browser.screenshot`、`browser.click_at`、`browser.type_at`、`browser.scroll`、`browser.wait`、`browser.solve_challenge`(见 [browser.md](browser.md)) |
|
||||
| 会话 | `agent.plan`、`agent.propose_options`、`agent.spawn`、`agent.await` |
|
||||
| 网页搜索 | `web.search`、`web.fetch`(见 [websearch.md](websearch.md)) |
|
||||
|
||||
AG-3 补的只读摘要(类别 read,scope `read`,都在后台调查 / 巡检白名单里):
|
||||
|
||||
- `subscription.list {status?, mediaKind?, query?, groupBy=status|mediaKind|none, limit≤200}`:订阅分组计数 + 条目(作品、模式、状态、优先级、版本目标总数 / 已满足数、上次 / 下次搜索)。查单个作品的文件与版本目标仍用 `inventory.query`。
|
||||
- `decision.list {status?, kind?, limit≤100}`:待处理事项摘要,缺省只列 open / investigating / awaiting_user,按严重度排序;每条带可选处理 `options`。只读,处理仍由用户在待处理中心选。
|
||||
- `download.inspect {downloadTaskId? | hash?}`:按下载任务 ID 或种子 hash(v1 / v2,大小写均可)读下载任务、关联计划、资源、业务任务(提交下载 / 核验入库,ID 可交给 `task.inspect` / `task.retry`)、整理记录与待处理事项;同 hash 在多个下载器实例时其余 ID 放 `otherMatches`。
|
||||
- `task.inspect` 只接受业务任务(`task` 表)ID;传入下载任务 ID 时返回 `invalid_input`:"这是下载任务 ID…用 download.inspect 查看"。
|
||||
|
||||
检索词(`catalog.lookup` / `release.search` / `inventory.query` / `subscription.list` 的 `query`)去掉首尾空白后不能为空、不能是单个英文字母 / 数字 / 符号、不能只有通配符与标点(`invalid_input`:"检索词太短…");中文单字片名允许。`catalog.lookup.externalId.externalId` 一律是字符串。
|
||||
|
||||
- **授权**(`agent/authorize.ts`):propose / approve / execute 类必须满足以下之一:
|
||||
- 单次审批 `approval`:状态为 approved,绑定计划类型 + 计划 ID + payload hash + revision,且未过期。执行成功后审批标记为 consumed。
|
||||
@@ -15,7 +33,7 @@
|
||||
模型参数里写"用户已同意"不起作用。输入里的 `approvalId` 只是一个指针,授权结果以库里的审批记录为准。控制台管理员从 Web 手动调用(actor=`user:*`)算人工授权,API Key、Agent 和后台任务都必须有授权记录。自动化总开关关闭或处于只读对账时,自动来源的 execute 一律拒绝。
|
||||
- **审计**:每次调用都写一条 `audit_event`,action 为 `capability.invoke` 或 `capability.denied`,payload 包含 outcome、授权 ID、幂等键和脱敏后的输入摘要。
|
||||
- **幂等键与操作账本**:有副作用的调用由服务端生成幂等键,格式为 `id:v版本:<agentRunId|taskId>:sha256(规范化输入)`,并记入 `capability_invocation`。状态为 succeeded 时直接返回记录的结果。状态为 running(进程在调用途中崩溃)时,用同一个键重跑处理器来对账,处理器本身是幂等的。
|
||||
- `download.plan` 只生成 **draft** 计划:不预留 Slot,不计入预算,也不会被后台巡检补提交。`download.submit` 在授权通过后先把 draft 转成 reserved(Slot revision 必须与生成计划时一致),再入队 `submitDownload`,和自动路径共用幂等键 `plan:<planId>`。
|
||||
- `download.plan` 只生成 **draft** 计划:不预留 Slot,不计入预算,也不会被后台巡检补提交。`requiresApproval` 按授权范围判定:有覆盖本计划的持续授权(action 覆盖 `download.submit`、对象 / 类型范围含目标作品、绑定策略仍发布、每日次数 / 字节预算有余量,与 authorize 同一函数 `coveringGrant`)时为 false,否则为 true;没生成计划时按 Slot 的作品判定。`download.submit` 在授权通过后先把 draft 转成 reserved(Slot revision 必须与生成计划时一致),再入队 `submitDownload`,和自动路径共用幂等键 `plan:<planId>`。
|
||||
- `organize.plan` 把冻结的整理计划存成 artifact(kind=plan),`payloadHash` 就是计划指纹。`organize.execute` 执行前会重新冻结一次,指纹不一致就返回 conflict。
|
||||
|
||||
## 会话 API
|
||||
@@ -49,10 +67,15 @@
|
||||
- 入库完成 → `succeeded`,汇报带整理记录 ID;
|
||||
- 仍在等待 → `waiting`;
|
||||
- 失败 → `failed`;
|
||||
- 超预算 → `budget_exceeded`,同时开一条待处理事项 `agent_budget:<runId>`;
|
||||
- 超预算 → `budget_exceeded`,同时开一条待处理事项。同根因只保留一条未关闭事项(`attempts`+1,`evidence.runIds` 累积,`agent_run_id` 指向最新一次):去重键为 `agent_budget:root:<被调查事项的去重键>`(后台调查)、`agent_budget:schedule:<定时任务>`(巡检)或 `agent_budget:goal:<目标模板指纹>`(去掉时间戳 / UUID / 数字后的目标 sha256 前 16 位)。业务任务行记 `failed`,`output.status=budget_exceeded`;任务页按引擎 run 的 `business.outcome`(= `agent_run.status`)显示「超出预算」,不显示「完成」;
|
||||
- 取消 → `cancelled`。
|
||||
|
||||
模型的最终文本只附在汇报后面,标注"模型汇报(未经核查)"。
|
||||
模型的最终文本只附在汇报后面,标注"模型汇报(未经核查)"。被预算或中止打断时,最后一次工具调用之前的文字只是中间过程,不作为模型汇报(`finalText` 置空,会话页显示服务端的中文汇总)。
|
||||
|
||||
**预算提醒**:工具调用只剩 ≤2 次,或 token / 费用 / 时长用到 85% 时,运行时在工具结果末尾追加「【预算提醒】…停止探查,下一条回复直接用中文写小结」,系统提示要求模型见到后直接收尾。
|
||||
**等待期间的用量**:会话挂起(审批 / 选方案 / 等子会话)时没有 `run_completed`,drive 退出前把运行时累计用量按字段取较大值写回 `agent_run.usage`,会话页和列表在等待期间照样显示已用 token / 费用。
|
||||
|
||||
模型汇报在会话页按 Markdown 安全子集渲染(标题、列表、表格、引用、代码、粗体 / 斜体 / 链接;原文 HTML 按文字显示,链接只放行 http(s) 与站内路径),流式输出中仍按原文显示。
|
||||
|
||||
worker 崩溃后,新 worker 在引擎租约到期后(约 30s)接手,`drive` 步骤会从头重跑。已经完成的工具调用不会重放。副作用调用的结果模型会看到"结果未知",模型需要重新核对;同参数再调用一次,会直接拿到账本里的结果。
|
||||
|
||||
@@ -154,7 +177,7 @@ runAgent 按 `runAgent{upstreamId}` → `agent_run.upstream_id` → 默认上游
|
||||
| `GET /pi/providers?models=false` | 能力表:authKinds(第一个是推荐项)、`oauth.modes`(browser / device)、`termsNote`(条款风险)、`baseUrlOverridable`、`envFields`、静态模型表 |
|
||||
| `GET /pi/upstreams`、`GET /pi/upstreams/{id}` | 不含密钥,只给 `hasCredential`、`credentialMask`(前 4 后 4)、`account`、`oauthExpiresAt`、`isDefault` |
|
||||
| `POST /pi/upstreams`、`PATCH /pi/upstreams/{id}`、`DELETE …` | `apiKey` 只写(PATCH 传 null 清除);provider 不可改;改 authKind 会删掉旧凭据;删除连同 secret |
|
||||
| `POST /pi/upstreams/{id}/test {mode?: auth\|completion, model?}` | 缺省 `auth`:解析凭据(OAuth 必要时刷新)+ 校验模型在目录中,**不产生费用**;`completion` 再发一次最多 16 token 的补全 |
|
||||
| `POST /pi/upstreams/{id}/test {mode?: auth\|completion, model?}` | 缺省 `auth`:解析凭据(OAuth 必要时刷新)+ 校验模型在目录中,**不产生费用**;`completion` 再发一次最多 16 token 的补全,带一次性 `sessionId`(OpenCode Zen / Go 据此加 `x-opencode-session` 头,缺了会被拒) |
|
||||
| `GET /pi/upstreams/{id}/models` | `{source: remote\|static, fetchedAt, models[], remoteSupported, error, errorKind}`:拉过远程列表 → 远程与静态目录合并去重(同 id 远程优先,远程缺的字段用静态补,远程在前);没拉过 → 静态目录(已配置凭据时按 provider 过滤,如 Copilot) |
|
||||
| `POST /pi/upstreams/{id}/models/refresh` | 「获取模型列表」:用该上游的凭据调 provider 的模型列表接口,成功存 `pi_upstream.models` + `models_fetched_at`(迁移 0044)。失败不动已存列表,返回当前列表 + 一句话 `error`,`errorKind` = auth(401/403)/ network / unsupported / config / other。改 Base URL 或 `extra.api` 会清掉已存列表 |
|
||||
| `POST /pi/models/probe {provider, authKind, apiKey?, baseUrl?, extra?}` | 新建上游前试拉(凭据只用这一次,不落库);新建向导创建后会用已存凭据再拉一次并存库 |
|
||||
|
||||
Reference in new issue
Block a user