aps-agent/docs/spec/protocol.md

5.9 KiB
Raw Blame History

客户端与服务端协议(v1)

契约本体在 contracts/schemas/(JSON Schema),TS 镜像在 contracts/,漂移由 scripts/check-contracts.test.mjs 卡。本文是给人看的同一份东西。

1 范围与所有权

服务端与客户端之间只认这一套接口。引擎协议(Pi 的 JSONL、Codex 的 app-server)只活在 server/agent 内部,客户端与 Core 都不感知——协议的所有权比协议的兼容性重要(架构设计 5.2)。

界面只依赖本文的事件模型:换引擎、换模型,事件不变。

2 版本与兼容规则

规则 说明
路径版本 前缀 {PROTOCOL_PREFIX} = /v1;改语义就换前缀,不原地改
事件版本 每个事件带 v,当前 1;字段只加不改不删
删除字段 先废弃(保留但不再填充)→ 下一个大版本再删
未知事件 客户端必须忽略不认识的 type,不能崩
未知字段 客户端必须忽略,不能因多字段报错

3 认证与身份

客户端 方式 说明
浏览器 Cookie: ap_session=<httpOnly> 沿用现有 JMS 登录;服务端不把业务系统 token 下发给客户端
桌面端 Authorization: Bearer <desktop-token> 授权码 + 设备绑定换来的短期令牌(沿用现有授权方式)

两者都由 server/entry 解析成同一个 Subject(用户 + 租户),再交给应用服务与 Core。首次调用的返回值就是 MeResponse。

4 端点

方法 路径 请求 响应 说明
GET /v1/health — HealthResponse 健康检查
GET /v1/me — MeResponse 当前身份与客户端形态
GET /v1/projects — ProjectListResponse 可见项目
GET /v1/sessions ?projectId= SessionListResponse 会话列表
POST /v1/sessions CreateSessionRequest CreateSessionResponse 建会话;写操作必须建在项目会话(ADR-0003)
GET /v1/sessions/{id} ?limit= SessionDetailResponse 会话详情与最近消息
GET /v1/sessions/{id}/events Last-Event-ID 或 ?since= SSE 事件流 回放 + 实时,见第 5 节
POST /v1/sessions/{id}/messages SendMessageRequest SendMessageResponse 发消息;返回受理,结果走事件流
POST /v1/sessions/{id}/cancel — CancelResponse 取消当前运行
GET /v1/capabilities ?sessionId= CapabilitiesResponse 按身份过滤的能力清单
GET /v1/executions/{executionId} — ExecutionReceipt 执行状态与回执
POST /v1/approvals/{approvalId} ApprovalDecisionRequest ApprovalDecisionResponse 确认卡响应

5 事件流(SSE)

规则 说明
传输 text/event-stream;event: 填事件 type,data: 填整条事件 JSON
序号 seq 在会话内单调递增,从 1 开始;客户端按它去重与排序
断点续传 客户端带 Last-Event-ID(或 ?since=)重连,服务端从该序号之后回放
回放 回放与实时用同一格式,客户端不需要两套解析
心跳 无事件时按固定间隔发 heartbeat,用于探活与代理保活
顺序 同一会话的事件严格有序;不同会话之间不保证
敏感 事件里只有参数摘要(argsDigest、paramsDigest),没有凭据与参数明文

6 事件清单

事件 含义 data 关键字段
message.delta 助手增量文本 messageId、text
message.completed 一条助手消息结束 messageId、finishReason
tool.call 引擎请求调用能力 callId、capabilityId、argsDigest
tool.result 能力调用的回执 callId、executionId、status
execution.updated 执行状态变化 executionId、status、errorKind
approval.requested 需要用户确认 approvalId、capabilityId、paramsDigest、impactSummary、revision、expiresAt
approval.resolved 确认结果 approvalId、decision
run.state 当前运行状态 state(idle/running/cancelling/cancelled)
session.updated 会话标题或状态变化 title、status
error 错误 code、message、retryable
heartbeat 保活 空对象

status 取值统一为 accepted / pending-confirmation / succeeded / failed。

7 审批时序

  1. 引擎请求写能力 → Core 判定需确认 → 落一条待确认动作(ADR-0003、架构设计 4.2)
  2. 服务端推 approval.requested,客户端渲染确认卡(影响范围、参数摘要、目标版本、有效期)
  3. 用户点批准 → POST /v1/approvals/{id},带 revision 与 idempotencyKey
  4. 服务端校验版本与有效期 → 推 approval.resolved → 执行 → 推 execution.updated
  5. 版本过期或已执行 → 返回 expired,客户端提示重新确认;确认人是会话发起人本人

8 错误模型

位置 形状 说明
HTTP ErrorEnvelope 请求本身失败(鉴权、参数、找不到)
SSE error 事件 运行中失败;retryable 表示可重试,客户端据此给"重试"按钮

9 幂等与取消

场景 规则
发消息 带 idempotencyKey;同一 key 重试不产生第二个 run
审批 带 idempotencyKey;同一 key 只生效一次
取消 幂等:重复取消不报错;已结束的运行返回 idle
结果未知 执行超时返回 failed 且 errorKind = unknown,由客户端提示查执行记录,不自动重试写操作

10 变更规则

改协议必须同时改三处,否则 pnpm test 会失败:

  1. contracts/schemas/*.json(规范本体)
  2. contracts/events.ts / contracts/protocol.ts(TS 镜像;第 4 节的端点表与 ENDPOINT_SPECS 由测试逐条比对)
  3. 本文档(第 4、6 节的表)