chore: initial import — heicode manager + website
This commit is contained in:
@@ -0,0 +1,372 @@
|
||||
# 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 反查日志)
|
||||
|
||||
@@ -0,0 +1,961 @@
|
||||
# Manager → Agnet 平台接口参数文档
|
||||
|
||||
**版本**: v0.3(P1/P5 联调契约)
|
||||
**生效日期**: 2026-05-03
|
||||
**状态**: 联调准备;当前仓库提供 Manager 侧最小验证端点,生产 Agnet 平台部署尚未在本文档中宣称完成。
|
||||
**方向**: Heicode Manager 主动请求 Agnet 平台;Agnet 平台返回部署、日志、监控与审计状态。
|
||||
**范围**: 创建/停止子 Agent 部署、查询部署、获取事件/日志/监控快照、解析 SK 快照、查询审计日志,以及 Agnet 辅助 NewAPI 重建/部署的参数约定。
|
||||
|
||||
> 2026-05-04 边界修正:Manager 当前不把 `tenant/project` 作为产品、认证或扣费主轴。新请求应使用 `user_context.user_id`、`user_context.channel_id`、`resource_grants[].binding_scope`、`billing_context(newapi)` 和 `agent_runtime(agnet)`。本文中仍出现的 `tenant_id/project_id` 只表示旧字段兼容或历史接口命名,不应作为新功能设计依据。
|
||||
**安全红线**: 请求体只允许传资源元数据、权限范围与 `secret_ref`/环境变量名;不得传明文密码、Token、私钥、连接串或云访问密钥。
|
||||
|
||||
> 本文档描述 Manager 对 Agnet 平台的出站集成契约。当前仓库中 `/api/agnet/*` 是 Manager 侧最小控制面/模拟端点,用于校验同一套 payload 结构;生产接入时,Manager 应将下列请求发送到 Agnet 平台网关。
|
||||
|
||||
## 0. 概述
|
||||
|
||||
本文档按登录接口文档的对接方式组织:先定义接入信息,再逐个接口给出请求、响应、错误和安全约束。接口分组如下:
|
||||
|
||||
| 接口 | 用途 | 当前性质 |
|
||||
|---|---|---|
|
||||
| `POST /api/agnet/deployments` | 创建子 Agent/运维任务部署,含 NewAPI 重建/部署场景 | 必需 |
|
||||
| `GET /api/agnet/deployments` | 查询部署列表 | 必需 |
|
||||
| `GET /api/agnet/deployments/{deployment_id}` | 查询单个部署详情 | 必需 |
|
||||
| `POST /api/agnet/deployments/{deployment_id}/stop` | 停止部署或取消排队任务 | 必需 |
|
||||
| `GET /api/agnet/deployments/{deployment_id}/logs` | 拉取部署日志 | 必需 |
|
||||
| `GET /api/agnet/deployments/{deployment_id}/logs/stream` | 实时日志 SSE | 可选 |
|
||||
| `GET /api/agnet/projects/{project_id}/dashboard-snapshot` | 资源作用域监控快照;路径名保留旧兼容,参数值按 `binding_scope` 解释 | 必需 |
|
||||
| `GET /api/agnet/deployments/{deployment_id}/metrics` | 单部署指标序列 | 建议 |
|
||||
| `GET /api/agnet/deployments/{deployment_id}/events` | 部署事件 | 必需 |
|
||||
| `GET /api/agnet/audit-logs` | 审计日志 | 必需 |
|
||||
| `POST /api/agnet/sk-snapshots/resolve` | 触发 SK 快照解析 | 必需 |
|
||||
| `GET /api/agnet/deployments/{deployment_id}/sk-snapshots` | 查询 SK 快照 | 必需 |
|
||||
|
||||
> 不在本文档范围:真实 Secret Store 写入、生产 SSH 登录、云账号授权回调、NewAPI 管理后台开放。生产部署动作只有实际执行并通过日志/监控/审计验证后,才能在报告中标记为“已部署”。
|
||||
|
||||
---
|
||||
|
||||
## 1. 接入约定
|
||||
|
||||
### 1.1 Base URL
|
||||
|
||||
由部署环境配置,不写入仓库。例如:
|
||||
|
||||
```text
|
||||
AGNET_PLATFORM_BASE_URL=https://agnet-platform.example.com
|
||||
```
|
||||
|
||||
联调环境建议使用独立域名或内网网关,示例不得包含真实凭据:
|
||||
|
||||
```text
|
||||
AGNET_PLATFORM_BASE_URL=https://staging-agnet.example.com
|
||||
MANAGER_SERVICE_TOKEN_SECRET_REF=vault://secret/users/manager-service/bindings/agnet-platform/service-token
|
||||
```
|
||||
|
||||
完整路径示例:
|
||||
|
||||
```http
|
||||
POST https://agnet-platform.example.com/api/agnet/deployments
|
||||
```
|
||||
|
||||
### 1.2 通用 Header
|
||||
|
||||
| Header | 必填 | 说明 |
|
||||
|---|---:|---|
|
||||
| `Authorization: Bearer <manager-service-token>` | 是 | Manager 服务身份令牌,由 Secret Store/运行环境注入。 |
|
||||
| `Content-Type: application/json` | POST/PUT 是 | JSON 请求体。 |
|
||||
| `X-User-Id: <user_id>` | 建议 | 登录用户边界;也可从 Manager 服务端 token 或 body `user_context.user_id` 推导。 |
|
||||
| `X-Binding-Scope: <binding_scope>` | 建议 | Git/SK/云资源作用域;也可从 `resource_grants[].binding_scope` 推导。 |
|
||||
| `X-Correlation-Id: <uuid>` | 是 | Manager 生成,全链路追踪。 |
|
||||
| `X-Request-Id: <uuid>` | 建议 | 单次 HTTP 请求追踪 ID,可与 correlation_id 不同。 |
|
||||
| `Idempotency-Key: <uuid>` | 创建类接口建议 | 避免重试造成重复部署。 |
|
||||
|
||||
### 1.3 通用响应包裹
|
||||
|
||||
成功:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
失败:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "human readable message",
|
||||
"error": {
|
||||
"code": "POLICY_REJECTED",
|
||||
"message": "human readable message",
|
||||
"request_id": "req_xxx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
建议错误码:
|
||||
|
||||
| code | 场景 |
|
||||
|---|---|
|
||||
| `POLICY_REJECTED` | 缺必填字段、权限策略不满足、风险等级非法。 |
|
||||
| `BUDGET_EXCEEDED` | 超过 token/金额/时长预算。 |
|
||||
| `MODEL_NOT_ALLOWED` | agent 默认模型不在允许列表内。 |
|
||||
| `FORBIDDEN_SCOPE` | Header 与 body/query 的用户或资源作用域不一致。 |
|
||||
| `RESOURCE_GRANT_INVALID` | Resource Grant 字段缺失、跨用户/跨资源作用域/角色不匹配。 |
|
||||
| `RESOURCE_GRANT_SECRET_REF_REQUIRED` | 凭据型资源缺少 `secret_ref`。 |
|
||||
| `RESOURCE_GRANT_SECRET_REJECTED` | 请求中出现明文密钥字段。 |
|
||||
| `SK_SOURCE_UNRESOLVABLE` | SK 来源不可解析。 |
|
||||
| `DEPLOYMENT_CONFLICT` | 部署不存在、状态冲突或重复提交。 |
|
||||
| `NOT_FOUND` | deployment、agent instance、snapshot 或审计资源不存在。 |
|
||||
| `CURSOR_EXPIRED` | 分页游标过期或不属于当前查询条件。 |
|
||||
| `RATE_LIMITED` | 平台限流;响应头建议包含 `Retry-After`。 |
|
||||
| `INTERNAL_ERROR` | 平台内部错误;Manager 应记录 request_id 并重试或提示稍后处理。 |
|
||||
|
||||
### 1.4 通用错误处理
|
||||
|
||||
| HTTP | business code | Manager 处理建议 |
|
||||
|---:|---|---|
|
||||
| 400 | `POLICY_REJECTED` / `RESOURCE_GRANT_INVALID` | 标记部署失败,展示校验原因,不自动重试。 |
|
||||
| 401 | `UNAUTHORIZED` | 检查 Manager 服务令牌的 `secret_ref`/环境注入,不把令牌写入日志。 |
|
||||
| 403 | `FORBIDDEN_SCOPE` / `MODEL_NOT_ALLOWED` | 阻断本次部署,写审计事件。 |
|
||||
| 404 | `NOT_FOUND` | 对查询类接口返回空态;对控制类接口提示资源不存在。 |
|
||||
| 409 | `DEPLOYMENT_CONFLICT` | 使用 `Idempotency-Key` 查询既有结果,避免重复创建。 |
|
||||
| 410 | `CURSOR_EXPIRED` | 丢弃 cursor,使用 `since` 重新拉取。 |
|
||||
| 422 | `RESOURCE_GRANT_SECRET_REF_REQUIRED` / `RESOURCE_GRANT_SECRET_REJECTED` | 要求 Manager 重新生成只含 `secret_ref` 的 payload。 |
|
||||
| 429 | `RATE_LIMITED` | 按 `Retry-After` 退避重试。 |
|
||||
| 500/503 | `INTERNAL_ERROR` | 指数退避重试;超过阈值后转人工排查。 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 创建子 Agent 部署
|
||||
|
||||
### 2.1 Endpoint
|
||||
|
||||
```http
|
||||
POST /api/agnet/deployments
|
||||
```
|
||||
|
||||
### 2.2 请求体
|
||||
|
||||
```json
|
||||
{
|
||||
"orchestration_plan": {
|
||||
"intent_id": "intent_20260502_001",
|
||||
"template_hint": "manager-resource-binding",
|
||||
"objective": "为已绑定的代码仓库启动 builder 子 Agent,允许其读取 SK 并在限定路径内提交代码",
|
||||
"risk_level": "low",
|
||||
"budget": {
|
||||
"max_tokens": 100000,
|
||||
"max_cost_usd": 30,
|
||||
"max_duration_sec": 7200
|
||||
},
|
||||
"user_context": {
|
||||
"user_id": "user_123",
|
||||
"email": "user@example.com",
|
||||
"role": "user",
|
||||
"channel_id": "channel_abc",
|
||||
"subscription_tier": "pro"
|
||||
},
|
||||
"billing_context": {
|
||||
"provider": "newapi",
|
||||
"newapi_user_ref": "newapi_user_123",
|
||||
"newapi_group": "development",
|
||||
"quota_ref": "newapi_token_or_group_quota_ref"
|
||||
},
|
||||
"agent_runtime": {
|
||||
"platform": "agnet",
|
||||
"agents": [
|
||||
{
|
||||
"role": "builder",
|
||||
"model_ref": "agnet_model_profile_builder",
|
||||
"instance_count": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"constraints": {
|
||||
"allowed_model_ids": ["gpt-5.4-mini", "gpt-5.4"]
|
||||
},
|
||||
"metadata": {
|
||||
"tenant_id": "legacy-user-scope",
|
||||
"project_id": "legacy-resource-scope",
|
||||
"correlation_id": "corr_20260502_001"
|
||||
},
|
||||
"agents": [
|
||||
{
|
||||
"role_template": "builder",
|
||||
"goal": "按 Manager 下发的任务在允许资源内完成实现、验证并回传状态",
|
||||
"default_model_id": "gpt-5.4-mini",
|
||||
"sk_sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"mime": "text/markdown",
|
||||
"repo_ref": {
|
||||
"connection_id": "conn_sk_repo_001",
|
||||
"repo_url": "https://example.com/org/sk-repo.git",
|
||||
"ref": "main",
|
||||
"paths": ["skills/heicode/**", "AGENTS.md"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"runtime_execution": {
|
||||
"profile_id": "aks-codex-standard",
|
||||
"cloud_principal_refs": ["principal://users/user_123/agnet-runtime"],
|
||||
"network_policy_ref": "netpol://bindings/repo_default/restricted-egress"
|
||||
},
|
||||
"sk_access_policy": {
|
||||
"policy_ref": "sk-policy://bindings/repo_default/default-readonly",
|
||||
"deny_skill_ids": ["dangerous-shell"],
|
||||
"inherit_deployment_defaults": true
|
||||
},
|
||||
"resource_grants": [
|
||||
{
|
||||
"grant_id": "grant_git_repo_001",
|
||||
"resource_id": "res_git_repo_001",
|
||||
"resource_type": "git",
|
||||
"user_id": "user_123",
|
||||
"binding_scope": "repo_default",
|
||||
"tenant_id": "legacy-user-scope",
|
||||
"project_id": "legacy-resource-scope",
|
||||
"target_role": "builder",
|
||||
"target_agent_ref": "agent-builder-1",
|
||||
"permission_scope": ["repo:read", "repo:write:current-branch"],
|
||||
"constraints": {
|
||||
"ref": "main",
|
||||
"allowed_paths": "heicode/**,docs/**",
|
||||
"forbid_branch_create": "true"
|
||||
},
|
||||
"metadata": {
|
||||
"provider": "gitee",
|
||||
"repo_url": "https://example.com/org/repo.git"
|
||||
},
|
||||
"status": "active",
|
||||
"secret_ref": "vault://secret/users/user_123/bindings/repo_default/resources/res_git_repo_001",
|
||||
"audit": {
|
||||
"created_by": "manager",
|
||||
"approval_id": "approval_001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"grant_id": "grant_doc_001",
|
||||
"resource_id": "res_project_doc_001",
|
||||
"resource_type": "project_doc",
|
||||
"user_id": "user_123",
|
||||
"binding_scope": "repo_default",
|
||||
"tenant_id": "legacy-user-scope",
|
||||
"project_id": "legacy-resource-scope",
|
||||
"target_role": "builder",
|
||||
"target_agent_ref": "agent-builder-1",
|
||||
"permission_scope": ["doc:read"],
|
||||
"constraints": {
|
||||
"doc_paths": "docs/heicode.md,docs/plan.md"
|
||||
},
|
||||
"metadata": {
|
||||
"doc_ref": "project-doc://project-a/docs-mainline"
|
||||
},
|
||||
"status": "active",
|
||||
"audit": {
|
||||
"created_by": "manager"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 字段说明
|
||||
|
||||
#### orchestration_plan
|
||||
|
||||
| 字段 | 类型 | 必填 | 约束/说明 |
|
||||
|---|---|---:|---|
|
||||
| `intent_id` | string | 是 | Manager 侧意图 ID,用于幂等、审计和追踪。 |
|
||||
| `template_hint` | string | 是 | Agnet 平台选择编排模板的提示,如 `manager-resource-binding`。 |
|
||||
| `objective` | string | 是 | 本次部署目标,应是自然语言但不能含密钥。 |
|
||||
| `risk_level` | enum | 是 | `low` / `medium` / `high`。高风险必须携带客户端审批证据;缺失或不匹配时只能只读或拒绝执行。 |
|
||||
| `budget.max_tokens` | int | 是 | 当前策略上限建议不超过 `500000`。 |
|
||||
| `budget.max_cost_usd` | number | 是 | 当前策略上限建议不超过 `200`。 |
|
||||
| `budget.max_duration_sec` | int | 是 | 当前策略上限建议不超过 `86400`。 |
|
||||
| `user_context` | object | 建议 | 登录用户上下文,优先使用 Heicode/Agnet 登录返回的 `user.id`/`channelId`。 |
|
||||
| `billing_context` | object | 条件 | NewAPI 扣费上下文;只表达 user/token/group/quota 映射,不表达子 Agnet 模型或实例数。 |
|
||||
| `agent_runtime` | object | 条件 | Agnet 平台运行时上下文;表达子 Agnet 角色、模型 profile 和实例数,不承载 NewAPI key 或扣费对象。 |
|
||||
| `constraints.allowed_model_ids` | string[] | 否 | agent 的 `default_model_id` 如填写,必须在此列表内。 |
|
||||
| `metadata.tenant_id` | string | 否 | 旧兼容字段;新实现不得作为产品租户边界。 |
|
||||
| `metadata.project_id` | string | 否 | 旧兼容字段;新实现不得作为项目账本边界。 |
|
||||
| `metadata.correlation_id` | string | 是 | 全链路追踪 ID。 |
|
||||
| `agents` | array | 是 | 至少 1 个子 Agent。 |
|
||||
|
||||
#### user_context / billing_context / agent_runtime
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---:|---|
|
||||
| `user_context.user_id` | string | 建议 | Manager 业务用户 ID,来自登录接口 `id` 或 JWT `sub`。 |
|
||||
| `user_context.channel_id` | string | 建议 | 用于关联 NewAPI 用户、Token、Group、余额或额度策略。 |
|
||||
| `billing_context.provider` | enum | 条件 | 当前只允许 `newapi`。设置后必须提供 `channel_id`、`newapi_user_ref`、`newapi_group` 或 `quota_ref` 之一。 |
|
||||
| `billing_context.newapi_user_ref` | string | 否 | NewAPI 用户映射引用,不是 NewAPI key。 |
|
||||
| `billing_context.newapi_group` | string | 否 | NewAPI Group 映射,用于额度或策略选择。 |
|
||||
| `billing_context.quota_ref` | string | 否 | Token 或 Group 额度引用,不得包含真实 Token 原文。 |
|
||||
| `agent_runtime.platform` | enum | 条件 | 当前只允许 `agnet`。 |
|
||||
| `agent_runtime.agents[].role` | string | 条件 | 必须匹配 `agents[].role_template`。 |
|
||||
| `agent_runtime.agents[].model_ref` | string | 条件 | Agnet 平台模型 profile 引用;不是 NewAPI 扣费字段。 |
|
||||
| `agent_runtime.agents[].instance_count` | int | 条件 | 子 Agnet 实例数量,必须大于 0。 |
|
||||
|
||||
#### agents[]
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---:|---|
|
||||
| `role_template` | string | 是 | 平台角色模板,如 `builder`/`reviewer`/`operator`。 |
|
||||
| `goal` | string | 是 | 此 agent 的任务目标。 |
|
||||
| `default_model_id` | string | 否 | 默认模型;若设置需满足 allowed_model_ids。 |
|
||||
| `sk_sources` | array | 否 | SK 来源,平台应解析为只读快照。 |
|
||||
| `runtime_execution` | object | 否 | 运行环境绑定;任一字段存在时 `profile_id` 必填。 |
|
||||
| `sk_access_policy` | object | 否 | SK 权限策略。若 `deny_skill_ids` 非空,需 `policy_ref` 或继承默认策略。 |
|
||||
| `resource_grants` | array | 否 | Manager 下发给子 Agent 的最小权限资源授权。 |
|
||||
|
||||
#### sk_sources[]
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---:|---|
|
||||
| `type` | enum | 否 | 空值表示不启用;支持 `git`、`upload`。 |
|
||||
| `artifact_id` | string | upload 必填 | 上传型 SK 包 ID。 |
|
||||
| `mime` | string | 否 | 内容类型,如 `text/markdown`。 |
|
||||
| `repo_ref.connection_id` | string | git 建议 | Git 连接资源 ID。 |
|
||||
| `repo_ref.repo_url` | string | git 建议 | 仓库 URL;不得带用户名密码。 |
|
||||
| `repo_ref.ref` | string | git 必填 | 分支/标签/commit。 |
|
||||
| `repo_ref.paths` | string[] | git 必填 | 允许读取的路径。 |
|
||||
|
||||
#### runtime_execution
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---:|---|
|
||||
| `profile_id` | string | 条件必填 | Agnet 平台运行规格,如 AKS profile。 |
|
||||
| `cloud_principal_refs` | string[] | 否 | 运行身份引用,不是明文凭据。 |
|
||||
| `network_policy_ref` | string | 否 | 网络策略引用,用于限制出站/入站。 |
|
||||
|
||||
#### resource_grants[]
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|---|---|---:|---|
|
||||
| `grant_id` | string | 是 | 授权记录 ID。 |
|
||||
| `resource_id` | string | 是 | Manager 资源 ID。 |
|
||||
| `resource_type` | enum | 是 | `git` / `sk` / `project_doc` / `cloud_account` / `cloud_resource`。 |
|
||||
| `user_id` | string | 建议 | 与 `user_context.user_id` 一致;为空时平台可从部署上下文推导。 |
|
||||
| `binding_scope` | string | 是 | Git/SK/云资源作用域,例如 repo/ref/path 或云资源引用。 |
|
||||
| `tenant_id` | string | 否 | 旧兼容字段;新实现不应依赖。 |
|
||||
| `project_id` | string | 否 | 旧兼容字段;新实现不应依赖。 |
|
||||
| `target_role` | string | 是 | 必须等于当前 agent 的 `role_template`。 |
|
||||
| `target_agent_ref` | string | 是 | Manager 侧对子 Agent 的逻辑引用。 |
|
||||
| `permission_scope` | string[] | 是 | 最小权限列表,如 `repo:read`、`doc:read`。 |
|
||||
| `constraints` | object<string,string> | 否 | 路径、分支、区域、超时等限制;不得含密钥字段。 |
|
||||
| `metadata` | object<string,string> | 否 | 资源展示/审计元数据;不得含密钥字段。 |
|
||||
| `status` | enum | 是 | `pending` / `active` / `disabled` / `revoked`。 |
|
||||
| `secret_ref` | string | 条件必填 | `git`、`sk`、`cloud_account`、`cloud_resource` 必填;`project_doc` 可为空。 |
|
||||
| `audit` | object<string,string> | 否 | 审计上下文;不得含密钥字段。 |
|
||||
|
||||
### 2.4 典型场景:Agnet 辅助 NewAPI 重建/部署
|
||||
|
||||
当 Manager 需要让 Agnet 平台协助重建或部署 NewAPI 时,仍使用 `POST /api/agnet/deployments`,但必须把任务表达为受控运维部署,不得把 VM、PostgreSQL、Redis、NewAPI key 等真实凭据写入请求体。
|
||||
|
||||
请求体示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"orchestration_plan": {
|
||||
"intent_id": "intent_newapi_rebuild_20260503_001",
|
||||
"template_hint": "newapi-rebuild-deploy",
|
||||
"objective": "在批准窗口内重建 NewAPI 服务并回传健康检查、日志与资源使用摘要",
|
||||
"risk_level": "high",
|
||||
"budget": {
|
||||
"max_tokens": 80000,
|
||||
"max_cost_usd": 20,
|
||||
"max_duration_sec": 3600
|
||||
},
|
||||
"constraints": {
|
||||
"allowed_model_ids": ["gpt-5.4", "gpt-5.4-mini"],
|
||||
"requires_approval": "true",
|
||||
"rollback_required": "true",
|
||||
"healthcheck_url_ref": "env://NEWAPI_HEALTHCHECK_URL"
|
||||
},
|
||||
"metadata": {
|
||||
"tenant_id": "legacy-user-scope",
|
||||
"project_id": "legacy-newapi-scope",
|
||||
"correlation_id": "corr_newapi_20260503_001",
|
||||
"service": "new-api",
|
||||
"environment": "production",
|
||||
"commit": "origin/main",
|
||||
"runbook_ref": "heicode/docs/deploy/new-api-rebuild-deploy-runbook.md"
|
||||
},
|
||||
"agents": [
|
||||
{
|
||||
"role_template": "operator",
|
||||
"goal": "按 runbook 执行构建、服务重启、健康检查和失败回滚;只通过 secret_ref/env 获取凭据",
|
||||
"default_model_id": "gpt-5.4",
|
||||
"runtime_execution": {
|
||||
"profile_id": "aks-codex-ops",
|
||||
"cloud_principal_refs": ["principal://users/user_123/agnet-ops"],
|
||||
"network_policy_ref": "netpol://bindings/newapi-prod/ops-egress"
|
||||
},
|
||||
"resource_grants": [
|
||||
{
|
||||
"grant_id": "grant_newapi_vm_ops",
|
||||
"resource_id": "res_newapi_vm",
|
||||
"resource_type": "cloud_resource",
|
||||
"user_id": "user_123",
|
||||
"binding_scope": "newapi-prod",
|
||||
"tenant_id": "legacy-user-scope",
|
||||
"project_id": "legacy-newapi-scope",
|
||||
"target_role": "operator",
|
||||
"target_agent_ref": "agent-operator-1",
|
||||
"permission_scope": ["vm:ssh:approved-window", "service:restart", "log:read", "healthcheck:read"],
|
||||
"constraints": {
|
||||
"approval_id": "approval_newapi_001",
|
||||
"window": "2026-05-03T10:00:00Z/2026-05-03T11:00:00Z",
|
||||
"rollback_command_ref": "runbook://newapi/rollback"
|
||||
},
|
||||
"metadata": {
|
||||
"host_ref": "env://NEWAPI_VM_HOST",
|
||||
"service_name": "new-api"
|
||||
},
|
||||
"status": "active",
|
||||
"secret_ref": "vault://secret/users/user_123/bindings/newapi-prod/resources/res_newapi_vm",
|
||||
"audit": {
|
||||
"created_by": "manager",
|
||||
"approval_id": "approval_newapi_001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"grant_id": "grant_newapi_runtime_env",
|
||||
"resource_id": "res_newapi_runtime_env",
|
||||
"resource_type": "cloud_resource",
|
||||
"user_id": "user_123",
|
||||
"binding_scope": "newapi-prod",
|
||||
"tenant_id": "legacy-user-scope",
|
||||
"project_id": "legacy-newapi-scope",
|
||||
"target_role": "operator",
|
||||
"target_agent_ref": "agent-operator-1",
|
||||
"permission_scope": ["env:read:runtime", "secret:read:scoped"],
|
||||
"constraints": {
|
||||
"allowed_env_refs": "DATABASE_DSN,REDIS_URL,NEWAPI_SERVICE_TOKEN",
|
||||
"plaintext_export_forbidden": "true"
|
||||
},
|
||||
"metadata": {
|
||||
"secret_provider": "openbao",
|
||||
"scope": "newapi-runtime"
|
||||
},
|
||||
"status": "active",
|
||||
"secret_ref": "vault://secret/users/user_123/bindings/newapi-prod/resources/res_newapi_runtime_env",
|
||||
"audit": {
|
||||
"created_by": "manager",
|
||||
"approval_id": "approval_newapi_001"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Agnet 平台返回的部署详情、日志、监控和审计中应至少能证明:构建版本/commit、服务重启结果、健康检查结果、资源使用情况、失败回滚状态。未执行真实 SSH/生产动作时,只能返回 `phase=planned` 或 `phase=pending_approval`。
|
||||
|
||||
NewAPI 重建/部署的完成判定必须同时满足:
|
||||
|
||||
1. `metadata.commit` 或部署详情中的 resolved commit 已在 VM 仓库中生效。
|
||||
2. 部署日志包含构建/compose/restart 的脱敏摘要。
|
||||
3. 健康检查返回成功,且监控接口能返回本次 deployment 的状态或资源摘要。
|
||||
4. 审计日志包含高风险审批 ID、执行者、目标环境和结果。
|
||||
5. 回滚指针或回滚命令引用已记录。
|
||||
|
||||
### 2.5 成功响应
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"deployment_id": "dep_abc123",
|
||||
"status": "accepted",
|
||||
"agent_instances": [
|
||||
{
|
||||
"instance_id": "agi_abc123",
|
||||
"role": "builder",
|
||||
"phase": "pending"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 部署状态与控制接口
|
||||
|
||||
### 3.1 查询部署列表
|
||||
|
||||
```http
|
||||
GET /api/agnet/deployments?user_id=user_123&binding_scope=repo_default
|
||||
```
|
||||
|
||||
返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"deployment_id": "dep_abc123",
|
||||
"status": "accepted",
|
||||
"phase": "pending",
|
||||
"created_at": "2026-05-02T00:00:00Z",
|
||||
"updated_at": "2026-05-02T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 查询单个部署
|
||||
|
||||
```http
|
||||
GET /api/agnet/deployments/{deployment_id}
|
||||
```
|
||||
|
||||
返回应包含部署状态、phase、agent_instances、最近错误、资源授权摘要和预算消耗摘要。Agnet 平台返回时必须对 `secret_ref` 以外的凭据信息做脱敏;原则上不返回任何明文凭据。
|
||||
|
||||
### 3.3 停止部署
|
||||
|
||||
```http
|
||||
POST /api/agnet/deployments/{deployment_id}/stop
|
||||
```
|
||||
|
||||
请求体可为空;如需原因可扩展:
|
||||
|
||||
```json
|
||||
{
|
||||
"reason": "user_requested",
|
||||
"requested_by": "manager"
|
||||
}
|
||||
```
|
||||
|
||||
成功:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"deployment_id": "dep_abc123",
|
||||
"status": "stopped"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
错误与幂等:
|
||||
|
||||
| HTTP | business code | 说明 |
|
||||
|---:|---|---|
|
||||
| 200 | - | 已停止的部署重复停止也可返回 200,并保持 `status=stopped`。 |
|
||||
| 404 | `NOT_FOUND` | 部署不存在或不属于当前租户/项目。 |
|
||||
| 409 | `DEPLOYMENT_CONFLICT` | 部署已进入不可停止的终态,如 `completed` 且无运行实例。 |
|
||||
| 422 | `POLICY_REJECTED` | 高风险停止缺少审批记录或 reason 不合法。 |
|
||||
|
||||
若停止请求触发异步回收,平台可返回 `status=stopping`;Manager 应继续通过事件、日志和监控接口确认最终状态。
|
||||
|
||||
---
|
||||
|
||||
## 4. 日志接口(Manager 拉取 Agnet 平台)
|
||||
|
||||
### 4.1 获取部署日志
|
||||
|
||||
```http
|
||||
GET /api/agnet/deployments/{deployment_id}/logs?agent_instance_id=agi_abc123&stream=stdout&since=2026-05-02T00:00:00Z&limit=200&cursor=cur_001
|
||||
```
|
||||
|
||||
Query:
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|---|---:|---|
|
||||
| `agent_instance_id` | 否 | 不传则返回该 deployment 下全部实例日志。 |
|
||||
| `stream` | 否 | `stdout` / `stderr` / `system` / `audit`,默认全部。 |
|
||||
| `since` | 否 | RFC3339 时间,增量拉取起点。 |
|
||||
| `limit` | 否 | 默认 200,建议最大 1000。 |
|
||||
| `cursor` | 否 | 分页游标。 |
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"log_id": "log_001",
|
||||
"deployment_id": "dep_abc123",
|
||||
"agent_instance_id": "agi_abc123",
|
||||
"stream": "stdout",
|
||||
"level": "info",
|
||||
"message": "task started",
|
||||
"redacted": true,
|
||||
"occurred_at": "2026-05-02T00:00:01Z"
|
||||
}
|
||||
],
|
||||
"next_cursor": "cur_002",
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
日志要求:
|
||||
|
||||
- Agnet 平台必须在返回前完成密钥脱敏。
|
||||
- `message` 不得包含密码、Token、私钥、连接串、云访问密钥。
|
||||
- Manager 只保存必要摘要和审计索引;长日志建议落对象存储并设置保留期。
|
||||
|
||||
### 4.2 实时日志流(可选)
|
||||
|
||||
```http
|
||||
GET /api/agnet/deployments/{deployment_id}/logs/stream?agent_instance_id=agi_abc123
|
||||
Accept: text/event-stream
|
||||
```
|
||||
|
||||
SSE event 示例:
|
||||
|
||||
```text
|
||||
event: log
|
||||
data: {"log_id":"log_002","level":"info","message":"step completed","occurred_at":"2026-05-02T00:00:02Z"}
|
||||
```
|
||||
|
||||
SSE 事件类型:
|
||||
|
||||
| event | 说明 |
|
||||
|---|---|
|
||||
| `log` | 普通日志行,必须已脱敏。 |
|
||||
| `heartbeat` | 保活事件,建议 15-30 秒一次。 |
|
||||
| `error` | 流式读取错误;不包含敏感上下文。 |
|
||||
| `done` | 部署进入终态或服务端主动结束流。 |
|
||||
|
||||
错误处理:
|
||||
|
||||
| HTTP | business code | Manager 处理建议 |
|
||||
|---:|---|---|
|
||||
| 401/403 | `UNAUTHORIZED` / `FORBIDDEN_SCOPE` | 立即断开流并记录审计。 |
|
||||
| 404 | `NOT_FOUND` | 停止订阅并刷新部署详情。 |
|
||||
| 429 | `RATE_LIMITED` | 退避后重连,保留 `Last-Event-Id`。 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 监控接口(Manager 拉取 Agnet 平台)
|
||||
|
||||
### 5.1 项目监控快照
|
||||
|
||||
```http
|
||||
GET /api/agnet/projects/{binding_scope}/dashboard-snapshot?window=1h
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"project_id": "project-a",
|
||||
"active_instances": 3,
|
||||
"phase_distribution": {
|
||||
"pending": 1,
|
||||
"running": 2,
|
||||
"stopped": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"failure_rate_1h": 0.02,
|
||||
"avg_task_duration": 185.3,
|
||||
"budget": {
|
||||
"tokens_used": 32000,
|
||||
"cost_usd": 4.21,
|
||||
"duration_sec": 930
|
||||
},
|
||||
"resource_usage": {
|
||||
"cpu_millicores": 1200,
|
||||
"memory_mb": 2048,
|
||||
"network_rx_bytes": 102400,
|
||||
"network_tx_bytes": 204800
|
||||
},
|
||||
"updated_at": "2026-05-02T00:05:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 单部署监控快照(建议平台实现)
|
||||
|
||||
```http
|
||||
GET /api/agnet/deployments/{deployment_id}/metrics?window=15m&step=60s
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"deployment_id": "dep_abc123",
|
||||
"window": "15m",
|
||||
"series": [
|
||||
{
|
||||
"metric": "tokens_used",
|
||||
"unit": "count",
|
||||
"points": [["2026-05-02T00:00:00Z", 1200]]
|
||||
},
|
||||
{
|
||||
"metric": "cpu_millicores",
|
||||
"unit": "millicore",
|
||||
"points": [["2026-05-02T00:00:00Z", 500]]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
建议指标:`tokens_used`、`cost_usd`、`duration_sec`、`cpu_millicores`、`memory_mb`、`restart_count`、`tool_call_count`、`error_count`、`queue_latency_ms`。
|
||||
|
||||
---
|
||||
|
||||
## 6. 事件与审计接口
|
||||
|
||||
### 6.1 部署事件
|
||||
|
||||
```http
|
||||
GET /api/agnet/deployments/{deployment_id}/events?since=2026-05-02T00:00:00Z&limit=200&cursor=cur_001
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"event_id": "evt_001",
|
||||
"event": "deployment.accepted",
|
||||
"schema_version": 1,
|
||||
"user_id": "user_123",
|
||||
"channel_id": "channel_abc",
|
||||
"binding_scope": "repo_default",
|
||||
"deployment_id": "dep_abc123",
|
||||
"correlation_id": "corr_20260502_001",
|
||||
"occurred_at": "2026-05-02T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"next_cursor": "cur_002",
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
常用事件名:
|
||||
|
||||
| event | 说明 |
|
||||
|---|---|
|
||||
| `deployment.accepted` | 平台接受部署请求。 |
|
||||
| `instance.phase_changed` | 子 Agent phase 变化。 |
|
||||
| `sk_snapshot_refreshed` | SK 快照解析/刷新完成。 |
|
||||
| `resource_grant.attached` | 资源授权已绑定到实例。 |
|
||||
| `resource_grant.revoked` | 授权被撤销或禁用。 |
|
||||
| `budget.threshold_reached` | 预算阈值触发。 |
|
||||
| `deployment.failed` | 部署失败。 |
|
||||
|
||||
### 6.2 审计日志
|
||||
|
||||
```http
|
||||
GET /api/agnet/audit-logs?user_id=user_123&binding_scope=repo_default&actor=agnet_control_plane&action=deployment.accepted&since=2026-05-02T00:00:00Z&limit=200&cursor=cur_001
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"audit_id": "aud_001",
|
||||
"actor": "agnet_control_plane",
|
||||
"action": "deployment.accepted",
|
||||
"resource": "dep_abc123",
|
||||
"user_id": "user_123",
|
||||
"channel_id": "channel_abc",
|
||||
"binding_scope": "repo_default",
|
||||
"request_id": "req_001",
|
||||
"correlation_id": "corr_20260502_001",
|
||||
"result": "ok",
|
||||
"occurred_at": "2026-05-02T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"next_cursor": "cur_002",
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. SK 快照接口
|
||||
|
||||
### 7.1 触发解析/刷新
|
||||
|
||||
```http
|
||||
POST /api/agnet/sk-snapshots/resolve
|
||||
```
|
||||
|
||||
请求:
|
||||
|
||||
```json
|
||||
{
|
||||
"deployment_id": "dep_abc123"
|
||||
}
|
||||
```
|
||||
|
||||
响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"deployment_id": "dep_abc123",
|
||||
"items": [
|
||||
{
|
||||
"snapshot_id": "sks_001",
|
||||
"deployment_id": "dep_abc123",
|
||||
"user_id": "user_123",
|
||||
"binding_scope": "repo_default",
|
||||
"source_type": "git",
|
||||
"source_ref": "main:skills/heicode/**@sha_xxx",
|
||||
"resolved_at": "2026-05-02T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 查询部署 SK 快照
|
||||
|
||||
```http
|
||||
GET /api/agnet/deployments/{deployment_id}/sk-snapshots
|
||||
```
|
||||
|
||||
Query:
|
||||
|
||||
| 参数 | 必填 | 说明 |
|
||||
|---|---:|---|
|
||||
| `user_id` | 建议 | 与 `X-User-Id` 或 deployment 的 `user_context.user_id` 一致。 |
|
||||
| `binding_scope` | 建议 | 与 `X-Binding-Scope` 或 deployment 的资源授权作用域一致。 |
|
||||
| `source_type` | 否 | `git` / `upload`,用于筛选。 |
|
||||
| `limit` | 否 | 默认 100,最大 500。 |
|
||||
| `cursor` | 否 | 分页游标。 |
|
||||
|
||||
成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"snapshot_id": "sks_001",
|
||||
"deployment_id": "dep_abc123",
|
||||
"user_id": "user_123",
|
||||
"binding_scope": "repo_default",
|
||||
"source_type": "git",
|
||||
"source_ref": "main:skills/heicode/**@sha_xxx",
|
||||
"artifact_ref": "artifact://bindings/repo_default/sk/sks_001",
|
||||
"checksum": "sha256:example-redacted",
|
||||
"status": "ready",
|
||||
"resolved_at": "2026-05-02T00:00:00Z"
|
||||
}
|
||||
],
|
||||
"next_cursor": "cur_002",
|
||||
"total": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
错误处理:
|
||||
|
||||
| HTTP | business code | 说明 |
|
||||
|---:|---|---|
|
||||
| 404 | `NOT_FOUND` | deployment 不存在或不属于当前租户/项目。 |
|
||||
| 410 | `CURSOR_EXPIRED` | cursor 过期,使用不带 cursor 的查询重拉。 |
|
||||
| 422 | `SK_SOURCE_UNRESOLVABLE` | 快照来源不可解析,详情在事件/日志中查看。 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 安全校验清单
|
||||
|
||||
Manager 发给 Agnet 平台前必须执行:
|
||||
|
||||
1. `user_id`、`binding_scope`、`target_role` 与部署计划一致。
|
||||
2. 凭据型资源只传 `secret_ref`,不传明文凭据。
|
||||
3. `metadata`、`constraints`、`audit` 的 key 中不得出现 `password`、`token`、`secret`、`private_key`、`access_key`、`credential` 等敏感词。
|
||||
4. `repo_url` 不得包含用户名、密码或访问 Token。
|
||||
5. `permission_scope` 使用最小权限;生产写操作必须携带客户端审批记录,Agnet 平台不得自行补批。
|
||||
6. 高风险操作(生产部署、云资源修改、删除、扩容)必须设置 `risk_level=high`,Agnet 平台执行前只校验客户端审批证据。
|
||||
7. 所有日志/事件/审计返回给 Manager 前必须脱敏。
|
||||
|
||||
Agnet 平台不承担高危操作审批主体。审批只发生在客户端;Agnet 平台只能在执行前校验以下字段和策略是否一致:
|
||||
|
||||
| 校验项 | 要求 |
|
||||
|---|---|
|
||||
| `approval_id` | 必须存在于高危任务的 `constraints` 或 `audit`,并可追溯到客户端审批记录。 |
|
||||
| 审批主体 | 审批用户必须与 `user_context.user_id`、`resource_grants[].user_id` 或授权代理主体一致。 |
|
||||
| 审批范围 | 审批范围必须覆盖 `binding_scope`、`permission_scope`、目标环境、资源 ID 和操作类型。 |
|
||||
| TTL / 时间窗口 | 审批记录必须未过期;若使用 `window` 或 TTL,当前执行时间必须落在允许范围内。 |
|
||||
| `risk_level` | 高危资源写入、生产部署、云资源修改、删除和扩容必须为 `high`。 |
|
||||
| 策略 | 平台 policy、OpenBao policy、Kubernetes/Workload Identity、网络策略和最小权限约束均必须允许本次动作。 |
|
||||
|
||||
任一校验不通过时,Agnet 平台应返回 `POLICY_REJECTED` 或 `FORBIDDEN_SCOPE`,不得发起额外批准流程。
|
||||
|
||||
### 8.1 字段级约束速查
|
||||
|
||||
| 对象/接口 | 必填最小集合 | 禁止内容 |
|
||||
|---|---|---|
|
||||
| `orchestration_plan` | `intent_id`、`template_hint`、`objective`、`risk_level`、`budget`、`user_context`、`billing_context`、`agent_runtime`、`metadata.correlation_id`、`agents[]` | 密钥、连接串、真实主机登录密码、NewAPI key 原文。 |
|
||||
| `agents[]` | `role_template`、`goal` | 让子 Agent 绕过 Manager/Agnet 审计的指令。 |
|
||||
| `runtime_execution` | 任一字段存在时 `profile_id` 必填 | 明文 kubeconfig、SSH key、云访问密钥。 |
|
||||
| `resource_grants[]` | `grant_id`、`resource_id`、`resource_type`、`user_id`、`binding_scope`、`target_role`、`target_agent_ref`、`permission_scope`、`status` | 明文 `password`、`token`、`private_key`、`access_key`、`credential`、数据库 DSN。 |
|
||||
| 日志/事件/审计返回 | `request_id` 或 `correlation_id`,以及发生时间 | 未脱敏命令行、环境变量 dump、密钥片段。 |
|
||||
| NewAPI 重建/部署场景 | `approval_id`、`rollback_command_ref`、健康检查引用、运行环境 `secret_ref` | 真实 VM 密码、PostgreSQL/Redis 连接串、NewAPI 服务令牌。 |
|
||||
|
||||
### 8.2 联调验收清单
|
||||
|
||||
- 创建部署请求只包含 `secret_ref`/`env://`/`runbook://` 引用,不包含真实凭据。
|
||||
- `user_id` 与 `binding_scope` 在 user context、resource grant、事件和审计中一致。
|
||||
- `risk_level=high` 的生产运维任务包含 `approval_id` 和回滚引用。
|
||||
- 日志、事件、监控、审计接口都能通过 `correlation_id` 串联。
|
||||
- NewAPI 重建/部署只在实际执行并通过健康检查后标记为已部署;未执行时状态只能是 `planned`、`pending_approval`、`accepted` 或 `running`。
|
||||
- Manager 本地 `/api/agnet/*` 占位端点通过 payload 校验不等于生产 Agnet 平台已上线。
|
||||
|
||||
---
|
||||
|
||||
## 9. Manager 侧当前实现映射
|
||||
|
||||
当前代码中可用于对齐/验证 payload 的 Manager 侧端点:
|
||||
|
||||
| Manager 路由 | 用途 |
|
||||
|---|---|
|
||||
| `POST /api/agnet/deployments` | 校验并接受 orchestration_plan。 |
|
||||
| `GET /api/agnet/deployments` | 按 user/binding scope 查询部署。 |
|
||||
| `GET /api/agnet/deployments/:deployment_id` | 查询部署详情。 |
|
||||
| `POST /api/agnet/deployments/:deployment_id/stop` | 停止部署。 |
|
||||
| `GET /api/agnet/deployments/:deployment_id/logs` | 查询脱敏日志占位/联调日志。 |
|
||||
| `GET /api/agnet/deployments/:deployment_id/metrics` | 查询单部署指标占位/联调指标。 |
|
||||
| `GET /api/agnet/deployments/:deployment_id/events` | 查询事件。 |
|
||||
| `POST /api/agnet/sk-snapshots/resolve` | 解析 SK 快照。 |
|
||||
| `GET /api/agnet/deployments/:deployment_id/sk-snapshots` | 查询 SK 快照。 |
|
||||
| `GET /api/agnet/projects/:project_id/dashboard-snapshot` | 资源作用域监控快照;路径名保留旧兼容。 |
|
||||
| `GET /api/agnet/audit-logs` | 审计日志。 |
|
||||
|
||||
生产对接时,Manager 应把相同契约的请求发送给 Agnet 平台;本地 Manager 端点仅作为最小验证与控制面占位,不代表所有日志/监控平台能力已完整实现。
|
||||
|
||||
当前本地 `logs` 与 `metrics` 端点只返回脱敏占位/联调数据,用于验证 Manager ↔ Agnet payload、路由和验收流程。生产级实时日志流 `GET /api/agnet/deployments/{deployment_id}/logs/stream` 仍属于 Agnet 平台能力;Manager 不得把“本地占位通过”误报为“生产日志/监控已上线”。
|
||||
@@ -0,0 +1,61 @@
|
||||
# Manager → mcp-server 契约补丁清单
|
||||
|
||||
> 来源:Heicode Manager 前端集成 §1–§6 时打的本地 patch。建议 mcp-server 侧把这些归一掉,前端就能删掉对应的兼容层。
|
||||
|
||||
## 1. `manager_actions[].deeplink` 命名空间
|
||||
|
||||
**当前现象**:mcp-server 返回的 deeplink 形如 `/manager/resources`、`/manager/wallet`、`/manager/audit`。
|
||||
|
||||
**Manager 实际路由**:`/sk-sources`、`/wallet`、`/audit`。
|
||||
|
||||
**前端兜底**:`src/features/tasks/task-card-view.tsx::normalizeDeeplink()` 做了映射表。
|
||||
|
||||
**建议**:mcp-server 直接返回 Manager 真实路径,或返回 `{kind: 'resources' | 'wallet' | 'audit', ...}` 让前端自己拼。前者更简单。
|
||||
|
||||
| mcp-server 现返回 | Manager 应跳 |
|
||||
|---|---|
|
||||
| `/manager/resources` | `/sk-sources` |
|
||||
| `/manager/wallet` | `/wallet` |
|
||||
| `/manager/audit` | `/audit` |
|
||||
| `/manager/tasks/{id}` | `/tasks/{id}` |
|
||||
|
||||
## 2. §5 审计日志的敏感字段 redact
|
||||
|
||||
**当前现象**:mcp-server `/api/agnet/audit` 返回的条目里 `payload` 字段可能包含 token / secret 原文(按 §5 设计应在服务端 mask)。
|
||||
|
||||
**前端兜底**:`src/features/agnet-console/pages.tsx::maskIfSecret()` 做了第二层 mask(按 key 名匹配 `secret|token|password|api_key`)。
|
||||
|
||||
**建议**:mcp-server 在写审计或读出时统一 mask,前端可以删掉那一层。
|
||||
|
||||
## 3. §6 任务卡 `manager_actions` 形状一致性
|
||||
|
||||
**当前确认**:HeicodeTaskCard 真实形状是 `{goal, scope, generated_artifacts, manager_actions: [{label, deeplink}]}`,前端已对齐。
|
||||
|
||||
**建议**:在 mcp-server contract 文档 §6 里把这个形状固定下来,避免后续漂移。
|
||||
|
||||
## 4. §4 usage 字段名
|
||||
|
||||
**当前消费**:`{date, total_quota, total_tokens, prompt_tokens, completion_tokens, count}`。
|
||||
|
||||
**Manager 用**:sparkline 取 `total_quota`、tooltip 拼 `date` + `formatQuota(total_quota)`。
|
||||
|
||||
**建议**:维持当前字段名即可。如果未来引入按模型聚合,建议另起 endpoint,不要在 `items` 里混。
|
||||
|
||||
## 5. §5 `/api/agnet/*` stub 数据
|
||||
|
||||
**当前**:mcp-server 内存 dict(按 §5.0 设计),无 agent-manager 真实转发。
|
||||
|
||||
**阻塞解除条件**:
|
||||
- agent-manager 侧给 mcp-server 派发 service token
|
||||
- mcp-server 把 stub 换成对 `20.212.121.126:80` 的真实转发(HTTP/80,Host 头 `agent-manager.taijiagnet.com`)
|
||||
|
||||
Manager 前端已按 §5 契约消费,stub → 真实数据无需前端改动。
|
||||
|
||||
## 6. SSE `/api/user/tasks/{id}/events` 状态
|
||||
|
||||
**当前**:Manager 用 `refetchInterval` 自适应轮询替代(active 状态 3 秒,terminal 状态停止,其它 15 秒)。
|
||||
|
||||
**建议**:mcp-server 把 SSE 帧格式(event name、data shape)写进契约文档,前端再切到 EventSource / fetch stream。事件至少要覆盖:
|
||||
- `status_changed`(包含新 status)
|
||||
- `followup_added`(包含 followup payload)
|
||||
- `card_updated`(包含完整 HeicodeTaskCard)
|
||||
Reference in New Issue
Block a user