diff --git a/docs/integration/heicode-desktop-unified-api.md b/docs/integration/heicode-desktop-unified-api.md index bf2659f4..401b0560 100644 --- a/docs/integration/heicode-desktop-unified-api.md +++ b/docs/integration/heicode-desktop-unified-api.md @@ -1,46 +1,45 @@ # Heicode 桌面客户端统一接口对接文档(v0.1) -更新时间:2026-06-02 -适用范围:Heicode Desktop 对接 Heicode Manager 的**统一接口层**(Sub Agile / Swarm 两模式)。 +更新时间:2026-06-03 +适用范围:Heicode Desktop 对接 Heicode Manager 的**统一接口层**(Sub Agile / Swarm 两模式)。端到端流程与三端职责以 [`heicode-sub-mode-flow-spec.md`](./heicode-sub-mode-flow-spec.md) 为准,本文是其接口层。 Manager 生产地址:`https://code.xinghanlab.com` 基准:统一调用方案 v0.1 + agent_management Sub Mode Runtime 对接指南。 > 本文取代旧的 `heicode-desktop-sub-agile-api.md`(其 `/api/agnet/*` 路由已废弃)。新客户端一律使用本文的 `/api/heicode/*` 与 `/api/agent/*` 接口。 -> **2026-06-02 更新(已对照客户端 gap-analysis 闭环 P0/P1 并在运行时实跑验证)**: -> - GET 全程无 cookie 的「无 body 设备签名」(§1,P0-1); -> - 审批列表 `GET .../approvals?status=`(§3.2,P0-2); -> - 产物列表归一化 `display_artifact_type=project_folder` + `is_project`(§5,P0-3); -> - `/archive` 下载契约(zip 头 + `ARTIFACT_ARCHIVE_NOT_READY`,§5,P0-4); -> - 单文件改 `?path=` 编码(§5,P1-1); -> - revision `accepted`/`applied` 语义 + `/messages`·`/execute` 自动用最新 accepted(§6,P1-2/P1-3); -> - Swarm 全量同形显式声明(§3,P1-4)。 +> **⚠️ 2026-06-03 流程对齐(权威端到端流程见 [`heicode-sub-mode-flow-spec.md`](./heicode-sub-mode-flow-spec.md),本文是其接口层)。几处认知已纠正:** +> - **客户端是 Claude-Code 式智能体程序**(本地能跑 agent、执行命令、本地部署),不是无 AI 的壳;**HM = 模型网关(`/v1/*`)+ 控制面**,给客户端和 agent_management 两边都提供模型;**agent_management = 云端多 agent 运行时**。 +> - **sub 模式 = 把多 agent 任务派到云端 agent_management 跑**(区别于客户端本地自己跑小任务)。 +> - **`display_status` 只代表"跑完没/有没有真产物(防空壳)",不代表"代码对不对"**。代码对错 = **客户端(本地能跑能测)+ 用户 review** 判,**不是 HM 判**(HM 没 AI、不读代码)。详见 spec §6。 +> - **部署 = 客户端执行 + 用户必须确认**;HM 只把凭据从 Key Vault 安全发给客户端,**HM 不部署、不连 VM**(见 §7,已改)。 +> - **产物归宿是用户自己的 git 仓库**(github/gitea);先绑仓库(及 vm/db/blob)→ §8 资源绑定。 +> +> **2026-06-02 更新(gap-analysis P0/P1 闭环并实跑验证)**:GET 无 body 设备签名(§1)、审批列表(§3.2)、`project_folder` 归一化(§5)、`/archive` 契约(§5)、`?path=`(§5)、revision accepted/applied(§6)、Swarm 同形(§3)。 ## 0. 命名与总原则 - **命名统一**:`agnet` 是历史拼写错误,已全量改为 `agent`。所有新接口为 `/api/agent/*`、`/api/heicode/*`;旧 `/api/agnet/*` 已下线(404)。 -- **客户端只调 Manager**:禁止直连 agent_management / HeiCode-Swarm / NewAPI / Runtime artifact 接口。 -- **Manager 是唯一状态裁判**:客户端只消费 `display_status`,不自行用正则判断产物是否有效。 -- **task_id ≡ deployment_id**:统一任务接口里 `{task_id}` 即 Manager 的 `deployment_id`。 +- **客户端只调 Heicode Manager(HM)**:任务/控制走 `/api/heicode/*`、`/api/agent/*`,模型走 `/v1/*`;禁止直连 agent_management / HeiCode-Swarm / Runtime artifact 接口。 +- **`display_status` 是 HM 的"进度/有无产物"裁决,不是"对错"裁决**:客户端用它判断"跑完没、是不是空交付"(防空壳),**但代码对不对由客户端自己拉下来跑/测 + 用户 review 决定**(HM 没 AI、不读代码、不编译)。 +- **task_id ≡ deployment_id**:统一任务接口里 `{task_id}` 即 HM 的 `deployment_id`。 ## 0.1 推荐完整流程 ```text +0. (一次性) 绑定资源: github/gitea 仓库 + (可选) vm/db/blob -> 凭据进 Key Vault, 拿 resource_binding_id (§8) 1. GET /api/heicode/capabilities 取模式/模型,渲染模式与模型选择 2. POST /api/heicode/sub-agile/tasks (需求包) 创建任务 -> 响应里拿 deployment_id(=task_id) 3. (可选) POST .../tasks/{id}/execute 若需"先建后跑"或重试派发 -4. 轮询 GET .../tasks/{id}/workflow (运行中 3-5s) 读 display_status + 三层状态 + agents +4. 轮询 GET .../tasks/{id}/workflow (运行中 3-5s) 读 display_status + 三层状态 + agents (work 视图) 5. 出现 approval 时: GET .../approvals?status=pending -> approve/reject -6. display_status=completed 后: - GET .../tasks/{id}/artifacts 拿 artifact_id - GET .../artifacts/{artifact_id}/manifest 项目文件树 - GET .../artifacts/{artifact_id}/files?path=<路径> 单文件正文 - GET .../artifacts/{artifact_id}/archive 整包 zip -7. (可选) 用户本地改后: POST .../artifacts/{id}/local-edits -8. (可选) 部署: GET /api/heicode/deployment-targets -> POST .../tasks/{id}/deployments +6. display_status=completed 后看产物 (两条路): + (a) 直接 git clone/pull 用户自己的仓库 (完整工程+历史+diff) + (b) 经 HM: GET .../artifacts -> /manifest -> /files?path= -> /archive +7. 不满意 -> 改/重做 (两条路): POST .../messages|/execute 回云端改; 或 git pull 本地用客户端自己的 agent 改 +8. (可选) 部署: 用户确认 -> 客户端凭 resource_binding_id 向 HM 取凭据(V2) -> 客户端本地 git/ssh/部署 (§7, HM 不代执行) ``` -> 成功判据:`display_status=completed`(不是 `needs_codegen` / `completed_without_deliverable`)且 artifacts 非空。 +> 成功判据:`display_status=completed` 且 artifacts 非空 = **跑完且有真东西**;但**"代码对不对"客户端自己拉下来跑/测 + 用户 review**(`completed` 不保证正确,见 §4)。 ## 1. 认证与加密(重要) @@ -116,7 +115,7 @@ signature = base64( ed25519_sign(device_priv, sha256(canonical)) ) | GET | `/api/heicode/sub-agile/tasks/{task_id}/approvals?status=pending` | 审批列表(gap P0-2) | | POST | `/api/heicode/sub-agile/tasks/{task_id}/approvals/{approval_id}/approve` | 同意审批 | | POST | `/api/heicode/sub-agile/tasks/{task_id}/approvals/{approval_id}/reject` | 拒绝审批 | -| GET | `/api/heicode/sub-agile/tasks/{task_id}/deployments` · POST 同路径 | 云部署列表 / 发起(见 §7) | +| GET | `/api/heicode/sub-agile/tasks/{task_id}/deployments` · POST 同路径 | ⚠️ 旧的「Manager 代部署」控制面,**不再作为部署主路径**;新部署=客户端执行(见 §7) | ### 3.1 创建 body(需求包) @@ -190,13 +189,15 @@ signature = base64( ed25519_sign(device_priv, sha256(canonical)) ) | display_status | 含义 | |---|---| | `accepted` / `running` / `waiting_approval` | 进行中 | -| `completed` | 完成且有有效交付物 | +| `completed` | 跑完且**有真实产物**(非空、非兜底)—— 注意:**不代表代码正确** | | `completed_without_deliverable` | Runtime 完成但无产物 | | `needs_codegen` | 只有方案/总结,需继续生成代码 | | `failed` / `stopped` | 终态 | 裁决规则:`completed` 且存在非兜底(`metadata.synthesized!=true` 且非纯总结)的真实 artifact → `completed`;否则降级为 `needs_codegen`(有总结)或 `completed_without_deliverable`(无产物)。 +> ⚠️ **`display_status` 的边界(重要,见 spec §6.6)**:HM 只判**事实**——跑完没、有没有真产物、是不是空壳/兜底;**HM 不读代码、不编译、不测试,判不了"代码对不对"**。`completed` 只保证"有真东西",**不保证代码正确**。**对错由客户端自己拉产物跑/测 + 用户 review 决定**。若 agent_management 跑了测试,会作为 `test_report` 产物给客户端看,**不是给 HM 裁决**。 + ### 4.1 三层状态(`GET .../workflow`) `GET /api/heicode/sub-agile/tasks/{task_id}/workflow` 返回客户端右侧面板需要的三层状态对象: @@ -339,40 +340,52 @@ Content-Length: <字节数> 冲突:若 `base_revision` 不等于当前最新,返回 `{ "success":false,"error":{"code":"ARTIFACT_REVISION_CONFLICT","retryable":false},"data":{"current_project_revision":3} }`,客户端提示用户先同步最新再提交。 -## 7. 云部署(控制面,执行待 Deploy Worker) +## 7. 部署(✅ 客户端执行 + 用户必须确认;HM 只发凭据) + +> ⚠️ **流程已改(对齐 spec §3.8)**:**HM 不部署、不连 VM、不执行命令**。部署由**客户端**在用户机器上执行(客户端是 Claude-Code 式程序),且**必须用户显式确认**。HM 的角色仅是:**把绑定的凭据从 Key Vault 解出 → 经 V2 加密通道安全发给客户端 → 记审计**。下面这套「Manager 代部署/Deploy Worker」是**旧模型,已废弃**。 + +**新流程:** +1. 用户先在 HM **绑定** git/vm/db/blob 资源(§8),拿到 `resource_binding_id`(凭据已进 Key Vault,只留 `secret_ref`)。 +2. 客户端发起部署 → **弹窗让用户确认**(目标 VM / 环境 / 用哪条 binding / 影响范围)。 +3. 用户确认 → 客户端向 HM 的**凭据读取接口**(V2 加密)凭 `resource_binding_id` 换取该绑定的凭据(经加密通道返回,带审计)。 +4. **客户端在用户机器上执行**:`git pull` 用户仓库 → ssh 到 VM → 跑部署命令 → 在 VM 上看日志。**全程 HM 不碰 VM。** + +> 🔴 接口待定:凭据读取接口(`GET /api/heicode/resources/{binding_id}/credential` 之类,V2 加密 + 审计)正在 HM 侧建。旧的 `/deployment-targets`、`POST .../deployments`(executor:pending_worker)**不再作为部署主路径**。 + +## 8. 资源绑定(git/vm/db/blob → Key Vault) + +用户先把自己的资源绑定到 HM,凭据进 **Azure Key Vault**,库里只留 `secret_ref`;任务/部署只引用 `resource_binding_id`,**绝不传明文凭据**。详见 spec §4。 + +**5 种类型**:`git`(github/gitea,用 `provider` 区分,即用户**自己的仓库** URL + PAT)、`vm`(ssh)、`database`、`blob`。git 仓库是产物归宿(agent 在此 commit/合并,客户端 clone/pull)。 + +**后端接口**(当前 `UserAuth` 会话鉴权,Manager 网页控制台「资源绑定」页已用;🔴 **面向桌面客户端的 V2 设备签名版正在建**——见下): | 方法 | 路径 | 说明 | |---|---|---| -| GET | `/api/heicode/deployment-targets` | 可部署云目标(azure 启用;aliyun/aws 预留) | -| POST | `/api/heicode/sub-agile/tasks/{task_id}/deployments` | 发起部署(body: artifact_id/target/environment/region/resource_binding_id/options) | -| GET | `/api/heicode/sub-agile/tasks/{task_id}/deployments` | 部署列表 | +| GET | `/api/resources/?status=active` | 列出已绑资源(给客户端选 `resource_binding_id`) | +| POST | `/api/resources/` | 建绑定(非密字段进 metadata,不含凭据) | +| POST | `/api/resources/{id}/secret` | 写凭据 → Key Vault,返回 `secret_ref` | +| DELETE | `/api/resources/{id}` | 解绑(吊销) | -发起部署请求: +建绑定示例(github):`{"name":"my-repo","resource_type":"git","provider":"github","external_id":"https://github.com/owner/repo","metadata":{"repo_url":"...","default_branch":"main"}}` → 再 `POST /{id}/secret {"data":{"token":"ghp_..."}}`。 -```json -{ "artifact_id":"art_xxx","artifact_revision":1,"target":"azure","environment":"preview", - "region":"eastasia","deployment_mode":"managed","resource_binding_id":123 } -``` +> 🔴 **待建(HM 侧地基)**:① 客户端用 **V2 设备签名** 拉资源列表(`/api/heicode/resources` 之类) → 让用户/任务选 binding;② 客户端凭 `resource_binding_id` **取凭据**(部署用,§7)。这两条上线后,客户端即可"读绑定去用 + 取凭据部署"。当前 `/api/resources/*` 是会话鉴权(网页控制台用)。 -响应:`{ "success":true,"data":{ "deployment_run_id":"deploy_xxx","deployment_id":"dep_xxx","target":"azure","environment":"preview","status":"deployment_requested","executor":"pending_worker" } }` +## 9. Runtime 回调(仅 Runtime 用,客户端无需关心) -客户端**禁止**传云厂商 AccessKey/Secret/连接串/secret_ref,只传 `resource_binding_id`(Manager 内部解析为凭据)。 -`environment=production` → `status=waiting_approval`(需审批);`executor: "pending_worker"` 表示真实云执行待 Deploy Worker 接入(当前部署不会真正起资源)。 - -## 8. Runtime 回调(仅 Runtime 用,客户端无需关心) - -Runtime → Manager 统一回调:`POST /api/agent/callbacks/runtime-events`。 +agent_management → HM 统一回调:`POST /api/agent/callbacks/runtime-events`。 Schema 查询:`GET /api/agent/callbacks/runtime-events/schema`。 -## 9. 客户端生产约束 +## 10. 客户端生产约束 -- 审批 approve/reject 必须调 Manager,禁止本地伪造。 +- 审批 approve/reject 必须调 HM,禁止本地伪造。 - 生产包禁用 mock 任务/审批/产物。 -- 只消费 Manager 的 `display_status` / manifest / diagnostics。 +- 用 HM 的 `display_status` 判**进度/有无产物**;**代码对错客户端自己跑/测 + 用户 review**(见 §4)。 +- 部署只在**用户确认后由客户端本地执行**;凭据凭 `resource_binding_id` 向 HM 取(§7),**不本地存明文凭据**。 - 普通用户文案不出现 `newapi`、上游厂商、模型网关字眼。 - 任务接口认证:写请求用 V2 加密 body + 设备签名,GET 用 V2 无 body 设备签名(见 §1),均复用模型调用同一套实现;base_url 来自 preset。 -## 10. 错误码(新增) +## 11. 错误码(新增) | code | 场景 | retryable | |---|---|---|