feat(web): W4-A wire console to real endpoints
- Agent page uses contracts (AgentRun/AgentRunDetail/AgentGoalReport) instead of a local mirror; ?mock=1 stays as an explicit demo switch; run snapshot refreshes on agent.run_status; stream auto-follow only while the user stays near the bottom (abort stays reachable) - settings: Pi provider select incl. fake, new Agent runtime card (budgets, fakeScript) - download trace uses /tasks?subjectId= and /organization-records?downloadTaskId= instead of time-window engine run matching and path matching; new business-task tab with cancel/retry - workbench download dialog posts /acquisition-plans and shows per-slot rejection reasons - preference tag revision history; subscription search by title/kind; identity/alias/subscription lists show entity titles; slot cards show current asset summary; policy preview sample titles - DecisionSummary / IdentityRevisionList / ReleaseIdentityResult / TaskAccepted / PolicyPreviewSummary / OrganizePlanArtifactContent taken from contracts - docs: SSE for console (cookie) vs GET /events?after=&limit= JSON replay for API keys Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
34e8751b45
commit
1023642ef9
30 files changed
+703
-271
No files matched your search
@@ -29,9 +29,13 @@
|
||||
| `GET/POST /automation-grants`、`PATCH /automation-grants/{id}` | 持续授权。PATCH 只能撤销或缩短有效期,扩大范围要新建一条 |
|
||||
| `POST /approvals {planType, planId}`、`PATCH /approvals/{id} {status, payloadHash}` | 单次审批。批准时要回传 payloadHash,计划变化后旧审批失效 |
|
||||
| `GET /capabilities`、`POST /capabilities/{id}/invoke` | 能力目录与调用,HTTP scope 按能力描述符再校验一次 |
|
||||
| `GET /tasks[/{id}]`、`POST /tasks/{id}/cancel`、`POST /tasks/{id}/retry` | 业务任务 |
|
||||
| `GET /tasks[/{id}]`、`POST /tasks/{id}/cancel`、`POST /tasks/{id}/retry` | 业务任务;`?subjectId=` 按业务对象查(submitDownload 的 subject 是计划,verifyAndImport 的是下载任务) |
|
||||
| `POST /acquisition-plans {sourceReleaseId, slotId? \| entityId?, note?}` | 手动提交下载(工作台下载入口):依次调 `download.plan` → `download.submit`,和 Agent 同一条能力路径(授权 / 审计 / 幂等键 / 账本)。没给 slotId 时按作品的 Slot 创建顺序逐个尝试,第一个生成计划的胜出;都没生成时 `submitted=false` 并逐个 Slot 给出原因。控制台管理员算人工授权;API Key 需要持续授权或单次审批 |
|
||||
| `GET /artifacts[/{id}]` | 产物只读:整理 dryRun 计划(kind=plan)、目标汇报(report)、候选评估(evidence)等 |
|
||||
|
||||
**增量推送**:事件先写 `agent_run_event`(run_id + seq 唯一),再经 `ctx.events` 推到全局 SSE(`GET /events`)。推送的类型有 `agent.run_status`、`agent.text_delta`、`agent.tool_call`;未授权导致的工具失败,`phase` 为 `denied`。断线后,先用全局 `?after=<seq>` 补读总线事件,再用 `GET /agent/runs/{id}?afterSeq=<最后收到的 runSeq>` 补读单个 run 的完整事件。
|
||||
**增量推送**:事件先写 `agent_run_event`(run_id + seq 唯一),再经 `ctx.events` 推到全局 SSE(`GET /events`)。推送的类型有 `agent.run_status`、`agent.text_delta`、`agent.tool_call`;未授权导致的工具失败,`phase` 为 `denied`。断线后,先用全局 `?after=<seq>` 补读总线事件,再用 `GET /agent/runs/{id}?afterSeq=<最后收到的 runSeq>` 补读单个 run 的完整事件。SSE 只给控制台(cookie 会话);API Key 调用者用 `GET /events?after=<seq>&limit=<n>` 取 JSON 页轮询(见 auth.md「SSE 多进程总线」)。
|
||||
|
||||
控制台 Agent 页直接用这些端点(合同取 `@umt/contracts` 的 `AgentRun` / `AgentRunDetail` / `AgentGoalReport`),`?mock=1` 只是演示开关(本地假数据,不连后端,`?mock=0` 退出)。页面收到 `agent.*` 事件后按 `afterSeq` 增量补读,`agent.run_status` 到达即刷新 run 快照;SSE 断开时 2.5 秒轮询兜底。
|
||||
|
||||
## runAgent 做什么
|
||||
|
||||
|
||||
@@ -79,5 +79,7 @@ update admin_session set revoked_at = now(), revoke_reason = 'reset' where revok
|
||||
|
||||
- `PgEventBus`(`http/sse-pg.ts`):`publish` 在事务里持咨询锁插 `sse_event`(seq = bigserial,提交顺序即 seq 顺序)并 `pg_notify('umt_events', seq)`;每个进程一条 LISTEN 连接,收到通知按 seq 从表里补读并分发给本进程订阅者;断线自动重连并补读。
|
||||
- `GET /events?after=<seq>`(或 `Last-Event-ID`)从表里补读;表只保留最近 10000 条(每 200 次发布裁剪),起点已被裁剪时先发 `system.resync`。
|
||||
- **谁用 SSE,谁用 JSON 轮询**(W4-A 决定):浏览器 `EventSource` 带不了 `Authorization` 头,所以 SSE 只给控制台用(cookie 会话 `umt_session`,同源,`withCredentials`)。外部程序 / API Key 调用者用同一个端点取 JSON 页:
|
||||
`GET /events?after=<seq>&limit=<1-1000>`(带 `limit`,或只发 `Accept: application/json` 时返回 JSON,缺省 100 条),响应 `{ items: EventEnvelope[], nextAfter, hasMore, latestSeq, gap }`。下次用 `after=nextAfter` 续读;`hasMore=true` 时立即再取,否则按自己的节奏轮询;`gap=true` 表示起点已被裁剪,先重拉业务快照再从 `latestSeq` 续读。数据来自同一张 `sse_event` 表,和 SSE 看到的 seq 一致。合同:`Api.events.list`(`EventReplayQuery` / `EventReplayPage`)。
|
||||
- `ctx.events.publish(type, payload)` 返回 `Promise<EventEnvelope | null>`,永不 reject(失败记日志),可以不 await。
|
||||
- 测试/无库场景用进程内 `EventBus`(`publishSync` / `sinceSync` 便于断言)。
|
||||
+2
-1
@@ -22,7 +22,8 @@ deno task dev # 同时起 server(4380)与 web(5180)
|
||||
```sh
|
||||
curl localhost:4380/api/v1/health
|
||||
# 开发模式可用 .env 的 DEV_ADMIN_KEY 作 admin
|
||||
curl -N -H "Authorization: Bearer umt-dev-admin-key" "localhost:4380/api/v1/events?after=0"
|
||||
curl -N -H "Authorization: Bearer umt-dev-admin-key" "localhost:4380/api/v1/events?after=0" # SSE 流(控制台用)
|
||||
curl -H "Authorization: Bearer umt-dev-admin-key" "localhost:4380/api/v1/events?after=0&limit=50" # JSON 补读页(API Key 调用者用)
|
||||
```
|
||||
|
||||
- OpenAPI:http://localhost:4380/api/openapi.json,文档页 http://localhost:4380/api/docs
|
||||
|
||||
Reference in new issue
Block a user