feat(agent): project-folder artifacts, local-edit revisions, cloud-deploy control plane

完成统一方案 v0.1 剩余客户端要求(#10/#11/#12)+ 对接文档。

- #10 项目文件夹产物(§12):Manager 解析 runtime 的 markdown 多文件 artifact 成项目文件树,
  新增 .../artifacts/{id}/manifest、/files/{path}、/archive 三接口(按需解析,zip 打包)。
- #11 本地修改 revision 协议(§12.7):新模型 AgentArtifactRevision + 迁移;
  .../local-edits、/local-edits/batch、/revisions;base_revision 冲突检测返回
  ARTIFACT_REVISION_CONFLICT;Manager 持有 accepted 基线,回调 Runtime(审计事件)。
- #12 云部署控制面(§18):新模型 AgentCloudDeployment + 迁移;
  GET /api/heicode/deployment-targets;.../tasks/{id}/deployments(创建/列表);
  生产环境进 waiting_approval;客户端只传 resource_binding_id(禁 inline secret);
  真实云执行留 executor=pending_worker,等 Deploy Worker 接入。
- 文档:新增 docs/integration/heicode-desktop-unified-api.md(取代旧 sub-agile 文档,
  覆盖 capabilities/统一任务路由/display_status/项目文件夹/本地修改/云部署/客户端约束/错误码)。

验证:go build ./... + go test(controller/router/model/middleware)全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 00:23:02 +08:00
co-authored by Claude Opus 4.8
parent 443f552917
commit 56eef58b3c
9 changed files with 881 additions and 0 deletions
@@ -0,0 +1,169 @@
# Heicode 桌面客户端统一接口对接文档(v0.1)
更新时间:2026-06-02
适用范围:Heicode Desktop 对接 Heicode Manager 的**统一接口层**(Sub Agile / Swarm 两模式)。
Manager 生产地址:`https://code.xinghanlab.com`
基准:统一调用方案 v0.1 + agent_management Sub Mode Runtime 对接指南。
> 本文取代旧的 `heicode-desktop-sub-agile-api.md`(其 `/api/agnet/*` 路由已废弃)。新客户端一律使用本文的 `/api/heicode/*` 与 `/api/agent/*` 接口。
## 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`。
## 1. 认证
| 方式 | 适用 |
|---|---|
| V2 加密 body + 设备签名(`Content-Encoding: heicode-aead-v1` + `X-Heicode-*`) | 桌面客户端 POST/有 body 请求(与模型调用同一套 `encryptedFetch`) |
| Manager session cookie + `New-Api-User: <user_id>` | Web 控制台 / 未加密 GET 查询兼容路径 |
加密/签名协议同旧文档 §2.2(未变)。
## 2. 能力发现
### `GET /api/heicode/capabilities`
无需登录,返回模式与模型目录。
```json
{ "success": true, "data": {
"modes": [
{"id":"sub_agile","name":"Sub Agile","runtime_kind":"agent_management","model_selection":"per_role","supports_roles":true,"supports_task_graph":false,"supports_artifacts":true,"supports_continue_chat":true,"enabled":true},
{"id":"swarm","name":"Swarm","runtime_kind":"heicode_swarm","model_selection":"primary","supports_roles":false,"supports_task_graph":true,"supports_artifacts":true,"supports_continue_chat":true,"enabled":false}
],
"models": [{"id":"gpt-5.4","name":"gpt-5.4","available":true}]
}}
```
`enabled` 反映该模式 Runtime 当前是否接通。
## 3. 统一任务接口
两套前缀,按模式选择:`/api/heicode/sub-agile/*`(→ agent_management)、`/api/heicode/swarm/*`(→ HeiCode-Swarm)。下表以 sub-agile 为例,swarm 同形。
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | `/api/heicode/sub-agile/tasks` | 创建任务(body 见 §3.1) |
| GET | `/api/heicode/sub-agile/tasks` | 任务列表 |
| GET | `/api/heicode/sub-agile/tasks/{task_id}` | 任务详情(含 `display_status`,读取时自动从 Runtime 收敛) |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/workflow` | 工作流投影(右侧面板:status/agents/artifacts/phase) |
| POST | `/api/heicode/sub-agile/tasks/{task_id}/stop` | 停止 |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/timeline` | 时间线(events/callbacks/artifacts 聚合) |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/logs` | 日志(含 `user_logs` 友好 + `debug_logs` 原始两层) |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/events` | 事件 |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/metrics` | 指标 |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/diagnostics` | 诊断(直查 Runtime 状态 + warnings) |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/sk-snapshots` | SK 快照 |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts` | 产物列表 |
| POST | `/api/heicode/sub-agile/tasks/{task_id}/approvals/{approval_id}/approve` | 同意审批 |
| POST | `/api/heicode/sub-agile/tasks/{task_id}/approvals/{approval_id}/reject` | 拒绝审批 |
### 3.1 创建 body(orchestration_plan)
```json
{ "orchestration_plan": {
"intent_id": "task-xxx",
"template_hint": "heicode-task",
"objective": "做一个待办系统 MVP",
"sub_mode": "agile",
"risk_level": "low",
"budget": {"max_tokens":20000,"max_cost_usd":1,"max_duration_sec":600},
"user_context": {"user_id":"22","channel_id":"default"},
"billing_context": {"provider":"newapi","default_model_id":"gpt-5.4","allowed_model_ids":["gpt-5.4"]},
"agents": [{"role_template":"backend","goal":"...","default_model_id":"gpt-5.4","resource_grants":[]}],
"constraints": {"allowed_model_ids":["gpt-5.4"]},
"metadata": {"correlation_id":"task-xxx-1"}
}}
```
模型必须用生产 NewAPI 已存在模型(当前推荐 `gpt-5.4`)。
## 4. 状态模型(display_status)
客户端只展示 `display_status`(Manager 裁决结果):
| display_status | 含义 |
|---|---|
| `accepted` / `running` / `waiting_approval` | 进行中 |
| `completed` | 完成且有有效交付物 |
| `completed_without_deliverable` | Runtime 完成但无产物 |
| `needs_codegen` | 只有方案/总结,需继续生成代码 |
| `failed` / `stopped` | 终态 |
裁决规则:`completed` 且存在非兜底(`metadata.synthesized!=true` 且非纯总结)的真实 artifact → `completed`;否则降级为 `needs_codegen`(有总结)或 `completed_without_deliverable`(无产物)。
## 5. 产物:项目文件夹
Runtime 返回单个文本/markdown 多文件 artifact;Manager 解析成项目文件树后提供:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `.../artifacts/{artifact_id}/content` | 原始正文(兼容) |
| GET | `.../artifacts/{artifact_id}/manifest` | 项目文件树(entries[path,type,mime,size,hash,content_path] + archive) |
| GET | `.../artifacts/{artifact_id}/files/{path}` | 单个文件正文 |
| GET | `.../artifacts/{artifact_id}/archive` | 整个项目 zip 下载 |
manifest 示例:
```json
{ "success": true, "data": {
"artifact_id":"art_xxx","artifact_type":"project_folder","root_dir":"project","revision":1,
"content_hash":"sha256:...","file_count":2,
"entries":[
{"path":"app.py","type":"file","mime_type":"text/x-python","size_bytes":420,"content_hash":"sha256:...","content_path":".../files/app.py"},
{"path":"test_app.py","type":"file","mime_type":"text/x-python","size_bytes":300,"content_hash":"sha256:...","content_path":".../files/test_app.py"}
],
"archive":{"format":"zip","download_path":".../archive"}
}}
```
## 6. 本地修改回传(revision)
用户在本地改了产物后,必须显式上传;Manager 存为新 revision。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `.../artifacts/{artifact_id}/revisions` | revision 列表 + `current_project_revision` |
| POST | `.../artifacts/{artifact_id}/local-edits` | 上传单文件修改 |
| POST | `.../artifacts/{artifact_id}/local-edits/batch` | 上传多文件修改(`changes[]`,op=update/create/delete) |
请求体核心:`base_revision`(基线版本)、`path`/`content` 或 `changes[]`、`change_summary`。
冲突:若 `base_revision` 不等于当前最新,返回 `ARTIFACT_REVISION_CONFLICT` + `data.current_project_revision`,客户端提示用户先同步。
## 7. 云部署(控制面,执行待 Deploy Worker)
| 方法 | 路径 | 说明 |
|---|---|---|
| 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` | 部署列表 |
客户端**禁止**传云厂商 AccessKey/Secret/连接串/secret_ref,只传 `resource_binding_id`(Manager 内部解析为凭据)。
`environment=production` 进入 `waiting_approval`;当前响应带 `executor: "pending_worker"`(真实云执行待 Deploy Worker 接入)。
## 8. Runtime 回调(仅 Runtime 用,客户端无需关心)
Runtime → Manager 统一回调:`POST /api/agent/callbacks/runtime-events`。
Schema 查询:`GET /api/agent/callbacks/runtime-events/schema`。
## 9. 客户端生产约束
- 审批 approve/reject 必须调 Manager,禁止本地伪造。
- 生产包禁用 mock 任务/审批/产物。
- 只消费 Manager 的 `display_status` / manifest / diagnostics。
- 普通用户文案不出现 `newapi`、上游厂商、模型网关字眼。
- 任务接口认证用 deviceToken / Manager session;base_url 来自 preset。
## 10. 错误码(新增)
| code | 场景 |
|---|---|
| `ARTIFACT_REVISION_CONFLICT` | 本地修改基于旧版本 |
| `RESOURCE_BINDING_INVALID` | resource_binding_id 不存在或非本人 |
| `DEPLOY_TARGET_DISABLED` | 云目标未启用 |
| `FILE_NOT_FOUND` | 项目文件不存在 |
其余错误码沿用旧文档 §13。