计算资产 API
管理项目的计算资产(分组、资产、连接、远程桌面、容器控制、磁盘),支持 managed(平台托管)和 external(外部连接)两种模式。
基础路径
/projects/:projectId/assets认证方式
所有端点均需要 JWT Bearer Token 或 API Key 认证(combinedAuth 中间件)。
权限说明
- 读取操作(GET):需要项目访问权限
- 写入操作(POST / PATCH / DELETE):需要项目写入权限(
write) - 删除分组:需要项目管理员权限(
admin)
分组 API
GET /projects/:projectId/assets/groups
获取项目的分组列表。
响应 200
{
"groups": [
{
"id": "uuid",
"name": "生产环境",
"description": "...",
"ai_accessible": true,
"sort_order": 0
}
]
}POST /projects/:projectId/assets/groups
创建分组。
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 分组名称 |
description | string | 否 | 分组描述 |
ai_accessible | boolean | 否 | 是否允许 AI 访问 |
响应 201
{
"group": { ... }
}| 状态码 | 说明 |
|---|---|
| 409 | 分组名称已存在 |
PATCH /projects/:projectId/assets/groups/reorder
批量排序分组。
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
orderedIds | string[] | 是 | 按新顺序排列的分组 ID 数组 |
响应 200
{
"success": true
}PATCH /projects/:projectId/assets/groups/:groupId
更新分组信息。
请求体
可选字段:name、description、ai_accessible。
响应 200
{
"group": { ... }
}DELETE /projects/:projectId/assets/groups/:groupId
删除分组(需要项目管理员权限)。
响应 200
{
"success": true
}资产 API
GET /projects/:projectId/assets/templates
获取可用的镜像模板列表(按类型分组),用于创建 managed 资产时选择模板。
响应 200
{
"templates": [ ... ]
}GET /projects/:projectId/assets
获取资产列表,支持按分组过滤。
Query 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
groupId | string | 否 | 按分组 ID 过滤 |
响应 200
{
"assets": [
{
"id": "uuid",
"name": "开发服务器",
"type": "docker",
"source": "managed",
"status": "running",
"group_id": "uuid"
}
]
}POST /projects/:projectId/assets
创建资产。
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 资产名称 |
type | string | 是 | 类型:docker / browser(desktop 暂未开放) |
source | string | 否 | 来源:managed(平台托管)/ external(外部连接) |
templateId | string | 条件必填 | 模板 slug(managed 资产必填) |
groupId | string | 否 | 所属分组 ID |
description | string | 否 | 资产描述 |
region | string | 否 | 区域 |
config | object | 否 | 额外配置 |
diskId | string | 否 | 磁盘 ID(仅 selfhosted 模式) |
connection | object | 否 | 连接信息(external 资产需提供 protocol/hostname/port) |
前置校验
- managed 资产需要 Worker 就绪,否则返回 503
- external 资产的 hostname 需通过 SSRF 校验
- 模板存在且已启用,类型匹配
响应 201
{
"asset": { ... }
}| 状态码 | 说明 |
|---|---|
| 400 | 输入校验失败 |
| 409 | 资产名称已存在 |
| 503 | Assets Worker 未就绪 |
PATCH /projects/:projectId/assets/:assetId
更新资产信息,支持磁盘绑定更新。
请求体
可选字段:name、description、groupId、diskId(仅 selfhosted 模式,需资产已停止)。
响应 200
{
"asset": { ... }
}DELETE /projects/:projectId/assets/:assetId
软删除资产。managed 资产若有容器需要 Worker 回收。
响应 200
{
"success": true
}| 状态码 | 说明 |
|---|---|
| 404 | 资产不存在 |
| 503 | Worker 未就绪,无法回收容器 |
连接凭证 API
POST /projects/:projectId/assets/:assetId/connections
保存外部资产的连接信息。
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
protocol | string | 是 | 协议:vnc / rdp / ssh / telnet |
hostname | string | 是 | 主机名(需通过 SSRF 校验) |
port | number | 是 | 端口(1-65535) |
username | string | 否 | 用户名 |
password | string | 否 | 密码 |
private_key | string | 否 | SSH 私钥 |
settings | object | 否 | 额外连接设置 |
特殊行为
- 保存成功后自动将 pending/error 状态的资产设为 running
响应 201
{
"success": true
}GET /projects/:projectId/assets/:assetId/connections
获取连接信息(脱敏,仅外部资产)。
响应 200
{
"connections": [ ... ]
}远程桌面连接 API
POST /projects/:projectId/assets/:assetId/connect
发起远程桌面连接,返回加密 Token 和 WebSocket URL。
前置检查
- Guacamole 代理就绪
- 资产状态为 running
- 并发会话数不超过 5
- 无连接锁定(指数退避)
响应 200
{
"wsUrl": "wss://host/ws/guacamole",
"token": "encrypted-token",
"sessionId": "uuid",
"protocol": "vnc",
"mode": "control"
}| 字段 | 类型 | 说明 |
|---|---|---|
wsUrl | string | WebSocket 连接地址 |
token | string | 加密连接令牌(10 秒过期) |
sessionId | string | 会话 ID |
protocol | string | 连接协议 |
mode | string | 会话模式:control(控制)/ observe(观察),VNC/RDP 协议同一资产仅一个 control 会话 |
| 状态码 | 说明 |
|---|---|
| 400 | 资产未运行 / 未配置连接信息 |
| 429 | 已达最大并发连接数 / 连接锁定中(含 Retry-After 头) |
| 503 | Guacamole 代理未就绪 |
容器控制 API(Managed 资产)
POST /projects/:projectId/assets/:assetId/start
启动 managed 资产。设置 desired_status = 'running',由 Worker 异步执行。
前置检查:资产为 managed 类型且未在运行中,Worker 就绪。
响应 200
{
"success": true,
"message": "启动请求已提交"
}POST /projects/:projectId/assets/:assetId/stop
停止 managed 资产。
响应 200
{
"success": true,
"message": "停止请求已提交"
}POST /projects/:projectId/assets/:assetId/restart
重启 managed 资产(通过 restart_requested 标记实现)。
响应 200
{
"success": true,
"message": "重启请求已提交"
}磁盘 API(仅 selfhosted 模式)
GET /projects/:projectId/assets/disks
获取项目的磁盘列表。
响应 200
{
"disks": [ ... ]
}POST /projects/:projectId/assets/disks
创建磁盘。
请求体
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 磁盘名称 |
description | string | 否 | 磁盘描述 |
响应 201
{
"disk": { ... }
}PATCH /projects/:projectId/assets/disks/:diskId
更新磁盘信息。
请求体
可选字段:name、description。
响应 200
{
"disk": { ... }
}DELETE /projects/:projectId/assets/disks/:diskId
删除磁盘(不能正在被资产使用)。
响应 200
{
"success": true
}| 状态码 | 说明 |
|---|---|
| 400 | 磁盘正在使用 |
| 404 | 磁盘不存在 |
| 501 | 非 selfhosted 模式不可用 |