@delta-infra/cli 1.0.61 → 1.0.63
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 -6
- package/checksums.txt +5 -5
- package/package.json +1 -1
- package/scripts/install-wizard.js +93 -41
- package/skills/delta-sandbox/SKILL.md +3 -3
- package/skills/delta-sandbox/references/commands.md +1 -1
- package/skills/delta-sandbox/references/lifecycle.md +9 -9
- package/skills/delta-shared/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -12,9 +12,10 @@ npx @delta-infra/cli@latest install
|
|
|
12
12
|
|
|
13
13
|
该命令会依次完成:
|
|
14
14
|
1. **全局安装** `@delta-infra/cli`(含 Go 二进制)
|
|
15
|
-
2.
|
|
16
|
-
3.
|
|
17
|
-
4.
|
|
15
|
+
2. **选择 AI 工具平台**(可多选):通用 Agent 目录 `~/.agents/skills/`(Codex/Cursor/OpenCode)、Claude Code `~/.claude/skills/`、OpenCode 原生 `~/.config/opencode/skills/`、Cursor `~/.cursor/skills/`、Memento-S 开发模式 `~/memento_s/skills/`
|
|
16
|
+
3. **安装 AI Skills** 到所选平台的 skills 目录
|
|
17
|
+
4. **初始化配置** `delta-cli config init`(交互式,非 TTY 跳过)
|
|
18
|
+
5. **身份认证** `delta-cli auth login`(交互式,非 TTY 跳过)
|
|
18
19
|
|
|
19
20
|
AI Agent 也可以直接使用以下指令完成安装:
|
|
20
21
|
|
|
@@ -26,7 +27,7 @@ AI Agent 也可以直接使用以下指令完成安装:
|
|
|
26
27
|
npx @delta-infra/cli@latest uninstall
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
清理全局包、所有已知平台的 AI Skills 和配置文件。
|
|
30
31
|
|
|
31
32
|
### 升级
|
|
32
33
|
|
|
@@ -197,8 +198,6 @@ delta-cli sandbox kill <sandbox_id>
|
|
|
197
198
|
| `delta-cli auth login` | 交互式登录 |
|
|
198
199
|
| `delta-cli auth login --token <token>` | Token 认证 |
|
|
199
200
|
| `delta-cli auth status` | 查看认证状态 |
|
|
200
|
-
| `delta-cli update check` | 检查更新(deprecated,请用 `upgrade --check`) |
|
|
201
|
-
| `delta-cli update` | 安装最新版本(deprecated,请用 `upgrade`) |
|
|
202
201
|
| `delta-cli upgrade` | 升级 CLI 和 AI Skills 到最新版本 |
|
|
203
202
|
| `delta-cli upgrade --check` | 检查是否有可用更新 |
|
|
204
203
|
| `delta-cli upgrade --cli-only` | 只升级 CLI 二进制 |
|
package/checksums.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
e5019395b7d3dbb9cbdd01b16d0407fe986ec4577ab839b92cf05f376d8f60a3 delta-cli-darwin-amd64.tar.gz
|
|
2
|
+
2d68e0ff3f65b688235fed99b7011c41949e9c222bd2ce9be41b2a9df67472ba delta-cli-darwin-arm64.tar.gz
|
|
3
|
+
2c3ea59c3d5f98af2f9200d8e940c1b08d374307dabc6976e31aa38cf6929fa3 delta-cli-linux-amd64.tar.gz
|
|
4
|
+
16c184a9cd9dd7d08da26a59c16364c23117a9edd82278f61c3e726595b6001d delta-cli-linux-arm64.tar.gz
|
|
5
|
+
a9e85daa3fb33ecf2c4db821d247df8cdd3c78b04a8af1ea08e997ef9117ff85 delta-cli-windows-amd64.zip
|
package/package.json
CHANGED
|
@@ -14,6 +14,38 @@ const GH_MIRRORS = ["https://gh.ddlc.top", "https://ghproxy.net", "https://gh-pr
|
|
|
14
14
|
const CONFIG_DIR = path.join(osHomedir(), ".delta-infra");
|
|
15
15
|
const isWindows = process.platform === "win32";
|
|
16
16
|
|
|
17
|
+
const PLATFORM_PATHS = {
|
|
18
|
+
agents: [".agents", "skills"],
|
|
19
|
+
claude: [".claude", "skills"],
|
|
20
|
+
opencode: [".config", "opencode", "skills"],
|
|
21
|
+
cursor: [".cursor", "skills"],
|
|
22
|
+
mementos: ["memento_s", "skills"],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const PLATFORM_LABELS = {
|
|
26
|
+
zh: {
|
|
27
|
+
agents: "通用 Agent 目录 (~/.agents/skills) — Codex / Cursor / OpenCode",
|
|
28
|
+
claude: "Claude Code (~/.claude/skills)",
|
|
29
|
+
opencode: "OpenCode 原生目录 (~/.config/opencode/skills)",
|
|
30
|
+
cursor: "Cursor (~/.cursor/skills)",
|
|
31
|
+
mementos: "Memento-S 开发模式 (~/memento_s/skills)",
|
|
32
|
+
},
|
|
33
|
+
en: {
|
|
34
|
+
agents: "Generic agent dir (~/.agents/skills) — Codex / Cursor / OpenCode",
|
|
35
|
+
claude: "Claude Code (~/.claude/skills)",
|
|
36
|
+
opencode: "OpenCode native dir (~/.config/opencode/skills)",
|
|
37
|
+
cursor: "Cursor (~/.cursor/skills)",
|
|
38
|
+
mementos: "Memento-S dev mode (~/memento_s/skills)",
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const SKILL_NAMES = ["delta-sandbox", "delta-shared"];
|
|
43
|
+
const LANG = "zh";
|
|
44
|
+
|
|
45
|
+
function platformSkillDir(platform) {
|
|
46
|
+
return path.join(osHomedir(), ...PLATFORM_PATHS[platform]);
|
|
47
|
+
}
|
|
48
|
+
|
|
17
49
|
// ── i18n ────────────────────────────────────────────────────────────────────
|
|
18
50
|
|
|
19
51
|
const messages = {
|
|
@@ -26,8 +58,10 @@ const messages = {
|
|
|
26
58
|
step1Upgraded: "已升级到 v%s",
|
|
27
59
|
step1Fail: "全局安装失败。运行以下命令重试: npm install -g %s",
|
|
28
60
|
step2: "安装 AI Skills",
|
|
61
|
+
step2SelectPlatforms: "选择需要安装 Delta Skills 的 AI 工具平台(可多选)",
|
|
29
62
|
step2Spinner: "正在安装 Skills...",
|
|
30
63
|
step2Done: "Skills 已安装",
|
|
64
|
+
step2DoneFor: "已安装至: %s",
|
|
31
65
|
step2Skip: "已安装,跳过",
|
|
32
66
|
step2Fail: "Skills 安装失败。运行以下命令重试: npx skills add %s -y -g",
|
|
33
67
|
step3: "正在初始化配置...",
|
|
@@ -52,8 +86,10 @@ const messages = {
|
|
|
52
86
|
step1Upgraded: "Upgraded to v%s",
|
|
53
87
|
step1Fail: "Failed to install globally. Run manually: npm install -g %s",
|
|
54
88
|
step2: "Install AI skills",
|
|
89
|
+
step2SelectPlatforms: "Select AI tool platforms to install Delta Skills (multi-select)",
|
|
55
90
|
step2Spinner: "Installing skills...",
|
|
56
91
|
step2Done: "Skills installed",
|
|
92
|
+
step2DoneFor: "Installed to: %s",
|
|
57
93
|
step2Skip: "Already installed. Skipped",
|
|
58
94
|
step2Fail: "Failed to install skills. Run manually: npx skills add %s -y -g",
|
|
59
95
|
step3: "Initializing config...",
|
|
@@ -252,7 +288,7 @@ async function stepInstallGlobally(msg) {
|
|
|
252
288
|
}
|
|
253
289
|
}
|
|
254
290
|
|
|
255
|
-
function
|
|
291
|
+
function findPackageSkillsDir() {
|
|
256
292
|
const candidates = [];
|
|
257
293
|
try {
|
|
258
294
|
const npmRoot = runSilent("npm", ["root", "-g"], { timeout: 10000 })
|
|
@@ -261,54 +297,69 @@ function installSkillsFromLocalPackage() {
|
|
|
261
297
|
} catch {}
|
|
262
298
|
candidates.push(path.join(__dirname, "..", "skills"));
|
|
263
299
|
|
|
264
|
-
let pkgSkillsDir = null;
|
|
265
300
|
for (const c of candidates) {
|
|
266
301
|
if (fs.existsSync(path.join(c, "delta-sandbox", "SKILL.md"))) {
|
|
267
|
-
|
|
268
|
-
break;
|
|
302
|
+
return c;
|
|
269
303
|
}
|
|
270
304
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const home = osHomedir();
|
|
274
|
-
const agentsDir = path.join(home, ".agents", "skills");
|
|
275
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
276
307
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const dst = path.join(agentsDir, skill);
|
|
281
|
-
fs.rmSync(dst, { recursive: true, force: true });
|
|
282
|
-
fs.cpSync(src, dst, { recursive: true });
|
|
283
|
-
}
|
|
308
|
+
function installSkillsFromLocalPackage(platforms) {
|
|
309
|
+
const pkgSkillsDir = findPackageSkillsDir();
|
|
310
|
+
if (!pkgSkillsDir) return false;
|
|
284
311
|
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
fs.mkdirSync(
|
|
288
|
-
for (const skill of
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
} catch { /* symlink may fail on some platforms */ }
|
|
312
|
+
for (const platform of platforms) {
|
|
313
|
+
const targetDir = platformSkillDir(platform);
|
|
314
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
315
|
+
for (const skill of SKILL_NAMES) {
|
|
316
|
+
const src = path.join(pkgSkillsDir, skill);
|
|
317
|
+
if (!fs.existsSync(src)) continue;
|
|
318
|
+
const dst = path.join(targetDir, skill);
|
|
319
|
+
try { fs.rmSync(dst, { recursive: true, force: true }); } catch {}
|
|
320
|
+
fs.cpSync(src, dst, { recursive: true });
|
|
295
321
|
}
|
|
296
322
|
}
|
|
297
|
-
|
|
298
323
|
return true;
|
|
299
324
|
}
|
|
300
325
|
|
|
301
|
-
async function
|
|
326
|
+
async function stepSelectPlatforms(msg) {
|
|
327
|
+
if (!isInteractiveEnv()) {
|
|
328
|
+
return ["agents"];
|
|
329
|
+
}
|
|
330
|
+
const labels = PLATFORM_LABELS[LANG];
|
|
331
|
+
const defaultPlatforms = fs.existsSync(path.dirname(platformSkillDir("claude")))
|
|
332
|
+
? ["agents", "claude"]
|
|
333
|
+
: ["agents"];
|
|
334
|
+
const selected = await p.multiselect({
|
|
335
|
+
message: msg.step2SelectPlatforms,
|
|
336
|
+
options: Object.keys(PLATFORM_PATHS).map((key) => ({
|
|
337
|
+
value: key,
|
|
338
|
+
label: labels[key],
|
|
339
|
+
})),
|
|
340
|
+
initialValues: defaultPlatforms,
|
|
341
|
+
required: true,
|
|
342
|
+
});
|
|
343
|
+
handleCancel(selected, msg);
|
|
344
|
+
return selected;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
async function stepInstallSkills(msg, platforms) {
|
|
302
348
|
const s = createSpinner();
|
|
303
349
|
s.start(msg.step2Spinner);
|
|
304
350
|
try {
|
|
305
351
|
try {
|
|
306
|
-
if (installSkillsFromLocalPackage()) {
|
|
352
|
+
if (installSkillsFromLocalPackage(platforms)) {
|
|
307
353
|
s.stop(msg.step2Done);
|
|
354
|
+
p.log.info(fmt(msg.step2DoneFor, platforms.join(", ")));
|
|
308
355
|
return;
|
|
309
356
|
}
|
|
310
357
|
} catch { }
|
|
311
358
|
|
|
359
|
+
if (!platforms.includes("agents")) {
|
|
360
|
+
throw new Error("local skills package not found and agent dir not selected");
|
|
361
|
+
}
|
|
362
|
+
|
|
312
363
|
const urls = [
|
|
313
364
|
`https://gh.ddlc.top/https://github.com/${SKILLS_REPO}`,
|
|
314
365
|
`https://ghproxy.net/https://github.com/${SKILLS_REPO}`,
|
|
@@ -323,6 +374,7 @@ async function stepInstallSkills(msg) {
|
|
|
323
374
|
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
|
|
324
375
|
});
|
|
325
376
|
s.stop(msg.step2Done);
|
|
377
|
+
p.log.info(fmt(msg.step2DoneFor, "agents"));
|
|
326
378
|
return;
|
|
327
379
|
} catch (e) {
|
|
328
380
|
lastErr = e;
|
|
@@ -406,17 +458,15 @@ async function stepUninstallSkills(msg) {
|
|
|
406
458
|
const s = createSpinner();
|
|
407
459
|
s.start("Removing AI skills...");
|
|
408
460
|
|
|
409
|
-
const home = osHomedir();
|
|
410
|
-
const agentsDir = path.join(home, ".agents", "skills");
|
|
411
|
-
const claudeDir = path.join(home, ".claude", "skills");
|
|
412
461
|
let removedLocally = false;
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
462
|
+
for (const platform of Object.keys(PLATFORM_PATHS)) {
|
|
463
|
+
const dir = platformSkillDir(platform);
|
|
464
|
+
for (const skill of SKILL_NAMES) {
|
|
465
|
+
try {
|
|
466
|
+
fs.rmSync(path.join(dir, skill), { recursive: true, force: true });
|
|
467
|
+
removedLocally = true;
|
|
468
|
+
} catch { }
|
|
469
|
+
}
|
|
420
470
|
}
|
|
421
471
|
|
|
422
472
|
if (removedLocally) {
|
|
@@ -466,14 +516,16 @@ async function doInstall() {
|
|
|
466
516
|
if (isInteractive) {
|
|
467
517
|
p.intro(messages.zh.setup);
|
|
468
518
|
await stepInstallGlobally(messages.zh);
|
|
469
|
-
await
|
|
519
|
+
const platforms = await stepSelectPlatforms(messages.zh);
|
|
520
|
+
await stepInstallSkills(messages.zh, platforms);
|
|
470
521
|
await stepConfigInit(messages.zh);
|
|
471
522
|
await stepAuthLogin(messages.zh);
|
|
472
523
|
p.outro(messages.zh.done);
|
|
473
524
|
} else {
|
|
474
525
|
console.log(messages.zh.setup);
|
|
475
526
|
await stepInstallGlobally(messages.zh);
|
|
476
|
-
|
|
527
|
+
const platforms = ["agents"];
|
|
528
|
+
await stepInstallSkills(messages.zh, platforms);
|
|
477
529
|
console.log(messages.zh.nonTtyHint);
|
|
478
530
|
}
|
|
479
531
|
}
|
|
@@ -49,7 +49,7 @@ metadata:
|
|
|
49
49
|
- `finished=true` + `exit_code!=0` → 失败
|
|
50
50
|
- `running=true` → 仍运行
|
|
51
51
|
|
|
52
|
-
**故障诊断**:连续 3 次 `running=true` 且 `stderr_tail`/`cursor` 无变化且距离提交超过 60 秒 → 用 `sandbox status <id>` 检查 sandbox 是否存活。注意:`cursor` 字段无 `omitempty`,永远会出现在响应中(即使为 0);`stderr_tail` 默认只保留 **最后 200 字节** stderr 片段(CLI 硬编码 `tailString(s,
|
|
52
|
+
**故障诊断**:连续 3 次 `running=true` 且 `stderr_tail`/`stdout_tail`/`cursor` 无变化且距离提交超过 60 秒 → 用 `sandbox status <id>` 检查 sandbox 是否存活。注意:`cursor` 字段无 `omitempty`,永远会出现在响应中(即使为 0);`stderr_tail` 默认只保留 **最后 200 字节** stderr 片段,`stdout_tail` 默认保留 **最后 800 字节** stdout 片段(CLI 硬编码 `tailString(s, n)`,按字节截取;ASCII 文本等同于 n 字符,多字节 UTF-8 可能被截断),`cursor=0` 通常意味着服务端从 provider 还没读到任何 stderr 行。
|
|
53
53
|
|
|
54
54
|
- 后台任务成功后仍需按规则 2/3 销毁 sandbox。
|
|
55
55
|
|
|
@@ -142,7 +142,7 @@ required_outputs:
|
|
|
142
142
|
| **命令执行** | |
|
|
143
143
|
| 同步运行命令(≤60s) | `sandbox run <id> --command "..." [--timeout <秒>] [--summary/--no-summary] [--artifacts]` |
|
|
144
144
|
| 后台运行命令(>60s) | `sandbox run-bg <id> --command "..." [--timeout <秒>] [--wait] [--summary/--no-summary] [--artifacts]` |
|
|
145
|
-
| 查看后台日志 | `sandbox logs <id> --execution-id <exec_id> [--tail N --grep <pattern> --context N
|
|
145
|
+
| 查看后台日志 | `sandbox logs <id> --execution-id <exec_id> [--tail N --grep <pattern> --context N]` |
|
|
146
146
|
| 中断后台命令 | `sandbox cancel <id> --execution-id <exec_id>` |
|
|
147
147
|
| **文件操作** | |
|
|
148
148
|
| 读取文件 | `sandbox read <id> --path <path> [--output <本地路径> --tail N --grep <pattern> --offset N --limit N --context N --max-bytes N --parse-json]` |
|
|
@@ -187,7 +187,7 @@ required_outputs:
|
|
|
187
187
|
- Go:`go run /workspace/main.go`
|
|
188
188
|
- Shell:`bash /workspace/run.sh`
|
|
189
189
|
- **长任务(预计 > 60 秒,如下载模型、训练、编译、大规模数据处理)**:`delta-cli sandbox run-bg <id> --command "<命令>" --timeout <秒> [--log-file <路径>]` 提交后台任务,获得 `execution_id` 后通过以下命令轮询:
|
|
190
|
-
|
|
190
|
+
- `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`。
|
|
191
191
|
禁止对长任务使用同步 `sandbox run`
|
|
192
192
|
|
|
193
193
|
**推荐实践**:让 sandbox 脚本在 `stdout` 末尾打印一个独立的结构化 JSON 对象(例如 `{"status":"ok", ...}`),CLI 的 `--summary` 默认会自动反向扫描 stdout 末尾 JSON 提取为 `data.result_summary` 字段。这样即使 `stdout` 前面是大量训练/下载日志,skill 也无需让大模型去“读整段日志再摘要”。
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|------|------|
|
|
28
28
|
| `sandbox run <id> --command "..." [--timeout N] [--summary/--no-summary] [--artifacts]` | 同步运行命令;默认 `--summary` 开启,返回 JSON 中 `summary` 字段已含 stdout 末尾 JSON 提取结果;`--artifacts` 附带 workspace 产物清单 |
|
|
29
29
|
| `sandbox run-bg <id> --command "..." [--timeout N] [--wait] [--summary/--no-summary] [--artifacts]` | 后台运行命令;不加 `--wait` 立即返回 `{execution_id, sandbox_id}`;加 `--wait` 等待完成返回含 `summary` 的完整结果 |
|
|
30
|
-
| `sandbox logs <id> --execution-id <eid> [--tail N --grep <pattern> --context N
|
|
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 也常驻响应**。 |
|
|
31
31
|
| `sandbox cancel <id> --execution-id <eid>` | 中断正在运行的后台命令 |
|
|
32
32
|
|
|
33
33
|
## 文件操作
|
|
@@ -51,30 +51,30 @@ delta-cli sandbox kill <id>
|
|
|
51
51
|
`sandbox logs` 返回的数据结构为:
|
|
52
52
|
|
|
53
53
|
```json
|
|
54
|
-
{"ok":true,"data":{"sandbox_id":"...","execution_id":"...","stderr_tail":"...","stderr_size":1234,"cursor":5,"running":false,"finished":true,"exit_code":0,"log_file":"/tmp/delta-result-...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":"/tmp/delta-result-...json"}}
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
字段说明:
|
|
58
58
|
- `sandbox_id` / `execution_id` — 与请求一致
|
|
59
|
-
- `
|
|
59
|
+
- `stdout_tail` — CLI 默认保留的 **最后 800 字节** stdout 片段,避免上下文爆炸
|
|
60
|
+
- `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
|
+
- `stdout_size` — 原始 stdout 字节数(CLI 端计算)
|
|
60
62
|
- `stderr_size` — 原始 stderr 字节数(CLI 端计算)
|
|
61
|
-
- `cursor` — 服务端 stderr 行计数器;**该字段无 `omitempty`,永远出现在响应中**(即使为 0
|
|
63
|
+
- `cursor` — 服务端 stderr 行计数器;**该字段无 `omitempty`,永远出现在响应中**(即使为 0)。`cursor=0` 通常意味着服务端从 provider 还没读到任何 stderr 行
|
|
62
64
|
- `running` — 命令是否仍在运行
|
|
63
65
|
- `finished` — 命令是否已完成(`finished = not running`)
|
|
64
66
|
- `exit_code` — 退出码(完成后才有值,运行中字段省略)
|
|
65
67
|
- `log_file` — 仅 `finished=true` 时出现,是 run envelope 日志文件路径(含完整 stdout + stderr + exit_code + finished + command + error),需读它用 `delta-cli sandbox read <id> --path <log_file>`
|
|
66
68
|
|
|
67
|
-
**stdout 路径说明**:`sandbox logs`
|
|
69
|
+
**stdout 路径说明**:`sandbox logs` 默认返回 stdout 末尾 800 字节(`stdout_tail`)提供实时中间进度预览,完整 stdout 仍在命令结束时被写入沙箱内的 `log_file`,需全文时用 `sandbox read` 读。CLI `run-bg --wait` 完成后默认开启 `--summary`,会自动 reverse-scan stdout 末尾 JSON 填入 `data.result_summary`,常用场景无需手动读 `log_file`。
|
|
68
70
|
|
|
69
|
-
要用 `--tail/--grep/--context
|
|
71
|
+
要用 `--tail/--grep/--context` 自定义切片:传任意一个 flag 时,CLI 会把过滤后的 stdout 和 stderr 分别写回 `stdout`/`stderr` 字段并更新 `stdout_size`/`stderr_size`;不传则保持 `stdout=""` + `stdout_tail` 末尾 800 字节预览 + `stderr=""` + `stderr_tail` 末尾 200 字节预览(总计约 1KB)。
|
|
70
72
|
|
|
71
73
|
```bash
|
|
72
|
-
# 看最后 50 行 stderr
|
|
74
|
+
# 看最后 50 行 stdout 和 stderr
|
|
73
75
|
delta-cli sandbox logs <id> --execution-id <eid> --tail 50
|
|
74
|
-
# 过滤 ERROR/warning
|
|
76
|
+
# 过滤 ERROR/warning 行(同时作用于 stdout 和 stderr)
|
|
75
77
|
delta-cli sandbox logs <id> --execution-id <eid> --grep "ERROR|warning" --context 2
|
|
76
|
-
# 兜底限流 32KB
|
|
77
|
-
delta-cli sandbox logs <id> --execution-id <eid> --max-bytes 32768
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
判断任务状态的规则(按优先顺序):
|