@delta-infra/cli 1.0.0
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 +211 -0
- package/package.json +24 -0
- package/scripts/install.js +110 -0
- package/scripts/run.js +21 -0
- package/skills/delta-sandbox/SKILL.md +73 -0
- package/skills/delta-sandbox/references/commands.md +17 -0
- package/skills/delta-sandbox/references/lifecycle.md +21 -0
- package/skills/delta-shared/SKILL.md +136 -0
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# delta-cli
|
|
2
|
+
|
|
3
|
+
Delta Infra 的命令行工具。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
### 方式一:直接下载 Binary(推荐)
|
|
8
|
+
|
|
9
|
+
从 [GitHub Releases](https://github.com/yzailab/delta-infra-cli/releases) 下载对应平台的压缩包:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# macOS (Apple Silicon)
|
|
13
|
+
curl -L https://github.com/yzailab/delta-infra-cli/releases/download/v1.0.0/delta-cli-darwin-arm64.tar.gz | tar -xz
|
|
14
|
+
sudo mv delta-cli-darwin-arm64/delta-cli /usr/local/bin/
|
|
15
|
+
|
|
16
|
+
# Linux (AMD64)
|
|
17
|
+
curl -L https://github.com/yzailab/delta-infra-cli/releases/download/v1.0.0/delta-cli-linux-amd64.tar.gz | tar -xz
|
|
18
|
+
sudo mv delta-cli-linux-amd64/delta-cli /usr/local/bin/
|
|
19
|
+
|
|
20
|
+
# Windows (AMD64)
|
|
21
|
+
# 下载 delta-cli-windows-amd64.zip 并解压
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 方式二:npm
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g @delta-infra/cli
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
安装时会自动从 GitHub Release 下载当前平台的二进制文件并解压到本地。
|
|
31
|
+
|
|
32
|
+
## 快速开始
|
|
33
|
+
|
|
34
|
+
### 1. 初始化配置
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
delta-cli config init
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
配置文件保存在 `~/.delta-infra/config.json`(权限 0600),通过 `delta-cli config set base_url <url>` 配置服务端地址。也可通过环境变量覆盖:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
export DELTA_INFRA_BASE_URL=<url>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. 认证
|
|
47
|
+
|
|
48
|
+
支持 API Key 或 Bearer Token:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# API Key
|
|
52
|
+
delta-cli auth login --api-key <your-api-key>
|
|
53
|
+
|
|
54
|
+
# Bearer Token
|
|
55
|
+
delta-cli auth login --token <your-token>
|
|
56
|
+
|
|
57
|
+
# 查看认证状态
|
|
58
|
+
delta-cli auth status
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Sandbox 生命周期
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 创建带 GPU 的 sandbox
|
|
65
|
+
delta-cli sandbox create \
|
|
66
|
+
--image deltarouter/pytorch-cuda13:latest \
|
|
67
|
+
--cpu 4 --memory 16Gi --gpu 1
|
|
68
|
+
|
|
69
|
+
# 运行训练命令
|
|
70
|
+
delta-cli sandbox run <sandbox_id> \
|
|
71
|
+
--command "python /workspace/train.py" \
|
|
72
|
+
--timeout 3600
|
|
73
|
+
|
|
74
|
+
# 读取结果文件
|
|
75
|
+
delta-cli sandbox read <sandbox_id> --path /workspace/result.json
|
|
76
|
+
|
|
77
|
+
# 销毁 sandbox
|
|
78
|
+
delta-cli sandbox kill <sandbox_id>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 命令列表
|
|
82
|
+
|
|
83
|
+
### 全局命令
|
|
84
|
+
|
|
85
|
+
| 命令 | 说明 |
|
|
86
|
+
|------|------|
|
|
87
|
+
| `delta-cli config init` | 初始化配置文件 |
|
|
88
|
+
| `delta-cli config show` | 查看当前配置(敏感字段已脱敏) |
|
|
89
|
+
| `delta-cli config set <key> <value>` | 修改配置项 |
|
|
90
|
+
| `delta-cli auth login` | 交互式登录 |
|
|
91
|
+
| `delta-cli auth login --api-key <key>` | API Key 认证 |
|
|
92
|
+
| `delta-cli auth login --token <token>` | Token 认证 |
|
|
93
|
+
| `delta-cli auth status` | 查看认证状态 |
|
|
94
|
+
| `delta-cli update check` | 检查更新 |
|
|
95
|
+
| `delta-cli update` | 安装最新版本 |
|
|
96
|
+
| `delta-cli --version` | 显示版本 |
|
|
97
|
+
|
|
98
|
+
### Sandbox 命令
|
|
99
|
+
|
|
100
|
+
| 命令 | 说明 |
|
|
101
|
+
|------|------|
|
|
102
|
+
| `delta-cli sandbox create --image <img>` | 创建 sandbox 容器 |
|
|
103
|
+
| `delta-cli sandbox connect <id>` | 连接 sandbox |
|
|
104
|
+
| `delta-cli sandbox status <id>` | 查看 sandbox 状态 |
|
|
105
|
+
| `delta-cli sandbox run <id> --command "..."` | 同步运行命令 |
|
|
106
|
+
| `delta-cli sandbox run-bg <id> --command "..."` | 后台运行命令 |
|
|
107
|
+
| `delta-cli sandbox logs <id> --execution-id <eid>` | 查看后台日志 |
|
|
108
|
+
| `delta-cli sandbox read <id> --path <path>` | 读取容器内文件 |
|
|
109
|
+
| `delta-cli sandbox write <id> --path <path> --data "..."` | 写入文件 |
|
|
110
|
+
| `delta-cli sandbox finish <id> --results '{...}'` | 标记完成并返回结果 |
|
|
111
|
+
| `delta-cli sandbox kill <id>` | 销毁 sandbox |
|
|
112
|
+
|
|
113
|
+
## 输出格式
|
|
114
|
+
|
|
115
|
+
所有命令返回统一的 JSON envelope:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
// 成功
|
|
119
|
+
{"ok":true,"data":{"id":"sb-xxx","status":"running"}}
|
|
120
|
+
|
|
121
|
+
// 错误
|
|
122
|
+
{"ok":false,"error":{"type":"auth","message":"not authenticated","hint":"run 'delta-cli auth login'"}}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
错误类型及退出码:
|
|
126
|
+
|
|
127
|
+
| Type | Exit Code | 场景 |
|
|
128
|
+
|------|-----------|------|
|
|
129
|
+
| validation | 2 | 参数错误 |
|
|
130
|
+
| auth | 3 | 未认证 |
|
|
131
|
+
| permission | 4 | 权限不足 |
|
|
132
|
+
| not_found | 5 | 资源不存在 |
|
|
133
|
+
| network | 6 | 网络错误 |
|
|
134
|
+
| api | 7 | 服务端错误 |
|
|
135
|
+
| internal | 10 | 客户端内部错误 |
|
|
136
|
+
|
|
137
|
+
## AI Agent Skills
|
|
138
|
+
|
|
139
|
+
delta-cli 内置 AI Agent 操作手册(Skills),帮助 Claude Code 等 AI 助手正确使用 CLI:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# 安装共享技能(认证、配置、通用规则)
|
|
143
|
+
npx skills add delta-infra/delta-infra-cli -s delta-shared
|
|
144
|
+
|
|
145
|
+
# 安装 sandbox 操作技能
|
|
146
|
+
npx skills add delta-infra/delta-infra-cli -s delta-sandbox
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Skill 文件位于 `skills/` 目录:
|
|
150
|
+
- `delta-shared/` — 全局通用规则(认证、配置、错误处理)
|
|
151
|
+
- `delta-sandbox/` — Sandbox 操作指南(生命周期、命令路由)
|
|
152
|
+
|
|
153
|
+
## 开发
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# 本地构建
|
|
157
|
+
make build
|
|
158
|
+
|
|
159
|
+
# 运行测试
|
|
160
|
+
make test
|
|
161
|
+
|
|
162
|
+
# 代码检查
|
|
163
|
+
make lint
|
|
164
|
+
|
|
165
|
+
# 跨平台发布构建(生成压缩包)
|
|
166
|
+
make release
|
|
167
|
+
|
|
168
|
+
# 安装到 GOPATH/bin
|
|
169
|
+
make install
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 日常开发流程
|
|
173
|
+
|
|
174
|
+
修改 `skills/` 或编译 `delta-cli` 后,需要同步到 Memento-S 项目才能生效:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# 1. 复制 skill 文档到 Memento-S(让 LLM 读到最新的约束规则)
|
|
178
|
+
cp skills/delta-sandbox/SKILL.md skills/delta-sandbox/references/*.md \
|
|
179
|
+
<memento-s>/builtin/skills/delta-sandbox/
|
|
180
|
+
cp skills/delta-shared/SKILL.md \
|
|
181
|
+
<memento-s>/builtin/skills/delta-shared/
|
|
182
|
+
|
|
183
|
+
# 2. 用 Docker 编译 Windows 版本(本地无 Go toolchain 时)
|
|
184
|
+
docker run --rm -v "$(pwd):/src" -w /src \
|
|
185
|
+
-e GOPROXY=https://goproxy.cn,direct \
|
|
186
|
+
golang:1.23 go build -buildvcs=false \
|
|
187
|
+
-ldflags "-X $(MODULE)/internal/build.Version=$(shell git describe --tags --always --dirty 2>/dev/null || echo dev)" \
|
|
188
|
+
-o bin/delta-cli-windows-amd64.exe ./cmd/delta-cli
|
|
189
|
+
|
|
190
|
+
# 3. 将 delta-cli 放到 Memento-S 的 node_modules/.bin(替换旧版本)
|
|
191
|
+
cp bin/delta-cli-windows-amd64.exe \
|
|
192
|
+
<memento-s>/electron_rebuild/node_modules/.bin/delta-cli
|
|
193
|
+
|
|
194
|
+
# 4. 重启 Memento-S sidecar 使新 binary 生效
|
|
195
|
+
# 在 Electron 界面中重新加载,或手动重启 sidecar 进程
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
> **注意**:`delta-cli` 替换后,Memento-S 的 `delta-sandbox` 技能默认使用内嵌 Bearer Token,无需再手动执行 `auth login`。
|
|
199
|
+
|
|
200
|
+
## 技术栈
|
|
201
|
+
|
|
202
|
+
- **语言**: Go 1.23+
|
|
203
|
+
- **CLI 框架**: [Cobra](https://github.com/spf13/cobra)
|
|
204
|
+
- **配置**: JSON 文件(`~/.delta-infra/config.json`,权限 0600)
|
|
205
|
+
- **输出**: JSON envelope(AI-agent 友好,可脚本化)
|
|
206
|
+
- **发布**: GitHub Release(tar.gz/zip) + npm wrapper
|
|
207
|
+
- **架构**: 扁平静态命令树,Factory 依赖注入,惰性初始化
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@delta-infra/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Delta Sandbox CLI",
|
|
5
|
+
"bin": {
|
|
6
|
+
"delta-cli": "scripts/run.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node scripts/install.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"scripts/",
|
|
13
|
+
"skills/"
|
|
14
|
+
],
|
|
15
|
+
"keywords": ["delta", "sandbox", "cli", "gpu", "compute"],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18.0.0"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/yzailab/delta-infra-cli.git"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const crypto = require('crypto');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const BINARY_NAME = 'delta-cli';
|
|
9
|
+
const VERSION = require('../package.json').version;
|
|
10
|
+
const RELEASE_BASE_URL = 'https://github.com/yzailab/delta-infra-cli/releases/download';
|
|
11
|
+
|
|
12
|
+
const platformMap = {
|
|
13
|
+
darwin: 'darwin',
|
|
14
|
+
linux: 'linux',
|
|
15
|
+
win32: 'windows',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const archMap = {
|
|
19
|
+
x64: 'amd64',
|
|
20
|
+
arm64: 'arm64',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function resolveUrl(base, location) {
|
|
24
|
+
if (!location) return base;
|
|
25
|
+
if (location.startsWith('http://') || location.startsWith('https://')) {
|
|
26
|
+
return location;
|
|
27
|
+
}
|
|
28
|
+
const baseUrl = new URL(base);
|
|
29
|
+
return new URL(location, baseUrl).href;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function download(url, dest) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const file = fs.createWriteStream(dest);
|
|
35
|
+
const hash = crypto.createHash('sha256');
|
|
36
|
+
|
|
37
|
+
const cleanup = () => {
|
|
38
|
+
try { fs.unlinkSync(dest); } catch {}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
https.get(url, (response) => {
|
|
42
|
+
if (response.statusCode >= 301 && response.statusCode <= 308 && response.headers.location) {
|
|
43
|
+
file.destroy();
|
|
44
|
+
cleanup();
|
|
45
|
+
download(resolveUrl(url, response.headers.location), dest).then(resolve).catch(reject);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (response.statusCode !== 200) {
|
|
49
|
+
file.destroy();
|
|
50
|
+
cleanup();
|
|
51
|
+
reject(new Error(`Download failed: ${response.statusCode}`));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
response.pipe(file);
|
|
55
|
+
response.on('data', (chunk) => hash.update(chunk));
|
|
56
|
+
file.on('finish', () => {
|
|
57
|
+
file.close(() => resolve(hash.digest('hex')));
|
|
58
|
+
});
|
|
59
|
+
}).on('error', (err) => {
|
|
60
|
+
file.destroy();
|
|
61
|
+
cleanup();
|
|
62
|
+
reject(err);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function extract(archivePath, destDir, platform) {
|
|
68
|
+
if (platform === 'windows') {
|
|
69
|
+
execSync(`unzip -o "${archivePath}" -d "${destDir}"`, { stdio: 'inherit' });
|
|
70
|
+
} else {
|
|
71
|
+
execSync(`tar -xzf "${archivePath}" -C "${destDir}"`, { stdio: 'inherit' });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function main() {
|
|
76
|
+
const platform = platformMap[process.platform];
|
|
77
|
+
const arch = archMap[process.arch];
|
|
78
|
+
if (!platform || !arch) {
|
|
79
|
+
console.error(`Unsupported platform: ${process.platform} ${process.arch}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const isWin = platform === 'windows';
|
|
84
|
+
const archiveExt = isWin ? '.zip' : '.tar.gz';
|
|
85
|
+
const binaryExt = isWin ? '.exe' : '';
|
|
86
|
+
const assetName = `${BINARY_NAME}-${platform}-${arch}${archiveExt}`;
|
|
87
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
88
|
+
const archivePath = path.join(binDir, assetName);
|
|
89
|
+
const binaryPath = path.join(binDir, `${BINARY_NAME}${binaryExt}`);
|
|
90
|
+
|
|
91
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
92
|
+
|
|
93
|
+
const url = `${RELEASE_BASE_URL}/v${VERSION}/${assetName}`;
|
|
94
|
+
console.log(`Downloading ${assetName} from GitHub...`);
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const checksum = await download(url, archivePath);
|
|
98
|
+
console.log(`Downloaded archive, SHA256: ${checksum}`);
|
|
99
|
+
console.log(`Extracting to ${binDir}...`);
|
|
100
|
+
extract(archivePath, binDir, platform);
|
|
101
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
102
|
+
fs.unlinkSync(archivePath);
|
|
103
|
+
console.log(`Installed to ${binaryPath}`);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
console.error('Install failed:', err.message);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
main();
|
package/scripts/run.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
|
|
5
|
+
const platform = process.platform === 'win32' ? 'windows' : process.platform;
|
|
6
|
+
const ext = platform === 'windows' ? '.exe' : '';
|
|
7
|
+
const binary = path.join(__dirname, '..', 'bin', `delta-cli${ext}`);
|
|
8
|
+
|
|
9
|
+
const child = spawn(binary, process.argv.slice(2), {
|
|
10
|
+
stdio: 'inherit',
|
|
11
|
+
windowsHide: true,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
child.on('error', (err) => {
|
|
15
|
+
console.error('Failed to start delta-cli:', err.message);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
child.on('exit', (code) => {
|
|
20
|
+
process.exit(code ?? 0);
|
|
21
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: delta-sandbox
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "通过 Delta Sandbox HTTP API 运行 GPU/CPU 计算任务。适用于训练、微调、CUDA/PyTorch 推理等场景。认证/配置/权限错误转 delta-shared。"
|
|
5
|
+
metadata:
|
|
6
|
+
requires:
|
|
7
|
+
bins: ["delta-cli"]
|
|
8
|
+
cliHelp: "delta-cli sandbox --help"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../delta-shared/SKILL.md`](../delta-shared/SKILL.md),其中包含认证、配置和通用错误处理**
|
|
12
|
+
|
|
13
|
+
# delta-sandbox
|
|
14
|
+
|
|
15
|
+
## 何时使用
|
|
16
|
+
|
|
17
|
+
- 用户提到 sandbox、容器、GPU、CUDA、训练、推理、计算任务。
|
|
18
|
+
- 用户需要创建/管理 sandbox 实例、在 sandbox 中运行命令、读写文件。
|
|
19
|
+
- **不要**用于:认证、配置初始化、权限恢复、更新检查 → 转 `delta-shared`。
|
|
20
|
+
|
|
21
|
+
## 使用边界
|
|
22
|
+
|
|
23
|
+
- 所有 sandbox 操作使用 `delta-cli sandbox <subcommand>`。
|
|
24
|
+
- delta-cli 不内嵌默认凭证,运行前必须按 `delta-shared` 完成认证配置。
|
|
25
|
+
- sandbox_id 必须来自真实返回,不要凭用户口述猜测。
|
|
26
|
+
|
|
27
|
+
## 强制规则(违规则任务视为失败)
|
|
28
|
+
|
|
29
|
+
1. **必须使用 delta-cli**:所有 sandbox 操作必须通过 `delta-cli sandbox <subcommand>` 执行。**禁止**用 Python(urllib/httpx/requests)或任何 SDK 直接调用 HTTP API。delta-cli 提供类型化错误输出(`error.type`),是 AI agent 正确解析错误的唯一途径。
|
|
30
|
+
2. **必须销毁**:每次 `sandbox create` 成功后,在当前任务的最终 `step_finish` 之前 **必须** 执行 `sandbox kill <id>` 或 `sandbox finish <id>` 销毁 sandbox。未销毁等价于任务失败。
|
|
31
|
+
3. **异常时也必须销毁**:即使 sandbox 内命令失败、超时或报错,仍然 **必须** 执行 `sandbox kill <id>`。异常不是跳过销毁的理由。
|
|
32
|
+
4. **不得依赖外部清理**:server 端 **没有** sandbox 的自动过期或 TTL 机制。不 kill → sandbox 永久占用 GPU 资源。
|
|
33
|
+
5. **一条命令内完成**:从 `create` 到 `kill` 的完整生命周期必须在同一次执行中完成。不允许跨任务保留 sandbox。
|
|
34
|
+
6. **禁止重复创建**:同一次任务中只允许存在一个活跃 sandbox。若命令失败需要重试,优先复用已创建的 `sandbox_id`;若确实需要重新创建,必须先 `sandbox kill <旧_sandbox_id>`,确认旧实例销毁后再执行新的 `sandbox create`。server 端没有 list 接口,AI agent 应通过任务上下文跟踪当前 `sandbox_id`,而不是反复 create。
|
|
35
|
+
|
|
36
|
+
## 快速路由
|
|
37
|
+
|
|
38
|
+
| 用户目标 | 命令 |
|
|
39
|
+
|---------|------|
|
|
40
|
+
| 查看可用镜像 | `sandbox images` |
|
|
41
|
+
| 创建 sandbox | `sandbox create --image <image>` |
|
|
42
|
+
| 连接 sandbox | `sandbox connect <id>` |
|
|
43
|
+
| 查看状态 | `sandbox status <id>` |
|
|
44
|
+
| 同步运行命令 | `sandbox run <id> --command "..."` |
|
|
45
|
+
| 后台运行命令 | `sandbox run-bg <id> --command "..."` |
|
|
46
|
+
| 查看日志 | `sandbox logs <id> --execution-id <exec_id>` |
|
|
47
|
+
| 读取文件 | `sandbox read <id> --path <path>` |
|
|
48
|
+
| 写入文件 | `sandbox write <id> --path <path> --data "..."` |
|
|
49
|
+
| 完成 sandbox | `sandbox finish <id> --results '{...}'` |
|
|
50
|
+
| 销毁 sandbox | `sandbox kill <id>` |
|
|
51
|
+
|
|
52
|
+
## 完整生命周期
|
|
53
|
+
|
|
54
|
+
1. **查看可用镜像**:`delta-cli sandbox images` — 查询服务端支持的镜像列表(含标签、最低资源要求、支持 provider),根据用户需求匹配镜像
|
|
55
|
+
2. **创建**:`delta-cli sandbox create --image <img> --cpu 4 --memory 16Gi --gpu 1`(创建后 sandbox 立即可用,无需额外连接)。**同一次任务若已有 `sandbox_id`,禁止再次 create,必须优先复用。**
|
|
56
|
+
3. **写入代码**:`delta-cli sandbox write <id> --path /workspace/train.py --data "..."`
|
|
57
|
+
4. **运行**:`delta-cli sandbox run <id> --command "python /workspace/train.py" --timeout 3600`
|
|
58
|
+
5. **读取结果**:`delta-cli sandbox read <id> --path /workspace/result.json`
|
|
59
|
+
6. **销毁**:`delta-cli sandbox kill <id>`(如需保存结果,用 `sandbox finish --results '{...}'` 替代 kill,finish 会自动销毁 sandbox)
|
|
60
|
+
|
|
61
|
+
详细步骤见 [lifecycle.md](references/lifecycle.md)。
|
|
62
|
+
|
|
63
|
+
## 常见恢复
|
|
64
|
+
|
|
65
|
+
| 错误 / 现象 | 恢复动作 |
|
|
66
|
+
|-------------|----------|
|
|
67
|
+
| `error.type: not_found` | 检查 sandbox_id 是否正确,是否已被 kill |
|
|
68
|
+
| `error.type: network` | 检查 base_url 和网络连通性 |
|
|
69
|
+
| `error.type: validation` | 检查参数格式和必填 flag |
|
|
70
|
+
| `error.type: auth / permission` | 参考 delta-shared 的权限不足处理 |
|
|
71
|
+
| `error.type: api`(5xx) | 服务端错误,检查 API 服务状态 |
|
|
72
|
+
| 命令执行失败(exit_code ≠ 0) | 查看 `run` 返回的 stdout/stderr |
|
|
73
|
+
| 命令超时 | 增加 `--timeout` 或使用 `run-bg` |
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
> **前置条件:** 先阅读 [`../delta-shared/SKILL.md`](../delta-shared/SKILL.md) 了解认证、配置和通用错误处理。
|
|
2
|
+
|
|
3
|
+
# 命令速查表
|
|
4
|
+
|
|
5
|
+
| 命令 | 说明 |
|
|
6
|
+
|------|------|
|
|
7
|
+
| `sandbox images` | 查看可用镜像列表 |
|
|
8
|
+
| `sandbox create` | 创建 sandbox |
|
|
9
|
+
| `sandbox connect` | 连接 sandbox |
|
|
10
|
+
| `sandbox kill` | 直接销毁 sandbox,不保存结果(有结果要保存时用 finish 替代) |
|
|
11
|
+
| `sandbox finish` | 保存结果后自动销毁 sandbox(二选一:finish 或 kill,不要同时调用) |
|
|
12
|
+
| `sandbox status` | 查看状态 |
|
|
13
|
+
| `sandbox run` | 同步运行命令 |
|
|
14
|
+
| `sandbox run-bg` | 后台运行命令 |
|
|
15
|
+
| `sandbox logs` | 获取日志 |
|
|
16
|
+
| `sandbox read` | 读取文件 |
|
|
17
|
+
| `sandbox write` | 写入文件 |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
> **前置条件:** 先阅读 [`../delta-shared/SKILL.md`](../delta-shared/SKILL.md) 了解认证、配置和通用错误处理。
|
|
2
|
+
|
|
3
|
+
# Delta Sandbox 生命周期
|
|
4
|
+
|
|
5
|
+
## 完整流程
|
|
6
|
+
|
|
7
|
+
1. **查看可用镜像** `delta-cli sandbox images` — 查询服务端支持的镜像列表,根据用户的 GPU/CPU 需求和标签匹配镜像
|
|
8
|
+
2. **创建** `delta-cli sandbox create --image <image> ...`(创建后立即可用,无需连接)
|
|
9
|
+
3. **写入代码/数据** `delta-cli sandbox write <id> --path /workspace/train.py --data "..."`
|
|
10
|
+
4. **运行命令** `delta-cli sandbox run <id> --command "python /workspace/train.py"`
|
|
11
|
+
5. **读取结果** `delta-cli sandbox read <id> --path /workspace/result.json`
|
|
12
|
+
6. **销毁** `delta-cli sandbox kill <id>`(如需保存结果用 finish,finish 会自动销毁)
|
|
13
|
+
|
|
14
|
+
## 后台任务
|
|
15
|
+
|
|
16
|
+
对于长时间运行的训练:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
delta-cli sandbox run-bg <id> --command "python train.py" --timeout 3600
|
|
20
|
+
delta-cli sandbox logs <id> --execution-id <exec_id>
|
|
21
|
+
```
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: delta-shared
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "delta-cli 全局共享规则。使用于首次配置、认证登录、权限不足恢复、配置查看、遇到 JSON 输出中的 _notice 或通用错误处理时。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# delta-cli 共享规则
|
|
8
|
+
|
|
9
|
+
本技能指导你如何通过 delta-cli 操作 Delta Sandbox 及相关资源,以及所有命令域通用的注意事项。
|
|
10
|
+
|
|
11
|
+
## 获取服务端地址(必须优先执行)
|
|
12
|
+
|
|
13
|
+
所有操作的前提是知道 delta-sandbox-server 的地址。按以下步骤获取:
|
|
14
|
+
|
|
15
|
+
1. 执行 `echo $DELTA_INFRA_BASE_URL` 检查环境变量是否已设置
|
|
16
|
+
2. 如果输出非空,说明已配置,直接使用,无需额外操作
|
|
17
|
+
3. 如果为空,**向用户询问真实地址**,然后运行 `delta-cli config set base_url <url>` 保存
|
|
18
|
+
|
|
19
|
+
**不要猜测或虚构地址。不确认地址就执行任何操作会导致 network 错误。**
|
|
20
|
+
|
|
21
|
+
## 配置初始化
|
|
22
|
+
|
|
23
|
+
首次使用需运行 `delta-cli config init` 完成配置:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
delta-cli config init
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
这会创建 `~/.delta-infra/config.json`,需按实际部署设置 base_url(`delta-cli config set base_url <url>`),也可通过环境变量 `DELTA_INFRA_BASE_URL` 覆盖。
|
|
30
|
+
|
|
31
|
+
## 配置管理
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
delta-cli config show
|
|
35
|
+
delta-cli config set base_url <url>
|
|
36
|
+
delta-cli config set api_key <key>
|
|
37
|
+
delta-cli config set token <token>
|
|
38
|
+
delta-cli config remove api_key
|
|
39
|
+
delta-cli config remove token
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 环境变量覆盖
|
|
43
|
+
|
|
44
|
+
以下环境变量优先级高于配置文件:
|
|
45
|
+
|
|
46
|
+
| 变量 | 说明 |
|
|
47
|
+
|------|------|
|
|
48
|
+
| `DELTA_INFRA_BASE_URL` | 覆盖 base_url |
|
|
49
|
+
| `DELTA_SANDBOX_API_KEY` | 覆盖 api_key |
|
|
50
|
+
| `DELTA_SANDBOX_TOKEN` | 覆盖 token |
|
|
51
|
+
|
|
52
|
+
## 认证
|
|
53
|
+
|
|
54
|
+
delta-cli **不再内嵌默认凭证**,使用前必须配置认证。
|
|
55
|
+
|
|
56
|
+
支持两种认证方式,优先级从高到低:
|
|
57
|
+
|
|
58
|
+
| 方式 | 命令 / 来源 | 适用场景 |
|
|
59
|
+
|------|------------|----------|
|
|
60
|
+
| API Key | `delta-cli auth login --api-key <key>` 或环境变量 `DELTA_SANDBOX_API_KEY` | 推荐 |
|
|
61
|
+
| Bearer Token | `delta-cli auth login --token <token>` 或环境变量 `DELTA_SANDBOX_TOKEN` | 使用已有 token |
|
|
62
|
+
|
|
63
|
+
### 默认认证说明
|
|
64
|
+
|
|
65
|
+
- binary 中没有默认 token,第一次使用**必须**执行 `delta-cli auth login` 或设置环境变量。
|
|
66
|
+
- 如需更换账号,重新执行 `delta-cli auth login --token <token>` 或 `delta-cli auth login --api-key <key>`。
|
|
67
|
+
- 未配置时 `auth status` 会显示 `method: none`。
|
|
68
|
+
|
|
69
|
+
### 查看认证状态
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
delta-cli auth status
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 权限不足处理
|
|
76
|
+
|
|
77
|
+
遇到认证/权限错误时(`error.type: auth` 或 `permission`):
|
|
78
|
+
|
|
79
|
+
1. 先执行 `delta-cli auth status` 确认当前认证状态
|
|
80
|
+
2. 如需更换认证,执行 `delta-cli auth login --token <token>` 或 `delta-cli auth login --api-key <key>`
|
|
81
|
+
3. 如已认证但仍报错,检查 base_url 是否正确
|
|
82
|
+
|
|
83
|
+
**禁止**:将 API Key 或 Token 输出到终端明文展示给用户。
|
|
84
|
+
|
|
85
|
+
## 安全规则
|
|
86
|
+
|
|
87
|
+
- **禁止输出密钥**:`api_key`、`token` 不得在日志、消息或终端中明文展示。
|
|
88
|
+
- **写入/删除操作前必须确认用户意图**:`sandbox kill`、`sandbox finish`、`sandbox write` 等操作前需明确告知用户影响。
|
|
89
|
+
- **配置文件权限**:`~/.delta-infra/config.json` 权限为 `0600`,严禁手动放宽。
|
|
90
|
+
- **sandbox 必须销毁**:调用 `sandbox create` 后,当前任务结束前必须调用 `sandbox kill`。server 端无自动清理,不销毁 = 永久占用 GPU。即使遇到错误也不得跳过销毁。
|
|
91
|
+
|
|
92
|
+
## JSON 输出约定
|
|
93
|
+
|
|
94
|
+
所有命令输出遵循统一 JSON envelope:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{"ok":true,"data":{...}}
|
|
98
|
+
{"ok":false,"error":{"type":"auth","message":"...","hint":"..."}}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
AI Agent 解析规则:
|
|
102
|
+
- 始终检查 `ok` 字段,不要仅依赖 exit code
|
|
103
|
+
- `error.type` 是稳定分支字段:`auth`, `permission`, `not_found`, `validation`, `network`, `api`, `internal`
|
|
104
|
+
- `error.hint` 是可读修复建议,可展示给用户
|
|
105
|
+
|
|
106
|
+
## 退出码约定
|
|
107
|
+
|
|
108
|
+
| Type | Exit Code | 场景 |
|
|
109
|
+
|------|-----------|------|
|
|
110
|
+
| validation | 2 | flag 错误、参数缺失 |
|
|
111
|
+
| auth | 3 | 未认证或认证失败 |
|
|
112
|
+
| permission | 4 | 权限不足 |
|
|
113
|
+
| not_found | 5 | sandbox/file 不存在 |
|
|
114
|
+
| network | 6 | DNS、超时、连接失败 |
|
|
115
|
+
| api | 7 | 服务端非 2xx 错误 |
|
|
116
|
+
| internal | 10 | 客户端内部错误 |
|
|
117
|
+
|
|
118
|
+
## 更新检查
|
|
119
|
+
|
|
120
|
+
`delta-cli update check` 检查最新版本。
|
|
121
|
+
|
|
122
|
+
**当你在 JSON 中看到 `_notice.update` 时**,完成用户当前请求后,主动提议更新:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
delta-cli update
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 常见恢复
|
|
129
|
+
|
|
130
|
+
| 错误 / 现象 | 恢复动作 |
|
|
131
|
+
|-------------|----------|
|
|
132
|
+
| `error.type: auth` | 先执行 `auth status` 确认;如无认证或需更换,执行 `auth login --token <token>` |
|
|
133
|
+
| `error.type: not_found` | 检查 sandbox_id 或 path 是否正确 |
|
|
134
|
+
| `error.type: network` | 检查 base_url 和网络连通性 |
|
|
135
|
+
| `error.type: validation` | 检查必填 flag 和参数格式 |
|
|
136
|
+
| 配置文件解析失败 | 检查 `~/.delta-infra/config.json` 是否为有效 JSON |
|