== Heicode integration (~41 endpoints across 5 modules) ==
- §2 ResourceBinding (5 endpoints) — resources.py / resource_grants.py
- §4 NewAPI metadata proxy (4 endpoints) — heicode_proxy.py + heicode_client.py
- §5 Agnet platform stub (12 endpoints, in-memory mock) — agnet_stub.py
- §6 Task orchestration (5 endpoints + 3 extension endpoints) — heicode_tasks.py
6.1-6.5: intent / list / get / answer / messages
6.6-6.8: execution / delivery / audit?tab=... (Slice 8/9/10)
- §7 SSE single channel + approvals (4 endpoints + 5 event types) —
heicode_events.py + event_bus.py
- §7.8.1 internal billing-provider PUT endpoint — auth.py (routes)
== Schema changes ==
- migrations/026 heicode_tasks (orchestration state)
- migrations/027 users.billing_provider (litellm | newapi switch)
- migrations/028 heicode_approvals (high-risk approval queue)
== Register transaction hardening (P0 + P1 + P2) ==
routes/auth.py register():
- Pre-existing P0: failed register returned IntegrityError str verbatim
(leaking SQL params + ~50 plaintext LiteLLM keys per attempt).
Now logs exc_info, returns {code: REGISTER_FAILED, message: ...}.
- Pre-existing P0: model dedupe — two ModelProvider rows with overlapping
supported_models (e.g. taiji/gpt-4o-mini in both taiji and azure providers)
collide on uq_tenant_model. seen_models set deduplicates within the loop.
- New P1: track created_litellm_keys; on any failure call delete_key() for
each — prevents remote orphan keys when DB rollback fires.
- New P1: replace verify_code with peek_verification_code at the start;
only call verify_code (which consumes) after commit succeeds. Failed
registrations no longer burn the user's one-shot code.
- New P2: narrow inner `except (LiteLLMClientError, Exception)` to just
LiteLLMClientError so SQLAlchemy errors bubble to the outer rollback
instead of being silently swallowed into a half-allocated 200 response.
- New P2: same narrowing on outer `except (AgentManagerError, Exception)`.
== Auth middleware ==
- app/auth.py: allow /api/auth/internal/billing-provider and
/api/auth/internal/approvals to bypass user JWT (service-token auth
via HEICODE_INTERNAL_SERVICE_TOKEN, validated in-route).
== Docs ==
- Heicode-接口契约文档.md v2.2 (41 endpoints + SSE schema + 6.6-6.8)
- Heicode-对接进度与待办.md (through §7.14 SSE + 7.8.2 delivery回执)
- Heicode-完整调用流程图.md (sequence + routing diagrams)
- Agent-Manager-Heicode对接需求文档.md
- HEICODE_API_INTEGRATION.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
49 KiB
Heicode ↔ mcp-server 接口契约文档
版本: v2.2
生效日期: 2026-05-08
状态: 已上线生产,可直接对接
当前镜像: taiji.azurecr.io/mcp-server:heicode-7.8.2-tasks-ext-20260508
本文档列出 Heicode 客户端可调用的全部 mcp-server 接口、入参与出参。 所有接口已在生产环境通过端到端测试。
v2.2 修订(2026-05-08,本次):
- 新增 §6.6 / §6.7 / §6.8(execution / delivery / audit)— Slice 8/9/10 配套,3 端点全过 13/13 smoke
- 接口总数:38 → 41
v2.1 修订(2026-05-08):
- 新增 §7 Server-Sent Events(5 类 event + 配套 REST)— §7.8.3 SSE 单通道全过 12/12 smoke
- 接口总数:34 → 38
v2.0 修订(2026-05-08):
- 新增 §4 NewAPI 元数据透传(4 接口)
- 新增 §5 Agnet 平台本地 stub(12 接口,mock 数据,前端可立即联调)
- 新增 §6 任务编排(5 接口,cc-haha 任务驾驶舱 / 工作台 配套)
- 接口总数:13 → 34
📍 调用关系全景见
Heicode-完整调用流程图.md。 📍 进度与待办见Heicode-对接进度与待办.md。
0. 接入信息
Base URL
https://apimtaiji.azure-api.net/api/mcp
完整路径示例:
POST https://apimtaiji.azure-api.net/api/mcp/api/auth/login
GET https://apimtaiji.azure-api.net/api/mcp/api/resources
⚠️ 重要:登录接口被两类调用方共用
经过代码核实(2026-05-05),mcp-server 的登录接口实际被以下两个调用方依赖:
| 调用方 | 调用方式 | 关键依赖字段 |
|---|---|---|
heicode 前端 (web/default/src/features/auth/api.ts) |
浏览器跨域,Authorization: Bearer |
data.token, data.refreshToken, data.user.{id,name,email,role,channelId} |
heicode 后端 (controller/heicode_agnet_session.go) |
服务端调 /me /refresh,验证前端给的 token |
data.{id,email,name,role,channelId,status} |
字段形态任何变更都会破坏对接。增加字段安全;删/改字段名/字段类型 = breaking change。
通用请求头
| Header | 必填 | 说明 |
|---|---|---|
Content-Type: application/json |
POST/PUT 时是 | 请求体 JSON 格式 |
Authorization: Bearer <accessToken> |
受保护接口必填 | JWT access token |
X-Request-Id: <uuid> |
建议 | 客户端生成,便于排障反查日志 |
通用响应封装
成功:
{
"success": true,
"data": { ... }
}
部分接口含 message:
{
"success": true,
"data": { ... },
"message": "操作成功"
}
失败(FastAPI 默认):
{
"detail": "邮箱或密码错误"
}
失败(结构化错误):
{
"detail": {
"code": "RESOURCE_GRANT_INVALID",
"message": "allowed_actions 超出对应 binding.permission_scope: ['repo:admin']"
}
}
Token 模型
| Token | TTL | 用途 |
|---|---|---|
| Access Token | 24 小时 | 调业务接口(含 /me、/logout) |
| Refresh Token | 7 天 | 仅用于 /refresh 换新 access |
JWT claims:sub(user_id)、email、role、channelId、type(access/refresh)、iat、exp。
Role 字段值与 heicode 前端解析
mcp-server 现有 role 取值(按用户类型):user, channel_admin, billing_admin, operations_admin, admin, super_admin, provider_admin。
heicode 前端 (api.ts:259-261) 硬编码解析为 3 档:
| mcp-server role 值 | heicode 前端解析 | 数值 |
|---|---|---|
root |
root | 100 |
admin |
admin | 10 |
user |
user | 1 |
| 其他(channel_admin, super_admin, provider_admin 等) | 默认 user | 1 |
对 Heicode 客户端的实际影响:
- Heicode 客户端预期登录的角色 =
user,前端解析为 1 ✓ - 高权限角色(admin/root)由 heicode 后端独立白名单 (
HEICODE_ROOT_EMAILS/HEICODE_ADMIN_EMAILS环境变量) 决定,不信任 mcp-server 返回的 role 字段 - mcp-server 这边无需调整 role 取值,保持现有取值即可
CORS 当前状态
mcp-server 生产环境 CORS_ORIGINS 未显式配置 → fallback 到 ["*"]。代码同时设置 allow_credentials=True。
| 调用方式 | 当前是否能用 |
|---|---|
Authorization: Bearer <token> |
✅ 能用(heicode 前端走这条) |
| 浏览器 cookie + credentials | ❌ 浏览器规范禁止 * + credentials 同用 |
Heicode 前端用 Bearer,不受影响。如需后续硬化(去掉 *),需 heicode 团队提供前端实际部署域名清单。
1. 登录认证(4 接口)
1.1 POST /api/auth/login
用途: 账号密码登录,换取 token 对。
请求
POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "YourPassword123",
"role": "user"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
email |
string | 是 | 用户邮箱 |
password |
string | 是 | 密码 |
role |
string | 是 | Heicode 客户端固定传 "user" |
成功响应 200
{
"success": true,
"data": {
"token": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"user": {
"id": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"name": "张三",
"email": "user@example.com",
"role": "user",
"channelId": "6e6fc470-76f8-4bb1-8ea4-625dc5b12bc6"
}
}
}
错误响应
| HTTP | 含义 |
|---|---|
| 401 | 邮箱或密码错误 |
| 403 | 账户已被禁用 / 权限不足 |
| 422 | 请求体 Pydantic 校验失败(邮箱格式不合法等) |
| 429 | 登录尝试过于频繁;响应头含 Retry-After: 60 |
限流: 每 IP 每 60 秒最多 5 次(不区分成功失败)。
1.2 GET /api/auth/me
用途: 校验 access token 有效性,返回当前用户资料。
⚠️ 高频调用 + 双调用方依赖:
- heicode 前端:客户端启动 + token 续期后立即调一次
- heicode 后端:每次走
from-agnet流程时调一次(即每次"建立 Manager 会话")- 字段形态被 hardcode 解析(id/email/name/role/channelId/status),绝不能改
- 性能敏感:响应时间影响登录用户体验
请求
GET /api/auth/me
Authorization: Bearer <accessToken>
成功响应 200
{
"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-05-05T06:01:23.456789"
}
}
错误响应
| HTTP | 含义 |
|---|---|
| 401 | token 无效 / 过期 / 已登出 / 用户不存在 |
| 403 | 账户已被禁用 |
1.3 POST /api/auth/refresh
用途: 用 refresh token 换取新的 access + refresh token 对。
请求
POST /api/auth/refresh
Authorization: Bearer <refreshToken>
⚠️ 必须传 refresh token,传 access token 会被拒绝。
成功响应 200
{
"success": true,
"data": {
"token": "eyJhbGc...",
"refreshToken": "eyJhbGc..."
}
}
客户端收到新 token 对后应替换本地缓存(旧的也作废)。
错误响应
| HTTP | 含义 |
|---|---|
| 401 | refresh token 无效 / 过期 / 错传了 access token(必须使用 refresh token 调用此接口) |
1.4 POST /api/auth/logout
用途: 登出,把当前 access token 加入黑名单。
请求
POST /api/auth/logout
Authorization: Bearer <accessToken>
成功响应 200
{
"success": true,
"data": null,
"message": "登出成功"
}
说明: 容错性强,token 黑名单写入失败也会返回 200。客户端总是清理本地 token + 跳登录页。
⚠️ 登出双调用约定:heicode 前端登出时会同时调用:
GET /api/user/logout(heicode 后端,清 heicode session cookie)POST /api/auth/logout(mcp-server,本接口;token 加黑名单)两次调用都做容错处理(不阻断登出体验)。前端最后总是清 localStorage 跳登录页。
2. 资源绑定 ResourceBinding(5 接口)
2.0 公共说明
对象语义: 用户绑定到 Heicode 的外部资源(Git 仓库 / SK / 项目文档 / 云账号 / 云资源)。
安全红线:
- DB 只保存元数据 +
secret_ref,不保存明文密钥 metadata/constraints/permission_scope中不得出现 key 包含以下关键词的字段(不区分大小写):违反返回 422password, token, secret, private_key, access_key, credentialRESOURCE_GRANT_SECRET_REJECTED- 例外:key 名为
secret_ref视为引用(如vault://...),允许通过
枚举值:
| 字段 | 允许值 |
|---|---|
type |
git / sk / project_doc / cloud_account / cloud_resource |
status |
pending / active / disabled / revoked |
2.1 POST /api/resources
用途: 创建资源绑定。
请求
POST /api/resources
Authorization: Bearer <accessToken>
Content-Type: application/json
{
"type": "git",
"name": "heicode-main-repo",
"external_ref": "https://example.com/org/heicode.git",
"metadata": {
"provider": "gitee",
"default_branch": "main"
},
"permission_scope": ["repo:read", "repo:write:current-branch"],
"constraints": {
"ref": "main",
"allowed_paths": "services/**,docs/**"
},
"secret_ref": "vault://secret/users/{user_id}/bindings/heicode-main-repo",
"status": "active"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type |
string (enum) | 是 | 资源类型,见 §2.0 |
name |
string (≤255) | 是 | 用户可见名称 |
external_ref |
string | 否 | 外部资源定位(repo URL、subscription ID 等) |
metadata |
object | 否,默认 {} |
元数据;不得含敏感 key |
permission_scope |
string[] | 否,默认 [] |
该资源允许的最大动作集合 |
constraints |
object | 否,默认 {} |
路径/分支/网络等限制 |
secret_ref |
string (≤500) | 否 | 凭证引用(vault://...),不是密钥本身 |
status |
string (enum) | 否,默认 pending |
见 §2.0 |
成功响应 200
{
"success": true,
"data": {
"id": "88963d56-5a95-4863-8a0b-91a83e456028",
"user_id": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"type": "git",
"name": "heicode-main-repo",
"external_ref": "https://example.com/org/heicode.git",
"metadata": { "provider": "gitee", "default_branch": "main" },
"permission_scope": ["repo:read", "repo:write:current-branch"],
"constraints": { "ref": "main", "allowed_paths": "services/**,docs/**" },
"secret_ref": "vault://secret/users/.../bindings/heicode-main-repo",
"status": "active",
"created_by": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"updated_by": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"created_at": "2026-05-05T06:10:00.123456",
"updated_at": "2026-05-05T06:10:00.123456"
}
}
错误响应
| HTTP | code | 含义 |
|---|---|---|
| 401 | — | 未登录 |
| 422 | — | type/status 枚举不合法 |
| 422 | RESOURCE_GRANT_SECRET_REJECTED |
metadata/constraints/permission_scope 含敏感字段 |
2.2 GET /api/resources
用途: 列出当前登录用户的资源绑定。
请求
GET /api/resources?type=git&status=active&limit=100&offset=0
Authorization: Bearer <accessToken>
| Query | 类型 | 默认 | 说明 |
|---|---|---|---|
type |
string | — | 按类型过滤 |
status |
string | — | 按状态过滤 |
limit |
int (1-500) | 100 | 返回上限 |
offset |
int (≥0) | 0 | 偏移 |
成功响应 200
{
"success": true,
"data": {
"items": [
{ "id": "...", "type": "git", "name": "...", ... }
],
"total": 1,
"offset": 0,
"limit": 100
}
}
items元素结构同 §2.1 的成功响应data字段。
2.3 GET /api/resources/{binding_id}
用途: 获取单个资源绑定详情。
请求
GET /api/resources/88963d56-5a95-4863-8a0b-91a83e456028
Authorization: Bearer <accessToken>
成功响应 200: 同 §2.1 的 data 字段。
错误响应
| HTTP | 含义 |
|---|---|
| 400 | binding_id 不是有效 UUID |
| 401 | 未登录 |
| 403 | 该资源不属于当前用户 |
| 404 | 资源不存在 |
2.4 PUT /api/resources/{binding_id}
用途: 更新资源绑定(部分字段)。
请求
PUT /api/resources/88963d56-5a95-4863-8a0b-91a83e456028
Authorization: Bearer <accessToken>
Content-Type: application/json
{
"name": "heicode-main-repo-renamed",
"permission_scope": ["repo:read"],
"status": "active"
}
可更新字段(全部可选):name / external_ref / metadata / permission_scope / constraints / secret_ref / status。
未传的字段保持原值。
成功响应 200: 同 §2.1(含更新后字段)。
错误响应: 同 §2.3 + §2.1 的 422。
2.5 DELETE /api/resources/{binding_id}
用途: 软删除资源绑定(设 status=revoked,保留历史)。
请求
DELETE /api/resources/88963d56-5a95-4863-8a0b-91a83e456028
Authorization: Bearer <accessToken>
成功响应 200
{
"success": true,
"data": {
"id": "88963d56-5a95-4863-8a0b-91a83e456028",
"status": "revoked"
}
}
说明: 软删除后 GET /api/resources/{id} 仍可读到(status=revoked)。基于该 binding 已存在的 grant 不会自动撤销 — 业务层自行判断或调 DELETE /api/resource-grants/{id}。
3. 资源授权 ResourceGrant(4 接口)
3.0 公共说明
对象语义: 把某个 ResourceBinding 授给某个角色 / 子 Agent 使用。
核心约束:
allowed_actions必须是对应 binding 的permission_scope的子集- 违反 → 400
RESOURCE_GRANT_INVALID
- 违反 → 400
constraints不得放宽对应 binding 的constraints(应用层校验)- 仅能基于自己的 binding 创建 grant
- 同一类敏感字段拒绝规则适用于
constraints/allowed_actions
枚举值:
| 字段 | 允许值 |
|---|---|
status |
active / suspended / revoked / expired |
role(建议值) |
product / frontend / backend / reviewer / ops / 自定义字符串 |
3.1 POST /api/resource-grants
用途: 创建资源授权。
请求
POST /api/resource-grants
Authorization: Bearer <accessToken>
Content-Type: application/json
{
"resource_id": "88963d56-5a95-4863-8a0b-91a83e456028",
"binding_scope": "main",
"role": "backend",
"agent_id": null,
"allowed_actions": ["repo:read"],
"constraints": {
"ref": "main",
"allowed_paths": "services/api/**"
},
"expires_at": "2026-06-05T00:00:00",
"status": "active"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
resource_id |
string (UUID) | 是 | 对应 ResourceBinding ID |
binding_scope |
string (≤255) | 是 | repo/ref/path 或云资源引用 |
role |
string | 否 | 子 Agent 角色 |
agent_id |
string (UUID) | 否 | 子 Agent ID;空表示授下次该角色部署 |
allowed_actions |
string[] | 否 | 必须是 binding.permission_scope 的子集 |
constraints |
object | 否 | 限制条件 |
expires_at |
string (ISO 8601) | 否 | 过期时间;高危资源建议必填 |
status |
string (enum) | 否,默认 active |
见 §3.0 |
成功响应 200
{
"success": true,
"data": {
"id": "1e8d7a4d-3a2c-4d5e-9b1f-12c3d4e5f6a7",
"user_id": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"binding_scope": "main",
"resource_id": "88963d56-5a95-4863-8a0b-91a83e456028",
"role": "backend",
"agent_id": null,
"allowed_actions": ["repo:read"],
"constraints": { "ref": "main", "allowed_paths": "services/api/**" },
"status": "active",
"expires_at": "2026-06-05T00:00:00",
"created_by": "b00a7b8e-9e8b-463d-9593-a3b4d0006778",
"revoked_by": null,
"created_at": "2026-05-05T06:15:00.123456",
"revoked_at": null
}
}
错误响应
| HTTP | code | 含义 |
|---|---|---|
| 400 | — | resource_id / agent_id 非合法 UUID |
| 400 | RESOURCE_GRANT_INVALID |
binding 状态不允许新建授权(如 disabled/revoked),或 allowed_actions 超出 binding.permission_scope |
| 401 | — | 未登录 |
| 403 | FORBIDDEN_SCOPE |
不能基于他人的 binding 创建授权 |
| 404 | NOT_FOUND |
对应 binding 不存在 |
| 422 | — | status 枚举不合法 |
| 422 | RESOURCE_GRANT_SECRET_REJECTED |
constraints/allowed_actions 含敏感字段 |
3.2 GET /api/resource-grants
用途: 列出当前用户的资源授权。
请求
GET /api/resource-grants?resource_id=...&role=backend&binding_scope=main&status=active&limit=100&offset=0
Authorization: Bearer <accessToken>
| Query | 类型 | 默认 | 说明 |
|---|---|---|---|
resource_id |
string (UUID) | — | 按 binding 过滤 |
role |
string | — | 按角色过滤 |
binding_scope |
string | — | 按作用域过滤 |
status |
string | — | 按状态过滤 |
limit |
int (1-500) | 100 | 返回上限 |
offset |
int (≥0) | 0 | 偏移 |
成功响应 200
{
"success": true,
"data": {
"items": [ { "id": "...", ... } ],
"total": 1,
"offset": 0,
"limit": 100
}
}
3.3 GET /api/resource-grants/{grant_id}
用途: 获取单个授权详情。
请求
GET /api/resource-grants/1e8d7a4d-3a2c-4d5e-9b1f-12c3d4e5f6a7
Authorization: Bearer <accessToken>
成功响应 200: 同 §3.1 的 data 字段。
错误响应:
| HTTP | code | 含义 |
|---|---|---|
| 400 | — | grant_id 非合法 UUID |
| 401 | — | 未登录 |
| 403 | FORBIDDEN_SCOPE |
不属于当前用户 |
| 404 | NOT_FOUND |
授权不存在 |
3.4 DELETE /api/resource-grants/{grant_id}
用途: 撤销授权(软删除:status=revoked + revoked_at + revoked_by)。幂等:重复撤销返回 200。
请求
DELETE /api/resource-grants/1e8d7a4d-3a2c-4d5e-9b1f-12c3d4e5f6a7
Authorization: Bearer <accessToken>
成功响应 200: 同 §3.1 的 data 字段(含 revoked_at / revoked_by)。
错误响应: 同 §3.3。
4. 完整使用流程示例
4.1 客户端启动
1. 读取本地缓存的 access token
2. GET /api/auth/me
- 200 → 进入主界面,刷新本地用户资料
- 401 → 看是否有 refresh token
├─ 有 → POST /api/auth/refresh
│ ├─ 200 → 替换 token 对,重试 /me
│ └─ 401 → 清理本地 token,跳登录页
└─ 无 → 跳登录页
4.2 用户登录
POST /api/auth/login {email, password, role: "user"}
├─ 200 → 存 token 对 + user 资料,进主界面
├─ 401 → 显示"邮箱或密码错误"
├─ 429 → 显示"尝试过于频繁,请 N 秒后再试"(N = Retry-After)
└─ 其他 → 通用错误提示
4.3 绑定 Git 资源
POST /api/resources
{
"type": "git",
"name": "my-repo",
"external_ref": "https://example.com/org/my-repo.git",
"permission_scope": ["repo:read", "repo:write:current-branch"],
"constraints": { "ref": "main" },
"secret_ref": "vault://secret/users/{user_id}/bindings/my-repo",
"status": "active"
}
→ 200, data.id = <binding_id>
4.4 把绑定授给一个 backend 子 Agent 角色
POST /api/resource-grants
{
"resource_id": "<binding_id>",
"binding_scope": "main",
"role": "backend",
"allowed_actions": ["repo:read"]
}
→ 200, data.id = <grant_id>
4.5 撤销与清理
DELETE /api/resource-grants/{grant_id} # 撤销授权
DELETE /api/resources/{binding_id} # 软删除 binding
4.6 业务请求中 token 过期
任意业务接口返回 401
└→ POST /api/auth/refresh (用 refresh token)
├─ 200 → 替换 token,重试原请求
└─ 401 → 清理 token,跳登录页
4.7 用户登出
POST /api/auth/logout
→ 不论结果都清理本地 token + 跳登录页
5. 错误码索引
| code | HTTP | 接口 | 含义 |
|---|---|---|---|
RESOURCE_GRANT_INVALID |
400 | resource-grants | binding 状态非法 / allowed_actions 超出 binding.permission_scope |
RESOURCE_GRANT_SECRET_REJECTED |
422 | resources / resource-grants | metadata/constraints/permission_scope/allowed_actions 含敏感字段 |
FORBIDDEN_SCOPE |
403 | resources / resource-grants | 跨用户访问别人的资源/授权 |
NOT_FOUND |
404 | resource-grants | 引用的 binding 或 grant 不存在 |
| —(detail 字符串) | 401 | 全部 | 未登录 / token 失效 / 已登出 |
| —(detail 字符串) | 403 | 登录 / /me | 账户已禁用 / 权限不足 |
| —(detail 字符串) | 429 | login | 限流(每 IP 5 次/60s) |
| —(detail 数组) | 422 | 全部 | Pydantic 校验失败(邮箱格式、枚举值等) |
6. 字段速查
资源类型枚举
type |
子 Agent 可见内容 | permission_scope 示例 |
|---|---|---|
git |
repo URL、ref、允许路径、读写范围 | repo:read, repo:write:current-branch |
sk |
SK 来源、版本、允许/禁止策略 | sk:read, sk:list |
project_doc |
文档引用、版本、可读范围 | doc:read, doc:list |
cloud_account |
account/project/subscription 元数据、允许动作 | cloud:list, cloud:read |
cloud_resource |
资源 ID、环境、网络边界、允许动作 | vm:ssh:approved-window, service:restart |
状态机
ResourceBinding:
pending ─→ active ─┬→ disabled ─→ active ...
└→ revoked (终态)
ResourceGrant:
active ─┬→ suspended ─→ active ...
├→ revoked (终态,由 DELETE 设置)
└→ expired (终态,由 expires_at 触发,当前由调用方判断)
7. 安全与配额
| 项 | 数值/规则 |
|---|---|
| 登录限流 | 每 IP 每 60 秒 ≤ 5 次(不区分成功失败) |
| Access token TTL | 24 小时 |
| Refresh token TTL | 7 天 |
| API 列表分页上限 | limit ≤ 500 |
name 长度上限 |
255 字符 |
secret_ref 长度上限 |
500 字符 |
| 敏感字段拒绝模式 | key 含 password|token|secret|private_key|access_key|credential(不区分大小写)→ 422 |
| 例外 key | secret_ref 不算敏感(视为引用) |
8. 测试账号(仅联调)
| 角色 | 邮箱 | 密码 |
|---|---|---|
| 普通用户 | 55@55.com |
By@123456. |
Heicode 客户端固定使用
role="user"。其他角色(channel/admin)由 mcp-server 现有业务使用,不开放给 Heicode。
9. 排障
如发现接口行为与本文档不一致:
- 客户端应在所有请求带
X-Request-Id头(UUID 格式) - 报告内容:
- 完整请求 URL + Method + Headers + Body
- 完整响应 HTTP 状态 + Body
X-Request-Id值- 时间戳(精确到秒)
- 后端按
X-Request-Id反查日志和审计
4. NewAPI 元数据透传(4 接口)
4.0 公共说明
Heicode 决策 ④(透传方案):mcp-server 包一层 /api/user/heicode/*,背后调 NewAPI(code.xinghanlab.com)admin token,按当前登录用户的 email 反查 NewAPI 本地 user_id 后透传。
前端只对接 mcp-server 一个域,不直连 code.xinghanlab.com,零 CORS 问题。
当前状态:代码已上线 + 4 端点全注册;未配置 admin token 时返回 503 HEICODE_NEWAPI_NOT_CONFIGURED。Heicode 配齐 token 后立即生效,无需重新构建/部署。
4.1 GET /api/user/heicode/balance
响应 200:
{
"success": true,
"data": {
"heicodeUserId": 123,
"email": "user@example.com",
"username": "user",
"displayName": "张三",
"group": "default",
"status": 1,
"quota": 100000,
"usedQuota": 12345,
"requestCount": 78
}
}
4.2 GET /api/user/heicode/models
响应 200:
{
"success": true,
"data": {
"heicodeUserId": 123,
"email": "...",
"items": [/* NewAPI 全部模型清单(admin 视角)*/],
"count": 28
}
}
客户端结合
/balance的group字段做用户可见性过滤。
4.3 GET /api/user/heicode/usage
Query: days (1-90,默认 30)
响应 200:
{
"success": true,
"data": {
"heicodeUserId": 123,
"email": "...",
"days": 30,
"items": [/* NewAPI 按日 quota 统计 */],
"count": 30
}
}
4.4 GET /api/user/heicode/logs
Query: limit (1-200,默认 50),page (默认 1)
响应 200:
{
"success": true,
"data": {
"heicodeUserId": 123,
"email": "...",
"page": 1,
"limit": 50,
"items": [/* NewAPI 调用日志 */],
"count": 50
}
}
4.x 共通错误码
| HTTP | code | 含义 |
|---|---|---|
| 401 | — | 未登录 |
| 404 | HEICODE_USER_NOT_FOUND |
在 NewAPI 找不到 email 的用户(用户需先在 Heicode 完成首次登录建账) |
| 502 | HEICODE_NEWAPI_UPSTREAM_ERROR |
NewAPI 调用失败 |
| 503 | HEICODE_NEWAPI_NOT_CONFIGURED |
mcp-server 未配置 admin token(见 §B-1) |
5. Agnet 平台本地 stub(12 接口)
5.0 公共说明
按 Heicode 仓库 docs/integration/agnet-platform-request-contract.md 字段形态返回 mock 数据。用于前端联调,真实 agent-manager 12 接口落地后切换为出站调用,字段 / 路径 / 错误码 0 改动。
存储:内存 dict,重启清空(仅联调用)。
通用 Header:
| Header | 必填 | 说明 |
|---|---|---|
Authorization: Bearer <accessToken> |
是 | 复用登录 token |
X-Correlation-Id |
建议 | mcp-server 生成;全链路追踪 ID |
X-Request-Id |
建议 | 单次 HTTP 请求追踪 |
Idempotency-Key |
创建类建议 | 同 key 返回原响应(避免重复创建) |
通用错误码:
| HTTP | business code |
|---|---|
| 400 | POLICY_REJECTED (字段缺/非法 / 高危无审批) |
| 403 | MODEL_NOT_ALLOWED / FORBIDDEN_SCOPE / POLICY_REJECTED (高危) |
| 404 | NOT_FOUND |
| 409 | DEPLOYMENT_CONFLICT |
| 422 | RESOURCE_GRANT_INVALID / RESOURCE_GRANT_SECRET_REJECTED / RESOURCE_GRANT_SECRET_REF_REQUIRED |
5.1 POST /api/agnet/deployments
请求体(详见 heicode 仓库 agnet-platform-request-contract.md §2,stub 严格按其字段校验):
{
"orchestration_plan": {
"intent_id": "intent_xxx",
"template_hint": "manager-resource-binding",
"objective": "...",
"risk_level": "low",
"budget": {"max_tokens": 100000, "max_cost_usd": 30, "max_duration_sec": 7200},
"user_context": {"user_id": "...", "channel_id": "..."},
"billing_context": {"provider": "newapi"},
"agent_runtime": {"platform": "agnet", "agents": [...]},
"metadata": {"correlation_id": "corr_xxx"},
"agents": [{
"role_template": "builder",
"goal": "...",
"default_model_id": "...",
"resource_grants": [{
"grant_id": "...", "resource_id": "...", "resource_type": "git",
"user_id": "...", "binding_scope": "main",
"target_role": "builder", "target_agent_ref": "...",
"permission_scope": ["repo:read"], "status": "active",
"secret_ref": "vault://...",
"constraints": {}, "metadata": {}
}]
}]
}
}
响应 200:
{"success": true, "data": {
"deployment_id": "dep_xxx",
"status": "accepted",
"agent_instances": [{"instance_id": "agi_xxx", "role": "builder", "phase": "pending"}]
}}
校验规则(stub 已实现):
risk_level=high必须有resource_grants[].constraints.approval_id或audit.approval_idbilling_context.provider∈ {newapi,litellm}- 凭据型资源(git/sk/cloud_*)必须有
secret_ref metadata/constraints/auditkey 不得含敏感词(password/token/secret/private_key/access_key/credential)→ 422RESOURCE_GRANT_SECRET_REJECTEDtarget_role必须等于所属 agent 的role_template
5.2 GET /api/agnet/deployments
Query: user_id, binding_scope, status, limit (1-500)
响应 200: {success, data: {items: [...], total: N}}
5.3 GET /api/agnet/deployments/{id}
响应 200: 完整 deployment 详情(含 agent_instances / resource_grants_summary / budget_consumed)
5.4 POST /api/agnet/deployments/{id}/stop
请求体可空。幂等:已 stopped 重复调返 200。
5.5 GET /api/agnet/deployments/{id}/logs
Query: agent_instance_id, stream (stdout/stderr/system/audit), since, limit (1-1000), cursor
响应: {items: [{log_id, deployment_id, agent_instance_id, stream, level, message, redacted, occurred_at}], next_cursor, total}
5.6 GET /api/agnet/deployments/{id}/logs/stream (SSE)
返回 text/event-stream,事件类型:log / heartbeat / done。
5.7 GET /api/agnet/projects/{binding_scope}/dashboard-snapshot
路径名
projects是契约保留旧名,参数实际是binding_scope。
响应: {project_id, binding_scope, active_instances, phase_distribution, failure_rate_1h, avg_task_duration, budget, resource_usage, updated_at}
5.8 GET /api/agnet/deployments/{id}/metrics
Query: window (默认 15m), step (默认 60s)
响应: {deployment_id, window, step, series: [{metric, unit, points: [[time, value], ...]}, ...]}
返回 9 个 metric: tokens_used / cost_usd / duration_sec / cpu_millicores / memory_mb / restart_count / tool_call_count / error_count / queue_latency_ms
5.9 GET /api/agnet/deployments/{id}/events
事件名(mock 已 seed): deployment.accepted / instance.phase_changed / sk_snapshot_refreshed / resource_grant.attached / resource_grant.revoked / budget.threshold_reached / deployment.failed / deployment.stopped
响应: {items: [{event_id, event, schema_version, user_id, channel_id, binding_scope, deployment_id, correlation_id, occurred_at}], next_cursor, total}
5.10 GET /api/agnet/audit-logs
Query: user_id, binding_scope, actor, action, since, limit (1-1000), cursor
5.11 POST /api/agnet/sk-snapshots/resolve
请求体: {"deployment_id": "dep_xxx"}
响应: {deployment_id, items: [snapshot], total: 1}
snapshot 形态: {snapshot_id, deployment_id, user_id, binding_scope, source_type, source_ref, artifact_ref, checksum, status, resolved_at}
5.12 GET /api/agnet/deployments/{id}/sk-snapshots
Query: source_type, limit, cursor
6. 任务编排(5 接口) — cc-haha 任务驾驶舱 / 工作台 配套
字段形态严格对齐 cc-haha/desktop/src/stores/heicodeTaskStore.ts。
对象语义:用户输入想法(intent)→ Heicode 追问(followups)→ 全部答完 → 生成任务卡(TaskCard)→ 进入"准备资源 / 部署"阶段。
状态机:
draft → configuring → running → (后续 awaiting_approval / completed / failed / paused)
6.1 POST /api/user/tasks/intent
请求体:
{ "intent": "做一个面向小团队的任务协作 SaaS", "name": "可选" }
响应 200 (HeicodeTask):
{
"success": true,
"data": {
"id": "uuid",
"user_id": "uuid",
"name": "做一个面向小团队的任务协作 SaaS",
"status": "configuring",
"status_caption": "等待你回答几个问题",
"intent": "做一个面向小团队的任务协作 SaaS",
"thread": [
{"kind": "user", "text": "...", "at": 1715168400000},
{"kind": "heicode", "text": "好的。我先问你两个问题...", "at": 1715168400001,
"followups": [
{"id": "scope", "question": "你希望第一阶段交付到什么程度?",
"options": [
{"id": "mvp", "label": "MVP:能跑通主流程"},
{"id": "polish", "label": "完整功能 + UI 细节打磨"},
{"id": "prod", "label": "直接上生产", "risk": "high-risk"}
]},
{"id": "tech", "question": "技术栈倾向?",
"options": [
{"id": "modern_web", "label": "现代 Web(React + Node/Python)"},
{"id": "py_backend", "label": "Python 后端为主"},
{"id": "let_heicode", "label": "让 Heicode 决定"}
]}
]}
],
"card": null,
"created_at": 1715168400000,
"updated_at": 1715168400000
}
}
6.2 GET /api/user/tasks
Query: status, limit (1-200), offset
响应: {items: [HeicodeTask], total, offset, limit}
6.3 GET /api/user/tasks/{id}
响应: 单个 HeicodeTask
错误: 404 NOT_FOUND / 403 FORBIDDEN_SCOPE(跨用户)
6.4 POST /api/user/tasks/{id}/answer
请求体: {"question_id": "scope", "option_id": "mvp"}
响应 200:返回更新后的 HeicodeTask。
- 还有未答的 followup →
status仍configuring,card仍 null - 所有 followup 都答完 →
status→running,card自动生成:
{
"card": {
"goal": "做一个面向小团队的任务协作 SaaS",
"scope": ["MVP 范围:核心功能跑通", "技术债务可后续清理", "暂不做高级 UI/性能优化"],
"generated_artifacts": ["产品说明", "原型描述", "技术方案", "代码骨架(React + Node/Python 后端)"],
"manager_actions": [
{"label": "去 Manager 准备资源", "deeplink": "/manager/resources?from=task"},
{"label": "查看团队建议", "deeplink": "/manager/team?from=task"}
]
}
}
错误:
- 400
INVALID_OPTION— option_id 不在该 followup 的 options 列表里 - 404
QUESTION_NOT_FOUND— question_id 不存在 - 400
TASK_STATE_INVALID— task 当前 status 不允许再答
6.5 POST /api/user/tasks/{id}/messages
请求体: {"text": "再补充:希望支持飞书集成"}
响应 200:thread 追加 user 消息 + heicode ack("收到。我会把这条要求纳入任务上下文。")。MVP 不再触发新 followups。
6.6 GET /api/user/tasks/{id}/execution(Slice 8 — 执行反馈)
请求: 仅需 Authorization: Bearer <jwt>,无 query。
响应 200:ExecutionState(字段对齐 cc-haha/desktop/src/stores/heicodeTaskStore.ts:ExecutionState)
{
"success": true,
"data": {
"sub_steps": [
{"id":"step_1","title":"需求分解","status":"done","caption":"已完成","at": 1778237397000}
// status ∈ done|running|waiting|failed|skipped
],
"sk_tool_calls": [
{"id":"tc_1","name":"read_codebase","status":"done","summary":"...","at": 1778237397200}
],
"events": [
{"id":"ev_1","level":"info","message":"任务启动...","at": 1778237397100}
// level ∈ info|warn|error
],
"artifacts": [
{"id":"art_1","kind":"doc","label":"产品说明(PRD)","url":"/manager/artifacts/<task_id>/prd.md"}
// kind ∈ doc|api|diff|report
],
"spend_today": "¥12.30" // 可空
}
}
生命周期约束:仅 task.status ∈ {running, awaiting_approval, completed} 才有数据;其他状态返回空 ExecutionState(5 个字段都是空数组 / spend_today=null)。前端可据此显示"等待启动"占位。
错误: 404 NOT_FOUND / 403 FORBIDDEN_SCOPE / 401。
6.7 GET /api/user/tasks/{id}/delivery(Slice 9 — 交付结果)
响应 200:DeliveryResult
{
"success": true,
"data": {
"summary": "任务「...」已交付。包含产品说明、代码骨架、测试报告 3 大类产物...",
"deliverables": [
{
"id":"deliv_1","kind":"product-spec","title":"产品说明 PRD v1",
"primary_action": {"label":"查看文档","deeplink":"/manager/artifacts/<task_id>/prd.md"},
"secondary_action": {"label":"...","deeplink":"..."} // 可选
}
// kind ∈ product-spec|code-diff|test-env|prod-env
],
"quality": [
{"id":"q_1","label":"单元测试覆盖率","status":"pass","detail":"82%"}
// status ∈ pass|warn|fail
],
"next_actions": [
{"label":"去 Manager 准备资源","intent":"manager.resources"}
]
}
}
生命周期约束:仅 task.status == "completed" 时返回完整数据;其他状态所有字段都为空字符串 / 空数组。前端可据此显示"任务尚未完成"占位。
错误: 404 / 403 / 401。
6.8 GET /api/user/tasks/{id}/audit(Slice 10 — 任务详情抽屉)
Query: tab 可选,∈ usage | resources | approvals | security。不传则一次性返回 4 个 tab 全量;传则只填该 tab,其他 tab 字段返回空数组(schema 始终稳定)。
响应 200:TaskAudit
{
"success": true,
"data": {
"usage": [{"id":"u_1","model":"gpt-4o-mini","input_tokens":12400,"output_tokens":3200,"cost":"¥4.20","at_iso":"2026-05-08T..."}],
"resources": [{"id":"r_1","resource":"git/heicode-frontend","scope":"read","last_used_iso":"2026-05-08T..."}],
"approvals": [{"id":"<approval_uuid>","operation":"deploy","target_resource":"prod-cluster","risk_level":"high","decision":"approve","enqueued_iso":"...","resolved_iso":"..."}],
"security": [{"id":"s_1","event":"task_created","level":"info","at_iso":"..."}]
}
}
approvals tab 是真表查询(heicode_approvals where task_id=...,按 enqueued_at DESC,limit 50),其他 3 tab 当前是 deterministic mock,后续可接入真实数据源(usage 接 NewAPI logs / resources 接 resource_grants 使用日志 / security 接 audit_logs)。
错误:
- 400
INVALID_TAB— tab 不在允许枚举内 - 404 / 403 / 401
7. Server-Sent Events(单通道事件推送)
状态:契约定义(mcp-server 端实现待发,预计 Day 2.5 上线 — 见
Heicode-对接进度与待办.md §7.11.1)。本节字段形态已冻结,cc-haha 可立即按此搭 Slice 15 SSE 订阅骨架。
7.0 公共说明
mcp-server 提供唯一一条 SSE 长连接给前端订阅所有用户级实时事件(高危审批、任务状态、执行进度、保活)。
合并成单通道的好处:
- 客户端只维护 1 个 EventSource(节省资源)
- 后端只管 1 个推送泵
- 不同事件类型按 SSE
event:字段路由,互不冲突
7.1 GET /api/user/events/stream
用途:当前登录用户的实时事件流。
请求:
GET /api/user/events/stream
Accept: text/event-stream
Authorization: Bearer <accessToken>
⚠️ 浏览器
EventSource不支持自定义 header。前端建议用fetch+ReadableStream手动解析 SSE,或使用支持 header 的 polyfill(如eventsource-polyfill)。
响应: 200 OK,Content-Type: text/event-stream,长连接。
事件路由(按 SSE event: 字段):
| event 类型 | 用途 |
|---|---|
approval.requested |
高危审批请求 — 弹审批弹窗 |
approval.resolved |
审批已被响应(其他设备处理 / 过期)— 关闭对应弹窗 |
task.status_changed |
任务 status 变化 — 切右侧面板 |
task.execution_progress |
sub_step 状态变化 — 刷新执行反馈面板 |
heartbeat |
保活(每 25s) |
7.2 event: approval.requested
字段对齐 cc-haha desktop/src/stores/approvalStore.ts:ApprovalRequest。
SSE 帧:
event: approval.requested
data: {"approval_id":"apr_xxx","task_id":"task_xxx","task_name":"…","operation":"在生产环境部署服务","target_resource":"vm://newapi-prod","requesting_role":"operator","risk_level":"high","impact_summary":["重启服务","回滚预案已备好"],"heicode_suggestion":"approve","derives_short_lived_credential":true,"ttl_minutes":60,"enqueued_at":"2026-05-08T10:00:00Z"}
字段:
| 字段 | 类型 | 说明 |
|---|---|---|
approval_id |
string | 审批唯一 ID |
task_id |
string | 关联任务 ID(可空,如系统级审批) |
task_name |
string | 任务名(弹窗显示) |
operation |
string | 待批准的操作描述 |
target_resource |
string | 受影响资源(如 vm://newapi-prod / repo://org/foo) |
requesting_role |
string | 发起请求的子 Agent 角色(builder / operator / reviewer 等) |
risk_level |
enum | low / medium / high |
impact_summary |
string[] | 影响摘要 bullet 列表 |
heicode_suggestion |
enum | Heicode 给出的建议:approve / reject / delegate |
derives_short_lived_credential |
bool | 批准后是否会生成短期凭据注入 Pod |
ttl_minutes |
int | 审批有效时长(minutes),过期自动 expired |
enqueued_at |
string (ISO 8601) | 入队时间 |
7.3 event: approval.resolved
SSE 帧:
event: approval.resolved
data: {"approval_id":"apr_xxx","decision":"approve","resolved_by":"user_55","resolved_at":"2026-05-08T10:01:23Z"}
| 字段 | 类型 | 说明 |
|---|---|---|
approval_id |
string | 与 approval.requested 对应 |
decision |
enum | approve / reject / expired |
resolved_by |
string | null | 谁做的决定(其他设备同步时使用;expired 时为 null) |
resolved_at |
string (ISO 8601) | 决定时间 |
客户端收到该事件应关闭对应 approval_id 的弹窗(避免多设备登录时弹窗鬼影)。
7.4 event: task.status_changed
SSE 帧:
event: task.status_changed
data: {"task_id":"task_xxx","old_status":"running","new_status":"completed","status_caption":"已交付","at":"2026-05-08T10:05:00Z"}
| 字段 | 类型 | 说明 |
|---|---|---|
task_id |
string | 任务 ID |
old_status |
string | 之前的 status(参见 §6.1 task.status 枚举) |
new_status |
string | 当前 status |
status_caption |
string | null | 副标题(如"等待生产部署审批") |
at |
string (ISO 8601) | 变化时间 |
客户端应据此切换右侧面板(running/awaiting_approval → ExecutionFeedbackPanel;completed → DeliveryResultPanel)。
7.5 event: task.execution_progress
SSE 帧:
event: task.execution_progress
data: {"task_id":"task_xxx","sub_step_id":"step_compile","status":"done","caption":"编译通过","at":"2026-05-08T10:03:12Z"}
| 字段 | 类型 | 说明 |
|---|---|---|
task_id |
string | 任务 ID |
sub_step_id |
string | 步骤 ID(与 /api/user/tasks/{id}/execution 返回的 sub_steps[].id 对应) |
status |
enum | waiting / running / done / failed / skipped |
caption |
string | null | 步骤当前描述 |
at |
string (ISO 8601) | 变化时间 |
客户端应据此就地刷新 ExecutionFeedbackPanel 中对应 sub_step 行(不需要重拉整个 execution)。
7.6 event: heartbeat
SSE 帧:
event: heartbeat
data: {"server_time":"2026-05-08T10:00:25Z"}
| 字段 | 类型 | 说明 |
|---|---|---|
server_time |
string (ISO 8601) | 服务端时间,便于客户端检测时钟漂移 |
发送频率:每 25 秒一次。客户端 60 秒未收到 heartbeat 应主动重连。
7.7 配套 REST 端点
实时通道之外,前端启动时需要拉一次"当前未处理审批",并提供"用户响应审批"入口:
7.7.1 GET /api/user/approvals
用途:拉取当前用户待响应的审批列表(启动时调一次,后续靠 SSE 增量)。
响应 200:
{
"success": true,
"data": {
"items": [/* ApprovalRequest 对象数组,字段同 §7.2 */],
"total": 0
}
}
7.7.2 POST /api/user/approvals/{approval_id}/decision
用途:用户在弹窗里选择批准/拒绝。
请求体:
{ "decision": "approve" }
decision ∈ approve / reject(不能传 expired,那是服务端自动设置)。
响应 200: 返回更新后的 ApprovalRequest 对象(含 decision / resolved_by / resolved_at)。
mcp-server 此时会广播 approval.resolved 事件到该用户所有 SSE 连接(其他设备的弹窗会自动关闭)。
错误响应:
| HTTP | code | 含义 |
|---|---|---|
| 404 | NOT_FOUND |
approval_id 不存在 |
| 403 | FORBIDDEN_SCOPE |
该审批不属于当前用户 |
| 410 | APPROVAL_EXPIRED |
已超时,决定无效 |
| 409 | ALREADY_RESOLVED |
已被响应(其他设备处理) |
7.8 错误处理(SSE)
| 场景 | mcp-server 行为 | 客户端建议 |
|---|---|---|
| 401(token 过期) | 立即关闭流 | 调 /api/auth/refresh 后重连 |
| 503 / 网络抖动 | — | 指数退避重连(1s / 2s / 5s / 10s) |
| 60s 无 heartbeat | — | 主动重连 |
7.9 客户端订阅最简实现(参考)
// cc-haha/desktop/src/lib/heicodeEventStream.ts
async function subscribe(token: string, handlers: { [evt: string]: (data: any) => void }) {
const res = await fetch(`${BASE}/api/user/events/stream`, {
headers: { Authorization: `Bearer ${token}`, Accept: 'text/event-stream' },
})
const reader = res.body!.getReader()
const decoder = new TextDecoder()
let buf = ''
while (true) {
const { value, done } = await reader.read()
if (done) break
buf += decoder.decode(value, { stream: true })
let idx
while ((idx = buf.indexOf('\n\n')) !== -1) {
const frame = buf.slice(0, idx); buf = buf.slice(idx + 2)
const evtLine = frame.split('\n').find(l => l.startsWith('event:'))
const dataLine = frame.split('\n').find(l => l.startsWith('data:'))
if (!evtLine || !dataLine) continue
const event = evtLine.slice(6).trim()
const data = JSON.parse(dataLine.slice(5).trim())
handlers[event]?.(data)
}
}
}
10. 版本历史
| 版本 | 日期 | 变更 |
|---|---|---|
| v1.0 | 2026-05-05 | 初版:登录 4 接口 + P1 资源模型 9 接口 |
| v2.0 | 2026-05-08 | + NewAPI 元数据透传 4 接口(§4) + Agnet stub 12 接口(§5) + 任务编排 5 接口(§6)。总计 34 接口 |
| v2.1 | 2026-05-08 | + SSE 单通道事件推送契约(§7)+ 配套审批 REST 2 接口(§7.7)。冻结字段形态供 cc-haha Slice 15 起骨架;mcp-server 实现 Day 2.5 上线 |
待开发(参考 Heicode-对接进度与待办.md):
- 高危审批 SSE 推送(cc-haha 客户端 ApprovalDialog 配套)
- P2 Secret Broker(等 Vault 部署)
- P5 出站调用真实 Agnet 平台(等 agent-manager 12 接口)
B. Heicode 团队待办清单
按 mcp-server 当前已交付的能力,Heicode 这边需要做以下 5 件事让全链路真跑起来。括号内是优先级与阻塞影响。
B-1 配置 NewAPI service token(🔴 高优 — 阻塞 P4 真跑)
Heicode 端要做:
- 在 NewAPI 创建一个专用账号
mcp-server-service,角色 = admin - 生成永久 access token
- 把 token + admin user_id 给 mcp-server 团队(通过安全通道,绝不写 Git/聊天/邮件)
mcp-server 端要做(拿到后 ~30 分钟):
- 通过 K8s secret 注入 env:
HEICODE_NEWAPI_SERVICE_TOKEN+HEICODE_NEWAPI_ADMIN_USER_ID kubectl rollout restart即可生效(无需重新构建镜像)
B-2 答复 P4 2 个细节(🟡 中优 — 不阻塞但影响实现细节)
详见 Heicode-对接进度与待办.md §2.3.2。两个问题:
- 细节①:mcp-server 调 NewAPI 时
New-Api-User怎么映射到 heicode 本地 user_id?(mcp-server 当前用 admin search by email,工作但有 1 次往返开销) - 细节②:子 Agent 部署
billing_context.provider怎么决定?(mcp-server 默认litellm,需 Heicode 用户场景默认newapi时给规则)
B-3 协调 heicode web 团队对接 P1 资源绑定 UI(🟡 中优)
cc-haha 桌面客户端切片 5 已下线 P1 UI(按 Heicode 产品包 08-client-guide.md 边界)。资源绑定 UI 现在归 heicode web (code.xinghanlab.com)。需要:
- heicode web 团队接 mcp-server 的 9 个 P1 接口(§2 / §3)
- 否则用户从客户端任务卡点"去 Manager 准备"会 404
B-4 推动 agent-manager 团队实现 12 真实接口(🟢 中优 — 阻塞 P5 出站联调)
agent-manager 12 接口契约见:
- Heicode 仓库
docs/integration/agnet-platform-request-contract.md - mcp-server 仓库
Docs/Agent-Manager-Heicode对接需求文档.md
mcp-server 已上线 stub(§5)字段形态完全一致,agent-manager 实装时可直接对照。
Heicode 这边要给 mcp-server:
- agent-manager 团队对接负责人
- staging 联调环境地址(建议
staging-agnet.xinghanlab.com) - 服务令牌方案确认(建议 A pre-shared bearer 起步)
B-5 联调测试(🟢 低优 — 可并行)
cc-haha 客户端 / heicode web 拿到本文档后即可开始联调:
- 登录链路(§1)已实测,无需 mcp-server 配合
- P1 资源(§2 / §3)已实测,无需 mcp-server 配合
- Agnet stub(§5)已实测,前端可立即开始任务执行联调
- 任务编排(§6)已实测,cc-haha 可立即把任务驾驶舱 / 工作台从 mock 切真
- NewAPI 透传(§4)等 B-1 完成后真跑
如发现接口问题,按 §9 排障流程提交。
C. 总账速查
| 模块 | 章节 | 端点数 | 状态 |
|---|---|---|---|
| 登录认证 | §1 | 4 | ✅ 上线 + Heicode 已对接 |
| P1 资源绑定 | §2 | 5 | ✅ 上线 |
| P1 资源授权 | §3 | 4 | ✅ 上线 |
| P4 NewAPI 透传 | §4 | 4 | ✅ 上线(待 B-1 token 真跑) |
| P5 Agnet stub | §5 | 12 | ✅ 上线(mock 数据) |
| 任务编排 | §6 | 5 | ✅ 上线 |
| 合计 | — | 34 | 全部上线 |