@delta-infra/cli 1.0.97 → 1.0.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/checksums.txt +5 -5
- package/package.json +1 -1
- package/skills/delta-sandbox/SKILL.md +51 -63
- package/skills/delta-sandbox/references/commands.md +12 -10
- package/skills/delta-sandbox/references/lifecycle.md +24 -16
- package/skills/delta-sandbox/references/recipes.md +15 -10
- package/skills/delta-science/AGENTS.md +6 -9
- package/skills/delta-science/SKILL.md +33 -34
- package/skills/delta-science/references/materials-design.md +109 -109
- package/skills/delta-science/references/{qe-dft.md → qe.md} +4 -4
- package/skills/delta-science/scripts/invoke.py +44 -44
- package/skills/delta-shared/SKILL.md +3 -1
- package/skills/delta-science/references/cli-contract.md +0 -53
- package/skills/delta-science/references/generated-catalog.md +0 -48
- package/skills/delta-science/references/ldm.md +0 -73
- package/skills/delta-science/references/molecule-enrich.md +0 -59
- package/skills/delta-science/references/operation-contracts.md +0 -137
- package/skills/delta-science/references/routing-index.md +0 -45
- package/skills/delta-science/references/services.md +0 -112
- package/skills/delta-science/references/workflows.md +0 -98
package/README.md
CHANGED
|
@@ -328,8 +328,10 @@ operation,并且只加载当前工具对应的 reference,避免大量独立
|
|
|
328
328
|
工具目录由 Science Server 数据库维护。新增工具时配置 `tools` 记录及对应的
|
|
329
329
|
`tool_endpoints` 记录;停用时设置 `status=false`。CLI 无需同步任何静态表或重新增加
|
|
330
330
|
命令。若需要让 AI 根据自然语言自动选择新工具并安全组装请求,再更新
|
|
331
|
-
`skills/delta-science/
|
|
332
|
-
|
|
331
|
+
`skills/delta-science/SKILL.md` 的工具选择表和对应的
|
|
332
|
+
`skills/delta-science/references/<tool>.md`;references 目录只保存真实工具文档,不能放置
|
|
333
|
+
目录、路由、服务映射或跨工具工作流等元文档。数据库中的 canonical tool name 与工具表、
|
|
334
|
+
对应 reference 必须完全一致。
|
|
333
335
|
|
|
334
336
|
## 开发
|
|
335
337
|
|
|
@@ -415,7 +417,7 @@ make release
|
|
|
415
417
|
```bash
|
|
416
418
|
export GH_TOKEN=<your-github-pat>
|
|
417
419
|
export NPM_TOKEN=<your-npm-token>
|
|
418
|
-
./release.sh v1.0.97
|
|
420
|
+
./release.sh v1.0.97
|
|
419
421
|
```
|
|
420
422
|
|
|
421
423
|
脚本执行步骤:
|
package/checksums.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
c29421f9b96cb23f2fb10fe833553591be95b851e8c0781fdf9865311222035a *delta-cli-darwin-amd64.tar.gz
|
|
2
|
+
ef5478c49ecb92036a3b463e61dcb4ac7f5767904cc89ecf43a1174b3ed7fc26 *delta-cli-darwin-arm64.tar.gz
|
|
3
|
+
5d41c6e91d0d57e18e72bbdb51acf00633f509f35ece88820a68843b634d05fc *delta-cli-linux-amd64.tar.gz
|
|
4
|
+
8c9dc65fd113f3fb8541e12ac7ba449467b1efb14ecfb86cdc7874abb410c792 *delta-cli-linux-arm64.tar.gz
|
|
5
|
+
be075b6892141d41c5ed845fef6b9813e1ed2abe5a13b19beefe23b08fbe0045 *delta-cli-windows-amd64.zip
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: delta-sandbox
|
|
3
|
-
description: "在 Delta Sandbox Linux 容器中运行任意命令或脚本。适用于训练、推理、编译、数据处理等任意需要 sandbox 的计算任务,支持 Python / Node.js / Go / Java / Rust 等语言。所有任务通用同一套输出约定:命令在 stdout 末尾输出结构化 JSON
|
|
3
|
+
description: "在 Delta Sandbox Linux 容器中运行任意命令或脚本。适用于训练、推理、编译、数据处理等任意需要 sandbox 的计算任务,支持 Python / Node.js / Go / Java / Rust 等语言。所有任务通用同一套输出约定:命令在 stdout 末尾输出结构化 JSON;SSE 路径下 CLI 检测 stdout 末尾 JSON 并直接在 complete 帧带出 `result_summary`,缺失时才需 skill 从 log_file 反向扫描提取(旧服务器回退路径由 CLI `--summary` 自动提取为 `data.result_summary`)。Planner 调用本 skill 时,请在 plan step 的 required_outputs 中声明 [{kind: 'file', extensions: ['.json']}]。请求中用中性动词(运行/执行)描述命令,只有真的会落盘文件时,才使用创建/写入/保存等动词并带上扩展名。认证/配置/权限错误转 delta-shared。"
|
|
4
4
|
metadata:
|
|
5
5
|
requires:
|
|
6
6
|
bins: ["delta-cli"]
|
|
@@ -23,6 +23,13 @@ metadata:
|
|
|
23
23
|
- delta-cli 不内嵌默认凭证,运行前必须按 `delta-shared` 完成认证配置。
|
|
24
24
|
- sandbox_id 必须来自真实返回,不要凭用户口述猜测。
|
|
25
25
|
|
|
26
|
+
## 沙箱环境(镜像源)
|
|
27
|
+
|
|
28
|
+
- **国内部署(domestic)**:沙箱创建时服务端已自动注入国内镜像配置。`pip install` / `npm install` / `git clone` / HuggingFace 下载**无需额外配置**,直接可用。覆盖:pip index-url(pypi.tuna.tsinghua.edu.cn)、npm registry(npmmirror)、HF_ENDPOINT(hf-mirror.com)、git insteadOf(github 代理)。
|
|
29
|
+
- **海外部署(overseas)**:不注入镜像,使用官方源。
|
|
30
|
+
- **第三方算力沙箱**:默认不注入镜像(默认关闭),按官方源使用。
|
|
31
|
+
- 若镜像源异常,优先检查沙箱所在区域的网络,而不是假设沙箱未配置。
|
|
32
|
+
|
|
26
33
|
## 强制规则(违规则任务视为失败)
|
|
27
34
|
|
|
28
35
|
1. **必须使用 delta-cli**:所有 sandbox 操作必须通过 `delta-cli sandbox <subcommand>` 执行。**禁止**用 Python(urllib/httpx/requests)或任何 SDK 直接调用 HTTP API。delta-cli 提供类型化错误输出(`error.type`),是 AI agent 正确解析错误的唯一途径。
|
|
@@ -40,10 +47,10 @@ metadata:
|
|
|
40
47
|
```bash
|
|
41
48
|
delta-cli sandbox run-bg <id> --command "<命令>" --timeout <秒> --wait
|
|
42
49
|
```
|
|
43
|
-
CLI
|
|
50
|
+
CLI 通过 SSE 实时流(`/logs/stream`)跟随输出,把原始 SSE 帧(`data: {...}`)**逐帧透传到 stdout**(curl -N 风格),帧类型见 JSON 的 `type` 字段:`init`(含 `execution_id`)/ `stdout` / `stderr` / `error` / `complete`。收到 `complete` 即命令结束。**CLI 会在 complete 帧里补全字段**:服务端给 `exit_code`/`execution_id`/`error`,CLI 注入流内累计的 `stdout`/`stderr`、兜底恢复的 `log_file`、以及检测到的末尾 JSON `result_summary`(stdout 末尾 50 行内有合法 JSON 对象时)。命令成败看 `complete` 帧里的 `exit_code`;**命令非零退出或报错时,CLI 追加一个 `error.type: command_failed` 信封并以非零码退出(进程退出码 8)**,信封 `message` 已附 stderr 尾部,便于 `&&` 链与按 `error.type` 分支、快速扫读失败原因;`type:"error"` 帧的 `message` 也会 best-effort 附上已流出的 stderr 尾部;成功则不追加信封。若在 `--timeout`(默认 300s,同时充当服务端命令超时和客户端等待 deadline)内未收到 `complete`,CLI 会在已透传的帧后**追加一个 `finished=false` 的快照信封**(`CommandLogsResult`),表示命令仍运行。完整 stdout 在 `finished` 后被写入沙箱内的 `log_file`(默认 `/workspace/{user_id}/sandbox_logs/delta-result-{sandbox_id}-{execution_id}.json`,以服务端返回的 `log_file` 字段为准),需要读全文时用 `sandbox read <id> --path <log_file>`(末尾 JSON 摘要已在 complete 帧里,通常无需再读)。**`--summary`/`--artifacts` 富化(含 hints)仅在旧服务器回退路径生效**(服务端无 `/logs/stream` 端点时 CLI 自动回退到 5s 轮询并输出 `CommandResult` 信封)。`execution_id` 可用于后续 `sandbox logs` / `cancel`。
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
**实时跟随 / 手动轮询(需要查看中间进度时)**:
|
|
53
|
+
`sandbox logs <id> --execution-id <exec_id> --stream` 实时跟随(SSE):原始 `data:` 帧逐帧透传到 stdout,直到 `complete` 事件,无末尾信封(`--stream` 必须传 `--execution-id`)。`sandbox logs <id> --execution-id <exec_id>`(不加 `--stream`)返回快照信封;`--execution-id` 可省略——省略时仅按 sandbox 查询,服务端因 sandbox_id / execution_id 未同时传递而自动走 ES(Elasticsearch)查询(此时返回按 execution_id 聚合的**数组**,而非单个快照对象):
|
|
47
54
|
- `finished=true` + `exit_code=0` → 完成
|
|
48
55
|
- `finished=true` + `exit_code!=0` → 失败
|
|
49
56
|
- `running=true` → 仍运行
|
|
@@ -52,11 +59,14 @@ metadata:
|
|
|
52
59
|
|
|
53
60
|
- 后台任务成功后仍需按规则 2/3 销毁 sandbox。
|
|
54
61
|
|
|
55
|
-
8.
|
|
62
|
+
8. **写入文件默认落到 sandbox 的 working-directory,禁止使用 Shell 变量路径**:
|
|
63
|
+
- ✅ **推荐**:`delta-cli sandbox write <id> --source train.py`(不传 `--path`,默认写到 `<working-directory>/train.py`)
|
|
64
|
+
- ✅ **显式指定**:`delta-cli sandbox write <id> --path <working-directory>/train.py --source train.py`(`--path` 传相对路径也会自动以 working-directory 为前缀)
|
|
56
65
|
- ❌ **禁止**:`--source "$WORKSPACE_ROOT/train.py"`、`--source "$(pwd)/train.py"`(Shell 展开路径 → 空文件或失败)
|
|
57
66
|
- ❌ **禁止**:`--data "大量代码..."`(Shell 转义问题)
|
|
58
|
-
-
|
|
59
|
-
-
|
|
67
|
+
- ❌ **不建议**:`--path /workspace/train.py` 这类直接写工作目录根、落在 `{user_id}` 之外的路径——kill 后 `rclone sync` 不会写回 OSS,文件不持久化。
|
|
68
|
+
- 查询 sandbox 的 working-directory:`delta-cli sandbox working-directory <id>`(返回 `data.path`)。`run`/`run-bg` 引用脚本时用 `python <working-directory>/train.py` 的完整路径。
|
|
69
|
+
- 少量配置(< 20 行)可用 `--data "..."`,此时必须带 `--path`(无法从文件名推断)。`--mode 755` 可设置文件权限。
|
|
60
70
|
|
|
61
71
|
9. **每个 `run-bg` 生成独立 `execution_id`**:每次调用 `sandbox run-bg` 都会返回一个唯一的 `execution_id`,多个后台任务之间通过它区分。务必保存每次返回的 `execution_id` 并与任务对应,后续通过 `sandbox logs <id> --execution-id <exec_id>` 分别查询各任务的结果。同步 `sandbox run` 无需 `execution_id`,结果直接返回。
|
|
62
72
|
|
|
@@ -67,7 +77,7 @@ metadata:
|
|
|
67
77
|
- 只有在**解析 JSON**(例如从 `sandbox read` 的信封中提取 `summary` 并写入 `result.json`)时,才使用 `python3`/`python_repl`。
|
|
68
78
|
|
|
69
79
|
11. **代码/数据必须经由 `delta-cli sandbox write` 进入 sandbox**
|
|
70
|
-
- 所有要送进 sandbox 执行的脚本、配置、数据文件,**必须**通过 `delta-cli sandbox write <id> --
|
|
80
|
+
- 所有要送进 sandbox 执行的脚本、配置、数据文件,**必须**通过 `delta-cli sandbox write <id> --source <本地文件名>` 写入,默认落到该 sandbox 的 working-directory(`/workspace/{user_id}/{sandbox_id}/`,可用 `delta-cli sandbox working-directory <id>` 查询),位于 OSS 同步范围内、kill 后可持久化。
|
|
71
81
|
- 不要把脚本先写到宿主 workspace 再依赖同步;宿主 workspace 的文件对 sandbox 内部不可见。
|
|
72
82
|
- 本规则关注的是“入口统一为 `sandbox write`”,不针对任何特定宿主工具。无论宿主提供何种文件操作接口,最终都要把内容送到 sandbox 内部。
|
|
73
83
|
|
|
@@ -79,12 +89,12 @@ metadata:
|
|
|
79
89
|
13. **`result.json` 是完成前的必要条件**
|
|
80
90
|
- 在调用 `step_finish` 之前,必须确认:
|
|
81
91
|
1. `delta-cli sandbox run` / `run-bg --wait` 已返回且 `finished=true`;
|
|
82
|
-
2. (默认)直接复用 `sandbox run` / `run-bg --wait`
|
|
92
|
+
2. (默认)直接复用 `sandbox run` / `run-bg --wait` 的 SSE `complete` 帧里的 `result_summary` 写入 `result.json`;缺失时(fallback)从 `log_file` 用 `sandbox read` + Python 解析
|
|
83
93
|
3. 已执行 `sandbox kill <id>` 销毁 sandbox;
|
|
84
94
|
4. `final_response` 只有一行 `RESULT: <result_summary>`。
|
|
85
95
|
|
|
86
96
|
14. **避免冗余检查与验证**
|
|
87
|
-
- 如果 `skill_request` 或用户请求已经明确指定了镜像与资源,**不要**在 `sandbox create` 前先调用 `sandbox
|
|
97
|
+
- 如果 `skill_request` 或用户请求已经明确指定了镜像与资源,**不要**在 `sandbox create` 前先调用 `sandbox images` 或 `sandbox recommend`。
|
|
88
98
|
- 文件写入 sandbox 后,只需要 `sandbox stat`(可选)确认 size 正常即可。**禁止**用 `sandbox ls` + `sandbox read` 把刚写入的文件读回宿主再验证内容;这会产生一次无意义的往返。
|
|
89
99
|
- 不要在 `sandbox create` 成功后反复调用 `sandbox status` 轮询;create 返回时 sandbox 已就绪。
|
|
90
100
|
|
|
@@ -128,12 +138,12 @@ required_outputs:
|
|
|
128
138
|
| 用户目标 | 命令 |
|
|
129
139
|
|---------|------|
|
|
130
140
|
| **发现** | |
|
|
131
|
-
|
|
|
132
|
-
|
|
|
141
|
+
| 查看可用镜像(镜像名) | `sandbox images` |
|
|
142
|
+
| 查看剩余可申请资源 | `sandbox resources` — 按算力分组返回 GPU/显存/核心可用量:`compute_sources[].source` 为 `private`(私有算力)或 `third_party`(第三方算力);`gpu_types` 结构随分组不同(private 含 `vgpu`/`core`/`memory_mib`,third_party 含 `gpu_name`/`total_gpu_num`/`idle_gpu_num`)。算力后端为内部概念,自动选择,无需指定 |
|
|
133
143
|
| 获取资源推荐 | `sandbox recommend --cpu N --memory XGi [--gpu N] [--gpu-mem N]` |
|
|
134
|
-
| 列出当前用户的 sandbox | `sandbox list` |
|
|
144
|
+
| 列出当前用户的 sandbox | `sandbox list [--status <running/finished/killed/error>] [--start-time <ISO8601>] [--end-time <ISO8601>] [--sandbox-id <id>] [--days N]` |
|
|
135
145
|
| **生命周期** | |
|
|
136
|
-
| 创建 sandbox | `sandbox create --image
|
|
146
|
+
| 创建 sandbox | `sandbox create --image-name <镜像名> [--cpu N --memory XGi --gpu N --gpu-mem N --max-life M]`;`--image-name` 用镜像名(`sandbox images` 返回的 `image_name` 字段,如 `"PyTorch CUDA13 (GPU)"`),底层镜像标识对用户隐藏;不希望被自动清理时加 `--no-auto-cleanup`(仅显式 kill/finish 可销毁);**单沙箱资源上限** cpu ≤ 512 / memory ≤ 1024Gi / gpu ≤ 64 / gpuMem ≤ 1024Gi,超出快速报错不挂起 |
|
|
137
147
|
| 连接 sandbox | `sandbox connect <id>` |
|
|
138
148
|
| 查看状态 | `sandbox status <id>` |
|
|
139
149
|
| 完成 sandbox | `sandbox finish <id> [--results '{...}']` |
|
|
@@ -141,12 +151,13 @@ required_outputs:
|
|
|
141
151
|
| **命令执行** | |
|
|
142
152
|
| 同步运行命令(≤60s) | `sandbox run <id> --command "..." [--timeout <秒>] [--summary/--no-summary] [--artifacts]` |
|
|
143
153
|
| 后台运行命令(>60s) | `sandbox run-bg <id> --command "..." [--timeout <秒>] [--wait] [--summary/--no-summary] [--artifacts]` |
|
|
144
|
-
| 查看后台日志 | `sandbox logs <id> --execution-id <exec_id> [--tail N --grep <pattern> --context N]`
|
|
154
|
+
| 查看后台日志 | `sandbox logs <id> [--execution-id <exec_id>] [--tail N --grep <pattern> --context N] [--stream]`(`--execution-id` 可选;省略时按 sandbox 从 ES 查询,仅 `--stream` 必须传)|
|
|
145
155
|
| 中断后台命令 | `sandbox cancel <id> --execution-id <exec_id>` |
|
|
146
156
|
| **文件操作** | |
|
|
147
157
|
| 读取文件 | `sandbox read <id> --path <path> [--output <本地路径> --tail N --grep <pattern> --offset N --limit N --context N --max-bytes N --parse-json]` |
|
|
148
158
|
| 拉取文件/目录 | `sandbox pull <id> --source <沙箱路径> --target <本地路径> [--recursive] [--pattern <glob>]` — 单文件或目录递归,含 sha1 校验(mirror of upload,flag 方向与 upload 相反:source=远程,target=本地) |
|
|
149
|
-
|
|
|
159
|
+
| 查询工作目录 | `sandbox working-directory <id>`(返回 `data.path`,形如 `/workspace/{user_id}/{sandbox_id}`)|
|
|
160
|
+
| 写入文件 | `sandbox write <id> --source <文件名>`(不传 `--path` 默认写到 working-directory);`--path <路径>` 传相对路径自动加 working-directory 前缀,绝对路径原样使用 |
|
|
150
161
|
| 批量写入 | `sandbox write-multiple <id> --entry <远程路径>=<本地路径> [--entry ...]` |
|
|
151
162
|
| 上传目录 | `sandbox upload <id> --source <本地目录> --target <沙箱路径>` |
|
|
152
163
|
| 列出目录 | `sandbox ls <id> --path <路径>`(默认 `.`)|
|
|
@@ -162,61 +173,38 @@ required_outputs:
|
|
|
162
173
|
|
|
163
174
|
## 完整生命周期
|
|
164
175
|
|
|
165
|
-
1.
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
- `delta-cli sandbox images` —
|
|
176
|
+
1. **选择镜像(按需)**:
|
|
177
|
+
- 算力后端(provider)是内部概念,由系统自动选择,**不需要也不支持用户指定**。
|
|
178
|
+
- 如果请求里已经明确指定了镜像(例如 `--image-name "PyTorch CUDA13 (GPU)"`,镜像名)和资源(cpu/memory/gpu),**直接跳到步骤 2 创建 sandbox**,不要再调 `sandbox images` / `sandbox recommend`。
|
|
179
|
+
- 只有在用户要求“推荐一个配置”或需要查询可用镜像时,才调用:
|
|
180
|
+
- `delta-cli sandbox images` — 服务端支持的镜像列表(返回镜像名,隐藏底层镜像标识)
|
|
170
181
|
- `delta-cli sandbox recommend --cpu N --memory XGi [--gpu N]` — 资源配置推荐
|
|
171
|
-
2. **创建**:`delta-cli sandbox create --image
|
|
182
|
+
2. **创建**:`delta-cli sandbox create --image-name <镜像名> --cpu 4 --memory 16Gi --gpu 1 --gpu-mem 8000 --max-life 120`。**返回的 JSON 信封中是 `data.sandbox_id`,不是 `data.id`;后续所有命令必须使用这个真实的 `sandbox_id`。**(创建后 sandbox 立即可用,无需额外连接)。**响应会回显请求的镜像名/resource(服务端未返回的字段由 CLI 用请求值补齐,服务端返回值优先),可直接核对一遍资源配置,无需额外调 status。**(镜像回显为显示名;`provider` 为内部概念,不再回显)。**同一次任务若已有 `sandbox_id`,禁止再次 create,必须优先复用。**
|
|
172
183
|
- --max-life 指定 sandbox 最大存活时间(分钟),默认 30。长任务请调高,确保 sandbox 在命令执行期间不被回收。
|
|
173
|
-
-
|
|
184
|
+
- **`--gpu-mem`(单位 MiB)要匹配实际运行的模型**:模型参数量/精度越大所需显存越大,大模型塞进过小显存会直接 OOM。示例中的 8000(8GiB)只适配小模型,跑 7B/9B/13B 前先评估显存需求并适当调大。
|
|
185
|
+
- `--no-auto-cleanup`:加此 flag 后该 sandbox **不会被自动清理**(服务端超时回收 + 本地周期 cleanup_stale 均跳过),只能通过显式 `sandbox kill`/`finish` 销毁。仅当任务确实需要跨越周期清理长期存活时才使用,任务结束后必须主动销毁,避免资源泄漏。
|
|
174
186
|
- **禁止在 create 成功后反复调用 `sandbox status` 轮询**。`sandbox create` 返回时 sandbox 已经就绪,直接用它返回的 `data.sandbox_id` 执行 `write`/`run` 即可。多余的轮询会增加工具调用次数且没有任何收益。
|
|
175
187
|
3. **写入代码/数据**:
|
|
176
|
-
- **单个文件**:`delta-cli sandbox write <id> --path /
|
|
188
|
+
- **单个文件**:`delta-cli sandbox write <id> --source <文件名>` — 不传 `--path`,默认写到该 sandbox 的 working-directory(`/workspace/{user_id}/{sandbox_id}/`,可用 `delta-cli sandbox working-directory <id>` 查询)。`--source` 只传本地文件名(如 `--source train.py`),**禁止**使用 `"$WORKSPACE_ROOT/train.py"` 或 `$(pwd)/train.py` 等 Shell 变量路径。`--source` 让 CLI 自行读取本地文件,不会经过 Shell 展开,是最安全的方式。若需指定路径,`--path <相对路径>` 会自动加 working-directory 前缀,绝对路径原样使用(**不建议**写 `/workspace/<filename>` 这种落在 `{user_id}` 之外的位置,kill 后不持久化)。写入后返回的 `size` 字段是实际磁盘字节数(来自 stat 验证),可对比确认写入完整性。少量配置(<20 行)可用 `--data "..."`,但此时必须带 `--path`。文件路径和扩展名由镜像中的运行时决定。
|
|
177
189
|
- **批量写入**:`sandbox write-multiple <id> --entry <远程路径>=<本地路径> [--entry ...]`(远程路径在 `=` 左边,本地路径在右边,`--data` 批量写入不可用)
|
|
178
190
|
- **上传目录**:`sandbox upload <id> --source <本地目录> --target <沙箱路径>` — CLI 将本地目录打包为 tar.gz,通过 multipart/form-data 上传,服务端自动解压到 target 目录。返回每个文件的路径、大小、模式。上传后 CLI 自动对比本地和远程文件清单做完整性校验(大小不匹配、多余文件等会告警)。
|
|
179
191
|
- **注意**:`--source` 是**本地目录路径**,`--target` 是**沙箱内的目标目录**,target 目录不存在会自动创建。
|
|
180
192
|
- 支持嵌套目录,空目录也会被创建。
|
|
181
193
|
- **写后验证(可选)**:`sandbox stat <id> --path <path>` 确认文件存在且 size 符合预期即可。**不要**用 `sandbox ls` + `sandbox read` 把刚写入的文件读回宿主再逐字对比;无异常时不需要读回。
|
|
182
194
|
4. **运行命令**:
|
|
183
|
-
- **短任务(预计 ≤ 60 秒)**:`delta-cli sandbox run <id> --command "<命令>" --timeout <秒>`
|
|
184
|
-
- Python:`python
|
|
185
|
-
- Node.js:`node
|
|
186
|
-
- Go:`go run
|
|
187
|
-
- Shell:`bash
|
|
188
|
-
- **长任务(预计 > 60 秒,如下载模型、训练、编译、大规模数据处理)**:`delta-cli sandbox run-bg <id> --command "<命令>" --timeout <秒> [--log-file <路径>]` 提交后台任务,获得 `execution_id`
|
|
189
|
-
- `delta-cli sandbox logs <id> --execution-id <execution_id
|
|
195
|
+
- **短任务(预计 ≤ 60 秒)**:`delta-cli sandbox run <id> --command "<命令>" --timeout <秒>` 同步执行,命令的 stdout/stderr 通过 SSE **以原始 `data:` 帧逐帧透传到 stdout**(无末尾信封),`exit_code` / `log_file` / `execution_id` 从 `complete` 帧读取。完整 `stdout` 在完成后写入 run envelope 日志文件(`log_file` 字段),需要读全文或提取末尾 JSON 时用 `sandbox read`,**不要**再调用 `sandbox logs`。可通过 `--log-file <路径>` 自定义 run envelope 日志文件路径;默认值为 `/workspace/{user_id}/sandbox_logs/delta-result-{sandbox_id}-{execution_id}.json`(以服务端返回的 `log_file` 字段为准)。脚本经 `sandbox write` 落盘后位于 working-directory,运行命令需用完整路径 `<working-directory>/<文件名>`(先 `sandbox working-directory <id>` 查询)。根据镜像中的运行时构造命令,常见示例(`<wd>` 为 working-directory):
|
|
196
|
+
- Python:`python <wd>/train.py`
|
|
197
|
+
- Node.js:`node <wd>/app.js`
|
|
198
|
+
- Go:`go run <wd>/main.go`
|
|
199
|
+
- Shell:`bash <wd>/run.sh`
|
|
200
|
+
- **长任务(预计 > 60 秒,如下载模型、训练、编译、大规模数据处理)**:`delta-cli sandbox run-bg <id> --command "<命令>" --timeout <秒> [--log-file <路径>]` 提交后台任务,获得 `execution_id` 后通过以下命令查询:
|
|
201
|
+
- `delta-cli sandbox logs <id> --execution-id <execution_id> --stream` — SSE 实时跟随,原始 `data:` 帧逐帧透传到 stdout,直到 `complete` 事件(含 `exit_code`/`log_file`),无末尾信封(`--stream` 必须传 `--execution-id`)。
|
|
202
|
+
- `delta-cli sandbox logs <id> --execution-id <execution_id>` — 快照信封,返回 `stdout_tail`(末尾 800 字节)、`stderr_tail`(末尾 200 字节)、`stdout_size`、`stderr_size`、`cursor`、`running`、`finished`、`exit_code`、`log_file`(完成后)。当 `finished=true` 时认为完成,完整输出需读取 `log_file`。`--execution-id` 可省略:省略时仅按 sandbox 查询,服务端因 sandbox_id / execution_id 未同时传递而自动走 ES 查询,返回按 execution_id 聚合的**数组**。
|
|
190
203
|
禁止对长任务使用同步 `sandbox run`
|
|
191
204
|
|
|
192
|
-
**推荐实践**:让 sandbox 脚本在 `stdout` 末尾打印一个独立的结构化 JSON 对象(例如 `{"status":"ok", ...}
|
|
193
|
-
5. **生成 result.json
|
|
194
|
-
-
|
|
195
|
-
```bash
|
|
196
|
-
delta-cli sandbox run <id> --command "..." --timeout 60 > /tmp/_run.json
|
|
197
|
-
```
|
|
198
|
-
```python
|
|
199
|
-
import json, os
|
|
200
|
-
r = json.load(open("/tmp/_run.json"))
|
|
201
|
-
data = r.get("data", {})
|
|
202
|
-
# CLI 字段名是 result_summary(不是 summary),是一个对象
|
|
203
|
-
cli_summary = data.get("result_summary") or {}
|
|
204
|
-
result = {
|
|
205
|
-
"exit_code": data.get("exit_code"),
|
|
206
|
-
"finished": data.get("finished", True),
|
|
207
|
-
"summary": cli_summary,
|
|
208
|
-
"result_summary": ", ".join(f"{k}={v}" for k,v in cli_summary.items()
|
|
209
|
-
if isinstance(v, (str,int,float,bool)) and len(str(v))<200),
|
|
210
|
-
"error": data.get("error"),
|
|
211
|
-
}
|
|
212
|
-
if not result["result_summary"]:
|
|
213
|
-
result["result_summary"] = f"exit_code={result['exit_code']}, finished={result['finished']}"
|
|
214
|
-
ws = os.environ.get("WORKSPACE_ROOT", ".")
|
|
215
|
-
json.dump(result, open(os.path.join(ws, "result.json"), "w", encoding="utf-8"),
|
|
216
|
-
indent=2, ensure_ascii=False)
|
|
217
|
-
print(result["result_summary"])
|
|
218
|
-
```
|
|
219
|
-
- **5b(fallback,仅当 `--no-summary` 或 `result_summary` 为 null)**:从 `sandbox run` / `sandbox run-bg --wait` / `sandbox logs` 返回数据中获得 `log_file` 路径,用 `sandbox read` + Python 解析。
|
|
205
|
+
**推荐实践**:让 sandbox 脚本在 `stdout` 末尾打印一个独立的结构化 JSON 对象(例如 `{"status":"ok", ...}`)。SSE 路径下 CLI 会检测该末尾 JSON 并直接在 `complete` 帧里带出 `result_summary`,**任务结束后直接复用 complete 帧的 `result_summary` 写入 result.json**,无需再 `sandbox read` log_file 反向扫描。仅当 complete 帧缺失 `result_summary`(末尾无合法 JSON)时,才用 `sandbox read <id> --path <log_file>` 读取并按步骤 5 反向扫描提取,避免让大模型“读整段日志再摘要”。
|
|
206
|
+
5. **生成 result.json**(SSE 首选:直接复用 complete 帧的 `result_summary`;缺失时才从 `log_file` 读取解析):
|
|
207
|
+
- **获取 `log_file` 路径**:`run` / `run-bg --wait` 的 SSE `complete` 帧含 `log_file` 字段(CLI 已兜底补全);`sandbox logs <id> --execution-id <eid>` 快照在 `finished=true` 后同样返回 `log_file`。需要 read 时再按下面方式解析:
|
|
220
208
|
- `sandbox read` 返回的是 CLI 信封 `{"ok":true,"data":{"content":"..."}}`,真实结果 JSON 在 `data.content` 字段里。
|
|
221
209
|
- **不要把 CLI 信封或完整长 `stdout` 原样写入本地 `result.json`**;应该解析后生成一份精简的结构化摘要。
|
|
222
210
|
- **推荐做法(避免 heredoc 引号失败)**:先用 `bash` 把信封写入临时文件,再用 `python3`(或 `python_repl`)读取该文件并生成 `result.json`。**不要**把 `delta-cli sandbox read` 的输出通过管道直接喂给内联 heredoc,管道+heredoc 的组合极易因 Shell 转义/引号问题失败。
|
|
@@ -280,8 +268,8 @@ required_outputs:
|
|
|
280
268
|
命令执行完毕后,推荐在 `stdout` 末尾打印一行**独立的结构化 JSON**。例如:
|
|
281
269
|
|
|
282
270
|
- CUDA 检查:`{"status":"ok","torch_version":"2.5.1+cu121","cuda_available":true,"device_name":"NVIDIA H100 80GB HBM3"}`
|
|
283
|
-
- 训练任务:`{"status":"ok","epochs":10,"final_loss":0.12,"final_accuracy":0.94,"model_file":"
|
|
284
|
-
- 数据处理:`{"status":"ok","input_rows":10000,"output_rows":9876,"output_file":"
|
|
271
|
+
- 训练任务:`{"status":"ok","epochs":10,"final_loss":0.12,"final_accuracy":0.94,"model_file":"<wd>/model.pt"}`
|
|
272
|
+
- 数据处理:`{"status":"ok","input_rows":10000,"output_rows":9876,"output_file":"<wd>/output.csv"}`
|
|
285
273
|
|
|
286
274
|
这样 SKILL 可以用同一套代码把它提取到 `result.json` 的 `summary` 字段,再生成 `RESULT:` 行。
|
|
287
275
|
|
|
@@ -308,8 +296,8 @@ required_outputs:
|
|
|
308
296
|
|
|
309
297
|
## 输出阅读与最终回答格式
|
|
310
298
|
|
|
311
|
-
1.
|
|
312
|
-
2.
|
|
299
|
+
1. **SSE 路径下 `sandbox run` / `run-bg --wait` 的 complete 帧直接带 `result_summary`**(CLI 检测 stdout 末尾 JSON 注入)以及 `stdout` / `stderr` / `log_file`(CLI 兜底补全)。`exit_code` / `log_file` / `execution_id` 从 complete 帧读取;命令失败时 complete 帧后追加 `error.type: command_failed` 信封(进程退出码 8)。`log_file` 路径也可从 `sandbox logs <id> --execution-id <eid>` 快照(`finished=true` 后)获得。
|
|
300
|
+
2. **提取摘要**:首选直接复用 complete 帧的 `result_summary`;缺失时用 `sandbox read <id> --path <log_file>` 读取 run envelope 日志文件并解析,反向扫描 stdout 末尾 JSON 生成 `result_summary`(见“完整生命周期”步骤 5)。
|
|
313
301
|
- run envelope 日志文件包含完整 `stdout`、`stderr`、`exit_code`、`finished`、`command`、`error`。
|
|
314
302
|
3. **生成本地精简 `result.json`**(见“完整生命周期”步骤 5 和“通用结构化输出约定”)。本地副本只应包含关键字段和摘要,**不应包含完整长 `stdout`**。
|
|
315
303
|
4. **最终回答必须且只能是 `RESULT:` 开头的一行。**
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
|
|
7
7
|
| 命令 | 说明 |
|
|
8
8
|
|------|------|
|
|
9
|
-
| `sandbox list` |
|
|
10
|
-
| `sandbox
|
|
11
|
-
| `sandbox images` |
|
|
9
|
+
| `sandbox list [--status <running/finished/killed/error>] [--start-time <ISO8601>] [--end-time <ISO8601>] [--sandbox-id <id>] [--days N]` | 列出当前用户的 sandbox(与 `ls` 不同:这是列 **沙箱实例**);支持按状态/时间/sandbox_id 过滤;时间范围优先级 start_time/end_time > days > 默认 7 天。**不再支持按算力后端(provider)过滤**——provider 为内部概念,自动选择 |
|
|
10
|
+
| `sandbox resources` | 查看各算力分组的当前**剩余可申请**资源(GPU/显存/核心);响应 `compute_sources[].source` 为 `private`(私有算力)或 `third_party`(第三方算力);`gpu_types` 结构随分组不同——private 含 `vgpu`/`core`/`memory_mib` 的 `total/used/available`,third_party 含 `gpu_name`/`total_gpu_num`/`idle_gpu_num` |
|
|
11
|
+
| `sandbox images` | 查看可用镜像列表(返回**镜像名**,底层镜像标识对用户隐藏);连"原逻辑"旧服务端时返回内部镜像名(URI),该值直接传给 `--image-name` 也能成功创建;连新逻辑服务端返回净化后的展示名 |
|
|
12
12
|
| `sandbox recommend --cpu N --memory XGi [--gpu N] [--gpu-mem N]` | 获取资源配置推荐 |
|
|
13
13
|
|
|
14
14
|
## 生命周期
|
|
15
15
|
|
|
16
16
|
| 命令 | 说明 |
|
|
17
17
|
|------|------|
|
|
18
|
-
| `sandbox create --image
|
|
18
|
+
| `sandbox create --image-name <镜像名> [--cpu N --memory XGi --gpu N --gpu-mem N --max-life M --no-auto-cleanup]` | 创建 sandbox 容器(`--image-name` 用镜像名,如 `"PyTorch CUDA13 (GPU)"`,底层镜像标识对用户隐藏;`--no-auto-cleanup` 不被自动清理,仅显式 kill/finish 可销毁);**响应回显请求的镜像名/resource**(服务端未返回字段用请求值补齐,服务端值优先);算力后端为内部概念,自动选择,不再支持 `--provider`。**单沙箱资源上限**:`--cpu` ≤ 512、`--memory` ≤ 1024Gi、`--gpu` ≤ 64、`--gpu-mem` ≤ 1024Gi,超出会在请求阶段**快速返回校验错误**(不会挂起),正常任务远低于这些上限 |
|
|
19
19
|
| `sandbox connect <id>` | 连接已有 sandbox |
|
|
20
20
|
| `sandbox status <id>` | 查看 sandbox 状态(running / done) |
|
|
21
21
|
| `sandbox finish <id> [--results '{...}']` | 保存结果后自动销毁 |
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
|
|
26
26
|
| 命令 | 说明 |
|
|
27
27
|
|------|------|
|
|
28
|
-
| `sandbox run <id> --command "..." [--timeout N] [--summary/--no-summary] [--artifacts]` |
|
|
29
|
-
| `sandbox run-bg <id> --command "..." [--timeout N] [--wait] [--summary/--no-summary] [--artifacts]` | 后台运行命令;不加 `--wait` 立即返回 `{execution_id, sandbox_id}`;加 `--wait`
|
|
30
|
-
| `sandbox logs <id> --execution-id <eid> [--tail N --grep <pattern> --context N]` | 获取后台命令日志;**默认返回 `stdout_tail`(末尾 800 字节)+ `stderr_tail`(末尾 200 字节)+ `stderr_size` + `cursor`**,总计约 1KB,避免上下文爆炸;`--tail N` 同时作用于 stdout 和 stderr(各取尾 N 行);`--grep <pattern>` 同时过滤 stdout 和 stderr(正则);`--context N` 提供 grep 匹配行前后 N 行上下文(同时用于 stdout 和 stderr);**`cursor` 字段无 `omitempty`,0
|
|
28
|
+
| `sandbox run <id> --command "..." [--timeout N] [--summary/--no-summary] [--artifacts]` | 同步运行命令(SSE 实时流,原始 `data:` 帧逐帧透传到 stdout;**成功无末尾信封**;`complete` 帧由 CLI 补全 `exit_code`/`execution_id`/`log_file`/`stdout`/`stderr`/`result_summary`;**命令非零退出或报错时追加 `error.type: command_failed` 信封并以非零码退出**,信封 `message` 附 stderr 尾部,`type:"error"` 帧 message 亦附 best-effort stderr 尾部);`--summary`/`--artifacts` 仅在旧服务器回退路径(无 SSE 端点时输出 `CommandResult` 信封)生效 |
|
|
29
|
+
| `sandbox run-bg <id> --command "..." [--timeout N] [--wait] [--summary/--no-summary] [--artifacts]` | 后台运行命令;不加 `--wait` 立即返回 `{execution_id, sandbox_id}`;加 `--wait` 通过 SSE 实时流跟随到 `complete`(原始 `data:` 帧透传到 stdout;`complete` 帧由 CLI 补全 `log_file`/`stdout`/`stderr`/`result_summary`;**命令失败时追加 `command_failed` 信封并非零退出**,信封 `message` 附 stderr 尾部;超时则追加 `finished=false` 快照信封);`--summary`/`--artifacts` 仅在旧服务器回退路径生效 |
|
|
30
|
+
| `sandbox logs <id> --execution-id <eid> [--tail N --grep <pattern> --context N] [--stream]` | 获取后台命令日志;**默认返回 `stdout_tail`(末尾 800 字节)+ `stderr_tail`(末尾 200 字节)+ `stderr_size` + `cursor`**,总计约 1KB,避免上下文爆炸;`--stream` 走 `/logs/stream` SSE 实时跟随,原始 `data:` 帧透传到 stdout 直到 `complete`(complete 帧由 CLI 补全 `stdout`/`stderr`/`log_file`/`result_summary`,无末尾信封);`--tail N` 同时作用于 stdout 和 stderr(各取尾 N 行);`--grep <pattern>` 同时过滤 stdout 和 stderr(正则);`--context N` 提供 grep 匹配行前后 N 行上下文(同时用于 stdout 和 stderr);**`cursor` 字段无 `omitempty`,0 也常驻响应**;快照含 `last_updated`(SSE 路径由 CLI 填,服务端快照路径待服务端补齐)。**省略 `--execution-id` 时按 sandbox 查询**(服务端走 ES),返回**数组**(按 execution_id 聚合,每项含 `execution_id`/`stdout`/`stderr`/`exit_code`/`command`/`finished`/`error`/`log_file`),CLI 对每个元素同样应用 tail/grep 裁剪。 |
|
|
31
31
|
| `sandbox cancel <id> --execution-id <eid>` | 中断正在运行的后台命令 |
|
|
32
32
|
|
|
33
33
|
## 文件操作
|
|
@@ -35,9 +35,10 @@
|
|
|
35
35
|
| 命令 | 说明 |
|
|
36
36
|
|------|------|
|
|
37
37
|
| `sandbox read <id> --path <path> [--output <本地路径>] [--tail N] [--grep <pattern>] [--offset N] [--limit N] [--context N] [--max-bytes N] [--parse-json]` | 读取文件;返回 `content` + `size` + `content_length`;`--output <path>` 保存到本地;`--tail/--grep` 用于过滤;非 UTF-8 文件 CLI 自动走 base64 fallback |
|
|
38
|
-
| `sandbox
|
|
39
|
-
| `sandbox write <id> --path
|
|
40
|
-
| `sandbox write
|
|
38
|
+
| `sandbox working-directory <id>` | 查询 sandbox 当前工作目录(绝对路径 `/workspace/{user_id}/{sandbox_id}`) |
|
|
39
|
+
| `sandbox write <id> [--path <路径>] --source <文件名>` | 写入文件(推荐)。不传 `--path` 默认写到 working-directory(`<working-directory>/<文件名>`);相对 `--path` 也会拼到 working-directory 下;仅绝对 `--path` 原样使用(但 `/workspace/<文件名>` 根路径不在 OSS 同步范围内,不推荐) |
|
|
40
|
+
| `sandbox write <id> --path <绝对路径> --data "..."` | 写入少量内联内容(`--data` 无源文件名,必须显式传 `--path`) |
|
|
41
|
+
| `sandbox write-multiple <id> --entry <src=path> [--entry ...]` | 批量写入多个文件(目标 `path` 相对则同样拼到 working-directory) |
|
|
41
42
|
| `sandbox pull <id> --source <沙箱路径> --target <本地路径> [--recursive] [--pattern <glob>]` | 拉取文件/目录到本地(mirror of `upload`,flag 方向相反:`--source`=远程沙箱路径,`--target`=本地路径);单文件自动识别;目录默认递归;CLI 端 + 服务端双向 sha1 完整性校验 |
|
|
42
43
|
| `sandbox ls <id> --path <path>` | 列出目录内容(默认 `.`) |
|
|
43
44
|
| `sandbox stat <id> --path <path>` | 获取文件元数据(size / mode / owner / group) |
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
## 注意事项
|
|
52
53
|
|
|
53
54
|
- `list` ≠ `ls`:`sandbox list` 列沙箱实例,`sandbox ls <id>` 列沙箱内目录
|
|
55
|
+
- **算力后端(provider)为内部概念**:系统自动选择,各命令不再支持 `--provider`;`sandbox providers` 命令已随服务端 `/providers` 端点移除而废弃,调用会返回 404,不要使用
|
|
54
56
|
- 写文件后返回的 `size` 是 stat 验证后的实际磁盘字节数
|
|
55
57
|
- 读文件返回 `size`(磁盘字节,来自 stat)和 `content_length`(内存字符数),对比可判断编码偏差
|
|
56
58
|
- 读不存在的文件会返回 error,不会静默返回空内容
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
1. **查看可用镜像** `delta-cli sandbox images` — 查询服务端支持的镜像列表。镜像决定了容器内的语言运行时(Python / Node.js / Go / Java / Rust 等),根据用户的技术栈和 GPU/CPU 需求匹配。
|
|
8
8
|
2. **列出现有 sandbox(可选)** `delta-cli sandbox list` — 查看当前用户已创建的活跃 sandbox,避免重复创建
|
|
9
|
-
3. **创建** `delta-cli sandbox create --image
|
|
10
|
-
4. **写入代码/数据** `delta-cli sandbox write <id> --
|
|
11
|
-
5. **运行命令** —
|
|
12
|
-
- **短任务 ≤60s**:`delta-cli sandbox run <id> --command "<命令>" --timeout <秒>`
|
|
9
|
+
3. **创建** `delta-cli sandbox create --image-name <镜像名> --cpu 4 --memory 16Gi --gpu 1 --gpu-mem 8000 --max-life 120`(创建后立即可用,无需连接;--max-life 指定 sandbox 最大存活时间(分钟),默认 30。`--no-auto-cleanup` 可让 sandbox 不被自动清理,仅显式 kill/finish 可销毁。`--image-name` 用镜像名,如 `"PyTorch CUDA13 (GPU)"`;算力后端为内部概念,自动选择,无需指定。**单沙箱资源上限**:cpu ≤ 512、memory ≤ 1024Gi、gpu ≤ 64、gpuMem ≤ 1024Gi,超出会在请求阶段快速返回校验错误而非挂起。)
|
|
10
|
+
4. **写入代码/数据** `delta-cli sandbox write <id> --source <文件名>` — 将本地文件直接写入 sandbox,**不传 `--path` 默认写到该 sandbox 的 working-directory**(`/workspace/{user_id}/{sandbox_id}/<文件名>`,在 OSS 同步范围内,kill 后文件不会丢)。写前可用 `delta-cli sandbox working-directory <id>` 确认路径。**必须**使用相对源路径(如 `--source infer.py`),禁止使用 `"$WORKSPACE_ROOT/<filename>"` 或 `$(pwd)/...`。相对 `--path` 也会拼到 working-directory 下;仅绝对 `--path` 原样使用(`/workspace/<filename>` 根路径不在 OSS 同步范围,不推荐)。也可用 `--data "..."` 写入少量内联内容(需显式 `--path`),`--mode 755` 可设置文件权限。写入后返回的 `size` 字段是 stat 验证后的实际磁盘字节数,可确认写入完整。批量写入用 `write-multiple`。文件路径和扩展名由镜像中的运行时决定。
|
|
11
|
+
5. **运行命令** — 先 `delta-cli sandbox working-directory <id>` 查询 `<wd>`,再根据镜像中的运行时构造命令,常见示例:`python <wd>/train.py`(Python)、`node <wd>/app.js`(Node.js)、`go run <wd>/main.go`(Go)、`bash <wd>/run.sh`(Shell)
|
|
12
|
+
- **短任务 ≤60s**:`delta-cli sandbox run <id> --command "<命令>" --timeout <秒>` 同步执行,SSE 原始 `data:` 帧透传到 stdout(无末尾信封),`exit_code`/`log_file` 从 `complete` 帧读取,完整 stdout 写入 log_file
|
|
13
13
|
- **长任务 >60s**:`delta-cli sandbox run-bg <id> --command "<命令>" --timeout <秒> --wait` 后台执行(推荐),或 `run-bg` + `logs` 手动轮询 (run-bg --wait 默认带 --summary;不加 --wait 立即返回 {execution_id, sandbox_id})
|
|
14
|
-
6. **读取结果** `delta-cli sandbox read <id> --path
|
|
14
|
+
6. **读取结果** `delta-cli sandbox read <id> --path <wd>/result.json`(`<wd>` 为 working-directory,可用 `delta-cli sandbox working-directory <id>` 查询) — 返回 `content`(内容)、`size`(磁盘字节,来自 stat)、`content_length`(字符数)。读不存在的文件返回 error 而非空内容。
|
|
15
15
|
7. **销毁** `delta-cli sandbox kill <id>`(如需保存结果用 finish,finish 会自动销毁)
|
|
16
16
|
|
|
17
17
|
> **注意**:server 端没有 sandbox 的自动过期或 TTL 机制,不 kill 会永久占用 GPU 资源。请务必在任务结束后销毁。
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
```bash
|
|
26
26
|
delta-cli sandbox run-bg <id> --command "<命令>" --timeout 7200 --wait
|
|
27
27
|
```
|
|
28
|
-
CLI
|
|
28
|
+
CLI 通过 SSE 实时流(`/logs/stream`)跟随输出,把原始 SSE 帧(`data: {...}`)**逐帧透传到 stdout**,收到 `complete` 帧即命令结束。**CLI 会在 complete 帧里补全字段**:除服务端给的 `exit_code`/`execution_id`/`error` 外,还注入流内累计的 `stdout`/`stderr`、兜底恢复的 `log_file`,以及检测到的末尾 JSON `result_summary`(stdout 末尾 50 行内若有合法 JSON 对象)。命令非零退出或报错时,CLI **追加一个 `error.type: command_failed` 信封并以非零码退出**(进程退出码 8),便于 `&&` 链和 agent 分支;成功则不追加信封。只消耗 **1 次 tool call**,适合不关心中间进度的场景。
|
|
29
29
|
|
|
30
|
-
> `--wait`
|
|
30
|
+
> `--wait` 的 SSE 路径 **complete 帧直接带 `result_summary`**(末尾 JSON 检测到即附上),无需再 `sandbox read <id> --path <log_file>` 反向扫描。仅当末尾没有合法 JSON 时才需手动读 log_file。`--summary`/`--artifacts` 富化(含 hints)仍仅旧服务器回退路径生效。
|
|
31
31
|
|
|
32
|
-
>
|
|
32
|
+
> **输出契约(SSE 路径)**:`run-bg --wait` 命令成功时 stdout 只有原始 SSE 帧,**没有末尾信封**;命令失败时在 complete 帧后追加 `{"ok":false,"error":{"type":"command_failed",...}}` 信封;`--timeout` 内未结束则追加一个 `finished=false` 的 `CommandLogsResult` 快照信封;旧服务器(无 `/logs/stream` 端点)回退到 5s 轮询并输出 `CommandResult` 信封(`finished` 键始终存在,`finished=true` 时带 `result_summary`/`hints` 富化)。
|
|
33
33
|
|
|
34
34
|
### 方式二:手动轮询(需要看实时输出时)
|
|
35
35
|
|
|
@@ -38,9 +38,16 @@ CLI 内部每 5 秒轮询一次,`finished=true` 时返回,结果中包含 `e
|
|
|
38
38
|
delta-cli sandbox run-bg <id> --command "<命令>" --timeout 7200
|
|
39
39
|
# ↑ 返回 execution_id
|
|
40
40
|
|
|
41
|
-
#
|
|
41
|
+
# 2a. 实时跟随(SSE,推荐):
|
|
42
|
+
delta-cli sandbox logs <id> --execution-id <exec_id> --stream
|
|
43
|
+
# ↑ 原始 data: 帧逐帧透传到 stdout,直到 complete 事件,无末尾信封(--stream 必须传 --execution-id)
|
|
44
|
+
|
|
45
|
+
# 2b. 手动轮询快照(可用 --tail N / --grep <pattern> 过滤大输出)
|
|
42
46
|
delta-cli sandbox logs <id> --execution-id <exec_id>
|
|
43
47
|
# ↑ 返回 {sandbox_id, execution_id, stderr_tail, stderr_size, cursor, running, finished, exit_code, log_file?}
|
|
48
|
+
# --execution-id 可省略:省略时仅按 sandbox 查询,服务端因 sandbox_id/execution_id 未同时传递而自动走 ES;
|
|
49
|
+
# 此时返回的是按 execution_id 聚合的**数组**(每项含 execution_id/stdout/stderr/exit_code/command/finished/error/log_file),
|
|
50
|
+
# 而非单个快照对象,CLI 对每个元素同样做 800/200 字节 tail 裁剪与 --tail/--grep/--context 过滤
|
|
44
51
|
|
|
45
52
|
# 3. 完成后销毁
|
|
46
53
|
delta-cli sandbox kill <id>
|
|
@@ -51,22 +58,23 @@ delta-cli sandbox kill <id>
|
|
|
51
58
|
`sandbox logs` 返回的数据结构为:
|
|
52
59
|
|
|
53
60
|
```json
|
|
54
|
-
{"ok":true,"data":{"sandbox_id":"...","execution_id":"...","stdout_tail":"...","stderr_tail":"...","stdout_size":1234,"stderr_size":1234,"cursor":5,"running":false,"finished":true,"exit_code":0,"log_file":"/
|
|
61
|
+
{"ok":true,"data":{"sandbox_id":"...","execution_id":"...","stdout_tail":"...","stderr_tail":"...","stdout_size":1234,"stderr_size":1234,"cursor":5,"running":false,"finished":true,"exit_code":0,"log_file":"/workspace/{user_id}/sandbox_logs/delta-result-{sandbox_id}-{execution_id}.json"}}
|
|
55
62
|
```
|
|
56
63
|
|
|
57
64
|
字段说明:
|
|
58
|
-
- `sandbox_id` / `execution_id` —
|
|
65
|
+
- `sandbox_id` / `execution_id` — 与请求一致;省略 `--execution-id` 时走 ES 按 sandbox 查询,该字段为空
|
|
59
66
|
- `stdout_tail` — CLI 默认保留的 **最后 800 字节** stdout 片段,避免上下文爆炸
|
|
60
67
|
- `stderr_tail` — CLI 默认保留的 **最后 200 字节** stderr 片段(CLI 硬编码 `tailString(s, n)` 按字节截取;ASCII 等同 n 字符,多字节 UTF-8 可能被截断),避免上下文爆炸。不传任何 range flag 时,CLI 会把原始 `stdout`/`stderr` 字段清空,只暴露 `stdout_tail`/`stderr_tail` 和 `stdout_size`/`stderr_size`
|
|
61
68
|
- `stdout_size` — 原始 stdout 字节数(CLI 端计算)
|
|
62
69
|
- `stderr_size` — 原始 stderr 字节数(CLI 端计算)
|
|
63
|
-
- `cursor` — 服务端 stderr 行计数器;**该字段无 `omitempty`,永远出现在响应中**(即使为 0)。`cursor=0` 通常意味着服务端从 provider 还没读到任何 stderr
|
|
70
|
+
- `cursor` — 服务端 stderr 行计数器;**该字段无 `omitempty`,永远出现在响应中**(即使为 0)。`cursor=0` 通常意味着服务端从 provider 还没读到任何 stderr 行;**仅凭 cursor 判断停滞不可靠**(纯 stdout 或静默任务 cursor 恒为 0),停滞检测应以 `last_updated` 为主
|
|
71
|
+
- `last_updated` — 最近活动时间(RFC3339)。SSE 流式路径由 CLI 填最后 data 帧到达时间;快照轮询路径由服务端填(当前服务端可能缺省),缺失时判断停滞退化用 `cursor`/`stdout_tail` 变化
|
|
64
72
|
- `running` — 命令是否仍在运行
|
|
65
73
|
- `finished` — 命令是否已完成(`finished = not running`)
|
|
66
74
|
- `exit_code` — 退出码(完成后才有值,运行中字段省略)
|
|
67
|
-
- `log_file` — 仅 `finished=true` 时出现,是 run envelope 日志文件路径(含完整 stdout + stderr + exit_code + finished + command + error),需读它用 `delta-cli sandbox read <id> --path <log_file
|
|
75
|
+
- `log_file` — 仅 `finished=true` 时出现,是 run envelope 日志文件路径(含完整 stdout + stderr + exit_code + finished + command + error),需读它用 `delta-cli sandbox read <id> --path <log_file>`;SSE 路径下 CLI 已在 complete 帧里兜底补全该字段
|
|
68
76
|
|
|
69
|
-
**stdout 路径说明**:`sandbox logs` 默认返回 stdout 末尾 800 字节(`stdout_tail`)提供实时中间进度预览,完整 stdout 仍在命令结束时被写入沙箱内的 `log_file`,需全文时用 `sandbox read` 读。
|
|
77
|
+
**stdout 路径说明**:`sandbox logs` 默认返回 stdout 末尾 800 字节(`stdout_tail`)提供实时中间进度预览,完整 stdout 仍在命令结束时被写入沙箱内的 `log_file`,需全文时用 `sandbox read` 读。SSE 路径下 CLI 已在 complete 帧里带 `stdout`(全文)与 `result_summary`(末尾 JSON 检测到即附上),`--summary` 富化(含 hints)仅旧服务器回退路径生效。
|
|
70
78
|
|
|
71
79
|
要用 `--tail/--grep/--context` 自定义切片:传任意一个 flag 时,CLI 会把过滤后的 stdout 和 stderr 分别写回 `stdout`/`stderr` 字段并更新 `stdout_size`/`stderr_size`;不传则保持 `stdout=""` + `stdout_tail` 末尾 800 字节预览 + `stderr=""` + `stderr_tail` 末尾 200 字节预览(总计约 1KB)。
|
|
72
80
|
|
|
@@ -82,11 +90,11 @@ delta-cli sandbox logs <id> --execution-id <eid> --grep "ERROR|warning" --contex
|
|
|
82
90
|
1. **`finished=true` + `exit_code=0`** → 正常完成,可以读取结果并销毁 sandbox
|
|
83
91
|
2. **`finished=true` + `exit_code≠0`** → 命令执行失败,查看 stderr/error 信息
|
|
84
92
|
3. **`running=true`** → 任务仍在运行,继续等待(建议每 15-30 秒查询一次)
|
|
85
|
-
4. **连续 3 次 `running=true`
|
|
93
|
+
4. **连续 3 次 `running=true` 且输出无变化且距离提交超过 60 秒** → 任务可能挂起或无输出,用 `sandbox status <id>` 检查 sandbox 是否存活。判断「输出无变化」:快照里有 `last_updated` 时,直接比较它与当前时间是否持续滞后;缺 `last_updated` 时才退化为 `stderr_tail`/`cursor` 无变化(注意 `cursor` 只反映 stderr 行数,纯 stdout 任务会恒为 0,勿据此误判挂起)
|
|
86
94
|
5. **`sandbox status` 返回正常但 logs 仍然无变化** → 用 `sandbox run <id> --command "ps aux | grep <进程名>" --timeout 15` 在容器内检查命令是否还在运行
|
|
87
95
|
|
|
88
96
|
**注意**:
|
|
89
97
|
- `sandbox logs` 只应配合 `sandbox run-bg` 使用;同步 `sandbox run` 的结果直接返回,不能也不应该调用 `logs`。
|
|
90
98
|
- `sandbox run-bg` 不加 `--wait` 时,HTTP 请求本身会快速返回 `{execution_id, sandbox_id}`;命令若超时会以非零退出码结束,需后续通过 `logs` 拿 `exit_code`。
|
|
91
|
-
- `sandbox run-bg --wait` 模式下,`--timeout`
|
|
99
|
+
- `sandbox run-bg --wait` 模式下,`--timeout` **同时**充当服务端命令执行超时和客户端等待 deadline(默认 300s);CLI 通过 SSE 实时流(`/logs/stream`)跟随,原始 `data:` 帧透传到 stdout,收到 `complete` 即结束(无末尾信封),超时则追加 `finished=false` 快照信封;初始 `/run-background` POST 有独立的 60s HTTP timeout。
|
|
92
100
|
- 后台命令可跨 tool call 轮次查询:保存 `sandbox_id` 和 `execution_id`,后续轮次通过 `sandbox status` / `sandbox logs` 获取结果。
|
|
@@ -22,7 +22,7 @@ required_outputs:
|
|
|
22
22
|
{"status":"ok","key_metric_1":"value_1","key_metric_2":123}
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
> `sandbox run` / `run-bg --wait`
|
|
25
|
+
> SSE 路径下 `sandbox run` / `run-bg --wait` 的 **complete 帧已带 `result_summary`**(CLI 检测 stdout 末尾 50 行内的合法 JSON 对象并注入,无需手动 read+parse)。脚本作者保证 stdout 最后一行是合法 JSON 即可,skill 端直接从 complete 帧取 `result_summary`;仅当 complete 帧缺失该字段(末尾无合法 JSON)时才退化为 `sandbox read` 读取 `log_file` 反向扫描提取。`--summary` 富化(含 hints)仍仅旧服务器回退路径生效。
|
|
26
26
|
|
|
27
27
|
SKILL 会把它提取为 `result.json` 的 `summary`,并生成 `result_summary` 与最终 `RESULT:` 行。
|
|
28
28
|
|
|
@@ -60,15 +60,17 @@ SKILL 会把它提取为 `result.json` 的 `summary`,并生成 `result_summary
|
|
|
60
60
|
## 2. 运行用户已有的脚本
|
|
61
61
|
|
|
62
62
|
```text
|
|
63
|
-
在 sandbox <sandbox_id> 中运行
|
|
63
|
+
在 sandbox <sandbox_id> 中运行 <wd>/train.py,参数为 --epochs 10 --batch-size 32。
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
> `<wd>` 为该 sandbox 的 working-directory(`/workspace/{user_id}/{sandbox_id}`,先 `delta-cli sandbox working-directory <id>` 查询)。
|
|
67
|
+
|
|
66
68
|
说明:文件已存在,用中性动词 `运行`,不使用 `创建` 等承诺动词。
|
|
67
69
|
|
|
68
70
|
## 3. 安装依赖并执行命令
|
|
69
71
|
|
|
70
72
|
```text
|
|
71
|
-
在 sandbox 中运行 pip install -r
|
|
73
|
+
在 sandbox 中运行 pip install -r <wd>/requirements.txt,然后运行 python <wd>/app.py。
|
|
72
74
|
```
|
|
73
75
|
|
|
74
76
|
说明:依赖安装和命令执行都没有落盘新文件,使用中性动词描述。
|
|
@@ -82,20 +84,20 @@ SKILL 会把它提取为 `result.json` 的 `summary`,并生成 `result_summary
|
|
|
82
84
|
说明:
|
|
83
85
|
|
|
84
86
|
- 训练日志可能很长,不要让 skill 去读整段日志再摘要;让脚本自己输出关键指标。
|
|
85
|
-
- 推荐脚本最终打印:`{"status":"ok","epochs":10,"final_loss":0.023,"final_accuracy":0.992,"model_file":"
|
|
87
|
+
- 推荐脚本最终打印:`{"status":"ok","epochs":10,"final_loss":0.023,"final_accuracy":0.992,"model_file":"<wd>/model.pt"}`
|
|
86
88
|
- skill 会把它提取为 `result.json` 的 `summary`,最终输出 `RESULT: exit_code=0, status=ok, epochs=10, ...`。
|
|
87
89
|
- 如需保存完整模型文件,可再用 `sandbox read` 或 `sandbox upload` 处理,不属于 `result.json` 的摘要范围。
|
|
88
90
|
|
|
89
91
|
## 5. 通用数据处理
|
|
90
92
|
|
|
91
93
|
```text
|
|
92
|
-
在 sandbox 中运行数据处理命令,读取
|
|
94
|
+
在 sandbox 中运行数据处理命令,读取 <wd>/input.csv,输出 <wd>/output.csv,并在 stdout 末尾打印包含 input_rows、output_rows、output_file 的结构化 JSON。
|
|
93
95
|
```
|
|
94
96
|
|
|
95
97
|
说明:
|
|
96
98
|
|
|
97
|
-
- 推荐脚本最终打印:`{"status":"ok","input_rows":10000,"output_rows":9876,"output_file":"
|
|
98
|
-
- skill 会把它提取为 `result.json` 的 `summary`,最终输出 `RESULT: exit_code=0, status=ok, input_rows=10000, output_rows=9876, output_file
|
|
99
|
+
- 推荐脚本最终打印:`{"status":"ok","input_rows":10000,"output_rows":9876,"output_file":"<wd>/output.csv"}`
|
|
100
|
+
- skill 会把它提取为 `result.json` 的 `summary`,最终输出 `RESULT: exit_code=0, status=ok, input_rows=10000, output_rows=9876, output_file=<wd>/output.csv`。
|
|
99
101
|
|
|
100
102
|
## 6. 模型推理(Qwen / LLM / 视觉等)
|
|
101
103
|
|
|
@@ -114,18 +116,21 @@ SKILL 会把它提取为 `result.json` 的 `summary`,并生成 `result_summary
|
|
|
114
116
|
```
|
|
115
117
|
- skill 会把它提取为 `result.json` 的 `summary`,最终输出 `RESULT: exit_code=0, status=ok, cuda_available=True, generated_text=110, ...`。
|
|
116
118
|
|
|
119
|
+
> **GPU 显存与模型匹配**:创建 sandbox 时的 `--gpu-mem`(单位 MiB)必须匹配实际运行的模型。模型参数量/精度越大,所需显存越大;把大模型塞进过小的 `--gpu-mem` 会直接 OOM。上面的示例用的是 `Qwen2.5-0.5B`(0.5B 小模型),**不要把它当作更大模型(如 7B/9B/13B)的显存参考**。跑较大模型前先评估其显存需求、适当调大 `--gpu-mem`,并建议先用小模型验证流程是否跑通。
|
|
120
|
+
|
|
117
121
|
## 注意事项
|
|
118
122
|
|
|
119
123
|
- 尽量用自然语言描述任务,完整代码由 skill 内部处理。
|
|
120
124
|
- 只有在 skill 会真实创建文件时,才在请求中显式写出 `*.py` / `*.json` / `*.csv` 等扩展名。
|
|
121
125
|
- 不要使用 `脚本需输出...` 这类把代码片段直接跟在承诺动词后的句式。
|
|
122
126
|
- **任务完成的标准是执行结果,不是脚本文件存在**。Planner 和 skill 都要以本地 `result.json` 的生成作为完成标志;`required_outputs` 必须声明 `.json`,不要只声明 `{"kind": "file"}`。
|
|
123
|
-
- **`skill_request` 里不要出现完整代码块或宿主文件路径概念**(如 `@ROOT/...`、`/Users/...`)。脚本应通过 `delta-cli sandbox write
|
|
127
|
+
- **`skill_request` 里不要出现完整代码块或宿主文件路径概念**(如 `@ROOT/...`、`/Users/...`)。脚本应通过 `delta-cli sandbox write <id> --source <文件名>` 写入 sandbox 的 working-directory(`/workspace/{user_id}/{sandbox_id}/...`)。
|
|
124
128
|
|
|
125
129
|
## 本地 `result.json` 的内容约定
|
|
126
130
|
|
|
127
|
-
-
|
|
128
|
-
- **
|
|
131
|
+
- **SSE 首选路径(推荐,一步到位)**:`sandbox run` / `run-bg --wait` 的 **complete 帧直接带 `result_summary`**(CLI 检测 stdout 末尾 JSON 注入),skill 从 complete 帧提取即可,无需 read+parse。
|
|
132
|
+
- **SSE 回退路径**:complete 帧缺失 `result_summary`(stdout 末尾无合法 JSON)时,`delta-cli sandbox read <id> --path <log_file>` 读取 run envelope 日志文件 + 反向扫描 stdout 末尾 JSON 提取。`log_file` 路径来自 SSE `complete` 帧(CLI 已兜底补全)或 `sandbox logs` 快照(`finished=true` 后)。
|
|
133
|
+
- **旧服务器回退路径**:`run` / `run-bg --wait` 走轮询回退时返回 `CommandResult` 信封,可直接复用 `data.result_summary` 字段。
|
|
129
134
|
- 本地 `result.json` 是一份**精简摘要**,用于 host deliverable 校验,不是完整日志存档。
|
|
130
135
|
- 必须包含 `result_summary` 字段,内容与最终 `RESULT:` 行一致,方便 Runner 直接读取结论。
|
|
131
136
|
- 只写入关键字段(`exit_code`、`finished`、`summary`、`result_summary`、`error`)。**不要**额外添加 `final_answer` 等字段。
|
|
@@ -14,11 +14,9 @@ delta-science/
|
|
|
14
14
|
├── agents/
|
|
15
15
|
│ └── openai.yaml # host agent registration
|
|
16
16
|
└── references/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
└── <tool>.md # per-tool operation contract (pubchem, rdkit, pymatgen, gsasii,
|
|
21
|
-
# lammps, delta-bo, ldm-bo, ldm, strbo, synbo, antbo, ...)
|
|
17
|
+
└── <tool>.md # one real tool's operation contract (pubchem, rdkit, pymatgen,
|
|
18
|
+
# gsasii, lammps, delta-bo, ldm-bo, materials-design, qe,
|
|
19
|
+
# strbo, synbo, antbo)
|
|
22
20
|
```
|
|
23
21
|
|
|
24
22
|
## WHERE TO LOOK
|
|
@@ -26,16 +24,15 @@ delta-science/
|
|
|
26
24
|
| Path | Content |
|
|
27
25
|
|------|---------|
|
|
28
26
|
| `SKILL.md` | Service boundary, 安全红线 (no curl/requests/httpx/browser direct gateway), invocation template, cross-tool handoff |
|
|
29
|
-
| `references
|
|
30
|
-
| `references/routing-index.md` | Which tool handles which science domain; stable routing |
|
|
31
|
-
| `references/<tool>.md` | Authoritative operation + request field schema per tool |
|
|
27
|
+
| `references/<tool>.md` | One real tool's authoritative operation, request-field, response and failure schema |
|
|
32
28
|
|
|
33
29
|
## CONVENTIONS
|
|
34
30
|
|
|
35
31
|
- All science operations go through `delta-cli science invoke --tool T --endpoint E --data JSON`; no alternate routes
|
|
36
32
|
- Tool/endpoint names are exact contracts from the server DB — read the matching reference first; never invent fields/enums from memory
|
|
37
33
|
- Success is reported only when subprocess exit is 0 AND top-level JSON `ok` is `true`; `data` holds the service response
|
|
38
|
-
- `references/`
|
|
34
|
+
- `references/` contains only one real tool per file; routing, service maps, catalogs and workflows belong in `SKILL.md` or live CLI discovery, not here
|
|
35
|
+
- `retired_skills` (old per-tool skills) are removed, not referenced
|
|
39
36
|
- Host-neutral: `delta-cli` is the sole service boundary; no host-specific tool/env dependencies
|
|
40
37
|
- Discover newly-deployed tools via `delta-cli science list` / `delta-cli science endpoints list <tool>`; do not copy the server registry into the Skill
|
|
41
38
|
|