docs: remove obsolete 普通 sub (old model) integration docs

The 普通 sub task-orchestration model was replaced by the template-agent model
and its backend deleted. Removed the now-obsolete docs describing it:
- heicode-desktop-sub-agile-api.md, heicode-desktop-subagile-e2e-demo.md
- heicode-desktop-unified-api.md, heicode-sub-mode-flow-spec.md
- 普通sub敏捷模式-AgentManager对接任务清单.md
- AgentManager普通sub{产物回调缺失问题,剩余补充要求,联调整改要求}.md

Fixed dangling references in the new docs (client-api / template-agent-model).
Swarm (蜂群) docs kept — different mode, out of scope.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 09:56:17 +08:00
co-authored by Claude Opus 4.8
parent 16cca5df1c
commit 15b17f39b0
11 changed files with 2 additions and 5068 deletions
@@ -1,389 +0,0 @@
# Agent Manager 普通 sub 产物回调缺失问题
更新时间:2026-05-29
发给:Agent Manager / Agent Runtime 负责人
范围:普通 sub 敏捷模式,不包含 HeiCode-Swarm 独立蜂群 Runtime。
## 1. 问题现象
Heicode 桌面客户端执行任务:
```text
给我做一个 oracle 云的代理商网站,做前后端分离
```
客户端最终只显示:
```text
Swarm initialized and planning started
Swarm execution completed
completed
```
但右侧运行数据中:
```text
ARTIFACTS = 0
SK SNAPSHOTS = 0
```
用户无法看到真正交付物,例如代码分支、提交、预览地址、部署清单、文档或最终结果摘要。
## 2. 本次链路归属
本次不是走 HeiCode-Swarm 独立蜂群 Runtime。
Heicode Manager 生产配置确认当前普通 sub 走:
```text
AGENT_RUNTIME_BASE_URL=http://20.212.121.126
AGENT_RUNTIME_CREATE_PATH=/api/swarms
```
`SWARM_RUNTIME_BASE_URL` 当前为空。
因此本问题归属:
```text
Heicode 桌面客户端
-> Heicode Manager 生产
-> Agent Manager / Agent Runtime 普通 sub 入口
-> Heicode Manager callback
-> 桌面客户端查询 artifacts/timeline
```
不是独立蜂群 Runtime `http://52.139.240.116:8000` 的问题。
## 3. Heicode Manager 生产侧实查结果
Heicode Manager deployment:
```text
dep_fa4f43da9e0a
```
Runtime 返回并保存的 swarm/deployment id:
```text
swm_f9ce3f6c90aa
```
Heicode Manager 生产库记录:
| 字段 | 值 |
|---|---|
| `deployment_id` | `dep_fa4f43da9e0a` |
| `status` | `completed` |
| `phase` | `deploy` |
| `runtime_state` | `completed` |
| `runtime_deployment_id` | `swm_f9ce3f6c90aa` |
| `runtime_swarm_id` | `swm_f9ce3f6c90aa` |
| `created_at_text` | `2026-05-29T08:40:50Z` |
| `updated_at_text` | `2026-05-29T08:40:51Z` |
Heicode Manager 收到的 callback 类型统计:
| callback event_type | count |
|---|---:|
| `agent.started` | 2 |
| `budget.alert` | 1 |
| `deployment.status_changed` | 3 |
| `phase.changed` | 2 |
| `timeline.updated` | 2 |
关键缺失:
```text
artifact.created = 0
task.completed = 0
sk_tool.completed = 0
```
Heicode Manager artifact 表查询结果:
```text
agent_artifacts where deployment_id = 'dep_fa4f43da9e0a'
=> 0 rows
```
说明:Heicode Manager 没有收到任何产物事件,因此客户端显示 `ARTIFACTS 0` 是真实数据,不是客户端漏显示。
## 4. Heicode Manager callback 接收链路是通的
生产日志中,Agent Manager 在任务完成时间段连续请求:
```text
POST /api/agent/callbacks/swarm-events
```
HTTP 状态均为:
```text
200
```
这说明:
1. Agent Manager 能打到 Heicode Manager callback 地址。
2. Heicode Manager 没有拒收这些 callback。
3. 问题不是 callback 鉴权失败。
4. 问题不是 Heicode Manager callback endpoint 不通。
但 callback 事件内容中没有 `artifact.created`,因此 Heicode Manager 无法落库 artifacts。
## 5. Agent Manager 侧直查结果
直查 Agent Manager Runtime:
```http
GET http://20.212.121.126/api/swarms/swm_f9ce3f6c90aa
```
返回关键信息:
```json
{
"deployment_id": "swm_f9ce3f6c90aa",
"swarm_id": "swm_f9ce3f6c90aa",
"status": "completed",
"phase": "planning",
"progress": 100,
"agents": [
{
"agent_id": "agi_backend_59717a71",
"role": "backend",
"status": "running",
"output": null
},
{
"agent_id": "agi_frontend_3063c6c9",
"role": "frontend",
"status": "running",
"output": null
}
],
"metrics": {
"total_messages": 0,
"tokens_used": 0
},
"artifacts": []
}
```
直查日志:
```http
GET http://20.212.121.126/api/swarms/swm_f9ce3f6c90aa/logs
```
返回:
```text
Logs will be fetched from K8s in Phase 2
```
这说明 Agent Manager 自己也没有保存或返回真实产物。
## 6. 当前判断
本问题根因不在 Heicode Manager,也不在桌面客户端。
当前证据指向 Agent Manager / Agent Runtime:
1. Runtime 将 deployment 标记为 `completed`。
2. Runtime 自身返回 `artifacts: []`。
3. Runtime 没有 callback `artifact.created`。
4. Runtime agents 仍显示 `running`,但 deployment 已 `completed`,状态不一致。
5. Runtime metrics 中 `tokens_used=0`、`total_messages=0`,没有真实模型执行用量。
6. Runtime logs 仍是占位文本,没有真实 K8s / Agent 日志。
因此客户端只能展示完成状态,不能展示交付结果。
## 7. Agent Manager 需要修复的内容
### P0:任务完成必须回调 artifact
普通 sub 任务完成时,Agent Manager 必须向 Heicode Manager callback:
```text
POST https://code.xinghanlab.com/api/agent/callbacks/swarm-events
event_type = artifact.created
```
即使没有 Git 分支,也必须返回一个可展示的交付物。
建议 artifact 类型:
| 场景 | artifact_type | uri / 内容 |
|---|---|---|
| 代码已提交 | `code_patch` | `git://repo#<branch>` 或 repo URL + branch + commit |
| 生成了前后端项目 | `deployment_manifest` | 项目结构、启动方式、服务端口、部署说明 |
| 只产出设计/说明 | `document` | 文档地址或文档摘要 |
| 无法生成正式产物 | `other` | 明确失败原因、已完成内容、下一步动作 |
最低要求:不能只发 `completed`,必须有一个 `artifact.created` 或明确失败事件。
### P0:completed 状态与 Agent 状态一致
当前 Runtime 返回:
```text
deployment.status = completed
agents[].status = running
```
需要修复为一致状态:
1. 如果 deployment completed,则相关 agent 应为 `completed`、`stopped` 或明确的终态。
2. 如果 agent 仍 running,则 deployment 不应为 completed。
3. 如果任务未真实执行,应返回 `failed` 或 `blocked`,并说明原因。
### P0:回调 task.completed / task.failed
当前 Heicode Manager 没收到:
```text
task.completed
task.failed
task.blocked
```
Agent Manager 应在每个子 Agent / 子任务结束时回调任务状态,至少包含:
```json
{
"event_type": "task.completed",
"deployment_id": "dep_fa4f43da9e0a",
"swarm_id": "swm_f9ce3f6c90aa",
"task_id": "task-backend-xxx",
"agent_instance_id": "agi_backend_59717a71",
"payload": {
"task_id": "task-backend-xxx",
"agent_role": "backend",
"status": "completed",
"summary": "后端实现完成,产物见 artifact"
}
}
```
### P1:回传真实 usage / cost
当前 Runtime 返回:
```text
tokens_used = 0
total_messages = 0
```
如果任务真实调用了模型,应回传:
```json
{
"model_usage": {
"input_tokens": 1234,
"output_tokens": 5678,
"total_tokens": 6912,
"model_cost_usd": 0.0123,
"model_id": "xxx"
}
}
```
如果没有真实调用模型,应明确返回 `blocked` 或 `failed`,不能标记为正常 completed。
### P1:提供真实日志
当前日志仍是:
```text
Logs will be fetched from K8s in Phase 2
```
需要至少返回可排障日志摘要:
1. Agent 是否启动成功。
2. 是否领取任务。
3. 是否调用模型。
4. 是否生成文件/分支/产物。
5. 失败原因。
## 8. 建议的 artifact.created callback 示例
```json
{
"event_id": "evt_artifact_<unique>",
"event_type": "artifact.created",
"deployment_id": "dep_fa4f43da9e0a",
"swarm_id": "swm_f9ce3f6c90aa",
"agent_instance_id": "agi_backend_59717a71",
"task_id": "task-backend-001",
"occurred_at": "2026-05-29T08:40:51Z",
"correlation_id": "corr_xxx",
"source": "agent-manager",
"payload": {
"artifact_id": "art_swm_f9ce3f6c90aa_backend_001",
"artifact_type": "code_patch",
"title": "Oracle 云代理商网站后端实现",
"summary": "已生成后端接口、数据模型和启动说明",
"uri": "git://repo#feature/swm_f9ce3f6c90aa",
"checksum": "commit_sha_if_available",
"metadata": {
"redacted": true,
"agent_role": "backend",
"runtime_deployment_id": "swm_f9ce3f6c90aa"
}
}
}
```
如果没有 Git 分支,也可以先回:
```json
{
"event_type": "artifact.created",
"deployment_id": "dep_fa4f43da9e0a",
"swarm_id": "swm_f9ce3f6c90aa",
"payload": {
"artifact_id": "art_swm_f9ce3f6c90aa_summary",
"artifact_type": "document",
"title": "任务执行结果摘要",
"summary": "Runtime 已完成任务,但未返回 Git 分支。这里应写清生成内容、文件位置或未生成原因。",
"uri": "runtime://swm_f9ce3f6c90aa/artifacts/summary",
"metadata": {
"redacted": true
}
}
}
```
## 9. 验收标准
修复后请用同类任务重新跑一次:
```text
给我做一个 oracle 云的代理商网站,做前后端分离
```
必须满足:
| 验收项 | 标准 |
|---|---|
| Runtime 状态 | deployment 和 agents 状态一致 |
| callback | Heicode Manager 收到 `artifact.created` |
| Manager artifacts | `/api/agent/user/deployments/{deployment_id}/artifacts` 返回 total > 0 |
| 客户端展示 | 右侧 `ARTIFACTS` 不再是 0 |
| 交付物 | 能看到 Git 分支、提交、预览地址、部署清单或最终结果文档 |
| usage | 如果真实调用模型,tokens/cost 不应一直为 0 |
| logs | 不再只有 Phase 2 占位文本 |
## 10. 当前结论
Heicode Manager 和桌面客户端当前表现是正确反映 Runtime 数据。
真正缺口在 Agent Manager / Agent Runtime:
```text
任务被标记 completed,但 Runtime 没有生成或回传 artifact.created。
```
请 Agent Manager 优先修复任务完成后的产物生成、产物回调、状态一致性、usage 和日志回传。
@@ -1,246 +0,0 @@
# Agent Manager 普通 sub 剩余补充要求
更新时间:2026-05-28
发给:Agent Manager / Agent Runtime 负责人
范围:普通 sub 敏捷开发模式,不包含蜂群模式完整 task graph。
## 1. 当前已验证事实
Heicode Manager 生产版本 `1.4.19` 已完成并验证以下链路:
| 项目 | 状态 | 生产验证 |
|------|------|----------|
| Manager 创建普通 sub run | 已跑通 | `POST https://code.xinghanlab.com/api/swarms` 返回 `dep_*` |
| Manager 调 Agent Manager | 已跑通 | Agent Manager 返回 `runtime_swarm_id=swm_*` |
| Agent Manager 自动 callback | 已跑通 | Manager `events/timeline` 可查到 callback |
| callback HMAC fallback | 已跑通 | 生产 callback 可验签入库 |
| Manager 状态反写 | 已跑通 | callback 后 `deployment.status/phase/runtime_state/agent_instances` 会更新 |
| billing_context 字段透传 | 已跑通 | `default_model_id/allowed_model_ids/secret_ref` 已保留 |
最新生产烟测样例:
| 字段 | 值 |
|------|----|
| Manager deployment | `dep_be665a25f6bc` |
| Runtime swarm | `swm_4c471d60972f` |
| Manager detail status | `completed` |
| Manager detail phase | `deploy` |
| Manager runtime_state | `completed` |
| Manager agent state | `completed` |
| Manager callback 数 | `9` |
| Manager event 数 | `12` |
因此,当前剩余问题主要不在 Manager 接收链路,而在 Agent Manager 真实执行数据、状态一致性、产物和用量回传。
## 2. Agent Manager 必须补充的 P0
| 优先级 | 缺口 | 当前实测表现 | Agent Manager 需要补什么 | 验收标准 |
|--------|------|--------------|---------------------------|----------|
| P0 | Runtime 状态一致性 | 直连 `GET /api/swarms/{swarm_id}/status` 返回整体 `completed`,但 `agents[].status` 仍是 `running` | 整体完成时同步更新 agent 状态,或发送 `agent.completed` callback | status 接口中整体和 agent 状态一致;Manager 不再需要兜底收敛 |
| P0 | 真实 artifact 回传 | Manager 收到 callback,但 `/artifacts` 仍为 `[]` | 执行完成时回调 `artifact.created`,至少包含摘要型交付物 | Manager `/artifacts` 至少有 1 条真实 artifact |
| P0 | 真实 usage / cost 回传 | `tokens_used=0`,budget callback 中 token/cost/runtime 多为 0 | 回传模型 token、模型成本、runtime 秒数、资源使用 | Manager timeline 中能看到非 0 或明确的真实 usage 字段 |
| P0 | 真实日志 | `/logs` 返回占位文本 `Logs will be fetched from K8s in Phase 2` | 接入真实 Pod/Runtime 日志或回调日志摘要 | `GET /logs` 返回真实执行日志或明确失败原因 |
| P0 | 阶段推进语义 | callback 有 phase/timeline,但当前非常短,直接 completed | 普通 sub 应按需求、设计、开发、测试、部署阶段推进 | 至少能看到 `requirements/design/development/testing/deploy` 中的真实阶段变化 |
| P0 | 失败原因回传 | 当前成功场景没有问题,但失败链路未验证 | 失败时回调 `deployment.status_changed` + `agent.crashed` 或 `sk_tool.failed` | Manager detail 出现 `failed` 和可读 `failure_reason` |
## 3. Agent Manager 应补充的 P1
| 优先级 | 缺口 | 要求 | 验收标准 |
|--------|------|------|----------|
| P1 | SK 工具调用展示 | 回调 `sk_tool.called/completed/failed`,参数和结果必须脱敏 | Manager `/sk-snapshots` 或 timeline 能看到工具调用记录 |
| P1 | 高危审批闭环 | 高危动作回调 `approval.requested`,等待 Manager/客户端 approve/reject 后继续或停止 | approve 后 Runtime 继续,reject 后 Runtime 停止或跳过高危动作 |
| P1 | stop 后真实停止 | Manager stop 会调用 Runtime stop | stop 后 status 为 `stopped`,不再继续发 running/completed callback |
| P1 | 幂等创建稳定性 | 同一个 `X-Idempotency-Key` 不重复创建 | 重放创建请求返回同一个 run |
| P1 | callback 重试/死信 | 文档写了重试/死信,但也写失败只 warning | 明确当前真实策略;失败后至少可人工重放 |
| P1 | runtime_id 字段稳定 | 当前 Manager 可兼容 `deployment_id=swm_*` | 后续响应和 callback 统一携带 `deployment_id`、`swarm_id`、`correlation_id` |
## 4. Callback 最低要求
Manager callback 地址:
```text
https://code.xinghanlab.com/api/agent/callbacks/swarm-events
```
创建 run 后,Agent Manager 至少需要主动回调这些事件:
| 事件 | 何时发送 | payload 最低字段 |
|------|----------|------------------|
| `deployment.status_changed` | accepted/running/completed/failed/stopped | `status` |
| `phase.changed` | 普通 sub 阶段变化 | `stage`、`checkpoint`、`summary` |
| `timeline.updated` | 用户可读进度 | `title`、`summary`、`stage`、`checkpoint` |
| `agent.started` | 子 Agent 开始 | `agent_role`、`status` |
| `agent.completed` | 子 Agent 完成 | `agent_role`、`status` |
| `agent.crashed` | 子 Agent 异常 | `agent_role`、`reason` |
| `artifact.created` | 产生中间或最终交付物 | `artifact_id`、`artifact_type`、`title`、`summary`、`uri` |
| `budget.alert` | 用量更新或预算告警 | `model_tokens`、`model_cost_usd`、`runtime_seconds`、`consumed_usd` |
| `sk_tool.completed` | SK 工具成功 | `tool_name`、`tool_invocation_id`、`summary` |
| `sk_tool.failed` | SK 工具失败 | `tool_name`、`tool_invocation_id`、`reason` |
| `approval.requested` | 需要高危审批 | `approval_id`、`operation`、`risk_level`、`reason` |
## 5. Artifact 最低格式
普通 sub 完成时至少回写一个 artifact:
```json
{
"event_type": "artifact.created",
"deployment_id": "dep_xxx",
"swarm_id": "swm_xxx",
"agent_instance_id": "agi_backend_001",
"payload": {
"artifact_id": "art_dep_xxx_summary",
"artifact_type": "test_report",
"title": "普通 sub 执行结果",
"summary": "本轮任务完成了哪些内容、测试结果、剩余风险",
"uri": "azblob://heicode-artifacts/dep_xxx/report.json",
"stage": "deploy",
"checkpoint": "completed",
"metadata": {
"agent_role": "backend",
"redacted": true
}
}
}
```
要求:
- `summary` 可直接展示给用户。
- 不允许出现明文 token、password、secret、private key、connection string。
- 大文件只传 URI 和摘要,不在 callback body 内联完整内容。
## 6. Usage / Cost 最低格式
Agent Manager 需要让 Manager 能区分预算和真实消耗。
```json
{
"event_type": "budget.alert",
"deployment_id": "dep_xxx",
"swarm_id": "swm_xxx",
"payload": {
"billing_source": "newapi",
"model_id": "model-runtime-smoke",
"prompt_tokens": 1200,
"completion_tokens": 800,
"model_tokens": 2000,
"model_cost_usd": 0.012,
"runtime_seconds": 42,
"cpu_core_seconds": 21,
"memory_mb_seconds": 86016,
"consumed_usd": 0.012,
"budget": {
"max_cost_usd": 0.05,
"remaining_usd": 0.038
}
}
}
```
如果当前测试任务确实没有模型调用,也需要明确回传:
```json
{
"model_tokens": 0,
"model_cost_usd": 0,
"runtime_seconds": 42,
"billing_source": "runtime_no_model_call"
}
```
不能只返回全 0 又没有解释。
## 7. 状态一致性要求
当前实测中 Agent Manager 状态存在矛盾:
```json
{
"status": "completed",
"agents": [
{
"status": "running"
}
],
"tokens_used": 0,
"artifacts": []
}
```
需要改为:
```json
{
"status": "completed",
"phase": "deploy",
"progress": 100,
"agents": [
{
"status": "completed"
}
],
"metrics": {
"tokens_used": 2000,
"elapsed_seconds": 42
},
"artifacts": [
{
"artifact_id": "art_xxx",
"artifact_type": "test_report"
}
]
}
```
如果执行失败,则整体和 agent 都要能表达失败:
```json
{
"status": "failed",
"error_message": "模型调用失败或资源授权不足",
"agents": [
{
"status": "failed",
"error_message": "具体失败原因"
}
]
}
```
## 8. 联调验收步骤
Agent Manager 补完后,按以下步骤验收:
1. Heicode Manager 通过 `POST /api/swarms` 创建普通 sub run。
2. Manager 返回 `deployment_id=dep_*`。
3. Runtime 返回并持久化 `runtime_swarm_id=swm_*`。
4. Agent Manager 主动 callback:
- `deployment.status_changed`
- `phase.changed`
- `timeline.updated`
- `agent.started`
- `agent.completed`
- `artifact.created`
- `budget.alert`
5. Manager 查询:
- `/api/agent/user/deployments/{deployment_id}`
- `/events`
- `/timeline`
- `/artifacts`
- `/sk-snapshots`
6. 期望结果:
- detail 状态为真实 Runtime 状态。
- timeline 有阶段推进。
- artifacts 有真实产物。
- usage 有可解释的真实消耗。
- 不出现明文密钥。
## 9. 当前非阻塞但需记录
| 项目 | 当前状态 | 说明 |
|------|----------|------|
| Agent Manager 域名 | 暂未作为联调依赖 | 当前统一使用 `http://20.212.121.126` |
| Azure Key Vault | Manager 侧 VM Managed Identity 未正式配好 | 当前 callback 使用 HMAC fallback 已跑通;正式 Key Vault 需后续云资源配置 |
| Manager 状态兜底 | 已完成 | Manager `1.4.19` 会根据 callback 收敛 detail 状态,但 Runtime 仍应修正自身状态 |
@@ -1,609 +0,0 @@
# Agent Manager 普通 sub 联调整改要求
更新时间:2026-05-28
发给:Agent Manager / Agent Runtime 负责人
范围:Heicode Manager 普通 sub 敏捷模式联调,不包含蜂群模式完整 task graph 的额外能力。
## 1. 当前结论
Agent Manager 新版文档 `HEICODE_API_INTEGRATION(5).md` 已经补充了 Runtime 主动 callback、HMAC、artifact、timeline、SK snapshot 等内容,方向基本对齐 Heicode Manager。
按 2026-05-28 生产实测,Manager 与 Agent Manager 的普通 sub 核心通讯链路已经跑通,但还不能认为“真实开发执行结果”完整闭环。当前结论是:
1. Agent Manager 当前联调统一使用 IP `http://20.212.121.126`;域名 `https://agent-manager.taijiagent.com` 后续解析和证书就绪后再切换,不作为当前联调阻塞项。
2. Manager 生产已切到 `/api/swarms` 创建入口,并验证能拿到 `runtime_swarm_id=swm_*`。
3. Agent Manager 自动 callback 已能写入 Manager `events/timeline`,Manager `1.4.19` 开始会把 callback 反写到 deployment 快照。
4. 当前仍缺真实产物和真实用量:Agent Manager status 接口返回 `tokens_used=0`、`artifacts=[]`,并出现整体 `completed` 但 agent 仍 `running` 的状态不一致。
5. 文档写了 callback 重试和死信,但同时又写“发送失败只 warning”,需要明确当前真实实现。
Heicode Manager 侧已确认:
- `POST https://code.xinghanlab.com/api/agent/callbacks/swarm-events` 生产路由在线。
- callback 支持 HMAC 和旧 token 兼容;当前生产为了先跑通自动 callback,已配置 HMAC fallback。
- `GET https://code.xinghanlab.com/api/agent/callbacks/swarm-events/schema` 已由 Manager 提供,用于联调前核对事件类型和必填字段。
- Manager 可接收 `deployment.status_changed`、`phase.changed`、`timeline.updated`、`agent.started/completed/crashed`,并在 `1.4.19` 反写 deployment 详情状态。
## 2. Agent Manager 必须整改的 P0
| 优先级 | 事项 | 当前问题 | 要求 |
|---|---|---|---|
| P0 | 固定联调地址 | 当前阶段约定先走 IP,后续再切域名 | 文档和配置先统一使用 `http://20.212.121.126`;域名切换另行确认 |
| P0 | 创建普通 sub deployment | `/api/swarms` 已能创建并返回 `swm_*` | 保持幂等和字段稳定,后续域名切换不能破坏 |
| P0 | deployment detail | Manager 已能记录 callback;Agent Manager status 仍有 `completed` 与 agent `running` 不一致 | 返回真实 phase、agent 状态、失败原因和更新时间 |
| P0 | deployment stop | `/api/agent/deployments/{deployment_id}/stop` 已可用 | 停止后 Runtime 真实停止,并回调 stopped 事件 |
| P0 | callback 主动推送 | 已验证 status/phase/timeline/agent/budget callback 能进入 Manager | 继续补 artifact、SK、approval 的真实运行数据 |
| P0 | usage 回传 | 当前 budget callback 中 token/cost/runtime 多为 0 | 通过 callback 或事件接口回传真实 token、成本、运行时长、资源使用 |
## 3. 推荐接口契约
### 3.1 健康检查
```http
GET /api/agent/health
```
要求:
- 不要求业务认证。
- 返回 200。
- 响应中包含 `success=true` 和 `data.status=healthy`。
### 3.2 创建普通 sub 运行
普通 sub 当前生产联调使用 Agent Manager `/api/agent/deployments`,蜂群 `/api/swarms` 另见 `AgentManager蜂群Runtime接口实现要求.md`。
```http
POST /api/agent/deployments
Authorization: Bearer <HEICODE_SERVICE_TOKEN>
Content-Type: application/json
X-User-ID: <user_id>
X-Binding-Scope: <binding_scope>
X-Correlation-ID: <correlation_id>
X-Idempotency-Key: <idempotency_key>
```
请求体示例:
```json
{
"orchestration_plan": {
"intent_id": "task_123",
"template_hint": "heicode-task",
"objective": "完成本轮普通 sub 敏捷任务",
"sub_mode": "agile",
"risk_level": "medium",
"budget": {
"max_tokens": 120000,
"max_cost_usd": 8,
"max_duration_sec": 3600
},
"user_context": {
"user_id": "123",
"channel_id": "heicode",
"binding_scope": "task-task-123"
},
"billing_context": {
"provider": "newapi",
"default_model_id": "model_xxx",
"allowed_model_ids": ["model_xxx"],
"secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/model-gateway-key"
},
"agile_context": {
"iteration": "2026-05-28",
"stage": "development",
"checkpoint": "draft_created",
"acceptance_criteria": [
"Runtime 接收创建请求",
"Runtime 主动回调 phase/timeline/artifact",
"Manager 页面和接口可查到回调数据",
"不出现明文密钥"
],
"next_action": "continue",
"requires_user_approval": false
},
"agents": [
{
"role": "backend"
},
{
"role": "frontend"
},
{
"role": "reviewer"
}
],
"resource_grants": []
},
"callback": {
"url": "https://code.xinghanlab.com/api/agent/callbacks/swarm-events",
"signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agent-callback-signing-key",
"subscribed_events": [
"deployment.status_changed",
"phase.changed",
"timeline.updated",
"agent.started",
"agent.completed",
"sk_tool.called",
"sk_tool.completed",
"sk_tool.failed",
"approval.requested",
"budget.alert",
"artifact.created"
]
}
}
```
成功响应必须包含:
```json
{
"deployment_id": "dep_runtime_123",
"status": "initializing",
"agent_instances": [
{
"agent_instance_id": "agi_backend_001",
"role": "backend",
"status": "pending"
}
],
"created_at": "2026-05-28T07:30:00Z",
"estimated_ready_at": "2026-05-28T07:32:00Z"
}
```
要求:
1. `deployment_id` 必须可用于 `/api/agent/deployments/{deployment_id}`、`/api/agent/deployments/{deployment_id}/stop`。
2. 同一个 `X-Idempotency-Key` 重复请求必须返回同一个运行,不应重复创建。
3. 请求缺少 `orchestration_plan`、`callback.url`、`sub_mode`、`user_context` 时必须返回 4xx。
### 3.3 查询普通 sub deployment
```http
GET /api/agent/deployments/{deployment_id}
Authorization: Bearer <HEICODE_SERVICE_TOKEN>
```
响应示例:
```json
{
"deployment_id": "dep_runtime_123",
"status": "running",
"phase": "development",
"agent_instances": [
{
"agent_instance_id": "agi_backend_001",
"role": "backend",
"status": "running",
"current_task": "实现接口"
}
],
"created_at": "2026-05-28T07:30:00Z",
"updated_at": "2026-05-28T07:31:00Z"
}
```
### 3.4 停止普通 sub deployment
```http
POST /api/agent/deployments/{deployment_id}/stop
Authorization: Bearer <HEICODE_SERVICE_TOKEN>
Content-Type: application/json
```
请求体:
```json
{
"reason": "Heicode Manager requested stop",
"manager_deployment_id": "dep_manager_123"
}
```
响应示例:
```json
{
"deployment_id": "dep_runtime_123",
"status": "stopped",
"stopped_at": "2026-05-28T07:40:00Z"
}
```
要求:
- 停止后不再继续执行任务。
- 停止后可以继续查询状态。
- 停止成功后建议 callback 一条 `deployment.status_changed`,状态为 `stopped`。
## 4. Callback 要求
Manager 生产 callback 地址:
```text
https://code.xinghanlab.com/api/agent/callbacks/swarm-events
```
### 4.1 认证方式
优先使用 HMAC:
```http
X-Agent-Event-Id: evt_xxx
X-Agent-Timestamp: <unix_ms>
X-Agent-Signature: sha256=<hex>
X-Correlation-ID: <correlation_id>
Content-Type: application/json
```
签名规则:
```text
signature_payload = timestamp + "." + event_id + "." + raw_body
signature = HMAC_SHA256(callback_signing_secret, signature_payload)
```
过渡期可使用旧 token:
```http
X-Agent-Service-Token: <HEICODE_SERVICE_TOKEN>
```
不要把真实 token 写入文档、日志或 artifact。
### 4.2 必须回调的事件
普通 sub 最少需要以下事件:
| 事件 | 目的 | 最低要求 |
|---|---|---|
| `deployment.status_changed` | 整体运行状态 | `status`、`stage`、`checkpoint` |
| `phase.changed` | 普通 sub 阶段推进 | `stage`、`checkpoint`、`progress_pct` |
| `timeline.updated` | 客户端可展示反馈 | `title`、`summary`、`stage`、`checkpoint` |
| `agent.started` | Agent 开始工作 | `agent_role`、`task_id` |
| `sk_tool.called` | 工具调用开始 | `tool_name`、脱敏参数摘要 |
| `sk_tool.completed` | 工具调用成功 | `tool_name`、耗时、摘要、可选 artifact 引用 |
| `sk_tool.failed` | 工具调用失败 | `tool_name`、脱敏错误 |
| `artifact.created` | 中间/最终产物 | `artifact_id`、`artifact_type`、`title`、`summary`、`uri` |
| `approval.requested` | 高危操作审批 | `operation`、`resource_type`、`risk_level`、`reason` |
| `budget.alert` | 预算告警/用量 | usage / cost 摘要 |
### 4.3 Callback body 示例
```json
{
"event_id": "evt_phase_001",
"event_type": "phase.changed",
"deployment_id": "dep_manager_123",
"agent_instance_id": "agi_backend_001",
"occurred_at": "2026-05-28T07:35:00Z",
"correlation_id": "corr_123",
"source": "agent-manager",
"payload": {
"stage": "development",
"checkpoint": "agent_running",
"progress_pct": 35,
"summary": "backend agent 已开始实现接口"
}
}
```
artifact 示例:
```json
{
"event_id": "evt_artifact_001",
"event_type": "artifact.created",
"deployment_id": "dep_manager_123",
"agent_instance_id": "agi_backend_001",
"occurred_at": "2026-05-28T07:38:00Z",
"correlation_id": "corr_123",
"source": "agent-manager",
"payload": {
"artifact_id": "art_backend_patch_001",
"artifact_type": "code_patch",
"title": "Backend API patch",
"summary": "新增普通 sub Runtime 联调接口",
"uri": "azblob://heicode-artifacts/task-123/backend.patch",
"mime_type": "text/x-diff",
"size_bytes": 18420,
"stage": "development",
"checkpoint": "artifact_ready",
"metadata": {
"agent_role": "backend",
"redacted": true
}
}
}
```
### 4.4 明文密钥禁止项
以下字段不能出现在 callback、artifact metadata、timeline、日志中:
- `password`
- `token`
- `secret`
- `private_key`
- `connection_string`
- `access_key`
- 明文数据库连接串
- 明文模型网关 key
- 明文 Git token
长期凭据只能传:
```text
azkv://<vault>/secrets/<name>
```
## 5. Usage / Cost 回传要求
Agent Manager 文档当前缺少真实 usage 字段。普通 sub 后续要支持模型费用、运行费用和审计归属,Runtime 必须回传至少以下字段。
可通过 `budget.alert`、`timeline.updated` 或专门的 `usage.updated` 事件回传。如果新增 `usage.updated`,需要提前和 Manager 对齐 schema。
```json
{
"event_id": "evt_usage_001",
"event_type": "budget.alert",
"deployment_id": "dep_manager_123",
"agent_instance_id": "agi_backend_001",
"occurred_at": "2026-05-28T07:39:00Z",
"correlation_id": "corr_123",
"source": "agent-manager",
"payload": {
"model_id": "model_xxx",
"model_tokens": 12000,
"prompt_tokens": 8000,
"completion_tokens": 4000,
"model_cost_usd": 0.23,
"runtime_seconds": 180,
"cpu_core_seconds": 36,
"memory_mb_seconds": 92160,
"billing_source": "newapi",
"budget": {
"max_tokens": 120000,
"max_cost_usd": 8,
"consumed_usd": 0.23,
"remaining_usd": 7.77
}
}
}
```
字段要求:
| 字段 | 必需 | 说明 |
|---|---|---|
| `model_id` | 是 | 本次 Agent 调用的模型 |
| `model_tokens` | 是 | 总 token |
| `prompt_tokens` | 建议 | 输入 token |
| `completion_tokens` | 建议 | 输出 token |
| `model_cost_usd` | 是 | 可归属的模型成本 |
| `runtime_seconds` | 是 | Agent 实际运行秒数 |
| `cpu_core_seconds` | 建议 | 集群资源成本核算 |
| `memory_mb_seconds` | 建议 | 集群资源成本核算 |
| `billing_source` | 是 | `newapi` / `manager_wallet` / `manager_subscription` / 其他约定 |
注意:`budget.max_cost_usd` 是预算上限,不是已扣费金额。不能把预算当真实账单。
## 6. Approval Decision 接收要求
Manager 端已有 approval、credential lease、approve/reject 和 Runtime decision adapter。Agent Manager 需要提供接收审批结果的接口。
推荐接口:
```http
POST /api/agent/deployments/{deployment_id}/approvals/{approval_id}
Authorization: Bearer <HEICODE_SERVICE_TOKEN>
Content-Type: application/json
```
请求体:
```json
{
"approval_id": "apr_123",
"decision": "approved",
"manager_deployment_id": "dep_manager_123",
"runtime_deployment_id": "dep_runtime_123",
"operation": "git.write",
"resource_type": "git",
"resource_id": "repo_main",
"risk_level": "high",
"requires_credential": true,
"credential_ref": "lease://agent/cred_123",
"lease_id": "lease_123",
"lease_expires_at": 1770000000000,
"decided_by": "user_123",
"reason": "允许本次写入",
"decided_at": 1770000000000
}
```
要求:
- `approved` 后 Runtime 继续对应高危动作。
- `rejected` 后 Runtime 停止该动作并回调 `timeline.updated` 或 `sk_tool.failed`。
- 不要求 Manager 回传明文密钥,只能使用 `credential_ref` 或 `lease://...`。
## 7. Callback 重试策略需要说清楚
Agent Manager 文档当前有两种说法:
1. 当前发送失败只记录 warning,不阻塞任务执行。
2. Runtime 推送失败时指数退避,最多重试 12 小时,超过进入死信队列。
请明确当前真实实现是哪一种:
| 能力 | 当前是否已实现 | 需要说明 |
|---|---|---|
| 失败重试 | 是/否 | 重试次数、间隔、最大时长 |
| 死信队列 | 是/否 | 存储位置、人工重放方式 |
| 幂等重放 | 是/否 | 是否复用原 `event_id` |
| 失败告警 | 是/否 | 是否有日志、监控或告警 |
如果当前只 warning,不重试,请在文档中写成“当前未实现重试/死信,后续增强”,不要把建议方案写成已完成。
## 8. 联调验收步骤
Agent Manager 改完后,按下面步骤验收。
| 步骤 | 操作 | 通过标准 |
|---:|---|---|
| 1 | `GET /api/agent/health` | 返回 healthy |
| 2 | `POST /api/agent/deployments` 创建普通 sub run | 返回 `deployment_id`、`status` |
| 3 | 重复同一个 `X-Idempotency-Key` 创建 | 不重复创建,返回同一个 ID |
| 4 | `GET /api/agent/deployments/{deployment_id}` | 返回真实状态和 agents |
| 5 | Runtime 主动 callback `phase.changed` | Manager callback 返回 success |
| 6 | Runtime 主动 callback `timeline.updated` | Manager timeline 可查到 |
| 7 | Runtime 主动 callback `artifact.created` | Manager artifacts 可查到 |
| 8 | Runtime 主动 callback `sk_tool.completed` | Manager SK/timeline 可查到 |
| 9 | Runtime 主动 callback usage | Manager 能看到 usage 摘要或 callback event |
| 10 | Runtime 主动 callback `approval.requested` | Manager pending approval 生成 |
| 11 | Manager approve/reject | Agent Manager 收到 decision |
| 12 | `POST /api/agent/deployments/{deployment_id}/stop` | Runtime 停止,状态变为 stopped |
| 13 | 检查日志和 artifact metadata | 不包含明文密钥 |
## 9. 当前实测记录
2026-05-28 已测:
| 接口 | 结果 | 说明 |
|---|---|---|
| `GET http://20.212.121.126/api/agent/health` | 200 | Agent Manager IP 健康检查正常 |
| `GET https://agent-manager.taijiagent.com/api/agent/health` | 暂不作为当前验收项 | 当前约定先走 IP,域名后续再切换 |
| `POST https://code.xinghanlab.com/api/agent/callbacks/swarm-events` 无认证 | 业务返回 `CALLBACK_UNAUTHORIZED` | Manager callback 路由在线 |
| `POST https://code.xinghanlab.com/api/agent/callbacks/swarm-events` 带旧 token 但空 body | 业务返回 `CALLBACK_INVALID` | 认证通过,进入事件校验 |
| `GET https://code.xinghanlab.com/api/agent/callbacks/swarm-events/schema` | 404 | Manager schema GET 生产未通,Manager 侧需复核 |
| `POST http://20.212.121.126/api/agent/deployments` | 200 | 普通 sub Runtime deployment 创建可用 |
### 9.1 2026-05-28 追加联调记录
本次按当前约定使用 Agent Manager IP `http://20.212.121.126`。
客户端完整用户态链路说明:
- 已尝试通过生产 Manager `/api/user/login` 获取用户 session,但手头用户名组合未登录成功。
- 因此本次没有宣称“桌面客户端登录后走 Manager 用户态创建 deployment”完整通过。
- 本次完成的是服务到服务联调:Manager/客户端等价 payload -> Agent Manager IP,以及 Agent Manager callback 协议 -> Heicode Manager callback 接收端。
Agent Manager `/api/agent/deployments` 服务到服务链路:
| 步骤 | 结果 | 证据 |
|---|---|---|
| `GET /api/agent/health` | 通过 | 返回 `success=true`、`status=healthy` |
| `POST /api/agent/deployments` | 通过 | 返回 `deployment_id=dep_dbafd1ac37c3`,状态 `pending` |
| `GET /api/agent/deployments/{deployment_id}` | 通过 | 能查到 `user_id`、`binding_scope`、`sub_mode=agile`、`callback_configured=true` |
| `GET /api/agent/deployments/{deployment_id}/events` | 部分通过 | 只看到 `deployment.accepted`,未看到 `phase.changed/timeline.updated/artifact.created/sk_tool.*` |
| `GET /api/agent/deployments/{deployment_id}/logs` | 部分通过 | 返回系统日志 `Pod ... has no logs yet` |
| `GET /api/agent/deployments/{deployment_id}/metrics` | 通过但疑似占位 | 返回 CPU/内存/网络指标,但值看起来是固定模拟值,需要 Runtime 说明来源 |
| `POST /api/agent/deployments/{deployment_id}/stop` | 通过 | `dep_dbafd1ac37c3` 停止成功,返回 `status=stopped` |
长等待测试:
| 项 | 结果 |
|---|---|
| 测试 deployment | `dep_cd170573cf47` |
| 等待时间 | 约 2 分钟 |
| 最终状态 | 已清理停止 |
| 事件结果 | 只有 `deployment.accepted` 和 `deployment.stopped` |
| 未观察到 | `phase.changed`、`timeline.updated`、`artifact.created`、`agent.started/completed`、`sk_tool.called/completed` |
| 结论 | Agent Manager 文档声称的“Runtime 主动推送 status/phase/timeline/agent/tool/artifact 事件”在本次实测中没有跑出来,需要 Agent Manager 继续排查 |
Heicode Manager callback 接收端:
| 步骤 | 结果 | 证据 |
|---|---|---|
| 无认证 POST callback | 通过预期 | 返回 `CALLBACK_UNAUTHORIZED` |
| 带旧 token 但缺事件字段 | 通过预期 | 返回 `CALLBACK_INVALID`,说明认证通过并进入业务校验 |
| 带旧 token 发送合法 `timeline.updated` | 通过 | 返回 `success=true`、`inserted=true` |
| 重复发送同一 `event_id` | 通过 | 返回 `deduplicated=true`、`inserted=false` |
本次合法 callback 测试事件:
```text
event_id=evt_agent_manager_ip_smoke_1779954828884
event_type=timeline.updated
runtime_deployment_id=dep_cd170573cf47
source=agent-manager-ip-smoke
```
结论:
1. Heicode Manager callback 接收端可用,旧 token 认证和幂等可用。
2. Agent Manager IP 的 `/api/agent/deployments` 创建、查询、停止可用。
3. Agent Manager 当前没有在实测中产生普通 sub 所需的 phase/timeline/artifact/SK 主动回调。
4. 因没有可用生产 Manager 用户 session,本次没有完成“客户端登录态 -> Manager 用户态 deployment -> Runtime”的完整端到端测试。
### 9.2 2026-05-28 测试用户客户端模拟链路
测试用户:
```text
email: zsbgnw@gmail.com
username: chenchen
user_id: 22
group: default
```
说明:密码只用于本次登录测试,不写入本文档。
本次已完成“客户端模拟 -> Heicode Manager 生产用户态接口 -> Agent Manager IP Runtime”链路。
| 步骤 | 结果 | 证据 |
|---|---|---|
| 登录生产 Manager | 通过 | `/api/user/login` 返回 `success=true`,用户 `id=22` |
| 查询用户信息 | 通过 | `/api/user/self` 返回用户 `chenchen`、`group=default` |
| 查询 Runtime 健康 | 通过 | `/api/agent/runtime/health` 返回 `enabled=true`、`configured=true`、`status=healthy`、`create_path=/api/agent/deployments`、远端为 Agent Manager IP |
| 客户端模拟创建 deployment | 通过 | `POST /api/agent/user/deployments` 返回 Manager deployment `dep_1ba14ccfb558` |
| Manager -> Agent Manager create | 通过 | Manager detail 写回 `runtime_deployment_id=dep_3335e54e9bdf`,`runtime_state=pending` |
| Manager 用户态 events | 通过 | 出现 `deployment.accepted`、`runtime.sync.started`、`runtime.sync.accepted` |
| Manager 用户态 logs | 通过 | 出现 control-plane 日志和 runtime sync 日志,均为 redacted |
| Manager 用户态 metrics | 部分通过 | 返回 `platform_estimated=true`,说明是 Manager 估算/占位,不是 Runtime 真实资源指标 |
| Manager 用户态 artifacts | 未产出 | 返回空列表 |
| Manager 用户态 timeline | 部分通过 | 能返回 deployment/events,但 callbacks/artifacts 为空 |
| Manager stop | 通过 | `POST /api/agent/user/deployments/dep_1ba14ccfb558/stop` 返回 `status=stopped` |
| Runtime stop 结果 | 通过 | 直查 Agent Manager `dep_3335e54e9bdf`,状态为 `stopped` |
本次真实 ID:
```text
manager_deployment_id=dep_1ba14ccfb558
runtime_deployment_id=dep_3335e54e9bdf
correlation_id=manager-client-sim-1779955103016
runtime_agent_instance_id=agi_ed399bf8cc70
```
Agent Manager 侧直查 `dep_3335e54e9bdf`:
| 接口 | 结果 |
|---|---|
| `GET /api/agent/deployments/dep_3335e54e9bdf` | 200,状态 `stopped`,`user_id=22` |
| `GET /api/agent/deployments/dep_3335e54e9bdf/events` | 200,仅有 `deployment.accepted`、`deployment.stopped` |
| `GET /api/agent/deployments/dep_3335e54e9bdf/logs` | 200,仅有 `Pod ... has no logs yet` |
| `GET /api/agent/deployments/dep_3335e54e9bdf/metrics` | 200,返回 CPU/内存/网络固定值 |
本次客户端模拟链路结论:
1. 测试用户登录、Manager 用户态接口、Manager Runtime bridge、Agent Manager create、Agent Manager stop 均已真实跑通。
2. Manager 能拿到 Runtime 健康状态,并能把用户态 deployment 同步到 Agent Manager IP。
3. Manager stop 能传递到 Agent Manager,Runtime deployment 已停止。
4. Agent Manager 仍未真实产生普通 sub 必需的阶段、timeline、artifact、SK 工具和 usage 回调。
5. 当前 metrics/logs 更像 Runtime 占位数据:日志显示 `Pod ... has no logs yet`,metrics 为固定 CPU/内存/网络值。
6. 本次 Manager 请求中的 agile context 没有在 Runtime 详情中表现为有效阶段推进,Runtime 事件里 `agile_context` 为空字段,需要双方继续核对字段解析和透传。
## 10. 完成定义
只有满足以下条件,才能认为普通 sub 敏捷 Runtime 联调完成:
1. Manager 能创建 Runtime run,并保存 Runtime 返回的 `deployment_id`。
2. Runtime 能主动回调 Manager,且 callback 通过认证、幂等、脱敏和 schema 校验。
3. Manager 的 artifacts / timeline / sk-snapshots / events 能看到 Runtime 回传数据。
4. Manager 发起 stop 后 Runtime 真实停止。
5. Runtime 高危审批能暂停,Manager approve/reject 后 Runtime 收到 decision 并继续或停止。
6. Runtime usage / cost 能按 user、deployment、task、agent role、model 归属。
7. 整个流程不传递、不记录明文长期密钥。
@@ -1,372 +0,0 @@
# Heicode 客户端 — 登录接口对接文档
**版本**: v1.0
**生效日期**: 2026-04-30
**状态**: 已上线生产,已通过端到端测试
---
## 1. 概述
本文档描述 Heicode 客户端(桌面/CLI)与 Heicode Manager(即 mcp-server)之间的**登录认证接口**。共 4 个接口,覆盖完整登录生命周期:
| 接口 | 用途 |
| ------------------------ | ----------------------- |
| `POST /api/auth/login` | 账号密码登录,换取 token |
| `GET /api/auth/me` | 校验 token 有效性 + 获取当前用户资料 |
| `POST /api/auth/refresh` | access token 过期时换新的 |
| `POST /api/auth/logout` | 登出(token 加入黑名单) |
> 不在本期范围:注册、找回密码、改密码 — 这些走官网 web 端完成。
---
## 2. 接入信息
### 2.1 Base URL
生产环境通过 Azure APIM 网关接入:
```
https://apimtaiji.azure-api.net/api/mcp
```
完整路径示例:
```
POST https://apimtaiji.azure-api.net/api/mcp/api/auth/login
```
### 2.2 通用请求头
| Header | 必填 | 说明 |
| -------------------------------- | ----------- | -------------- |
| `Content-Type: application/json` | 是(POST/PUT) | 请求体 JSON |
| `Authorization: Bearer <token>` | 受保护接口必填 | 见 §3 |
| `X-Request-Id: <uuid>` | 建议 | 全链路追踪 ID,客户端生成 |
### 2.3 Token 模型
登录成功返回两个 token:
| Token | 用途 | 有效期 |
| ----------------- | ------------------------ | ----- |
| **Access Token** | 调业务接口(含 `/me`、`/logout`) | 24 小时 |
| **Refresh Token** | 仅用于 `/refresh` 换新 access | 7 天 |
JWT claims 包含:`sub`(user_id)、`email`、`role`、`channelId`、`type`(access/refresh)、`iat`、`exp`。
---
## 3. 接口详情
### 3.1 POST /api/auth/login — 登录
**请求**
```http
POST /api/auth/login HTTP/1.1
Content-Type: application/json
{
"email": "user@example.com",
"password": "YourPassword123",
"role": "user"
}
```
字段:
- `email` (string, 必填)
- `password` (string, 必填)
- `role` (string, 必填):Heicode 客户端**固定传 `"user"`**
**成功响应 200**
```json
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"name": "张三",
"email": "user@example.com",
"role": "user",
"channelId": "6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6"
}
}
}
```
**错误响应**
| HTTP | 含义 | 客户端处理建议 |
| ---- | ------------------------- | -------------------------------- |
| 401 | 邮箱或密码错误 | 显示"账号或密码错误",让用户重新输入 |
| 403 | 账户已被禁用 | 提示用户联系管理员 |
| 429 | 登录尝试过于频繁(**每 IP 5 次/分钟**) | 显示倒计时;响应头 `Retry-After: 60` 表示秒数 |
| 422 | 请求体校验失败(邮箱格式不合法等) | 检查 `detail` 字段 |
| 500 | 服务异常 | 重试或提示稍后再试 |
**重要:限流规则**
- **每 IP 每分钟最多 5 次**登录尝试(不区分成功失败)
- 超出返回 **429 Too Many Requests**,含 `Retry-After` 头(秒)
- 计数滑动窗口,60 秒后自动恢复
---
### 3.2 GET /api/auth/me — 获取当前用户
客户端**启动时**应调用此接口校验本地缓存的 access token 是否仍有效,并刷新用户信息。
**请求**
```http
GET /api/auth/me HTTP/1.1
Authorization: Bearer <accessToken>
```
**成功响应 200**
```json
{
"success": true,
"data": {
"id": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"email": "user@example.com",
"name": "张三",
"role": "user",
"channelId": "6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6",
"status": "active",
"subscriptionTier": "free",
"lastLoginAt": "2026-04-30T06:38:14.765457"
}
}
```
**错误响应**
| HTTP | 含义 | 客户端处理建议 |
| ---- | --------------------- | ------------------------------------------ |
| 401 | Token 无效/过期/已登出/用户不存在 | 调 `/refresh` 换新 token;若 refresh 也 401,跳登录页 |
| 403 | 账户已被禁用 | 强制登出,提示联系管理员 |
---
### 3.3 POST /api/auth/refresh — 刷新 token
access token 接近或已过期时调用,使用 **refresh token** 换取新的 access + refresh token 对。
**请求**
```http
POST /api/auth/refresh HTTP/1.1
Authorization: Bearer <refreshToken>
```
> ⚠️ **必须传 refresh token**,传 access token 会被拒绝。
**成功响应 200**
```json
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}
}
```
客户端收到新的 token 对后**应替换本地缓存**(包括 refresh token,旧的也作废)。
**错误响应**
| HTTP | 含义 | 客户端处理建议 |
| ---- | ---------------------------------------- | ------- |
| 401 | refresh token 无效 / 过期 / 错传了 access token | 跳登录页 |
实施细节:
- 服务端会校验 token claims `type == "refresh"`,否则拒绝
- 旧 refresh token 不会被立即吊销(容许并发换发期),但客户端应丢弃旧的
---
### 3.4 POST /api/auth/logout — 登出
将当前 access token 加入黑名单,使其立即失效。
**请求**
```http
POST /api/auth/logout HTTP/1.1
Authorization: Bearer <accessToken>
```
**成功响应 200**
```json
{
"success": true,
"data": null,
"message": "登出成功"
}
```
**错误响应**
logout 容错性较强,token 黑名单写入失败也会返回 200(前端清理本地 token 即可)。
**客户端登出流程**:
1. 调 `/api/auth/logout`
2. 清除本地存储的 access + refresh token
3. 清除当前用户资料缓存
4. 跳转到登录页
---
## 4. 完整登录流程(示例)
### 启动时
```
┌─ 本地有 access token ?
│
├─ 是 ─→ GET /me
│ ├─ 200 ─→ 进入主界面
│ └─ 401 ─→ 本地有 refresh token ?
│ ├─ 是 ─→ POST /refresh
│ │ ├─ 200 ─→ 替换 token,进入主界面
│ │ └─ 401 ─→ 跳登录页
│ └─ 否 ─→ 跳登录页
│
└─ 否 ─→ 跳登录页
```
### 登录页提交
```
POST /login
├─ 200 ─→ 存 token 对,进主界面
├─ 401 ─→ 显示"账号或密码错误"
├─ 429 ─→ 显示"尝试过于频繁,请 N 秒后重试"(N 取响应头 Retry-After)
└─ 其他 ─→ 显示通用错误
```
### 业务请求过程中 access token 过期
```
任意业务接口返回 401
└─→ POST /refresh (用 refresh token)
├─ 200 ─→ 替换 token,重试原请求
└─ 401 ─→ 清理 token,跳登录页
```
### 登出按钮
```
POST /logout
└─→ 不论结果都清理本地 token,跳登录页
```
---
## 5. 错误响应格式
当前为 FastAPI 默认格式(下个版本 `/api/v1/*` 路径会改为标准 envelope,本期保留兼容):
```json
{
"detail": "邮箱或密码错误"
}
```
422 校验错误格式(Pydantic):
```json
{
"detail": [
{
"type": "value_error",
"loc": ["body", "email"],
"msg": "value is not a valid email address: ...",
"input": "abc"
}
]
}
```
---
## 6. 安全注意事项
| 项 | 说明 |
| -------------- | -------------------------------------------------------------------------------------- |
| **token 存储** | 桌面应用建议存到 OS 安全凭据存储(Windows Credential Manager / macOS Keychain / Linux Secret Service) |
| **HTTPS 强制** | 生产 base URL 已是 HTTPS;客户端**禁止**回退 HTTP |
| **token 泄露应对** | 用户怀疑泄露时提示去官网 web 端改密码(改密会导致所有 session 黑名单) |
| **审计日志** | 所有 login 尝试(成功/失败)服务端均写审计 |
| **状态码不泄漏** | 错误信息已统一用"邮箱或密码错误",不区分账号是否存在,防爆破 |
---
## 7. 测试账号(仅供联调)
| 角色 | 邮箱 | 密码 |
| ---- | ----------- | ------------ |
| 普通用户 | `55@55.com` | `By@123456.` |
> ⚠️ 测试账号仅用于联调阶段,正式上线前请务必关闭。
---
## 8. 已上线生产验证清单
| 测试项 | 结果 |
| ------------------------------------------ | --- |
| login 200 + 返回 access/refresh token | ✅ |
| /me 用 access token → 200 + 完整 profile | ✅ |
| /refresh 用 refresh token → 200 + 新 token 对 | ✅ |
| /refresh 用 access token → 401 拒绝 | ✅ |
| logout → 200 | ✅ |
| logout 后旧 token 调 /me → 401(黑名单生效) | ✅ |
| 连续 7 次错密 → 第 6 次起 429(每 IP 5/min 限流) | ✅ |
| 服务器审计日志记录所有 login(含成功/失败) | ✅ |
镜像 digest: `sha256:339b64ae090dc81fa13cb29705958167e77fe0698e27ac227c05054ed5c42309`
镜像 tag: `taiji.azurecr.io/mcp-server:heicode-auth-fix2-20260430`
部署日期: 2026-04-30
---
## 9. 联系
如对接过程发现接口行为与本文档不一致,请联系 Heicode Manager 后端团队,附上:
- 请求完整 URL / Headers / Body
- 响应 HTTP 状态 + Body
- `X-Request-Id` 头值(便于服务端按 ID 反查日志)
@@ -5,7 +5,7 @@
> 生产地址:`https://code.xinghanlab.com`
> 状态图例:🟢 已实现并生产验证 · 🔴 待建(依赖 AM)
> **本文取代旧的 `heicode-desktop-unified-api.md`**(那份描述的是已下线的 sub 任务编排模型:tasks/workflow/display_status/git_ref/产物下载等,均已删除)。新客户端一律按本文对接。
> **本文取代旧的桌面 sub 任务编排接口文档**(描述 tasks/workflow/display_status/git_ref/产物下载的那套已下线,相关 md 已删除)。新客户端一律按本文对接。
---
File diff suppressed because it is too large Load Diff
@@ -1,232 +0,0 @@
# Heicode 桌面客户端 ↔ Manager Sub Agile 端到端联调演练(真实数据)
> 更新时间:2026-06-02
> 环境:Heicode Manager(生产同构 VM)→ agent_management(Sub Agile Runtime)
> 用途:给桌面客户端团队**逐步对照**接入实现。本文每一步都是**一次真实跑出来的请求 + 真实响应**(任务 `dep_39e53ee4c692`,模型 `gpt-5.4`)。
> 配套:接口细节见同目录 [`heicode-desktop-unified-api.md`](./heicode-desktop-unified-api.md)。
本演练验证的核心结论:**Sub Agile 任务跑完后,agent_management 产出的是真实代码文件 + 目录结构**,Manager 解析成 `project_folder`,客户端可拿到「文件树 / 单文件正文 / 整包 zip」,zip 解压即真实文件夹。
---
## 0. 角色与链路
```text
桌面客户端 ──(只调 Manager)──> Heicode Manager ──(归口)──> agent_management(Sub Agile Runtime)
```
- 客户端**只**调 `https://code.xinghanlab.com/api/heicode/sub-agile/*`,不直连 Runtime。
- Manager 是唯一状态裁判:客户端只看 `display_status`。
- 认证:与模型调用同一套(写请求 V2 加密 body + 设备签名;GET 无 body 设备签名)。详见统一文档 §1。本演练为聚焦业务流程,示例用已登录态表示,不展开加密细节。
---
## 1. 创建任务(提交需求包)
客户端提交**需求包**(不是 Runtime 原始参数),Manager 翻译成编排计划并创建。
**请求**
```http
POST /api/heicode/sub-agile/tasks
Content-Type: application/json
```
```json
{
"mode": "sub_agile",
"requirement": {
"objective": "做一个前后端分离的 Todo 应用。后端放在 backend/ 目录:backend/main.py (FastAPI, 提供 /todos 增删查) 和 backend/models.py (Todo 数据模型)。前端放在 frontend/ 目录:frontend/src/App.jsx 和 frontend/package.json。根目录加 README.md。每个文件用对应语言代码块, 文件名写在代码块第一行注释里。"
},
"model_selection": { "type": "single", "default_model": "gpt-5.4" },
"roles": ["backend"]
}
```
**响应(真实)**
```json
{ "success": true, "data": {
"deployment_id": "dep_39e53ee4c692",
"sub_mode": "agile",
"mode": "sub_agile",
"status": "accepted",
"display_status": "accepted",
"runtime_state": "runtime_syncing",
"agent_instances": [ { "instance_id": "agi_...", "role": "backend", "phase": "pending" } ]
}}
```
要点:
- `deployment_id` 就是后续所有接口的 `{task_id}`(`task_id ≡ deployment_id`)。
- 客户端本地保存:`deployment_id` / `mode` / `display_status`,以便重启后恢复。
- `roles` 决定起几个 agent / 出哪些目录:本例只起了 `backend`,所以只产出 `backend/` 下文件。要前后端并列目录,传 `["backend","frontend"]`。
---
## 2. 轮询工作流,直到终态
**请求**
```http
GET /api/heicode/sub-agile/tasks/dep_39e53ee4c692/workflow
```
运行中每 3–5 秒轮询一次,终态后停止。本次真实轨迹:
```text
poll 1: display_status = accepted
poll 2: display_status = running
poll 3: display_status = completed <- 终态
```
**workflow 响应(真实,节选)**
```json
{ "success": true, "data": {
"task_id": "dep_39e53ee4c692",
"mode": "sub_agile",
"sub_mode": "agile",
"display_status": "completed",
"cloud_deployment_status": "completed",
"runtime_execution_status": "completed",
"phase": "development",
"phases": [ { "phase_id": "development", "name": "development", "status": "completed", "agents": ["backend"] } ],
"agent_count": 1,
"agents": [ { "agent_id": "agi_...", "role": "backend", "status": "completed",
"tokens": 0, "tools": 0, "elapsed_seconds": 0, "artifact_ids": ["art_swm_826fe9814483_backend_1"] } ],
"metrics": { "tokens_used": 618, "tools": 0, "elapsed_seconds": 33, "total_messages": 2 },
"artifact_ids": ["art_swm_826fe9814483_backend_1"]
}}
```
客户端判定规则:
- **只看 `display_status`**。`completed` = 完成且有有效交付物;`needs_codegen` / `completed_without_deliverable` = 没有效产物,别当成功。
- per-agent 的 `tokens`/`tools` 当前为 `0`(agent_management 暂未上报 per-agent 指标,顶层 `metrics` 是真实值)。
---
## 3. 取产物列表(确认是项目而非文本)
**请求**
```http
GET /api/heicode/sub-agile/tasks/dep_39e53ee4c692/artifacts
```
**响应(真实,节选)**
```json
{ "success": true, "data": { "items": [
{
"artifact_id": "art_swm_826fe9814483_backend_1",
"artifact_type": "code_patch",
"is_project": true,
"display_artifact_type": "project_folder",
"manifest_path": ".../artifacts/art_swm_826fe9814483_backend_1/manifest",
"files_path": ".../artifacts/art_swm_826fe9814483_backend_1/files",
"archive_path": ".../artifacts/art_swm_826fe9814483_backend_1/archive"
}
] }}
```
要点:**主产物类型看 `display_artifact_type`**。即使 Runtime 原始 `artifact_type=code_patch`,Manager 归一化为 `project_folder` 且 `is_project=true`,并直接给出 manifest/files/archive 子路径,客户端不用自己猜。
---
## 4. 取文件树(manifest,含目录层级)
**请求**
```http
GET /api/heicode/sub-agile/tasks/dep_39e53ee4c692/artifacts/art_swm_826fe9814483_backend_1/manifest
```
**响应(真实)**
```json
{ "success": true, "data": {
"artifact_id": "art_swm_826fe9814483_backend_1",
"artifact_type": "project_folder",
"root_dir": "project",
"file_count": 2,
"entries": [
{ "path": "backend/models.py", "type": "file", "mime_type": "text/x-python", "size_bytes": 228,
"content_path": ".../files?path=backend%2Fmodels.py" },
{ "path": "backend/main.py", "type": "file", "mime_type": "text/x-python", "size_bytes": 927,
"content_path": ".../files?path=backend%2Fmain.py" }
],
"archive": { "format": "zip", "download_path": ".../archive" }
}}
```
要点:`entries[].path` 带**真实目录层级**(`backend/main.py`)。客户端用 `content_path`(已是 `?path=` URL 编码)直接取单文件,无需自己拼路径。
---
## 5. 取单文件正文(确认是真代码)
**请求**
```http
GET /api/heicode/sub-agile/tasks/dep_39e53ee4c692/artifacts/art_swm_826fe9814483_backend_1/files?path=backend%2Fmain.py
```
**响应(真实,节选)**
```python
# backend/main.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from .models import Todo, TodoCreate
app = FastAPI(title="Todo API")
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True,
allow_methods=["*"], allow_headers=["*"])
todos: list[Todo] = []
next_id = 1
@app.get("/todos", response_model=list[Todo])
def list_todos():
...
```
---
## 6. 下载整包 zip(确认解压是真实文件夹)
**请求**
```http
GET /api/heicode/sub-agile/tasks/dep_39e53ee4c692/artifacts/art_swm_826fe9814483_backend_1/archive
```
**响应头(真实)**
```text
HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="art_swm_826fe9814483_backend_1.zip"
Content-Length: 896
```
**解压后真实落盘结构**
```text
project/
└── backend/
├── main.py
└── models.py
```
客户端下载契约(务必遵守):
- 读 `Content-Disposition` 文件名、按 `Content-Length` 校验后再落盘,**保存成功才提示「已下载」**。
- 产物未就绪时返回 `{"success":false,"error":{"code":"ARTIFACT_ARCHIVE_NOT_READY","retryable":true}}`,此时不要提示已下载。
---
## 7. 客户端核对清单(照此自检即三端对齐)
- [ ] 创建任务用**需求包**(`requirement.objective` + `model_selection` + `roles`),从响应拿 `deployment_id`(=`task_id`)。
- [ ] 运行中每 3–5 秒 `GET .../workflow`,**只读 `display_status`** 判断完成;不订阅 `/events/stream`(未提供)。
- [ ] 列表/详情/workflow 都读顶层 `mode`(`sub_agile`|`swarm`)做模式标签与路由,重启后用它恢复。
- [ ] 产物以 `display_artifact_type=project_folder` / `is_project=true` 为准,走 `manifest → files?path= → archive`。
- [ ] `files?path=` 用 manifest 给的 `content_path`(已 URL 编码),支持 `backend/main.py` 这种嵌套路径。
- [ ] `archive` 按响应头校验落盘;`ARTIFACT_ARCHIVE_NOT_READY` 时重试不报「已下载」。
- [ ] 终态成功判据:`display_status=completed` 且 artifacts 非空(`is_project=true`)。
---
## 附:已知由 Runtime(agent_management)决定、非 Manager 缺陷的点
- **目录范围由 `roles` 决定**:只传 `["backend"]` 就只出 `backend/`;要 `frontend/` 等并列目录,传对应角色。
- **per-agent `tokens`/`tools`/`elapsed_seconds`**:待 agent_management 在状态里上报 per-agent 指标,未上报时为 `0`(顶层 `metrics` 为真实值)。
- **artifact 归属 agent**:依赖 Runtime 在 artifact metadata 标 `source_agent_role`,未标时 per-agent `artifact_ids` 可能为空。
- **阶段细分 `phases[]`**:Runtime 现仅上报单个 `phase`,故默认是「当前阶段」一条;待上报阶段历史后展开。
@@ -1,601 +0,0 @@
# Heicode 桌面客户端统一接口对接文档(v0.1)
> ⛔ **已废弃(2026-06-04)**:本文描述的是**已下线的 sub 任务编排模型**(tasks/workflow/display_status/git_ref/产物下载/部署租约等,相关后端已删除)。
> **新客户端请改用 [`heicode-desktop-client-api.md`](./heicode-desktop-client-api.md)(模板 Agent 模型)。** 本文仅作历史留存。
更新时间: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-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)、Swarm 同形(§3)。
>
> **2026-06-03 更新(产物模型对齐)**:sub 模式**强制绑定 git** 才能用,否则只能本地跑——因此**代码产物的唯一归宿是用户自己的 git 仓库**(clone/pull)。早期"HM 把文本产物解析成项目文件夹(`project_folder`/manifest/files/archive)"是无 git 流程的残留,**不再作为代码交付路径**;artifacts 接口仅保留给**非代码产物**(test_report/摘要)。详见 §5。
## 0. 命名与总原则
- **命名统一**:`agnet` 是历史拼写错误,已全量改为 `agent`。所有新接口为 `/api/agent/*`、`/api/heicode/*`;旧 `/api/agnet/*` 已下线(404)。
- **客户端只调 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. (★必做) 绑定 git 仓库 (github/gitea) + (可选) vm/db/blob -> 凭据进 Key Vault, 拿 resource_binding_id (§8)
未绑 git 则禁用 sub 入口 (强制绑 git, §3.1)
1. GET /api/heicode/capabilities 取模式/模型,渲染模式与模型选择
2. POST /api/heicode/sub-agile/tasks (需求包, 带 resource_bindings.git + X-Idempotency-Key)
创建任务 -> 响应里拿 deployment_id(=task_id) (§3.1)
3. (可选) POST .../tasks/{id}/execute 若需"先建后跑"或重试派发
4. 轮询 GET .../tasks/{id}/workflow (运行中 3-5s) / 将来 SSE 读 display_status + 三层状态 + agents + git_ref (§4b)
5. 出现 approval 时: GET .../approvals?status=pending -> approve/reject
6. display_status=completed 后: 按 workflow 里的 git_ref 做 git clone/pull (完整工程+历史+diff) (§5)
(非代码运行信息如 test_report/摘要 -> GET .../artifacts 查看; HM 不托管/不解析项目代码)
7. 不满意 -> 改/重做: POST .../messages|/execute 回云端改; 或 git pull 本地用客户端自己的 agent 改 (§6)
8. (可选) 部署: 用户确认 -> 客户端凭 resource_binding_id 取短期租约(V2) -> 客户端本地 git/ssh/部署 (§7, HM 不代执行)
```
> 成功判据:`display_status=completed` 且 `git_ref` 有新 commit = **跑完且有真东西**;但**"代码对不对"客户端自己拉下来跑/测 + 用户 review**(`completed` 不保证正确,见 §4)。
## 1. 认证与加密(重要)
桌面客户端调用本文所有 `/api/heicode/*` 接口,**body 加密与签名和模型调用(`/v1/*`)完全一致**——直接复用同一套 `encryptedFetch` / V2 设备签名实现,无需新增协议。
| 方式 | 适用 |
|---|---|
| **V2 加密 body + 设备签名**(`Content-Encoding: heicode-aead-v1` + `X-Heicode-*`,ChaCha20-Poly1305 + Ed25519) | 有 body 的请求(POST/PUT/DELETE) |
| **V2 无 body 设备签名**(`X-Heicode-*` 签名头,**不带** `Content-Encoding`) | GET 等无 body 请求(fetch 规范禁止 GET 带 body) |
| Manager session cookie + `New-Api-User: <user_id>` | Web 控制台兼容路径(桌面端可不用) |
要点(与模型调用相同,未变):
- `aad` / `canonical` 里的 `path_with_query` 必须是 Manager 实际收到的 path,例如 `/api/heicode/sub-agile/tasks`,不含 origin。
- 每次新 `X-Heicode-Nonce` + 新 X25519 临时 key;签名里 `sha256_hex(plaintext_body)` 与加密前 JSON 字节一致。
- 服务端在新路由上用同一中间件 `UserOrV2DeviceAuth` 解密+验签,从设备绑定 token 解析用户身份;失败读响应头 `X-Heicode-Auth-Error`。
**GET 全程无 cookie 的设备签名(已支持)**:GET 没有 body,因此**不发** `Content-Encoding`、**不加密**,但仍发同一套签名头并用相同 canonical 公式签名,`sha256_hex(plaintext_body)` 处填**空 body 的哈希** `sha256("")`:
```text
canonical = method + "\n" # "GET"
+ path_with_query + "\n" # 例如 /api/heicode/sub-agile/tasks/dep_x/workflow
+ timestamp_ms + "\n"
+ nonce_hex + "\n"
+ device_fingerprint + "\n"
+ ephemeral_pubkey_b64 + "\n" # GET 仍生成一对临时 X25519 key 并带 X-Heicode-Eph-Pubkey
+ sha256_hex("") # e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
signature = base64( ed25519_sign(device_priv, sha256(canonical)) )
```
即:GET 与写请求共用同一签名实现,区别仅是「不加密 body、body 哈希为空串哈希」。服务端凭 `X-Heicode-Signature` + `X-Heicode-Device-Id` + `X-Heicode-Eph-Pubkey` 三个头识别该模式(gap P0-1 已闭环)。客户端可用同一 `encryptedFetch`,对 GET 走「跳过加密、空 body」分支即可。
## 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 当前是否接通(HM 探测 agent_management / HeiCode-Swarm 的健康;`enabled:false` 时**不要**让用户进该模式)。
字段:`runtime_kind`(后端运行时)、`model_selection`(`default|per_role|primary`)、`supports_roles/task_graph/continue_chat`(UI 能力位)、`models[].available`(该模型当前可用)。
### 2.1 判断 sub 模式是否可用(就绪闸门)🟡
客户端在让用户点「sub 模式」前,必须先过**四道闸门**;任一不满足就**禁用 sub 入口**并提示对应引导。这是一个**客户端本地组合判断**(HM 不提供单一「ready」接口):
| # | 闸门 | 数据来源 | 不满足时 |
|---|---|---|---|
| 1 | **Runtime 接通** | `GET /api/heicode/capabilities` → `modes[id=sub_agile].enabled === true` | 灰掉 sub,提示「云端暂不可用」 |
| 2 | **已认证(设备已绑定)** | 本地有设备绑定 token(§1;无则先走 heicode-auth 登录/配对) | 引导登录 |
| 3 | **已绑有效 git 仓库** | `GET /api/heicode/resources?type=git&status=active`(§8.2)非空 | 引导去「资源绑定」绑 git,或改用本地模式 |
| 4 | **余额充足** | `GET /api/user/self` → `quota - used_quota > 0`(§2.2) | 引导充值 |
```text
canUseSub =
capabilities.modes.find(m => m.id==='sub_agile')?.enabled
&& isDeviceBound()
&& gitBindings.some(b => b.status==='active')
&& self.quota > self.used_quota
```
- 闸门 3「强制绑 git」对齐 spec §3.1;建任务时若仍没传有效 git binding,HM 也会兜底拒绝(`SUB_GIT_BINDING_REQUIRED`,§11)。
- 闸门 1/4 用现有接口(🟢);闸门 3 的客户端版资源列表是 🔴 待建(§8.2),上线前可临时用 `/api/resources/`(会话鉴权)联调。
- **本地模式**(客户端自己跑 agent)不需要闸门 1/3,只需 2/4。
### 2.2 账户与余额(判断能不能跑 / 给概览用)🟢
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET | `/api/user/self` | 会话/设备 | 当前用户:`quota`(剩余额度)、`used_quota`(累计已用)、`request_count`(调用次数)、分组等 |
| GET | `/api/user/self/groups` | 同上 | 用户可用模型分组 |
| GET | `/api/user/self/models` | 同上 | 当前用户**可用模型**列表(与 `capabilities.models` 互补,按分组过滤) |
```json
// GET /api/user/self → data 摘要
{ "id":22, "username":"...", "quota":160470000, "used_quota":39530000, "request_count":521, "group":"default" }
```
- 余额/用量单位是内部 quota(展示按汇率换算);`quota` 为**剩余**,`used_quota` 为**累计已用**。
- 建任务前应检查 `quota > used_quota`(闸门 4);运行中若超预算 HM 会把任务标 `budget_exceeded`(§4)。
- 模型选择(需求包 `model_selection`)只能用 `capabilities.models` ∩ `/api/user/self/models` 里 `available` 的模型。
## 3. 统一任务接口
两套前缀,按模式选择:`/api/heicode/sub-agile/*`(→ agent_management)、`/api/heicode/swarm/*`(→ HeiCode-Swarm)。**下表以 sub-agile 为例,swarm 路径把前缀 `sub-agile` 换成 `swarm` 后完全同形(approvals/deployments/workflow 等子接口)**——两组路由由同一注册函数生成,不存在「只实现了 sub-agile」的情况。(注:`files/archive/revisions/local-edits` 这些遗留子接口两侧也都还在,但已不作为代码交付路径,见 §5/§6。)
| 方法 | 路径 | 说明 |
|---|---|---|
| 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 收敛) |
| POST | `/api/heicode/sub-agile/tasks/{task_id}/messages` | 持续对话:追加用户消息 |
| POST | `/api/heicode/sub-agile/tasks/{task_id}/execute` | 触发/确保执行(未派发则派发 Runtime) |
| DELETE | `/api/heicode/sub-agile/tasks/{task_id}` | 删除/停止任务 |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/workflow` | 工作流投影(右侧面板:mode/display_status/phases/agents(含 current_action/branch/tokens/tools/elapsed/artifact_ids)/metrics/**git_ref**/artifacts) |
| 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` | 产物列表(**仅非代码产物**:test_report/摘要等;代码看 git,见 §5) |
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts/{artifact_id}/content` | 单产物正文(如测试报告) |
| ~~GET~~ | ~~`.../artifacts/{artifact_id}/{manifest,files,archive,revisions}`~~ | **遗留**:无 git 流程的"HM 解析项目文件夹"接口,sub 强制 git 后不再作为代码交付路径(后端仍在,见 §5) |
| ~~POST~~ | ~~`.../artifacts/{artifact_id}/local-edits[/batch]`~~ | **遗留**:本地改产物改用 git 提交 |
| 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 同路径 | ⚠️ 旧的「Manager 代部署」控制面,**不再作为部署主路径**;新部署=客户端执行(见 §7) |
### 3.1 创建 body(需求包)
客户端提交**需求包**,不提交 Runtime 原始参数;Manager 内部翻译成 orchestration_plan 并创建。
```json
{
"mode": "sub_agile",
"client_role": "main_agent",
"conversation_id": "conv_xxx",
"requirement": {
"objective": "做一个 Oracle 云代理商网站,前后端分离",
"context": [], "attachments": [], "constraints": [], "acceptance_criteria": []
},
"model_selection": {
"type": "per_role",
"default_model": "gpt-5.4",
"roles": {"backend":"gpt-5.4","frontend":"gpt-5.4"}
},
"roles": ["backend", "frontend"],
"resource_bindings": {
"git": "rb_git_xxx", // ★ 必填:用户绑定的 git 仓库(§8)。缺则拒绝建任务
"vm": "rb_vm_xxx", // 可选:部署目标,仅在需要时
"database": "rb_db_xxx", // 可选
"blob": "rb_blob_xxx" // 可选
},
"git_options": { // 可选:覆盖 binding 默认
"base_branch": "main", // 从哪个分支拉基线
"mode": "existing", // greenfield(绿地新建) | existing(已有代码上增量改)
"allowed_paths": ["backend/", "frontend/"], // 限定 agent 工作目录,避免动无关代码
"write_mode": "pr" // pr(开 PR/交付分支,建议) | branch | main
}
}
```
- **★ `resource_bindings.git` 必填**:sub 模式强制绑 git(spec §3.1 决策)。未传或 binding 失效 → HM 拒绝建任务,返回 `SUB_GIT_BINDING_REQUIRED`(见 §11)。客户端 UI 应在未绑 git 时**禁用 sub 入口**,引导先绑(§8)或改用本地模式。
- 只传 `resource_binding_id`(如 `rb_git_xxx`),**绝不内联明文凭据**;HM 从 Key Vault 解出短期 PAT 注入 AM。
- `model_selection.type`:`default`(全局 `default_model`)/ `per_role`(`roles` 映射)/ `primary`(Swarm 用 `primary_model`)。
- `conversation_id` 作为任务关联键(落到 `correlation_id`)。
- 模型必须用生产 NewAPI 已存在模型(当前推荐 `gpt-5.4`)。
- 兼容:也接受直接传 `{ "orchestration_plan": {...} }`(高级用法)。
**幂等**:创建请求带 `X-Idempotency-Key: <uuid>`(spec §9.3)。HM 对同 key 去重,网络重试不会建重复任务/重复 git 分支;重复命中返回首次的 `deployment_id`。
> 状态标注:`resource_bindings` / `git_options` / `SUB_GIT_BINDING_REQUIRED` / `X-Idempotency-Key` 均为 🔴 待建(随 git 化与客户端版资源接口一起上线,见 §8)。当前后端建任务尚未强制 git;客户端应**按本规范预留字段**,HM 侧补齐校验后即对齐。
`/messages` body:`{"message":"继续把测试补上","role":"user"}`。
`/execute` body 可空;用于"创建后再触发"或重试派发。
**创建响应**(`deployment_id` 即后续所有 `{task_id}`):
```json
{ "success": true, "message": "", "data": {
"deployment_id": "dep_b5fab27e9255",
"sub_mode": "agile",
"status": "accepted",
"display_status": "accepted",
"runtime_state": "runtime_syncing",
"runtime_swarm_id": "",
"agent_instances": [
{"instance_id":"agi_xxx","role":"backend","phase":"pending","runtime_state":"queued","failure_reason":""}
],
"permission_manifest": {"user_id":"22","binding_scope":"","resource_grants":[]}
}}
```
**任务详情** `GET .../tasks/{task_id}` 返回同形 + 完整 `orchestration_plan`;**任务列表** `GET .../tasks` 返回 `{"items":[ ...同上... ],"total":N}`。客户端按 `display_status` 渲染,详情/列表读取时 Manager 会自动从 Runtime 收敛终态。
### 3.2 审批列表(gap P0-2)
`GET .../tasks/{task_id}/approvals?status=pending`:
```json
{ "success": true, "data": {
"task_id":"dep_xxx","total":1,
"items":[
{"approval_id":"appr_xxx","deployment_id":"dep_xxx","type":"deploy","risk_level":"high",
"title":"生产部署审批","status":"pending","created_at":"2026-06-02T00:00:00Z"}
]
}}
```
`status` 省略则返回全部;对每条 `pending` 项调 `.../approvals/{approval_id}/approve|reject` 闭环。
## 4. 状态模型(display_status)
客户端只展示 `display_status`(Manager 裁决结果):
| display_status | 含义 |
|---|---|
| `accepted` / `running` / `waiting_approval` | 进行中 |
| `completed` | 跑完且**有真实产物**(非空、非兜底)—— 注意:**不代表代码正确** |
| `completed_without_deliverable` | Runtime 完成但无产物(无 git 提交) |
| `needs_codegen` | 只有方案/总结,需继续生成代码 |
| `budget_exceeded` 🔴 | 超 token/时长/成本上限,已暂停待用户决定续不续(spec §9.3) |
| `failed` / `stopped` | 终态 |
裁决规则(对齐 spec §6.4):AM 说 `completed` 后,HM 看**有没有真交付**——
- **目标态**:回调带 `git_ref` 且有**真实提交**(commit/改了 N 个文件)→ `completed` ✅。
- 只有方案/总结、没有提交 → `needs_codegen`;什么都没有 → `completed_without_deliverable`。
- 过渡期(AM 未 git 化):带"改了 N 个文件"信号的非兜底 artifact(`metadata.synthesized!=true` 且非纯总结)也按真交付算。
HM 判的是**"有没有真东西"这个事实**,**不读代码、不判对错**。
> ⚠️ **`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` 返回客户端右侧面板需要的三层状态对象:
```json
{ "success": true, "data": {
"task_id":"dep_xxx","conversation_id":"conv_xxx",
"mode":"sub_agile", // 顶层模式 sub_agile|swarm(与 capabilities 一致)
"sub_mode":"agile", // sub_agile 内的节奏 agile|waterfall
"cloud_deployment_status":"completed", // Manager 控制面状态
"runtime_execution_status":"completed", // Runtime 上报状态
"display_status":"completed", // 唯一展示状态(客户端只看这个)
"last_synced_at":"2026-06-02T...",
"title":"...","summary":"...","phase":"development","agent_count":1,
"phases":[ // 阶段列表(runtime 未给细分时为当前阶段单条)
{"phase_id":"development","name":"development","status":"completed","agents":["backend"]}
],
"agents":[
{"agent_id":"agi_x","name":"backend","role":"backend","status":"completed",
"current_action":"已合并到交付分支", // 🔴 一句话「现在在干啥」,给 work 视图滚动
"branch":"agent/backend", // 🔴 该 agent 的分支(看单角色 diff)
"tokens":0,"tools":0,"elapsed_seconds":0,"artifact_ids":["art_x"]}
],
"git_ref": { // 🔴 交付引用(见 §5.2);未就绪时为 null
"provider":"github","repo_url":"https://github.com/owner/repo",
"branch":"delivery/dep_xxx","commit_sha":"a1b2c3d","tag":"delivery-dep_xxx-rev1",
"pull_request_url":null
},
"artifacts":[{"artifact_id":"art_x","title":"测试报告","artifact_type":"test_report"}], // 仅非代码运行信息
"artifact_ids":["art_x"],
"metrics":{"tokens_used":618,"tools":0,"elapsed_seconds":33,"total_messages":2},
"tokens":618,"tools":0,"elapsed_seconds":33
}}
```
字段说明(gap A/D/F):
- `mode`:顶层 `sub_agile|swarm`,与 `capabilities` 一致;列表 `GET .../tasks` 的每个 item 也带 `mode` 和 `display_status`,重启后从列表恢复任务不会把 swarm 当成 sub-agile。`sub_mode` 是 sub_agile 内部节奏。
- `git_ref`:**客户端据此 `git pull` 看产物**(§5.2)。`completed` + `git_ref` 有 `commit_sha` = 本轮真交付落到了用户仓库;续跑/重做后 `commit_sha` 会更新。🔴 待 AM 回调带 git_ref + HM 透出。
- `phases[]`:始终是数组。当前 sub-mode runtime 只上报单个 `phase`,故默认是「当前阶段」一条;待 runtime 上报阶段细分后会展开。
- `metrics` / 顶层 `tokens/tools/elapsed_seconds`:来自 runtime 状态指标(`tokens_used`/`elapsed_seconds`/`total_messages` 为真实值)。
- 每个 agent 的 `current_action`/`branch`/`tokens`/`tools`/`elapsed_seconds`:**待 agent_management 上报 per-agent 富字段**(🔴),未上报时为空/`0`;`artifact_ids` 按 `source_agent_role` 归到对应 agent。
- `artifacts[]`:只放**非代码运行信息**(test_report/summary);代码看 `git_ref`,不在此处。
`client_task_status`(本地交互态)由客户端自己维护,不由 Manager 返回。
### 4.2 运行信息接口(日志 / 时间线 / 诊断 / 事件 / 指标)🟢
work 视图除 `/workflow` 外,下列接口给**过程信息**(都只读、GET、V2 无 body 签名)。**它们只承载"运行信息",不承载代码产物**(代码看 git_ref,§5)。
| 方法 | 路径 | data 关键字段 | 用途 |
|---|---|---|---|
| GET | `.../tasks/{id}/logs` | `user_logs[]`(友好)、`debug_logs[]`(原始)| 日志面板分两层:普通用户看 user,调试面板看 debug |
| GET | `.../tasks/{id}/timeline` | `events[]`(task./agent./phase./handoff./delivery.)、`callbacks[]`、`artifacts[]` 聚合 | 任务时间线 |
| GET | `.../tasks/{id}/events` | `events[]`(原始事件流) | 细粒度事件 |
| GET | `.../tasks/{id}/metrics` | `tokens_used`、`elapsed_seconds`、`total_messages` | 指标卡 |
| GET | `.../tasks/{id}/diagnostics` | `runtime_status`、`warnings[]`(直查 Runtime) | 排障 |
| GET | `.../tasks/{id}/sk-snapshots` | `snapshots[]` | SK 快照 |
```json
// GET .../logs → data
{ "task_id":"dep_xxx",
"user_logs":[{"ts":"2026-06-03T..","level":"info","agent":"backend","message":"开始实现登录接口"}],
"debug_logs":[{"ts":"2026-06-03T..","level":"debug","message":"tool: write_file path=backend/auth.go"}] }
```
```json
// GET .../timeline → data
{ "task_id":"dep_xxx",
"events":[{"event_type":"phase.changed","occurred_at":"..","payload":{"phase":"development"}},
{"event_type":"delivery.pushed","occurred_at":"..","payload":{"git_ref":{"branch":"delivery/dep_xxx","commit_sha":"a1b2c3d"}}}],
"callbacks":[], "artifacts":[{"artifact_id":"art_x","artifact_type":"test_report"}] }
```
> 轮询建议:work 视图主要轮询 `/workflow`(含 display_status + agents + git_ref,一次拿全);需要日志/时间线明细时再单独拉 `/logs`、`/timeline`。SSE 上线后这些都可由事件流推送(§4b)。
## 4b. 响应 envelope 与实时刷新
**成功**:`{ "success": true, "message": "", "data": {...} }`
**失败**:`{ "success": false, "message": "...", "error": { "code": "...", "message": "...", "retryable": false, "request_id": "..." } }`
`task_id` / `deployment_id` / `conversation_id` / `correlation_id` 在各接口的 `data` 内返回(无独立 `trace` 字段)。
**实时刷新(现状 🟢 轮询)**:当前**未提供 SSE**;客户端按统一方案 §17.3 兜底用**轮询**刷新:
- 运行中:每 3–5 秒 `GET .../workflow`(或 `.../timeline`);
- 终态:降到 15–30 秒或停止。
- 现在**不要**订阅 `.../events/stream`(未提供,会 404)。
**实时流(目标 🔴,对齐 spec §5)**:上线后 HM 提供 `GET /api/heicode/sub-agile/tasks/{id}/events/stream`(SSE),把 AM 回调实时转发给客户端,**只推运行信息**(不推产物文件)。统一事件信封:
```json
{ "event_type":"agent.action", "deployment_id":"dep_xxx", "agent_id":"agi_x",
"phase":"development", "occurred_at":"2026-06-03T...", "payload":{ "...": "..." } }
```
事件类型(最小集):`agent.action`(某 agent 现在在干啥)、`tool.call`(调了什么工具)、`phase.changed`(阶段切换)、`log.line`(日志行,分 user/debug)、`delivery.pushed`(**产物就绪通知,payload 带 `git_ref`,不是文件**)、`status.changed`(display_status 变化)、`approval.required`(出现待审批)。
- **断线重连**:用 `Last-Event-ID`(基于 HM 事件游标)续传。
- **降级**:SSE 不可用自动回落轮询,UI 行为一致(只是延迟);未上线前 `/events/stream` 返回未实现,客户端按 `capabilities`/探测决定走哪条,**别硬连**。
## 5. 产物(代码只在 git;artifacts 仅非代码运行信息)
> **前提:sub 模式强制绑定 git 才能用**(未绑 git 只能本地跑,进不了 sub)。所以**代码产物的唯一归宿就是用户自己绑定的 git 仓库**。**没有"下载产物"这回事**(`project_folder`/manifest/files/archive zip 全部退役,见 5.4)。
### 5.1 代码产物 = git 仓库(唯一路径)🟡
`display_status=completed` 后,客户端直接对**用户自己绑定的仓库**(§8 资源绑定里的 `git` 类型)做 `git clone` / `git pull`,拿到完整工程 + 提交历史 + diff。本地改、重做、合并、部署都在工作副本上走标准 git,**不经 HM**——HM 不托管、不解析、不打包项目代码。
> 状态:AM 真正"git 入库 + 多 agent 分支 + 合并"为 🔴 待建;当前过渡实现见 spec §3.5。
### 5.2 交付引用 `git_ref`:客户端怎么知道去哪 pull 🔴
客户端**不需要自己猜分支**——HM 在任务详情 / `workflow` 里回带一个 `git_ref`,指明交付落在哪个仓库/分支/commit;客户端据此 `pull`:
```json
"git_ref": {
"provider": "github",
"repo_url": "https://github.com/owner/repo",
"branch": "delivery/dep_b5fab27e9255", // 交付分支(或 PR 源分支)
"commit_sha": "a1b2c3d…", // 本轮交付的提交
"tag": "delivery-dep_b5fab27e9255-rev2", // 可选:版本标签,便于回溯/指定版本部署
"pull_request_url": "https://github.com/owner/repo/pull/12", // 若走 PR 模式
"agent_branches": [ // 可选:各 agent 的分支,便于看单角色 diff
{"role":"backend","branch":"agent/backend"},
{"role":"frontend","branch":"agent/frontend"}
]
}
```
- `git_ref` 出现 = 本轮已 push 到用户仓库(配合 `display_status=completed`)。客户端 `git fetch && git checkout <branch>`(或 pull)即可。
- **重做/续跑**会更新 `commit_sha`(及可能新的 `branch`/`tag`);客户端 pull 最新即可。
- HM 只**记录并回带这个引用**,自己不执行任何 git 操作(git 由 AM 用注入的短期 PAT 执行,见 spec §7)。
- 状态:🔴 待建——需 AM 回调带 `git_ref`、HM 在 `workflow`/详情透出。当前过渡期 AM 还回 blob artifact(见 5.4)。
### 5.3 非代码产物 = artifacts 接口(运行信息,非下载交付物)🟡
agent_management 跑出的**非代码**东西(如 `test_report` 测试报告、`summary` 摘要、说明),通过 artifacts 列表给客户端在 work 视图里**查看**,**不是可下载的工程产物**:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `.../tasks/{task_id}/artifacts` | 非代码产物列表(test_report / summary 等运行信息记录) |
| GET | `.../artifacts/{artifact_id}/content` | 单条记录正文(如测试报告全文) |
`test_report` 只是给客户端/用户**看**,**不参与 HM 的 `display_status` 裁决**(HM 不读代码、不判对错,见 §4 / spec §6.6)。
### 5.4 遗留接口(已退役,新集成勿用)
早期「无 git 流程」里 runtime 只吐一坨 markdown 文本,HM 现解析成项目文件树(`project_folder` / `manifest` / `files?path=` / `archive` / `revisions` / `local-edits`)供浏览、下载、回传。**sub 强制 git 后这套全部退役**:看代码=git 工作副本,回传改动=`git commit/push`。后端实现暂保留(向后兼容),但**新集成不要依赖**,也不要再用 `is_project` / `display_artifact_type:"project_folder"` 判交付——交付以 `display_status=completed`(§4)+ `git_ref` 有新 commit 为准。
## 6. 修改 / 重做(基线 = git)🟡🔴
> **唯一基线 = 用户仓库的最新提交**。不存在 HM 侧 `local-edits`/revision 回传机制(已退役)。
| 动作 | 接口 | 谁干 | 状态 |
|---|---|---|---|
| **续跑/改**(路径 A,回云端) | `POST .../tasks/{id}/messages`(追加要求) | AM 先 `git pull` 取最新提交作基线 → 在其上改 → push;HM 转发 | 🟡 HM 转发已通;AM 中途续跑 🔴 |
| **重做** | `POST .../tasks/{id}/execute`(或将来 `/redo`) | AM 在**新分支**重新生成(旧交付分支保留可对比),回带新 `git_ref` | 🔴 待 AM 支持 redo 语义 |
| **本地改**(路径 B,回本地模式) | 客户端 `git pull` → 本地 agent 改 → `git push` | 客户端(模型仍走 HM `/v1/*`);想让云端接力就 push 后再 `/messages`,AM `pull` 自然拿到 | 🟡 |
| **停止** | `POST .../tasks/{id}/stop` / `DELETE .../tasks/{id}` | 已 commit 的代码**保留在分支不回滚**,任务标 `stopped`;可在该分支续跑或丢弃 | 🟢/🟡 |
`/messages` body:`{"message":"继续把测试补上","role":"user"}`。`/execute` body 可空。
## 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` 换取**短期凭据租约**(经加密通道返回,带 TTL + 审计)。
4. **客户端在用户机器上执行**:`git pull` 用户仓库 → ssh 到 VM → 跑部署命令 → 在 VM 上看日志。**全程 HM 不碰 VM。**
**凭据租约接口(🔴 待建,对齐 spec §3.8/§4.5):**
`POST /api/heicode/resources/{binding_id}/lease`(V2 加密 + 设备签名)
请求:`{ "purpose":"deploy", "target":"vm:rb_vm_xxx", "task_id":"dep_xxx", "ttl_seconds":600 }`
响应:
```json
{ "success": true, "data": {
"lease_id": "lease_xxx",
"binding_id": "rb_vm_xxx",
"credential": { "type":"ssh_key", "username":"deploy", "private_key":"<经 V2 通道明文,仅本次>" },
"expires_at": "2026-06-03T...Z", // 短 TTL
"revocable": true
}}
```
- 凭据**只在本次响应内**经 V2 加密通道下发,客户端**用完即弃、不落盘、不进日志**(§10)。
- **高危目标**(如生产 VM):HM 先建一条审批(`display_status=waiting_approval` / §3.2),**审批通过后才发租约**。
- 吊销:`DELETE /api/heicode/resources/leases/{lease_id}`,或用户删 binding → 已发租约到期自然失效。
- HM 只**发租约 + 记审计**(谁/哪条 binding/用途/时间/TTL,明文不入审计),**不代执行部署**。
> 旧的 `/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)。
**8.1 网页控制台接口(🟢 已用,`UserAuth` 会话鉴权)**
Manager 网页控制台「资源绑定」页已在用:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/api/resources/?status=active` | 列出已绑资源 |
| POST | `/api/resources/` | 建绑定(非密字段进 metadata,不含凭据) |
| POST | `/api/resources/{id}/secret` | 写凭据 → Key Vault,返回 `secret_ref` |
| DELETE | `/api/resources/{id}` | 解绑(吊销) |
建绑定示例(github):
```json
{ "name":"my-repo", "resource_type":"git", "provider":"github",
"external_id":"https://github.com/owner/repo",
"metadata":{ "repo_url":"https://github.com/owner/repo", "default_branch":"main",
"api_base":null, // gitea 自建需填 API 地址
"mode":"existing", // greenfield | existing
"allowed_paths":["backend/","frontend/"],
"permission_scope":"repo:write" } }
```
→ 再 `POST /{id}/secret {"data":{"token":"ghp_..."}}`(PAT 进 KV,库里只留 `secret_ref`)。
- **provider 由 `repo_url` 推断**:`github.com` → github API;其他 → gitea(需 `api_base`)。
- **凭据有效性预检**:HM 在用前对 git binding 做一次 `GET repo` 预检;失效则标 `status=invalid`,建任务/部署时报 `RESOURCE_BINDING_INVALID`,提示用户**重新绑定**,不静默失败。
- vm:`{resource_type:"vm",metadata:{host,port,user,auth:"ssh_key|password"}}`;database:`{engine,host,port,db}`;blob:`{account,container}`。secret 一律走 `/{id}/secret` 进 KV。
**8.2 客户端接口(🔴 待建,V2 设备签名)**
桌面客户端不走会话 cookie,需要一套 **V2 设备签名**版资源接口(与任务接口同一套加密/签名,§1):
| 方法 | 路径 | 说明 | 状态 |
|---|---|---|---|
| GET | `/api/heicode/resources?type=git&status=active` | 列已绑资源 → 让用户/任务选 `resource_binding_id` | 🔴 |
| GET | `/api/heicode/resources/{id}` | 单条详情(非密元数据 + status) | 🔴 |
| POST | `/api/heicode/resources` + `/{id}/secret` | 客户端内直接绑定(经 V2 加密传凭据) | 🔴 |
| DELETE | `/api/heicode/resources/{id}` | 解绑 | 🔴 |
| POST | `/api/heicode/resources/{id}/lease` | 取**短期凭据租约**(部署用,见 §7) | 🔴 |
> 这两层(网页 8.1 / 客户端 8.2)操作的是**同一份绑定数据**,只是鉴权方式不同。8.2 上线后客户端即可"列绑定 → 建任务时引用 → 部署时取租约"全闭环。**当前客户端可先用 8.1 的会话路径联调**,待 8.2 就绪切换。
## 9. Runtime 回调(仅 Runtime 用,客户端无需关心)
agent_management → HM 统一回调:`POST /api/agent/callbacks/runtime-events`。
Schema 查询:`GET /api/agent/callbacks/runtime-events/schema`。
## 10. 客户端生产约束
- 审批 approve/reject 必须调 HM,禁止本地伪造。
- 生产包禁用 mock 任务/审批/产物。
- 用 HM 的 `display_status` 判**进度/有无产物**;**代码对错客户端自己跑/测 + 用户 review**(见 §4)。
- 部署只在**用户确认后由客户端本地执行**;凭据凭 `resource_binding_id` 向 HM 取(§7),**不本地存明文凭据**。
- 普通用户文案不出现 `newapi`、上游厂商、模型网关字眼。
- 任务接口认证:写请求用 V2 加密 body + 设备签名,GET 用 V2 无 body 设备签名(见 §1),均复用模型调用同一套实现;base_url 来自 preset。
## 11. 错误码(新增)
| code | 场景 | retryable |
|---|---|---|
| `SUB_GIT_BINDING_REQUIRED` 🔴 | sub 建任务未带(或失效的)`resource_bindings.git`——强制绑 git(§3.1) | false |
| `RESOURCE_BINDING_INVALID` | `resource_binding_id` 不存在/非本人/预检失效(提示重新绑定,§8.1) | false |
| `LEASE_EXPIRED` 🔴 | 凭据租约已过期(重新取,§7) | true |
| `LEASE_REVOKED` 🔴 | 租约已被吊销/binding 已删 | false |
| `APPROVAL_REQUIRED` 🔴 | 高危部署需先过审批(`waiting_approval`,§3.2/§7) | false |
| `BUDGET_EXCEEDED` 🔴 | 任务超 token/时长/成本上限,已暂停待用户决定(spec §9.3) | false |
| `DEPLOY_TARGET_DISABLED` | 目标未启用 | false |
| ~~`ARTIFACT_REVISION_CONFLICT`~~ / ~~`ARTIFACT_ARCHIVE_NOT_READY`~~ / ~~`ARTIFACT_ARCHIVE_FAILED`~~ / ~~`FILE_NOT_FOUND`~~ / ~~`FILE_PATH_REQUIRED`~~ | **遗留**(local-edits/archive/files 已退役,见 §5.4/§6) | — |
其余错误码沿用旧文档 §13。所有错误统一形如 `{"success":false,"error":{"code","message","retryable"}}`,可读 `error.retryable` 决定是否重试。
## 12. 完整接口清单(按流程,覆盖核查)
> 以**真实路由**为准(`router/api-router.go`)。`sub-agile` 路径把前缀换 `swarm` 即同形。状态:🟢 已实现 / 🟡 部分 / 🔴 待建。
**① 启动与就绪(§2)**
| 接口 | 状态 | 章节 |
|---|---|---|
| `GET /api/heicode/capabilities` | 🟢 | §2 |
| `GET /api/user/self`、`/self/groups`、`/self/models` | 🟢 | §2.2 |
| sub 可用性组合判断(客户端本地) | 🟡 | §2.1 |
| 设备绑定 / 登录(`/api/heicode-auth/*`、`/api/user/...`) | 🟢 | 见 heicode-auth 文档 |
**② 建任务与对话(§3)**
| 接口 | 状态 |
|---|---|
| `POST /api/heicode/sub-agile/tasks`(需求包,含 resource_bindings、X-Idempotency-Key) | 🟢 建任务 / 🔴 强制 git 校验 + 幂等 |
| `GET .../tasks`、`GET .../tasks/{id}` | 🟢 |
| `POST .../tasks/{id}/messages`、`.../execute` | 🟢 |
| `POST .../tasks/{id}/stop`、`DELETE .../tasks/{id}` | 🟢 |
**③ 运行监控 / work 视图(§4)**
| 接口 | 状态 |
|---|---|
| `GET .../tasks/{id}/workflow`(含 git_ref、per-agent 富字段) | 🟢 本体 / 🔴 git_ref + per-agent 字段 |
| `GET .../tasks/{id}/logs`、`/timeline`、`/events`、`/metrics`、`/diagnostics`、`/sk-snapshots` | 🟢 |
| `GET .../tasks/{id}/events/stream`(SSE) | 🔴 §4b |
**④ 审批(§3.2)**
| 接口 | 状态 |
|---|---|
| `GET .../tasks/{id}/approvals?status=pending` | 🟢 |
| `POST .../approvals/{approval_id}/approve`、`/reject` | 🟢 |
**⑤ 产物(§5)**
| 接口 | 状态 |
|---|---|
| `git_ref`(在 workflow/详情里)→ 客户端 `git clone/pull` | 🔴 |
| `GET .../tasks/{id}/artifacts`、`.../artifacts/{aid}/content`(仅非代码运行信息) | 🟢 |
| ~~`.../artifacts/{aid}/{manifest,files,archive,revisions,local-edits}`~~ | 退役(§5.4) |
**⑥ 修改 / 重做(§6)**:复用 ②的 `messages`/`execute`(+ 将来 `/redo` 🔴);本地改走 git。
**⑦ 部署(§7)**
| 接口 | 状态 |
|---|---|
| `POST /api/heicode/resources/{id}/lease`(短期凭据租约) | 🔴 |
| `DELETE /api/heicode/resources/leases/{lease_id}`(吊销) | 🔴 |
| ~~`GET /api/heicode/deployment-targets`、`POST/GET .../tasks/{id}/deployments`~~ | 废弃(旧代部署) |
**⑧ 资源绑定(§8)**
| 接口 | 状态 |
|---|---|
| `GET/POST /api/resources/`、`POST /{id}/secret`、`PUT/DELETE /{id}`(会话鉴权,网页台) | 🟢 §8.1 |
| `GET/POST/DELETE /api/heicode/resources*`、`/{id}/lease`(V2 设备签名,客户端) | 🔴 §8.2 |
> 凡标 🔴 的,客户端**按本文契约预埋字段**即可;HM 侧补齐后无需改协议直接对齐。本清单即"整个流程要用到的接口"的核查表——发现遗漏请回填本表对应分组。
@@ -2,7 +2,7 @@
> 更新时间:2026-06-03
> 范围:**HM 端**(后端 + 网页控制台)在「模板 agent + 客户端直连」新模型下的改造清单。
> 关联文档:`heicode-sub-mode-flow-spec.md`、`heicode-desktop-unified-api.md`(这两份的旧「sub 任务编排」内容将按本文裁剪)。
> 关联文档:客户端对接见 `heicode-desktop-client-api.md`;旧代码清理见 `heicode-hm-legacy-teardown.md`。(旧的「sub 任务编排」设计文档 heicode-sub-mode-flow-spec.md / heicode-desktop-unified-api.md 等已删除。)
---
@@ -1,487 +0,0 @@
# Heicode Sub 模式 端到端流程与三端规范(v0.1 草案)
> **2026-06-03 产物模型钉死(最重要的认知)**:
> - **sub 模式强制绑定 git** 才能用(未绑 git 只能走客户端本地模式,进不了 sub)。
> - **最终产物只存在于用户自己的 git 仓库**。**没有"下载产物"这回事**——不存在 `project_folder` / `manifest` / `files` / `archive` zip / `local-edits` 回传这一整套(已全部退役)。要代码就 `git clone/pull`。
> - **运行期间 HM 流式给客户端的,只有"运行信息"**:日志(user_logs/debug_logs)、状态(display_status + 三层状态)、work 视图杂项(每个 agent 在做什么、跑了什么工具、改了哪些文件、阶段进度、测试输出等)。这些是**给人看的过程信息,不是可下载交付物**。
> - HM 眼里的 "artifact" 退化成**交付/完成记录**(带 `git_ref`、改了哪些文件、`source_agent_role` 等元数据),仅用于 ① `display_status` 的"有无真交付"防空壳核对、② 在 work 视图里展示;**客户端不从 HM 下载任何产物文件**。
>
> 更新时间:2026-06-03(产物模型对齐)/ 2026-06-02(初稿)
> 范围:**Sub(普通子代理协作)模式**——桌面客户端(一个像 Claude Code 的智能体程序)把一个**多 agent 重活外包到云端 agent_management**:客户端发起 → 经 Heicode Manager(模型网关 + 控制面)→ agent_management 多 agent 并行执行 → 流式回客户端展示的**完整闭环**,含资源绑定、git 仓库、产物合并、修改/重做、部署。
> 前提认知(**务必先读 §0**):客户端本身能本地跑 agent;**sub 模式是把大任务派到云端,不是客户端唯一的干活方式**;**模型统一由 HM 的 `/v1/*` 提供给客户端和 AM 两边**。
> 目的:**统筹三端(桌面客户端 / Heicode Manager / agent_management)的颗粒度与理解**,作为三方共同对齐的权威流程文档与契约规范。
> 性质:本文是**目标设计** + **现状标注**。每节用标记区分:
> - 🟢 **已实现**(当前代码/线上已具备)
> - 🟡 **部分实现**(有基础,缺字段/流式/打通)
> - 🔴 **待建**(目标态,尚未实现)
> - ❓ **待决策**(需产品/三端确认的设计点,附我的建议)
相关文档:客户端对接接口见 [`heicode-desktop-unified-api.md`](./heicode-desktop-unified-api.md);runtime 契约见 agent_management《Sub Mode Runtime 对接指南》。
---
## 0. 术语与三端角色(先把名字钉死,避免歧义)
> ⚠️ **名字钉死**:本文用 **HM** = Heicode Manager(那个 Go 网关),用 **AM** = agent_management(就是你口中的「Agent Manager / Sub Mode Runtime」)。两者**完全是两个不同的服务**,本文不再用模糊的「Manager」一词。三方按下表对号入座。
| 简称 | 全名 | 是什么 | 栈 |
|---|---|---|---|
| **客户端** | 桌面客户端 cc-haha / Desktop | **像 Claude Code 那样的智能体编程程序**:本地自己能跑 agent、写代码、执行命令。用模型时**调 HM 的模型接口** | TS(Tauri+React/CLI) |
| **HM** | **Heicode Manager** | **① 模型调用网关(new-api)**——给「客户端」和「AM」**两边都提供模型调用接口 `/v1/*`**(鉴权/计费/路由都在这);**② 控制面 / 状态裁判 / 凭据中介**。HM 自己不跑 agent、不执行命令、不连 VM | Go(Gin/GORM) |
| **AM** | **agent_management**(= 你说的 Agent Manager / Sub Mode Runtime,在 `20.212.121.126`) | **云端多 agent 运行时**:把任务拆成多 agent 并行干活、写代码、git 入库;这些 agent **也是调 HM 的模型接口 `/v1/*`** 来用模型 | 独立服务 |
> **「AI」从哪来**:AI = 模型。**模型统一由 HM 的 `/v1/*` 提供**。**智能体执行(跑 agent)发生在两处**:本地(桌面客户端,像 Claude Code)和云端(AM,sub 模式多 agent)。两边都**通过 HM 调模型**。HM 是大家共用的**模型网关**,自己不当 agent。
### 0.1 关键能力边界(谁跑 agent / 谁提供模型 / 谁执行命令)
| 能力 | 客户端 | **HM** | **AM** |
|---|---|---|---|
| 智能体程序 / 跑 agent | ✅ 本地跑(像 Claude Code) | ❌ 不跑 agent | ✅ 云端跑多 agent |
| **提供模型调用接口 `/v1/*`** | ❌(是调用方) | ✅ **是模型网关,给客户端和 AM 都提供** | ❌(是调用方) |
| 调模型 | ✅ 调 HM `/v1/*` | —(被调方) | ✅ 调 HM `/v1/*` |
| 本地执行命令 / 部署 / 看 VM 日志 | ✅ 在用户机器上执行(像 Claude Code) | **❌ 从不执行、不连 VM** | ❌(AM 在自己沙箱产代码,不部署用户 VM) |
| 解密验签 / 鉴权 / 计费 | ❌ | ✅ | ❌ |
| 裁决 display_status | ❌ | ✅ **唯一裁判** | ❌(只报执行事实) |
| 托管凭据(KV)/ 发短期凭据 | ❌ | ✅ | ❌ |
> **澄清几个之前易错的点**:
> - **HM 不部署、不执行命令、不连 VM、不看 VM 日志**——它是模型网关 + 控制面,不是执行器。
> - **部署到用户 VM + 在 VM 看日志 = 客户端**自己在用户机器上干(像 Claude Code 本地执行;用户确认后 HM 只把短期凭据加密发给客户端)。
> - **sub 模式 = 把多 agent 任务派到云端 AM 跑**(区别于客户端本地自己跑一个小任务);AM 的 agent 调 HM 用模型,流式回 HM,HM 裁决后回客户端。
### 0.2 sub 模式是什么、什么时候用(既然客户端本地就能跑 agent)
> 关键澄清:客户端本身能在**本地**跑智能体(像 Claude Code)完成小/快任务。那为什么还要 sub?
- **本地模式**(客户端自己):在用户机器上跑单个/轻量 agent,适合小改动、即时、交互式。**计算在用户机器上**。
- **sub 模式**(本文主题):客户端把一个**更大的、需要多 agent 并行协作、或希望云端异步跑(关掉电脑也继续)**的任务,**派发到云端 AM** 执行。**计算在云端 AM**,多 agent 并行(backend/frontend/reviewer 同时干)。
- **两种模式的模型都走 HM `/v1/*`**,鉴权 + 计费统一在 HM。
- **sub 模式下客户端的角色** = **发起任务 + 实时看 work + 本地看/改产物 + 本地执行部署**;真正的 codegen 多 agent 在云端 AM。客户端不在 sub 模式里本地跑 codegen agent(那是本地模式)。
> 一句话:**sub = 把多 agent 重活外包到云端 AM;客户端当指挥台 + 取货 + 本地部署。本地模式 = 客户端自己干小活。模型两边都问 HM 要。**
### 0.3 三端铁律
1. 客户端**任务/控制走 HM**(`/api/heicode/*`、`/api/agent/*`),模型走 HM(`/v1/*`),**禁止直连 AM** / Runtime artifact。
2. **HM 是唯一状态裁判**,客户端只消费 `display_status`(定义见 §6)。
3. 凭据只进 **Azure Key Vault**,全链路只传/存 `secret_ref`,明文绝不落库/日志/回调。
4. **HM 不执行任何命令、不部署、不连 VM、不跑 agent**;agent 执行在云端 AM(sub 任务期)或客户端本地(本地模式 / 部署期)。模型由 HM 提供给两边。
---
## 1. 端到端总体流程(时序)
```text
┌── 桌面客户端 ──┐ ┌──── Heicode Manager ────┐ ┌── agent_management ──┐
│ │ │ │ │ │
│ 0 选 sub 模式 │ │ │ │ │
│ 0.5 (可选)绑 git/vm/db ─┼─► 资源绑定→Key Vault │ │ │
│ │ V2加密 │ 存 secret_ref │ │ │
│ 1 填需求包 ────┼───────►│ 2 解密+验签+鉴权+配额 │ │ │
│ │ │ 3 需求包→orchestration ├──────► │ 4 拆分多 agent │
│ │ │ _plan + 注入资源授权 │ HMAC │ 分配角色/模型 │
│ │ │ │ │ 5 各 agent 干活: │
│ │ │ │ ◄──────┤ 流式回调状态/日志/ │
│ 7 轮询/订阅 ◄──┼────────┤ 6 收敛三层状态+运行信息 │ callback│ 状态/日志/work + │
│ 展示 work(只有 │ │ 裁决 display_status │ │ git 入库 + push │
│ 日志/状态/work)│ │ (只转发运行信息) │ │ 8 各 agent 代码→分支 │
│ │ │ │ │ 9 合并→交付分支(git) │
│ 10 看产物 ─────┼──git──► (直接 git clone/pull 用户 │ ◄──────┤ push 用户仓库 + │
│ 只走 git │ 自己的仓库; 不经 HM) │ git_ref │ 回调 git_ref 通知 HM │
│ 11 不满意 ─────┼───────►│ /messages | /execute ├──────► │ 12 修改/重做(git) │
│ │ │ │ │ │
│ 13 本地 git │ ◄─git── (pull/改/push, 不经 HM) │ │ │
│ 14 部署 VM ────┼───────►│ 取凭据(加密) → 客户端执行│ │ │
└────────────────┘ └──────────────────────────┘ └──────────────────────┘
```
---
## 2. 三端颗粒度契约(一图看清谁给谁什么)
> 表头里 **HM = Heicode Manager**,**AM = agent_management**。
| 数据/动作 | 客户端 → **HM** | **HM → AM** | **AM → HM**(回调) | **HM → 客户端** |
|---|---|---|---|---|
| 建任务 | 需求包(objective/context/约束/验收/模型选择/角色) | orchestration_plan + 资源授权 grants | deployment_id/swarm_id | deployment_id(=task_id) + display_status |
| 运行状态 | — | — | `status`+`runtime_execution_status`+`phase` | **`display_status`**(裁决后) |
| 日志/work | — | — | 事件流(task./agent./phase./handoff./artifact.) | `user_logs`+`debug_logs` / work 视图(**只有运行信息**) |
| 每 agent 指标 | — | — | 🔴 per-agent tokens/tools/elapsed | workflow.agents[].* |
| 代码产物 | — | — | **git push + 回调 `git_ref`**(commit/分支/改了哪些文件 + `source_agent_role`,仅元数据) | **git_ref(让客户端去 git pull)**——HM 不提供产物文件下载 |
| 修改/重做 | message / execute | 续跑/重做指令 | 新 commit + git_ref + 状态 | 新 display_status + 新 git_ref |
| 凭据 | 只传 `resource_binding_id` | 注入 `secret_ref`(azkv://) | — | 只回 secret_ref(打码) |
> ⚠️ **上表只画了「任务控制面」。还有一条独立的并行通道——模型调用:**
> - **客户端 → HM `/v1/*`**(客户端本地 agent 用模型)
> - **AM → HM `/v1/*`**(AM 的 agent 用模型)
> 两边用**同一套模型接口**,HM 统一做鉴权 + 计费 + 路由。模型调用与上面的任务控制面是**两条不同的通道**,别混在一起。
---
## 3. 阶段详解
### 3.0 完整执行流程(逐步,明确每一步谁做什么)
> 全程三个主体:**客户端**(像 Claude Code 的智能体程序)、**HM**(模型网关 + 控制面,不跑 agent、不执行命令)、**AM**(云端多 agent 运行时)。**客户端和 AM 的 agent 用模型时都调 HM 的 `/v1/*`。**
**A. 准备(一次性)**
1. 用户在**客户端**绑定自己的 **git 仓库**(github/gitea URL + 一个 PAT)。客户端经 V2 加密把 PAT 发给 **HM** → **HM** 把 PAT 写进 **Key Vault**,库里只留 `secret_ref`,返回一个 `resource_binding_id`。
2. (需要部署时)同样绑定 **VM**(host + ssh key)、数据库、blob,凭据进 KV,各得一个 `resource_binding_id`。
**B. 发起任务**
3. 用户在**客户端**选 `sub` 模式、填**需求包**(目标/约束/验收/角色/模型/要用哪条 `resource_binding_id`)。
4. **客户端** → `POST /api/heicode/sub-agile/tasks`(V2 加密 body + 设备签名)。
5. **HM**:解密 → 验签 → 鉴权 → 查配额 → 把需求包译成 `orchestration_plan`,**从 KV 取出 git 凭据注入**(短期 token),落库,返回 `deployment_id`(= task_id)。**HM 不写代码、不跑 agent。**
**C. 执行(AM 干活,HM 中转)**
6. **HM** → `POST /api/agent/sub-agile/deployments`(给 **AM**),带:需求、角色/模型、回调地址、HMAC 签名密钥、**git 仓库 + 短期凭据**。
7. **AM**:把需求拆成多个 **agent**(如 backend / frontend / reviewer),各自分配模型,开始干活。**每个 agent 用模型时调 HM 的 `/v1/*`(和桌面客户端用同一套模型接口)。**
8. **AM** 的每个 agent:clone 用户仓库 → 在自己分支(`agent/<role>`)写代码、跑工具/测试(调 HM `/v1/*` 用模型)→ **commit & push 到用户仓库**(用第 5/6 步注入的短期 PAT)。
9. **AM** 持续把「每个 agent 在做什么 / 跑了什么工具 / 改了哪些文件 / 当前阶段 / 产物」**流式回调**给 **HM**(HMAC 签名):`POST /api/agent/callbacks/runtime-events`。
10. **HM** 收回调 → 聚合事件 + **裁决 `display_status`**(见 §6)+ 持久化。
**D. 客户端看 work**
11. **客户端**轮询 `GET .../tasks/{id}/workflow`(运行中 3–5s;将来 SSE)→ 拿 `display_status` + 各 agent 状态/动作 + 阶段 + 产物列表,渲染成「work 视图」(参考 Claude Code)。
**E. 合并与产物**
12. **AM** 阶段结束 → 把各 agent 分支**合并**成一个交付分支(`delivery/<task_id>` 或 PR)→ push 到用户仓库 → 回调通知 **HM** 产物就绪(带 `git_ref` + artifact)。
13. **客户端**看产物:直接 `git clone/pull` 用户自己的仓库(完整工程 + 历史 + diff)。**只此一条路**——产物在 git,HM 不托管/不打包/不提供产物文件下载;HM 给的只是 `git_ref`(告诉客户端去哪个仓库/分支/commit pull)。
**F. 不满意 → 改 / 重做**
14. **客户端** → `POST .../messages`(追加要求)或 `.../execute`(重跑)→ **HM** 取最新 accepted 基线转给 **AM** → **AM** 在原产物上改/重做 → 回到第 9 步。
**G. 部署(客户端执行 + 用户确认;HM 只发凭据)**
15. **客户端**发起部署 → **弹窗让用户确认**(目标 VM / 环境 / 用哪条 binding / 影响)。
16. 用户确认 → **客户端**向 **HM** 换**短期凭据租约**(HM 从 KV 解出 VM ssh key,经 V2 加密发回客户端,带 TTL)。
17. **客户端在用户自己机器上执行**部署:`git pull` 用户仓库 → ssh 到 VM → 跑部署命令 → **在 VM 上看日志**。**HM 全程不碰 VM、不执行命令、不看日志**;**HM 只记审计**(谁、哪条 binding、何时、TTL)。
> 一句话区分执行位:**写代码 = AM 沙箱里执行;部署到用户 VM + 看 VM 日志 = 客户端在用户机器上执行;HM 永远只做网关/裁判/凭据中介,不执行任何东西。**
---
### 3.1 选择 sub + 准备(资源绑定前置)
🟢 客户端选 `mode=sub_agile`(区别于 `swarm`)。
✅ **决策(2026-06-02)**:**git 仓库 = 用户绑定自己的仓库**(gitea / github,用户提供 URL)。**没有 Heicode 托管仓库**。
✅ **决策(2026-06-03)**:**sub 模式强制绑定 git**——未绑仓库则**不能进 sub**(UI 上禁用 sub,引导用户先绑 git 或改用客户端本地模式)。**不再有"未绑仓库走仅产物轻量路径"这种东西**(`project_folder`/manifest/files/archive 已退役)。代码产物的唯一归宿就是用户绑定的 git 仓库(§4.1):agent 在此入库/合并,客户端 `git clone/pull` 看产物。
### 3.2 客户端 → HM(加密 + 鉴权 + 建任务)
🟢 **加密链路**:与模型调用完全一致。
- 写请求(POST/PUT/DELETE):`Content-Encoding: heicode-aead-v1`,X25519-ECDH + HKDF + ChaCha20-Poly1305 加密 body,Ed25519 设备签名(`X-Heicode-*`)。
- GET:无 body 设备签名(同 canonical,body 哈希为空串哈希)。
- HM 中间件 `UserOrV2DeviceAuth` 解密 + 验签 + 从设备绑定 token 解析用户身份。
🟢 **鉴权/配额**:解析 user_id、绑定 scope、计费上下文。
🟢 **建任务**:`POST /api/heicode/sub-agile/tasks`,body = **需求包**(见客户端接口文档 §3.1),HM 译成 `orchestration_plan` 并落库,返回 `deployment_id`(= task_id)。
### 3.3 HM → agent_management(分发)
🟢 `POST /api/agent/sub-agile/deployments`(env 当前指向 `http://20.212.121.126`),Bearer service token。
🟢 注入:callback URL(`/api/agent/callbacks/runtime-events`)+ HMAC 签名密钥引用 + metadata.manager_deployment_id + 角色/模型 + **资源授权 grants(secret_ref,不含明文)**。
🟡 **回调竞态**:AM 回调可能早于 HM 存 runtime_id → HM 用「读时收敛」(`reconcileDeploymentFromRuntime`) 兜底(已实现)。
### 3.4 多 agent 执行 + 流式回传(work 视图,参考 Claude Code)
🟡 **现状**:AM 通过回调上报 `deployment.status_changed / task.* / handoff.* / artifact.created / phase.changed` 等事件;HM 聚合成 timeline/events/logs;客户端**轮询**展示。
🔴 **目标(work 视图)**:像 Claude Code 的 work 面板那样**实时流式**展示「每个 agent 正在做什么、跑了哪些工具、产了哪些文件、各阶段进度」。需要补:
1. 🔴 **流式协议**:HM 提供 `GET .../tasks/{id}/events/stream`(SSE)或 WS,把 AM 回调实时转发给客户端。**现状无 SSE**,客户端轮询 `/workflow`(3–5s)兜底(见 §5)。
2. 🔴 **per-agent 富字段**:AM 在状态/回调里上报每个 agent 的 `tokens / tools(工具调用数) / elapsed_seconds / 当前动作描述 / artifact_ids`。HM 的 `/workflow` 已预留这些字段(缺值时为 0/空),等 AM 填。
3. 🔴 **artifact 来源角色**:AM 给 artifact 打 `source_agent_role`,HM 才能把产物准确归到对应 agent。
4. 🔴 **阶段细分**:runtime 上报 `phases[]`(每阶段 status/agents),而非单个 `phase` 字符串。
> work 视图的最小可用版(不等 SSE):客户端轮询 `/workflow` 拿 `agents[] + phases[] + metrics`,3–5s 刷新即可先跑起来;SSE 是体验升级项。
### 3.5 代码入 git + 多 agent 产物合并
🔴 **目标**:每个 agent 把自己产的代码 **commit 到 git 仓库的独立分支**(如 `agent/backend`、`agent/frontend`),最后 **合并成一个完整产物**(merge 到 `main` 或一个交付分支)。
❓ **关键决策(§7 详述)**:
- 仓库在哪?(Heicode 托管 vs 用户绑定的 git)
- 谁负责合并?(agent_management 合并后给一个最终分支/commit;HM 不碰 git 操作,只记录引用)
- 合并策略?(按目录隔离自然无冲突:backend/ + frontend/ 并列;同文件冲突由一个「集成 agent」或规则解决)
🟡 **现状**:sub 模式 AM 当前还是把产物当 blob/文本 artifact 回传(每角色一个,多角色=多个),**尚未真正 git 入库 + 合并**——这是**待迁移的旧实现**,不是目标态。目标态(本节)是 AM 全程在用户 git 仓库里 commit/合并,产物只在 git。客户端不再"拼 manifest 展示产物"。
### 3.6 产物查看(只走 git)
🔴 **唯一路径 = git**:sub 完成后客户端直接 `git clone/pull` 用户自己绑定的仓库,看完整工程 + 提交历史 + diff。HM 给的只是 `git_ref`(repo/branch/commit),告诉客户端去哪 pull。
> **退役**:旧的「经 HM 看产物」(`/artifacts`→`/manifest`→`/files?path=`→`/archive`)是无 git 流程的残留,**sub 强制 git 后不再使用**。HM 在运行期只向客户端流式推**运行信息**(日志/状态/work,见 §5),**不提供产物文件的浏览或下载**。HM 的 `/artifacts` 接口若保留,只列**非代码的运行信息记录**(如 `test_report` 测试报告、摘要),供 work 视图展示,**不是可下载交付物**。
### 3.7 不满意 → 修改 / 重做(**两条路:云端改 或 本地改**)
> 因为客户端本身是智能体程序(像 Claude Code),迭代有**两条等价路径**,用户按场景选:
> **基线就是 git**:两条路都以**用户仓库的最新提交**为唯一基线,不存在 HM 侧的 `local-edits`/revision 回传机制(已退役)。本地改完 `git push`,云端续跑前 `git pull`,冲突/历史/diff 全交给 git。
**路径 A — 回云端 AM 改(继续 sub)**
- 🟡 **修改(续跑)**:`POST .../tasks/{id}/messages`(追加要求)→ HM 转给 AM → AM 先 `git pull` 取用户仓库最新提交作基线 → 在其上改 → 再 push。(AM 真正「中途续跑」🔴待支持)
- 🔴 **重做**:`POST .../tasks/{id}/execute`(或新增 `/redo`)→ AM 在新分支上重新生成(旧交付分支保留可对比)。需 AM 支持「redo」语义。
**路径 B — 拉到本地用客户端自己的 agent 改(回到本地模式)**
- 🟢/🔴 客户端 `git pull` 用户仓库 → 用**客户端本地 agent**(像 Claude Code,模型仍走 HM `/v1/*`)在本地改 → `git push` 回仓库。**不必每次回云端**,适合小修小补。
- 改完想让云端接力:直接 push 后再 `/messages`,AM `git pull` 自然拿到本地改动——**无需任何 HM 回传接口**。
### 3.8 部署(✅ 必须客户端执行 + 必须用户确认)
✅ **决策(2026-06-02)**:**部署绝对走客户端,且必须用户显式确认才执行**。HM 不自动部署、AM 不自动部署。
- 流程:客户端发起部署 → **弹用户确认**(目标/环境/影响) → 用户确认 → 客户端向 HM 的**加密密钥接口**换取**短期凭据租约**(VM SSH key / git PAT 等从 KV 解出,经 V2 加密通道回客户端,带 TTL) → **客户端本地执行**(git pull 用户仓库 → push/部署到 VM,或连库迁移)。
- HM 角色:**只发短期凭据 + 记审计**(谁、哪条 binding、何时、TTL),不代执行。
- 凭据租约:短 TTL、可吊销、用完即弃;高危目标(如生产)可叠加**审批门**(waiting_approval)后再发租约。
🟡 **现状**:有云部署控制面占位(`/deployments`,返回 `executor:pending_worker`);凭据租约模型(approval→lease)有骨架。🔴 待建:客户端取凭据的加密接口 + 客户端本地执行器。
---
## 4. 资源绑定规范(git / vm / database / blob → Key Vault)
> 🔴 **前置硬卡点**:Azure Key Vault 当前**托管身份取 token 400、不可达**。资源绑定的核心是「凭据进 KV、只存 secret_ref」,**KV 不通则整个功能不可用**。必须先由运维给 VM 托管身份在目标 KV 授 `Key Vault Secrets Officer` 角色(Phase 0)。
### 4.0 通用模型
每个资源绑定 = `{ resource_binding_id, type, name, metadata(非敏感), secret_ref(azkv://…), permission_scope, binding_scope(租户/工作区), status }`。
- 客户端**只传 `resource_binding_id`** 给任务;HM 内部解析为凭据注入 AM。
- 客户端**禁止 inline** secret_ref / AccessKey / 连接串。
- 凭据录入**一次性**:客户端经 V2 加密通道把凭据传给 HM → HM 写 KV → 库里只留 `azkv://`。
### 4.1 Git 仓库绑定 ✅(已定方向)
**模型**:**用户绑定自己的仓库**(gitea / github,用户提供 URL)。agent 在此仓库读写代码、git 入库、合并;客户端 clone/pull 看产物;后续从此仓库 git 到 VM 部署。
| 项 | 方案(已定 / 建议) |
|---|---|
| **仓库归属** | ✅ **用户自己的仓库**。用户提供 `repo_url`(github.com/... 或自建 gitea URL)。无 Heicode 托管仓库。 |
| **绑定鉴权(用户输入密钥)** | ✅ **HTTPS + 细粒度 PAT(个人访问令牌)为主**——github 与 gitea **通用**、用户只需粘贴一个 token、可按仓库范围授权、可随时吊销、不暴露账号密码。流程:用户在自己 git 生成范围化 PAT(建议 `repo` 读写)→ 客户端经 V2 加密通道把 PAT 传 HM → HM 写 KV,库里只留 `secret_ref`。**备选**:SSH deploy key(用户把 HM 出示的公钥加到仓库 Deploy keys;适合不愿发 PAT 的场景)。 |
| **provider 识别** | 由 `repo_url` 推断(github.com → github API;其他 → gitea,需带 `api_base`)。metadata:`provider / repo_url / default_branch / api_base?`。 |
| **绑定粒度** | 单仓库级(一个 binding = 一个 repo + 默认分支 + 允许路径 allowed_paths)。permission_scope:`repo:read` / `repo:write`。 |
| **凭据有效性/过期** | PAT 会过期/被吊销 → HM 在用前**预检**(一次 `GET repo`),失效则标记 binding `status=invalid` 并提示用户**重新绑定**,不静默失败。 |
| **工单 / 里程碑** | **可选增强**(默认关,用户显式开):把 sub 子任务映射为 **issues**、阶段映射为 **milestone**、handoff/审批映射为 **issue 评论**,让用户在自己 git 看板跟踪 agent 进度。需要 PAT 额外授 issues 权限。 |
| **分支模型 / 合并** | 见 §7。 |
### 4.2 VM 连接绑定 🔴
`type=vm`,metadata:host/port/user/连接方式(ssh key / 密码);secret 进 KV。用于部署/运维。高危,建议绑定时声明用途 + 部署需审批。
### 4.3 数据库绑定 🔴
`type=database`,metadata:引擎/host/port/db 名;连接串/密码进 KV。用于 agent 生成需要连库的代码或迁移。
### 4.4 Blob 存储绑定 🔴
`type=blob`,metadata:账号/容器;key/SAS 进 KV。用于大产物/数据集存取。
### 4.5 凭据生命周期
- 录入 → KV(HM 写)→ 只存 secret_ref。
- 使用 → 任务/部署时 HM 从 KV 解出注入 AM,或发**短期租约**(TTL + 可吊销)给客户端。
- 审计 → 谁在什么 scope 用了哪条绑定、发了哪些租约、何时吊销(只记 secret_ref + 打码摘要)。
---
## 5. 流式协议规范(work 视图)
| 阶段 | 协议 | 状态 |
|---|---|---|
| 现状 | 客户端轮询 `GET .../workflow`(运行中 3–5s、终态 15–30s) | 🟢 |
| 目标 | `GET .../tasks/{id}/events/stream`(SSE):HM 把 AM 回调实时转发;事件含 `agent.action / tool.call / phase.changed / log.line / delivery.pushed`(产物就绪=带 `git_ref` 的通知,**不是文件**) | 🔴 |
**规范**:
- SSE event 统一信封:`{ event_type, deployment_id, agent_id?, phase?, occurred_at, payload }`。
- 客户端断线重连用 `Last-Event-ID`(基于 HM 的事件游标)。
- **降级**:SSE 不可用时自动回落轮询,UI 行为一致(只是延迟)。
- 客户端**不要**订阅不存在的流(未上线前 `/events/stream` 返回未实现,别硬连)。
---
## 6. 状态模型与 `display_status` 裁决(完整定义,给三方)
🟢 已实现。**这是全文最关键的概念之一,三方必须一致理解。**
### 6.1 HM 只做"事实透传 + 防空壳",**不判断代码对错**
- **AM 只上报执行事实**(`completed` 只代表"我跑完了")。
- **HM 没 AI、不读代码、不跑代码、不编译、不测试。** 所以 **HM 不判断"代码对不对、有没有效"**——那不是 HM 能做、也不该做的事。
- HM 的 `display_status` 只做两件事:**① 忠实透传 AM 的执行状态**;**② 防"空壳/兜底假成功"**——AM 说 `completed` 时,HM 顺手核对一下"**到底有没有产物**"(这是**事实层面**的核对:有/无、是不是兜底占位,**不是质量判断**)。
- **真正"对不对、有没有效"由客户端 + 用户判断**(见 §6.6):客户端是 Claude-Code 式程序,**能把产物/git 拉下来自己跑、自己测、看 diff**,用户 review 拍板。
- 客户端只看 `display_status` 决定**"这轮跑完了没、是不是空交付"**;**"代码好不好"客户端自己看产物。**
### 6.2 三层状态(`GET .../tasks/{id}/workflow` 同时返回)
| 字段 | 含义 | 谁产生 |
|---|---|---|
| `cloud_deployment_status` | HM 控制面状态(accepted/running/stopped…) | HM |
| `runtime_execution_status` | **AM 上报的原始执行状态**(AM 说它自己到哪了) | AM |
| **`display_status`** | **HM 裁决后、给用户展示的唯一状态** | **HM** |
### 6.3 `display_status` 的全部取值(枚举)
| 值 | 含义 | 客户端该怎么展示 |
|---|---|---|
| `accepted` | 已受理,排队中 | 进行中(灰/黄) |
| `running` | 正在执行 | 进行中(蓝,转圈) |
| `waiting_approval` | 等用户审批高风险操作 | 黄,弹审批 |
| `completed` | **完成,且有真实可交付的代码产物** | **绿,成功** |
| `needs_codegen` | AM 说完成了,但**只产了方案/总结、没有真实代码** → 需继续生成 | 黄,提示"需补充代码/继续" |
| `completed_without_deliverable` | AM 说完成了,但**完全没有产物** | 红/橙,**视为没成功** |
| `failed` | 执行失败 | 红,失败 |
| `stopped` | 被用户/系统停止 | 灰,已停止 |
### 6.4 裁决算法(HM 收到 AM 状态后怎么算 `display_status`)
```text
输入: AM 的 runtime_status, 该任务的 artifacts 列表
规则:
if runtime_status 不是 "completed":
display_status = runtime_status 原样透传
(running / waiting_approval / failed / stopped / accepted ...)
else # AM 说 completed,进入"是否真有交付物"的裁决
遍历该任务的 artifacts:
只要存在 1 个"真实交付物" → display_status = "completed" ✅
否则 if 有 artifacts 但全是总结/兜底 → display_status = "needs_codegen"
否则 (一个 artifact 都没有) → display_status = "completed_without_deliverable"
```
**"真实交付物"的判定**(逐条排除"假产物"):AM 回报的交付记录满足以下**才算真实**——
- **目标态(git)**:回调带 **`git_ref`**(repo/branch/commit_sha)且有**真实提交**(commit 数 > 0 / 改了 N 个文件) → 真交付。HM 据此判"有没有真东西",**不下载、不读代码内容**。
- `metadata.synthesized != true`(不是 AM 的兜底占位记录),**且**
- 不是纯总结类(标题/正文不含 "runtime execution summary"、"without per-agent artifacts" 等兜底标记;不是 `document`/`summary` 类)。
- 兼容旧实现:在 AM 尚未 git 化前,带"改了 N 个文件"结构化信号的 `code_patch`/`diff` 记录也按真交付算(过渡期)。
> 注意:HM 判的是**"有没有真提交"这个事实**(防空壳),**不是判代码对不对**(§6.6)。`git_ref` 是元数据,不是可下载产物。
> 一句话:**`completed` 必须"AM 说完成 + 真的有代码产物"两个条件都满足;只有总结没代码 = `needs_codegen`;啥都没有 = `completed_without_deliverable`。客户端据此就能准确区分成败,不会被假成功骗到。**
### 6.5 成功判据(客户端用)
> **`display_status == "completed"` 且 artifacts 非空 = 真成功**;其余都不是成功(各有不同处理)。
### 6.6 ⚠️ "对不对/有没有效"归谁判 —— **客户端 + 用户,不是 HM**(三方必读)
| 谁 | 判什么 | 怎么判 |
|---|---|---|
| **HM** | 只判**事实**:这轮跑完没?有没有产物?是不是空壳/兜底? | 看 AM 状态 + artifact 有无(**不读代码、不编译、不测试、不判对错**) |
| **客户端**(Claude-Code 式) | 判**代码对不对、能不能跑、是不是要的** | **把产物/git 拉到本地,自己跑、自己测、看 diff**;有问题就本地改或回云端改 |
| **用户** | **终裁**:满不满意、收不收货 | 在客户端 review 产物,满意才算真完;不满意 → 改/重做(§3.7) |
> **直接回答你的问题**:
> - **HM 不需要、也不该编译/测试/判断代码真伪**——那不合理。HM 是网关,没 AI。
> - **完成后是对是错,客户端当然知道**:它是智能体程序,把代码拉下来一跑一测就清楚,用户也会 review。**这才是判"有效"的地方。**
> - HM 的 `display_status` 顶多帮客户端**省一步**:告诉它"这轮跑完了 / 是不是空交付",**避免把一个空壳当成功**;但**"代码好不好"绝不由 HM 判**。
**关于测试/编译**(纠正我之前的错误说法):
- 跑测试/编译是 **AM 在自己沙箱里做**(任务执行的一部分),或**客户端在本地做**。
- 若 AM 跑了测试,**测试结果就是一个产物(`test_report` artifact)给客户端看**——**不是回传给 HM 去"裁决"**。HM 不参与对错判断。
---
## 7. Git 仓库与分支 / 合并模型 ❓
**目标流程**:
```text
任务开始 → 建/选仓库 → 拉基线分支 base
每个 agent → 自己分支 agent/<role> → 多次 commit(流式可见 diff)
阶段结束 → 集成:合并各 agent 分支 → 交付分支 delivery/<task_id>(或 main)
完成 → 交付分支即「完整产物」;客户端 clone/pull 看;不满意 → 在交付分支上续跑/重做
```
**决策点**:
| 点 | 方案(已定 / 建议) |
|---|---|
| 仓库归属 | ✅ **用户绑定的仓库**(github/gitea,用户给 URL)。无托管仓库。 |
| 谁执行 git | ✅ **agent_management 执行**所有 git 操作(clone 用户仓库、各 agent commit 到分支、合并到交付分支、push)——用 HM 注入的**短期 PAT**(从 KV 解出,最小权限)。HM **只记录引用**(repo_url/branch/commit_sha)并在 artifact metadata 带 `git_ref`,**不做 git**。 |
| 提交身份 | agent 提交用一个明确的 **bot 身份**(如 `heicode-agent <bot@heicode>`)+ commit message 带任务/agent/角色标注,便于用户在 git 历史里分辨人/机改动。 |
| 合并冲突 | 目录隔离(backend/、frontend/ 并列)天然无冲突;同文件冲突由「集成 agent」或规则化合并解决,无法自动解则上报 `needs_codegen` 让用户介入/再跑一轮。 |
| 写入方式 | ❓建议:agent **不直接 push 到用户的 `main`**,而是 push 到 `delivery/<task_id>` 或开 **PR**,由用户在自己 git 上 review/merge → 既安全又复用用户的 PR/CI 工作流。是否强制 PR 模式待定。 |
| 客户端看产物 | **只走 git**:直接对用户自己的仓库 `git clone/pull`。HM 不提供 `/archive` 等产物下载(已退役)。 |
---
## 8. 决策点(部分已定,2026-06-02)
| # | 决策 | 结论 |
|---|---|---|
| 1 | git 归属 | ✅ **用户绑自己的仓库**(github/gitea,给 URL),无托管仓库 |
| 2 | git 鉴权 | ✅ **HTTPS + 细粒度 PAT 为主**(github/gitea 通用、用户粘贴 token)、SSH deploy key 备选 |
| 3 | 部署 | ✅ **必须客户端执行 + 必须用户确认**;HM 只发短期凭据 + 记审计 |
| 4 | git 执行方 | ✅ **agent_management 执行 git**(用注入的短期 PAT),HM 只记引用 |
| 5 | 工单/里程碑 | 可选增强,默认关 —— ❓ 是否纳入 v1? |
| 6 | 流式 | v1 先轮询 work、SSE 放 v1.1 —— ❓ 接受? |
| 7 | 写入方式 | ❓ agent 是 push 到 `delivery/<task_id>` 分支 / 开 PR,还是直接进 main? 建议 PR/分支模式 |
| 8 | 未绑仓库 | ✅ **未绑 git 则禁用 sub**(强制绑 git)。不再有"仅产物"轻量路径;产物只在 git,无 project_folder/manifest/archive/local-edits |
---
## 9. 更多需要考虑的细节(我补充的,超出已提问题)
> 这些是我认为**必须在 v1 前定清**的边界/细节,大多附我的建议,标 ❓ 的需你拍板。
### 9.1 仓库与代码库状态
- **空仓库 vs 已有代码**:agent 是在**已有代码库上增量改**,还是**绿地新建**? 建议 binding 时声明 `mode: greenfield | existing`;existing 时 agent 先读现有结构再改,且**只动 allowed_paths 内**的文件。
- **多仓库任务**:一个任务是否可能跨多个仓库(前端仓 + 后端仓)? 建议 v1 **单仓库**,多仓库 v2。
- **monorepo / 子目录**:用 `allowed_paths` 限定 agent 工作目录,避免动到无关代码。
- **大文件 / LFS**:是否支持 git-lfs? v1 可不支持,但要**拒绝把大二进制/数据集塞进 git**(走 blob 绑定)。
- **.gitignore + 防止误提交密钥**:agent **绝不能把任何凭据/secret_ref/.env 提交进仓库**;runtime 侧需有 secret 扫描,提交前拦截。
### 9.2 凭据与安全
- **PAT 最小权限 + 短时效**:注入 AM 的 PAT 应尽量是**短期/单仓库范围**;若用户给的是长期 PAT,HM 至少做范围校验并提醒。
- **凭据只在内存**:AM 用完 PAT 不落盘、不进日志;HM 注入走加密。
- **scope 隔离**:一条 binding 的凭据**只能被该用户(binding_scope)的任务**使用,跨用户禁用。
- **审计**:每次「解 KV、注入 AM、发客户端租约」都留审计(user / binding / 用途 / 时间 / TTL),明文不入审计。
- **吊销**:用户删 binding 或吊销租约后,进行中的任务该如何? 建议:已注入的短期凭据自然过期,新操作立即失效。
### 9.3 任务执行与失败
- **预算/配额**:每任务 token/时长/成本上限;**跑超预算**时如何? 建议:到上限**暂停 + 标 `needs_codegen`/`budget_exceeded`**,让用户决定续不续,不静默烧钱。
- **中途停止(stop)**:停止时已 commit 的代码**保留在分支**(不回滚),任务标 stopped;用户可在该分支续跑或丢弃。
- **agent 崩溃 / 部分失败**:多 agent 里某个失败 → 整体 `completed_without_deliverable`/部分交付? 建议:HM 裁决时若有 agent 失败但有有效产物,仍可 `completed` 但带 warning;全失败则 failed。
- **幂等**:同一需求重复提交(网络重试)用 `X-Idempotency-Key` 去重,避免建重复任务/重复 git 分支。
- **超时**:AM 长时间无回调 → HM 标 `stale`/超时,客户端可见。
### 9.4 产物与验收
- **验收标准如何验证**:需求包里的 `acceptance_criteria` 谁来验? 建议:AM 跑测试(若有)并把**测试结果作为 `test_report` 产物给客户端**;**客户端 + 用户**据此判对错(**不经 HM 裁决**,§6.6)。
- **产物版本/标签**:每次交付打 tag(`delivery-<task>-rev<N>`)或记 commit_sha,便于回溯 + 部署指定版本。
- **修改 vs 重做的边界**:`/messages`(在现有产物上改)与 `/redo`(重新生成)语义要清晰;redo 是否丢弃旧分支? 建议:redo 开新分支,旧的保留可对比。
### 9.5 协作与团队
- **谁能看/操作一个任务**:binding_scope = 租户/工作区;同 scope 内成员可见,跨 scope 禁。
- **并发任务同仓库**:两个任务同时改一个 repo → 用不同 `delivery/<task_id>` 分支隔离,合并到 main 时各自 PR,冲突由用户处理。
### 9.6 git provider 细节
- **rate limit**:github/gitea API 有限流,频繁 commit/查询要退避,避免触发封禁。
- **私有 / 公开仓库**:都支持;私有仓库凭 PAT 访问。
- **网络可达**:runtime 要能访问用户的 git(公网 github 没问题;自建 gitea 若在内网,需用户提供可达地址或白名单)。
- **webhook 回写(可选)**:若用户在自己仓库手动改了代码,是否要 webhook 通知 HM 同步基线? v2 考虑。
### 9.7 部署细节(客户端执行 + 用户确认)
- **确认内容**:弹窗要清楚展示**部署目标、环境(prod/staging)、用哪条 binding、影响范围**,用户确认后才发凭据。
- **目标多样性**:v1 先支持 **VM(SSH)**;k8s/serverless v2。
- **回滚**:部署失败/效果不好 → 客户端能回滚到上一个交付 tag。
- **租约最小化**:发给客户端的凭据是**单目标、短 TTL**;用完吊销。
### 9.8 体验(参考 Claude Code work)
- **work 视图最小信息**:每个 agent 的「当前在做什么(一句话)+ 正在改哪个文件 + 跑了什么命令/工具 + 产出」,实时滚动。
- **可中断**:用户能在 work 视图里随时停/插话(`/messages`)。
- **可读日志分层**:普通用户看 `user_logs`(友好),调试面板看 `debug_logs`(原始)。
---
## 10. 与现状的差距清单(三端 TODO)
**Phase 0(运维,硬卡点)**
- 🔴 打通 Key Vault 托管身份(VM identity 授 KV Secrets Officer)——不通则资源绑定/凭据全链路不可用。
**Heicode Manager**
- 🟡→🟢 资源绑定 API(git/vm/db/blob CRUD + 凭据写 KV + secret_ref;KV 通后启用)
- 🔴 SSE 事件流转发(`/events/stream`)
- 🔴 给 agent/客户端的「绑定读取 + 短期租约」接口(部署取凭据用)
- 🟡 workflow per-agent 富字段(已预留,等 AM 填)
- 🔴 资源绑定 UI(重做干净版)
**agent_management(runtime)**
- 🔴 真正 git 入库 + 多 agent 分支 + 合并成交付分支
- 🔴 跑测试/编译并把结果作为 **`test_report` 产物给客户端看**(**不是给 HM 裁决**;对错由客户端+用户判,§6.6)
- 🔴 对照 `acceptance_criteria` 自检,结果同样作为产物给客户端
- 🔴 per-agent 指标上报(tokens/tools/elapsed/当前动作)
- 🔴 artifact 带 `source_agent_role` + `git_ref`
- 🔴 phases[] 阶段细分上报
- 🔴 中途续跑 / redo 语义
**桌面客户端**(本身是 Claude-Code 式智能体程序)
- 🟡 模式选择:本地模式(本地跑 agent)vs sub 模式(派云端 AM);**未绑 git 时禁用 sub 入口**
- 🟡 work 视图(先轮询 workflow,SSE 后接)——**只展示运行信息**(日志/状态/work),不做产物下载
- 🔴 **看产物 = git**:`git clone/pull` 用户仓库展示工程/历史/diff(不再拼 artifact 项目树)
- 🔴 迭代路径 B:`git pull` → 本地 agent 改 → push(复用本地能力,不必每次回云端)
- 🔴 部署:经 HM 取短期凭据 + 用户确认后本地执行
---
*本文为 v0.1 草案,决策点(§8)确认后转 v1。三端以本文对齐颗粒度与职责边界。*
@@ -1,516 +0,0 @@
# Agent Manager 普通 sub 敏捷模式对接任务清单
更新时间:2026-05-28
发给:Agent Manager 负责人
范围:普通 sub 模式,也就是 Heicode 的普通敏捷开发 Agent 模式。本文不要求 Agent Manager 实现完整蜂群 task graph;蜂群模式另见 `蜂群模式-AgentManager对接任务清单.md`。
## 1. 结论
普通 sub 敏捷模式下,Heicode 桌面客户端是用户主体验,Manager 是控制面,Agent Manager 是执行层。
Agent Manager 需要做的是:接收 Manager 生成的 deployment payload,按 `sub_mode=agile` 和 `agile_context` 执行阶段化开发,持续把阶段状态、日志、事件、artifact、审批请求、用量和最终结果回传给 Manager。
计费边界:PayPal 只作为 Heicode Manager 未来收款渠道,用于余额充值或购买 Heicode 内部订阅套餐;普通 sub 任务执行中的模型费用仍按 Manager/NewAPI 的钱包余额或订阅额度扣费。Agent Manager 不需要接 PayPal,但必须回传模型用量和运行 usage,方便 Manager/NewAPI 做归属和审计。
普通 sub 不等于蜂群模式:
| 项 | 普通 sub 敏捷 | 蜂群模式 |
|---|---|---|
| 重点 | 需求、设计、开发、测试、修复、部署等阶段推进 | 多 Agent 任务图、claim、heartbeat、handoff |
| 是否必须 task graph | 否 | 是 |
| 是否需要 artifact 回流 | 是 | 是 |
| 是否需要高危审批 | 是 | 是 |
| 是否需要日志/事件/指标 | 是 | 是 |
| 客户端主体验 | 是 | 是 |
## 2. 当前 Manager 已完成
| 能力 | 状态 | 说明 |
|---|---|---|
| HeicodeTask -> deployment draft | 已完成 | `POST /api/agent/user/tasks/{task_id}/deployment-draft` |
| 用户态 deployment 创建 | 已完成 | `POST /api/agent/user/deployments` |
| Runtime create bridge | 已完成 | 通过环境变量调用 Agent Manager |
| Runtime stop bridge | 已完成 | 停止时同步 Runtime |
| callback 接收 | 已完成 | `POST /api/agent/callbacks/swarm-events` |
| phase / timeline 聚合 | 已完成 | deployment timeline 聚合 audit、callback、artifact、SK |
| artifact 查询 | 已完成 | `GET /api/agent/user/deployments/{deployment_id}/artifacts` |
| approval 查询/approve/reject | 已完成 | `/api/agent/approvals` |
| V2 body 加密 | 已完成 | 桌面客户端到 Manager 的 POST 请求复用模型调用加密协议 |
| 生产验证 | 已完成核心链路 | 生产已验证 Manager `1.4.18` 可通过 `/api/swarms` 创建普通 sub run,持久化 `runtime_swarm_id=swm_*`,Agent Manager 自动 callback 可写入 `events/timeline`;`1.4.19` 补齐 callback 后反写 deployment 快照 |
| callback 状态反写 | 已完成 | Manager 接收 `deployment.status_changed`、`phase.changed`、`timeline.updated`、`agent.started/completed/crashed` 后,会同步更新 deployment `status/phase/runtime_state/agent_instances`,避免详情页长期停留 `initializing/pending` |
| PayPal/计费边界文档 | 已完成 | `docs/integration/Heicode-Manager-PayPal支付接入与计费关系说明.md` 已明确收款、余额、订阅、NewAPI 扣费和 Agent 运行预算关系 |
## 3. Agent Manager 需要实现或确认的 P0
| 任务 | 必需 | 原因 | 验收 |
|---|---:|---|---|
| 接收 Manager 创建请求 | 是 | Manager 会把普通 sub deployment 发送给 Agent Manager | `POST /api/agent/deployments` 或配置的 create path 返回 2xx |
| 支持 `sub_mode=agile` | 是 | 普通敏捷模式核心标识 | 不认识时不能按蜂群 task graph 强制处理 |
| 支持 `agile_context` | 是 | 用于阶段、检查点、验收标准和下一步动作 | Runtime 能读取并在回调里更新 stage/checkpoint |
| 支持阶段状态回传 | 是 | 客户端需要知道当前处在需求/设计/开发/测试/修复/部署哪个环节 | 回调 `phase.changed` 或 `timeline.updated` |
| 支持 artifact 回写 | 是 | 中间交付物和最终结果必须回到 Heicode | 回调 `artifact.created` |
| 支持审批请求 | 是 | 高危操作必须客户端审批 | 回调 `approval.requested` 并等待 decision |
| 支持 stop | 是 | 用户停止任务时 Runtime 必须停止真实执行 | stop 接口返回 stopped |
| 支持日志/事件/指标 | 是 | 联调和验收需要排障数据 | 提供 callback 或查询接口 |
| 支持用量归属 | 是 | NewAPI / CodeGW 计费要按 deployment/task/role 归属 | 回传 usage/budget 事件或在模型调用中带 correlation |
| 支持 Runtime usage 回传 | 是 | `budget.max_cost_usd` 只是预算上限,真实 Agent 运行费用不能由 Manager 猜 | 回传模型 token/cost、runtime 秒数、CPU/内存等可核对 usage |
## 4. Runtime 创建接口
Manager 当前默认 create path:
```text
AGENT_RUNTIME_CREATE_PATH=/api/agent/deployments
```
如果 Agent Manager 统一使用 `/api/swarms`,Manager 也可以配置切过去。但普通 sub 敏捷模式建议先支持:
```http
POST /api/agent/deployments
Authorization: Bearer <service_token>
X-User-ID: <manager_user_id>
X-Binding-Scope: <binding_scope>
X-Correlation-ID: <correlation_id>
X-Idempotency-Key: manager-<manager_deployment_id>
Content-Type: application/json
```
请求体核心形状:
```json
{
"orchestration_plan": {
"intent_id": "task-client-sim-1779875397",
"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": "heicode",
"binding_scope": "task-client-sim"
},
"billing_context": {
"provider": "newapi",
"default_model_id": "smoke-model",
"allowed_model_ids": ["smoke-model"],
"secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/model-gateway-key"
},
"agile_context": {
"iteration": "2026-05-28",
"stage": "planning",
"checkpoint": "draft_created",
"acceptance_criteria": [
"接口返回成功",
"artifact 可回写到 timeline",
"不出现明文密钥"
],
"next_action": "continue",
"requires_user_approval": false
},
"agent_runtime": {
"platform": "agent",
"agents": [
{
"role": "backend",
"model_ref": "smoke-model",
"instance_count": 1
}
]
},
"agents": [
{
"role_template": "backend",
"goal": "完成本轮后端任务",
"default_model_id": "smoke-model",
"resource_grants": []
}
],
"resource_grants": []
},
"agents": [
{
"role": "backend",
"resource_grants": []
}
],
"risk_level": "low",
"budget": {
"max_tokens": 20000,
"max_cost_usd": 1,
"max_duration_sec": 600
},
"billing_context": {
"provider": "newapi",
"default_model_id": "smoke-model",
"allowed_model_ids": ["smoke-model"],
"secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/model-gateway-key"
},
"resource_grants": [
{
"grant_id": "grant-client-sim-git",
"resource_id": "git-client-sim",
"resource_type": "git",
"permission_scope": ["repo:read"],
"secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/client-sim-git",
"ref": "azkv://heicode-kv.vault.azure.net/secrets/client-sim-git",
"target_role": "backend"
}
],
"callback": {
"url": "https://code.xinghanlab.com/api/agent/callbacks/swarm-events",
"signing_secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/agent-callback-signing-key",
"subscribed_events": [
"deployment.status_changed",
"phase.changed",
"agent.started",
"agent.completed",
"agent.crashed",
"sk_tool.called",
"sk_tool.completed",
"sk_tool.failed",
"approval.requested",
"budget.alert",
"artifact.created",
"timeline.updated"
]
},
"agile_context": {
"iteration": "2026-05-28",
"stage": "planning",
"checkpoint": "draft_created",
"next_action": "continue",
"requires_user_approval": false
},
"sub_mode": "agile",
"metadata": {
"manager_deployment_id": "dep_xxx",
"heicode_deployment_id": "dep_xxx",
"heicode_runtime_bridge": true,
"correlation_id": "corr_xxx"
}
}
```
响应:
```json
{
"success": true,
"data": {
"deployment_id": "runtime-dep-123",
"status": "running",
"estimated_ready_at": "2026-05-28T10:02:00Z"
}
}
```
建议也返回 `swarm_id`,即使普通 sub 不强依赖蜂群任务图,后续统一追踪会更方便。
## 5. 普通 sub 敏捷阶段
Agent Manager 至少要支持以下阶段语义,并通过 callback 回写当前阶段:
| stage | 含义 | 建议 checkpoint |
|---|---|---|
| `planning` | 需求澄清/任务拆分 | `draft_created`, `requirements_confirmed` |
| `design` | 方案/API/数据结构设计 | `design_ready` |
| `development` | 编码实现 | `backend_done`, `frontend_done`, `artifact_ready` |
| `testing` | 自动测试/手工验证 | `ready_for_test`, `test_passed`, `test_failed` |
| `fixing` | 根据测试或用户反馈修复 | `fix_started`, `fix_ready` |
| `deployment` | 部署/发布准备 | `deploy_ready`, `deployed` |
| `review` | 复核/总结/交付 | `review_ready`, `completed` |
| `done` | 结束 | `completed` |
| `failed` | 失败 | `failed` |
阶段回调示例:
```json
{
"event_id": "evt_phase_1",
"event_type": "phase.changed",
"deployment_id": "dep_xxx",
"agent_instance_id": "agent-backend-1",
"occurred_at": "2026-05-28T10:10:00Z",
"correlation_id": "corr_xxx",
"source": "agent-manager",
"payload": {
"stage": "development",
"checkpoint": "backend_done",
"title": "后端实现完成",
"summary": "已完成工单列表和状态流转接口,等待测试",
"agent_role": "backend",
"severity": "success",
"next_action": "submit_test_result"
}
}
```
如果 Agent Manager 暂时不支持 `phase.changed`,也可以先使用 `timeline.updated`,但 payload 中必须带 `stage` 和 `checkpoint`。
## 6. timeline.updated
普通 sub 敏捷下,客户端主要看 timeline。Agent Manager 应持续回写可展示事件。
联调前可以先请求 Manager 当前接受的 callback schema:
```http
GET https://code.xinghanlab.com/api/agent/callbacks/swarm-events/schema
```
该接口只返回事件类型、分类和必填字段,不返回任何 token 或密钥。普通 sub 敏捷重点核对 `phase.changed`、`timeline.updated`、`artifact.created`、`approval.requested`、`sk_tool.*` 和 `budget.alert`。
```json
{
"event_id": "evt_timeline_1",
"event_type": "timeline.updated",
"deployment_id": "dep_xxx",
"occurred_at": "2026-05-28T10:11:00Z",
"source": "agent-manager",
"payload": {
"title": "测试完成",
"summary": "接口测试通过 12 项,未发现阻塞问题",
"stage": "testing",
"checkpoint": "test_passed",
"agent_role": "reviewer",
"severity": "success",
"next_action": "submit_artifact"
}
}
```
## 7. artifact.created
普通 sub 模式必须回流中间交付物和最终交付结果。不要只写 Runtime 本地日志。
```json
{
"event_id": "evt_artifact_1",
"event_type": "artifact.created",
"deployment_id": "dep_xxx",
"task_id": "task-backend-1",
"source": "agent-manager",
"payload": {
"artifact_id": "art_test_report_1",
"artifact_type": "test_report",
"title": "接口测试报告",
"summary": "12 项接口测试通过",
"uri": "artifact://runtime/dep_xxx/test-report",
"checksum": "sha256:abc123",
"stage": "testing",
"checkpoint": "test_passed"
}
}
```
支持的 `artifact_type` 建议:
| artifact_type | 说明 |
|---|---|
| `code_patch` | 代码补丁或分支引用 |
| `document` | 需求/设计/说明文档 |
| `test_report` | 测试报告 |
| `deployment_manifest` | 部署清单 |
| `log_bundle` | 日志包 |
| `other` | 其他 |
## 8. approval.requested 和 decision
普通 sub 模式也需要高危审批。高危动作包括但不限于:
| 操作 | 例子 |
|---|---|
| 写 Git 仓库 | push 分支、改配置、创建 PR |
| 改云资源 | 创建/删除 VM、AKS、存储、数据库 |
| 部署到生产 | 发布、迁移、重启服务 |
| 使用敏感凭据 | 需要从 `secret_ref` 派生短期凭证 |
审批请求:
```json
{
"event_id": "evt_approval_1",
"event_type": "approval.requested",
"deployment_id": "dep_xxx",
"agent_instance_id": "agent-backend-1",
"source": "agent-manager",
"payload": {
"approval_id": "appr_runtime_1",
"operation": "git.write",
"resource_id": "repo-main",
"resource_type": "git",
"resource_scope": "feature/*",
"target_role": "backend",
"risk_level": "high",
"requires_credential": true,
"secret_ref": "azkv://heicode-kv.vault.azure.net/secrets/repo-main",
"ttl_seconds": 900,
"reason": "需要写入功能分支以提交本轮修改"
}
}
```
Manager 回传 decision:
```http
POST /api/swarms/{swarm_id}/approvals/{approval_id}
```
如果普通 sub 不使用 `swarm_id`,可让 Manager 配置为:
```text
AGENT_RUNTIME_APPROVAL_DECISION_PATH=/api/agent/deployments/{deployment_id}/approvals/{approval_id}
```
Runtime 需要接收:
```json
{
"approval_id": "appr_runtime_1",
"decision": "approved",
"manager_deployment_id": "dep_xxx",
"runtime_deployment_id": "runtime-dep-123",
"operation": "git.write",
"resource_id": "repo-main",
"resource_type": "git",
"target_role": "backend",
"requires_credential": true,
"credential_ref": "lease://agent/lease_xxx",
"lease_id": "lease_xxx",
"lease_expires_at": 1779850900000
}
```
Runtime 收到:
| decision | Runtime 动作 |
|---|---|
| `approved` | 继续该高危动作,只使用 `credential_ref` 对应的短期凭证 |
| `rejected` | 停止该动作,回调 `timeline.updated` 或 `phase.changed`,标记被拒绝 |
## 9. logs / events / metrics
Manager 当前有用户态查询位置,但真实数据需要 Agent Manager 产出。
Agent Manager 至少需要支持以下一种方式:
| 方式 | 说明 |
|---|---|
| callback 摘要 | 用 `timeline.updated` 持续回写阶段、耗时、错误摘要 |
| 查询接口 | 提供 `/logs`、`/events`、`/metrics`,Manager 后续可拉取 |
| 混合 | 关键状态 callback,详细日志走查询接口 |
建议指标:
| 指标 | 用途 |
|---|---|
| `status` | running/stopped/failed/completed |
| `stage` / `checkpoint` | 当前敏捷阶段 |
| `agent_role` | 哪个角色在执行 |
| `tokens_used` / `cost_usd` | 用量归属 |
| `duration_ms` | 阶段耗时 |
| `error_code` / `error_message` | 失败排障 |
| `artifact_count` | 产物数量 |
## 10. billing / NewAPI 用量归属
Agent Manager 调模型时,需要把 Manager 传入的上下文带上,便于 NewAPI / CodeGW 计费归属。
PayPal 不在这条链路里。PayPal 支付成功后只会把用户权益写入 Heicode 钱包余额或内部订阅;普通 sub 执行时,Agent Manager 仍然按 `billing_context.provider=newapi` 使用 Manager 传入的用户、deployment、role 和模型上下文。
至少保留:
| 字段 | 来源 | 用途 |
|---|---|---|
| `user_id` | `user_context.user_id` | 用户归属 |
| `manager_deployment_id` | `metadata.manager_deployment_id` | deployment 归属 |
| `correlation_id` | header 或 metadata | 链路追踪 |
| `agent_role` | agents[].role | 角色归属 |
| `task_id` | Runtime 内部任务 | 子任务归属 |
| `model_id` | billing/default model | 模型用量 |
Agent Manager 回传 usage 时建议至少包含:
| 字段 | 说明 |
|---|---|
| `model_tokens` | 本 deployment/task/role 消耗的模型 token。 |
| `model_cost_usd` | Runtime 或 NewAPI 可确认的模型成本。 |
| `runtime_seconds` | Agent 实际运行秒数。 |
| `cpu_core_seconds` | 如 Runtime 具备集群指标,应回传 CPU 使用量。 |
| `memory_mb_seconds` | 如 Runtime 具备集群指标,应回传内存使用量。 |
| `billing_source` | 建议为 `newapi`、`manager_wallet`、`manager_subscription` 或 Runtime 约定值。 |
注意:`budget.max_tokens`、`budget.max_cost_usd`、`budget.max_duration_sec` 是预算和拦截上限,不是已结算金额。Manager 只能展示和审计预算;真实扣费或成本归属必须基于 Agent Manager / Runtime 回传的 usage。
如果发生预算告警,回调:
```json
{
"event_id": "evt_budget_1",
"event_type": "budget.alert",
"deployment_id": "dep_xxx",
"source": "agent-manager",
"payload": {
"consumed_usd": 7.2,
"max_cost_usd": 8,
"threshold_pct": 90,
"severity": "warning"
}
}
```
## 11. 安全要求
| 要求 | 说明 |
|---|---|
| 不接收/不打印明文长期密钥 | password/token/private_key/access_key/connection_string/model key 都不能出现在日志、callback、artifact metadata |
| 只使用 `secret_ref` | 长期凭据引用统一 `azkv://<vault>/secrets/<name>` |
| 只用 `credential_ref` 执行审批后的动作 | Manager 同意后返回 `lease://...`,不要要求长期密钥 |
| callback 必须幂等 | 重试同一个 `event_id` 不能重复创建 artifact/approval |
| callback 必须有来源 | `source=agent-manager` 或 `heicode-swarm-runtime` |
## 12. 普通 sub 联调验收步骤
| 步骤 | 操作 | 期望 |
|---:|---|---|
| 1 | Manager 调 Agent Manager health | healthy |
| 2 | Manager 创建 `sub_mode=agile` deployment | Runtime 返回 `deployment_id`,建议返回 `swarm_id` |
| 3 | Runtime 回调 `phase.changed` planning/design/development/testing | Manager timeline 可见阶段推进 |
| 4 | Runtime 回调 `timeline.updated` | 客户端可展示当前子环节反馈 |
| 5 | Runtime 回调 `artifact.created` | Manager artifacts 列表出现中间产物 |
| 6 | Runtime 回调 `approval.requested` | Manager pending approval 出现 |
| 7 | Manager approve/reject | Runtime 收到 decision 并继续/停止对应动作 |
| 8 | Manager stop | Runtime deployment 真实停止 |
| 9 | Runtime 回调 completed/failed | Manager detail/timeline 显示终态 |
| 10 | Runtime 回调用量 | Manager 能看到 model token/cost 或 usage 摘要,且与 deployment/task/role/correlation 关联 |
| 11 | 查日志 | 不出现明文密钥,不丢 `correlation_id` |
| 12 | 生产路由复核 | `GET /api/agent/callbacks/swarm-events/schema` 返回 200,用户态/后台态接口使用有效登录态通过 smoke |
## 13. Agent Manager 不需要处理的内容
| 不需要处理 | 原因 |
|---|---|
| 桌面客户端 V2 body 加密 | 这是客户端到 Manager,Manager 已处理 |
| Manager 用户登录/session | Manager 控制 |
| HeicodeTask 追问/任务卡生成 | 客户端和 Manager 代理处理 |
| Azure Key Vault 写入长期密钥 | Manager 负责资源绑定和 `secret_ref` 管理 |
| Web 控制台页面展示 | Manager 负责 |
| PayPal 收款和充值订单 | Manager 负责;Agent Manager 只需要回传执行和用量,不直接处理支付 |
## 14. 当前已知缺口
| 缺口 | 属于谁 | 说明 |
|---|---|---|
| 真实 Runtime 是否完整消费 `agile_context` | Agent Manager | 需要确认字段被使用,不只是透传 |
| 阶段状态持续回传 | Agent Manager | 2026-05-31 生产复核已收到 running/completed、phase、timeline、task.completed 等真实回调;后续需在更复杂多阶段任务中继续验证 |
| artifact 真实产出 | Agent Manager | 2026-05-31 生产复核已收到业务 `code_patch` artifact,并可通过 Manager content 代理下载;Git/部署 URL 类产物仍按具体任务继续验证 |
| approval decision 接收路径 | Agent Manager + Manager 配置 | 需确认最终路径是 `/api/swarms/...` 还是 `/api/agent/deployments/...` |
| 用量回传 | Agent Manager + NewAPI/CodeGW | 2026-05-31 生产复核已回传 `tokens_used=2682`、`newapi_request_id=chatcmpl-DlbZce3VZnsv5DptBILFoiRYy5ZHN`;后续需继续按 user/deployment/task/role 归属 |
| Agent 运行费用真实结算 | Agent Manager + Manager | Runtime 已能回传 token usage;真实费用结算仍需按 Manager/NewAPI 订阅/钱包规则和 Runtime usage 口径统一 |
| 生产 callback schema 路由 | Manager 部署/路由 | 本地代码和测试已覆盖,2026-05-28 生产公开访问 `/api/agent/callbacks/swarm-events/schema` 返回 404,需要重新上线或核对生产镜像/路由 |
| 无 body GET 的 V2 签名 | 客户端 + Manager | 这是客户端全链路无 cookie 的后续项,不阻塞 Agent Manager 创建/回调联调 |