Runtime Operations API
这一页记录最新 main 中新增和扩展的 Runtime Operations 能力:从 Control Plane 安全查看/操作客户 Cell 的文件系统、环境变量、模型配置、用量计量与 Drive 搜索。它面向 AIDC 内部开发者、FDE 和平台运维,不面向客户售前阅读。
Runtime Operations API 不是通用远程 shell。它把高风险 runtime 操作收敛成可授权、可审计、可缓存、可回滚的受控接口:文件操作只走允许路径,环境变量默认只显示 masked 值,模型切换先写 ActionLog,token 用量只聚合计数不取 prompt 内容。
资源模型
Company / Cell
├── Runtime Server
│ ├── File System
│ │ ├── list / mkdir / rename / move / delete / upload / edit
│ │ └── preview / download / search
│ ├── Environment Files
│ │ ├── inventory masked keys
│ │ ├── reveal single key
│ │ ├── set single key
│ │ └── unset single key
│ ├── Hermes Profiles
│ │ ├── live model config inventory
│ │ ├── planned model switch
│ │ └── profile gateway restart pending runtime channel
│ └── Usage Metering
│ ├── aggregate state.db sessions table
│ ├── per-agent tokens
│ └── per-model list-price estimate
└── Action Log
├── File operations
├── Env operations
└── Model switch intent
当前新增 / 扩展接口总览
| 能力 | Method | Path | 权限 | 状态 |
|---|---|---|---|---|
| 列出远端目录 | GET | /api/v1/control-plane/companies/{cell}/fs?path=<rel> | viewer | live |
| 文件夹/文件写操作 | POST | /api/v1/control-plane/companies/{cell}/fs | operator | live |
| 预览/下载单文件 | GET | /api/v1/control-plane/companies/{cell}/fs/file?path=<rel> | viewer | live |
| Drive 全盘搜索 | GET | /api/drive/{cell}/search?q=<query> | session user | live |
| 环境变量 inventory | GET | /api/v1/control-plane/companies/{cell}/env | viewer | live |
| 环境变量 reveal/set/unset | POST | /api/v1/control-plane/companies/{cell}/env | operator | live |
| 模型切换意图 | POST | /api/v1/control-plane/companies/{cell}/model-switch | operator | planned action |
通用前置条件
- Company / Cell 已存在:接口通过
{cell}定位公司和运行节点。 - 运行中服务器有 IP:Control Plane 会选择 running 且有 public IP 的 server;没有则返回
no_running_server_with_ip。 - SSH key 已配置:runtime 操作依赖
AIDC_RUNTIME_CONTROL_SSH_KEY_PATH或 cell-specific key resolver。 - 路径基线已配置:文件、环境变量、Hermes profiles 都由 per-cell root/base 映射限制。
- 权限守卫:viewer 可读,operator 可写,高风险动作必须写 ActionLog。
1. 文件系统 API
列出目录
GET /api/v1/control-plane/companies/{cell}/fs?path=<relative-path>&refresh=1
返回指定 Cell runtime root 下的目录列表。refresh=1 绕过 Redis cache,适用于刚做过写操作后的人工复核。
目录列表响应
{
"ok": true,
"host": "<runtime-host>",
"root": "<runtime-root>",
"path": "<relative-path>",
"entries": [
{
"name": "<file-or-folder>",
"relPath": "<relative-path>",
"kind": "file",
"size": 1234,
"modifiedAt": "<iso-8601>"
}
],
"cached": false,
"fetchedAt": "<iso-8601>"
}
写操作
POST /api/v1/control-plane/companies/{cell}/fs
Content-Type: application/json
| op | Body | ActionLog | 说明 |
|---|---|---|---|
mkdir | {"op":"mkdir","path":"<dir>","name":"<name>"} | CreateFolder | 创建子目录 |
rename | {"op":"rename","path":"<rel>","newName":"<name>"} | RenameFile | 重命名文件或目录 |
move | {"op":"move","path":"<rel>","destDir":"<dir>"} | MoveFile | 移动文件或目录 |
delete | {"op":"delete","path":"<rel>"} | DeleteFile | 高风险删除 |
write | {"op":"write","path":"<rel>","content":"..."} | EditFile | 只允许可编辑扩展名,最大 2MB |
上传文件
POST /api/v1/control-plane/companies/{cell}/fs
Content-Type: multipart/form-data
path=<target-dir>
file=@<local-file>
上传成功后会失效该 cell 的文件列表 cache,并写入 UploadFile ActionLog。
2. 文件预览、下载与 Drive 搜索
预览或下载单文件
GET /api/v1/control-plane/companies/{cell}/fs/file?path=<relative-path>&preview=1
GET /api/v1/control-plane/companies/{cell}/fs/file?path=<relative-path>&download=1
preview=1 写入 PreviewFile;download=1 写入 DownloadFile。响应使用 fileResponseHeaders() 设置 inline / attachment。
Drive 搜索
GET /api/drive/{cell}/search?q=<query>
Drive 搜索使用当前 session user 认证,不走 Control Plane role guard。查询字符串至少 2 个字符;搜索文件名和可索引文本内容,返回命中行号和 snippet。
{
"ok": true,
"hits": [
{
"name": "<file-name>",
"relPath": "<relative-path>",
"size": "1.2 MB",
"modified": "2026-07-04",
"match": "content",
"snippet": "...",
"line": 42
}
]
}
3. Environment API
列出 .env 文件与 masked keys
GET /api/v1/control-plane/companies/{cell}/env?refresh=1
Inventory 在实例上完成解析与 masking。列表视图只返回 key name、masked value、length、line、owner、mode、backup count;不会把 secret 明文存入 Control Plane DB,也不会写入缓存。
{
"ok": true,
"host": "<runtime-host>",
"roots": ["<scan-root>"],
"files": [
{
"path": "<absolute-env-path>",
"mode": "0o600",
"owner": "<linux-user>",
"backups": 1,
"keys": [
{"name":"API_TOKEN","sensitive":true,"masked":"••••••••…tail","length":64,"line":3}
]
}
],
"cached": false,
"fetchedAt": "<iso-8601>"
}
Reveal / Set / Unset 单个变量
POST /api/v1/control-plane/companies/{cell}/env
Content-Type: application/json
| op | Body | ActionLog | 安全说明 |
|---|---|---|---|
reveal | {"op":"reveal","file":"<env-path>","key":"API_TOKEN"} | RevealEnvVar | 返回单个 plaintext value;日志只写 “value read, not logged” |
set | {"op":"set","file":"<env-path>","key":"API_TOKEN","value":"<secret>"} | CreateEnvVar / UpdateEnvVar | 远端先备份再写入;返回 backup path,不回显 value |
unset | {"op":"unset","file":"<env-path>","key":"API_TOKEN"} | RemoveEnvVar | 远端先备份再删除 |
Environment API 的设计原则是“密钥永不入库”。只有 reveal 单 key 时明文跨线返回给已授权 operator;inventory、cache、ActionLog、docs 和 examples 都不能保存真实密钥值。
4. Model catalog 与模型切换
最新 main 引入 model-catalog.ts 作为 Console 模型目录的单一来源,包含 provider、model id、上下文长度、tier 和 list-price 估算。Console 的 Models 页面会通过 SSH 读取实例中 Hermes profile 的 config.yaml 和 auth.json 白名单字段:只读 model.default、model.provider、active_provider 和 provider 名称,不读取 token。
模型切换 API
POST /api/v1/control-plane/companies/{cell}/model-switch
Content-Type: application/json
{
"profile": "<hermes-profile-name>",
"model": "gpt-5.5"
}
当前实现会校验模型在 catalog 中存在,写入 SwitchModel ActionLog,并失效该 cell 的 model cache。真实改写 config.yaml model.default + 重启 gateway 的 runtime channel 尚未接通,因此响应明确是 planned action。
{
"ok": false,
"planned": true,
"profile": "<hermes-profile-name>",
"model": "gpt-5.5",
"provider": "openai"
}
5. Usage metering
Usage 页面目前不是公开 HTTP API,而是 server component 调用 getCellUsageReport(cellId)。它通过 SSH 只读打开每个 Hermes profile 的 state.db,聚合 sessions 表 token 计数,不读取 prompt、message、tool output 原文。
| 字段 | 来源 | 说明 |
|---|---|---|
input | sessions.input_tokens | 输入 token |
output | sessions.output_tokens | 输出 token |
cacheRead | sessions.cache_read_tokens | 缓存读取 token |
cacheWrite | sessions.cache_write_tokens | 缓存写入 token |
reasoning | sessions.reasoning_tokens | reasoning token |
cost | estimateCost() | 按 list price 估算,可由 AIDC_MODEL_PRICING 覆盖 |
6. 缓存、审计与错误
| 能力 | 缓存 | 失效条件 | 审计 |
|---|---|---|---|
| FS list | cacheKey.fs(cell,path) | mkdir/rename/move/delete/write/upload 成功 | 写操作写 ActionLog |
| Env inventory | cacheKey.env(cell) | set/unset 成功或 refresh=1 | reveal/set/unset 全部写 ActionLog |
| Model configs | cacheKey.models(cell) | model-switch intent | SwitchModel |
| Usage | cacheKey.usage(cell) | TTL 或手动刷新策略 | 只读聚合,默认不写业务 ActionLog |
常见错误
| reason | 含义 | Operator 下一步 |
|---|---|---|
company_not_found | 无法用 cell 定位 Company | 检查 cell id / runtime-sync 状态 |
no_running_server_with_ip | 没有可连接的运行中实例 | 检查 server state / public IP |
ssh_key_not_configured | 缺少 runtime SSH key | 配置 cell key resolver 或 env |
ssh_denied | SSH 认证被拒 | 检查 key 与实例用户 |
unknown_op | POST op 不支持 | 核对 op 枚举 |
not_editable | 文件扩展名不允许在线编辑 | 改走 download / upload 流程 |
too_large | 文件或编辑内容超过限制 | 改走离线编辑或分块流程 |
CLI 映射草案
aidc fs ls --cell <cell-id> --path <relative-path>
aidc fs upload --cell <cell-id> --path <dir> --file <local-file>
aidc env list --cell <cell-id> --refresh
aidc env reveal --cell <cell-id> --file <env-path> --key API_TOKEN
aidc env set --cell <cell-id> --file <env-path> --key API_TOKEN --value-stdin
aidc model list --cell <cell-id>
aidc model switch --cell <cell-id> --profile <profile> --model gpt-5.5
aidc usage report --cell <cell-id> --format table
安全边界
- 文档和示例不得出现真实公司、真实客户、真实 token 或生产路径中的敏感值。
- Env inventory 只能显示 masked 值;reveal 明文只能给 operator,且必须审计。
- Usage 只能读 token 聚合,不读取 prompt、completion 或工具结果。
- Model switch 当前是 planned action,不得在产品文案中说已经 live 改写模型。
- Drive 搜索和文件系统操作必须受 cell root 限制,不能变成任意主机文件浏览器。
- 所有写操作完成后必须让相关 cache 失效,并在 ActionLog 留证据。
这页与当前 main 对齐:FS、FS file、Drive search、Env API 已可运行;model-switch 已写入 SwitchModel planned ActionLog;usage/model inventory 为 server-side console 能力。后续若 runtime channel 接通真实模型切换,需要更新本页状态和响应示例。