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

当前新增 / 扩展接口总览

能力MethodPath权限状态
列出远端目录GET/api/v1/control-plane/companies/{cell}/fs?path=<rel>viewerlive
文件夹/文件写操作POST/api/v1/control-plane/companies/{cell}/fsoperatorlive
预览/下载单文件GET/api/v1/control-plane/companies/{cell}/fs/file?path=<rel>viewerlive
Drive 全盘搜索GET/api/drive/{cell}/search?q=<query>session userlive
环境变量 inventoryGET/api/v1/control-plane/companies/{cell}/envviewerlive
环境变量 reveal/set/unsetPOST/api/v1/control-plane/companies/{cell}/envoperatorlive
模型切换意图POST/api/v1/control-plane/companies/{cell}/model-switchoperatorplanned action

通用前置条件

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
opBodyActionLog说明
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 写入 PreviewFiledownload=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
opBodyActionLog安全说明
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.yamlauth.json 白名单字段:只读 model.defaultmodel.provideractive_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 原文。

字段来源说明
inputsessions.input_tokens输入 token
outputsessions.output_tokens输出 token
cacheReadsessions.cache_read_tokens缓存读取 token
cacheWritesessions.cache_write_tokens缓存写入 token
reasoningsessions.reasoning_tokensreasoning token
costestimateCost()按 list price 估算,可由 AIDC_MODEL_PRICING 覆盖

6. 缓存、审计与错误

能力缓存失效条件审计
FS listcacheKey.fs(cell,path)mkdir/rename/move/delete/write/upload 成功写操作写 ActionLog
Env inventorycacheKey.env(cell)set/unset 成功或 refresh=1reveal/set/unset 全部写 ActionLog
Model configscacheKey.models(cell)model-switch intentSwitchModel
UsagecacheKey.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_deniedSSH 认证被拒检查 key 与实例用户
unknown_opPOST 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

安全边界

// 实现状态

这页与当前 main 对齐:FS、FS file、Drive search、Env API 已可运行;model-switch 已写入 SwitchModel planned ActionLog;usage/model inventory 为 server-side console 能力。后续若 runtime channel 接通真实模型切换,需要更新本页状态和响应示例。