diff --git a/docs/integration/heicode-desktop-sub-agile-api.md b/docs/integration/heicode-desktop-sub-agile-api.md index f367689c..340232d0 100644 --- a/docs/integration/heicode-desktop-sub-agile-api.md +++ b/docs/integration/heicode-desktop-sub-agile-api.md @@ -18,13 +18,13 @@ Manager 负责辅助控制面:任务草稿桥接、资源/权限、Agnet deplo | API 前缀 | 用途 | 认证 | |---|---|---| -| `/api/heicode-auth/api/user/tasks/*` | HeicodeTask 任务编排代理,创建任务、追问、查询任务 | `Authorization: Bearer ` | -| `/api/agnet/user/*` | Manager 用户态 Agnet 控制面,deployment、timeline、artifact、审批 | Manager 登录 session cookie + `New-Api-User: ` | +| `/api/heicode-auth/api/user/tasks/*` | HeicodeTask 任务编排代理,创建任务、追问、查询任务 | V2 加密 body + `Authorization: Bearer ` | +| `/api/agnet/user/*` | Manager 用户态 Agnet 控制面,deployment、timeline、artifact、审批 | V2 加密 body;未加密 Web 控制台请求继续使用 Manager session + `New-Api-User` | | `/api/user/self` | 查询当前 Manager 用户 | Manager 登录 session cookie | ### 2.2 桌面端请求 body 加密 -桌面客户端调用 Manager 的 sub 流程接口时,应优先使用与模型调用一致的 V2 加密请求协议。 +桌面客户端调用 Manager 的 sub 流程接口时,应使用与模型调用一致的 V2 加密请求协议。生产 Manager 自 `1.4.7` 起已支持该能力。 适用接口: @@ -74,9 +74,17 @@ Authorization: Bearer 原因:该 token 是上游 HeicodeTask 服务认证用;V2 设备签名只证明请求来自已配对的 Manager 桌面设备。 +客户端实现要求: + +1. sub 流程调用不要新增一套加密协议,直接复用模型调用的 `encryptedFetch` / V2 设备签名实现。 +2. `aad` 和 `canonical` 中的 `path_with_query` 必须是 Manager 实际收到的 path,例如 `/api/agnet/user/tasks/task-1/deployment-draft`,不能把 origin 写进去。 +3. 加密前的 plaintext 必须是最终 JSON body;签名里的 `sha256_hex(plaintext_body)` 必须和该 JSON 字节完全一致。 +4. 每次请求必须使用新的 `X-Heicode-Nonce` 和新的 X25519 ephemeral key。 +5. V2 请求失败时优先读取 `X-Heicode-Auth-Error` 和 `X-Heicode-Server-Time`,用于提示设备未配对、时间漂移、nonce 重放、签名错误或解密失败。 + ### 2.3 Manager 用户态 Header -调用 `/api/agnet/user/*` 时必须带: +未加密 Web 控制台请求调用 `/api/agnet/user/*` 时必须带: ```http Cookie: session= @@ -87,7 +95,7 @@ Accept: application/json `New-Api-User` 必须等于当前登录用户 ID,否则会返回未授权。 -使用 V2 加密 body 时,`/api/agnet/user/*` 可以不依赖浏览器 session cookie;Manager 会从设备绑定 token 中解析用户身份。为兼容当前 Web 控制台,未加密请求仍按 session cookie + `New-Api-User` 处理。 +使用 V2 加密 body 时,`/api/agnet/user/*` 不依赖浏览器 session cookie,也不需要 `New-Api-User`;Manager 会从设备绑定 token 中解析用户身份。为兼容当前 Web 控制台,未加密请求仍按 session cookie + `New-Api-User` 处理。 ### 2.4 统一响应 Envelope @@ -1116,31 +1124,61 @@ Runtime callback / timeline 中可使用: ## 14. 桌面端最小伪代码 ```ts +type Json = Record + +// 复用模型调用已经使用的 V2 加密 fetch: +// - 自动拉取 /api/server-pubkey +// - 每次请求生成 nonce + X25519 ephemeral key +// - 用 ChaCha20-Poly1305 加密 body +// - 用设备 Ed25519 私钥签名 canonical +// - 设置 Content-Encoding: heicode-aead-v1 和所有 X-Heicode-* 头 +async function encryptedManagerRequest( + method: 'POST', + path: string, + body?: Json, + extraHeaders: Record = {} +): Promise { + return encryptedFetch(`${managerBaseUrl}${path}`, { + method, + plaintextJson: body, + headers: { + Accept: 'application/json', + ...extraHeaders, + }, + }) +} + const self = await manager.get('/api/user/self') const userId = self.data.id -const task = await mcp.post('/api/heicode-auth/api/user/tasks/intent', { - intent: userInput, -}, { - headers: { +const task = await encryptedManagerRequest>( + 'POST', + '/api/heicode-auth/api/user/tasks/intent', + { intent: userInput }, + { Authorization: `Bearer ${heicodeAccessToken}`, - }, -}) + } +) let current = task.data while (current.status === 'configuring') { const followup = findNextFollowup(current) const answer = await askUser(followup) - current = await mcp.post( + current = await encryptedManagerRequest>( + 'POST', `/api/heicode-auth/api/user/tasks/${current.id}/answer`, { question_id: followup.id, option_id: answer.id, + }, + { + Authorization: `Bearer ${heicodeAccessToken}`, } ).then((r) => r.data) } -const draft = await manager.post( +const draft = await encryptedManagerRequest>( + 'POST', `/api/agnet/user/tasks/${current.id}/deployment-draft`, { task: current, @@ -1148,26 +1186,25 @@ const draft = await manager.post( binding_scope: `task-${current.id}`, role_templates: ['backend', 'frontend', 'reviewer'], default_model_id: 'agnet-model-builder', - }, - { headers: { 'New-Api-User': String(userId) } } + } ) -const deployment = await manager.post( +const deployment = await encryptedManagerRequest>( + 'POST', '/api/agnet/user/deployments', - { orchestration_plan: draft.data.orchestration_plan }, - { headers: { 'New-Api-User': String(userId) } } + { orchestration_plan: draft.data.orchestration_plan } ) const deploymentId = deployment.data.deployment_id setInterval(async () => { - const timeline = await manager.get( + const timeline = await manager.get>( `/api/agnet/user/deployments/${deploymentId}/timeline`, { headers: { 'New-Api-User': String(userId) } } ) renderTimeline(timeline.data.timeline) - const approvals = await manager.get( + const approvals = await manager.get>( `/api/agnet/approvals?status=pending&deployment_id=${deploymentId}`, { headers: { 'New-Api-User': String(userId) } } ) @@ -1175,11 +1212,21 @@ setInterval(async () => { }, 5000) ``` +兼容说明: + +- 桌面客户端对 `POST` 等有 body 的 sub 请求走 V2 加密时,`/api/agnet/user/*` 不需要 `New-Api-User`,也不依赖浏览器 cookie。 +- `GET` 查询接口本身没有请求 body,当前生产兼容路径仍使用 Manager session cookie + `New-Api-User`。如果桌面本地服务后续要完全脱离 session cookie 查询 timeline / artifact / approval,需要再补“无 body 的 V2 设备签名 GET”协议。 +- `/api/heicode-auth/*` 仍必须带 `Authorization: Bearer `,该 token 只用于上游 HeicodeTask 认证。 +- 如果客户端临时还没有接入 V2 加密,只能作为调试兼容路径使用 Manager session + `New-Api-User` 调 `/api/agnet/user/*`;正式桌面流程不要依赖该路径。 + ## 15. 当前生产注意事项 -1. `https://code.xinghanlab.com` 的 Manager 用户态接口已上线。 +1. `https://code.xinghanlab.com` 的 Manager 用户态接口已上线,当前生产版本为 `1.4.7`。 2. Manager 本地控制面可创建 `sub_mode=agile/waterfall` deployment。 3. 生产 Manager 已配置 Agent Manager Runtime,当前直接走 `http://20.212.121.126`;域名和 HTTPS 后续单独处理,不作为客户端当前接入阻塞项。 -4. `deployment-draft -> create -> detail -> stop` 已在生产验证通过,客户端可按本文参数形状接入。 +4. V2 加密 `deployment-draft` 已在生产验证通过:真实构造 `Content-Encoding: heicode-aead-v1` 请求返回 200,`sub_mode=agile`,`user_id=22`。 5. `events/logs/artifacts/sk-snapshots/timeline` 查询接口已验证不报错;真实阶段事件、产物、SK 调用结果需要 Agent Manager 执行任务并回调后才会出现。 -6. `POST /api/heicode-auth/api/user/tasks/intent` 需要桌面客户端提供 `heicode_access_token`;没有该 token 会返回 401。 +6. `deployment-draft -> create -> detail -> stop` 已在生产验证通过,客户端可按本文参数形状接入。 +7. `POST /api/heicode-auth/api/user/tasks/intent` 需要桌面客户端提供 `heicode_access_token`;没有该 token 会返回 401。 +8. malformed V2 请求已在生产验证会返回 `X-Heicode-Auth-Error`,客户端应把该头转成可读错误提示。 +9. 当前 `GET` 查询接口没有请求 body,仍按 session + `New-Api-User` 验证;这不影响 body 加密要求,但客户端若要全链路无 cookie,需要后续补无 body 签名 GET。