@sandbank.dev/core 0.2.1 → 0.3.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.
@@ -0,0 +1,78 @@
1
+ import type { Sandbox } from './types.js';
2
+ export type ClaudeHookEvent = 'PreToolUse' | 'PostToolUse' | 'PostToolUseFailure' | 'Stop';
3
+ export interface InjectHooksConfig {
4
+ /**
5
+ * Event destination.
6
+ * - http: 使用 Claude Code 内置 HTTP hook 类型(sandbox 需能访问该 URL)
7
+ * - file: 使用 command hook 将事件追加到 JSONL 文件
8
+ */
9
+ endpoint: {
10
+ type: 'http';
11
+ url: string;
12
+ headers?: Record<string, string>;
13
+ } | {
14
+ type: 'file';
15
+ path?: string;
16
+ };
17
+ /** 要捕获的事件。默认: ['PostToolUse', 'Stop'] */
18
+ events?: ClaudeHookEvent[];
19
+ /** 是否异步执行 hook(不阻塞 agent)。默认: true */
20
+ async?: boolean;
21
+ /**
22
+ * settings.json 写入路径。默认: 自动检测 $HOME/.claude/settings.json
23
+ * 传入目录时会追加 /.claude/settings.json
24
+ */
25
+ settingsDir?: string;
26
+ }
27
+ export interface HookEventData {
28
+ /** Unix timestamp (ms) */
29
+ ts: number;
30
+ /** 原始 hook 输入数据 */
31
+ data: Record<string, unknown>;
32
+ }
33
+ export interface ClaudeLoginConfig {
34
+ /** 每次按 Enter 的间隔秒数。默认: 2 */
35
+ enterInterval?: number;
36
+ /** 最大按 Enter 次数。默认: 30 */
37
+ maxRetries?: number;
38
+ /** 安装依赖的命令。默认: apt-get update -qq && apt-get install -y -qq screen */
39
+ installCommand?: string;
40
+ }
41
+ export interface ClaudeLoginResult {
42
+ /** OAuth 授权 URL,用户需要在浏览器中打开 */
43
+ url: string;
44
+ /**
45
+ * 将 OAuth 回调返回的 auth code 发送到沙箱内的 claude login 进程。
46
+ * 使用 screen -X source 注入字符到 PTY,避免 shell 转义问题。
47
+ */
48
+ sendCode: (code: string) => Promise<void>;
49
+ /**
50
+ * 等待登录完成。用户在浏览器中完成授权后,此函数 resolve。
51
+ * 超时则 reject。
52
+ */
53
+ waitForCredentials: (timeoutMs?: number) => Promise<void>;
54
+ }
55
+ export declare const DEFAULT_EVENTS_FILE = "/tmp/sandbank-hook-events.jsonl";
56
+ /**
57
+ * 将 Claude Code hooks 配置注入沙箱。
58
+ * hooks 会在 agent 的每次工具调用后自动触发,将事件发送到指定端点。
59
+ */
60
+ export declare function injectClaudeHooks(sandbox: Sandbox, config: InjectHooksConfig): Promise<void>;
61
+ /**
62
+ * 从沙箱内的 JSONL 文件读取 hook 事件。
63
+ * 用于 file 模式下拉取事件。
64
+ */
65
+ export declare function readHookEvents(sandbox: Sandbox, path?: string): Promise<HookEventData[]>;
66
+ /**
67
+ * 在沙箱内自动化 `claude login`,捕获 OAuth 授权 URL。
68
+ *
69
+ * 使用 GNU screen 管理 PTY:
70
+ * - screen 提供真实 PTY,满足 claude login 的 TUI 需求
71
+ * - screen -X stuff 注入按键(导航 TUI)
72
+ * - screen -X hardcopy 截取屏幕纯文本(无 ANSI 转义码)
73
+ * - screen -X source 执行 stuff 命令文件(精确控制注入内容)
74
+ *
75
+ * 返回 URL 和 sendCode/waitForCredentials 回调。
76
+ */
77
+ export declare function startClaudeLogin(sandbox: Sandbox, config?: ClaudeLoginConfig): Promise<ClaudeLoginResult>;
78
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAIzC,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,aAAa,GAAG,oBAAoB,GAAG,MAAM,CAAA;AAE1F,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,QAAQ,EACJ;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAC/D;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAEnC,yCAAyC;IACzC,MAAM,CAAC,EAAE,eAAe,EAAE,CAAA;IAE1B,sCAAsC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAA;IAEf;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzC;;;OAGG;IACH,kBAAkB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1D;AAID,eAAO,MAAM,mBAAmB,oCAAoC,CAAA;AAOpE;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,iBAAiB,GACxB,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,EAAE,CAAC,CAU1B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,iBAAiB,GACzB,OAAO,CAAC,iBAAiB,CAAC,CAwH5B"}
package/dist/hooks.js ADDED
@@ -0,0 +1,218 @@
1
+ // --- Constants ---
2
+ export const DEFAULT_EVENTS_FILE = '/tmp/sandbank-hook-events.jsonl';
3
+ const HANDLER_SCRIPT_PATH = '/tmp/sandbank-hook-handler.sh';
4
+ const SCREEN_SESSION = 'claude-login';
5
+ const SCREEN_OUTPUT = '/tmp/sandbank-screen-output';
6
+ // --- Public API ---
7
+ /**
8
+ * 将 Claude Code hooks 配置注入沙箱。
9
+ * hooks 会在 agent 的每次工具调用后自动触发,将事件发送到指定端点。
10
+ */
11
+ export async function injectClaudeHooks(sandbox, config) {
12
+ const events = config.events ?? ['PostToolUse', 'Stop'];
13
+ const isAsync = config.async ?? true;
14
+ const hooksConfig = {};
15
+ for (const event of events) {
16
+ const hookDef = buildHookDef(event, config, isAsync);
17
+ hooksConfig[event] = [{
18
+ ...(event !== 'Stop' ? { matcher: '.*' } : {}),
19
+ hooks: [hookDef],
20
+ }];
21
+ }
22
+ const settings = { hooks: hooksConfig };
23
+ // 确定 settings 目录:用户指定 > 自动检测 $HOME
24
+ let baseDir = config.settingsDir;
25
+ if (!baseDir) {
26
+ const homeResult = await sandbox.exec('echo $HOME');
27
+ baseDir = homeResult.stdout.trim() || '/root';
28
+ }
29
+ const claudeDir = `${baseDir}/.claude`;
30
+ const settingsPath = `${claudeDir}/settings.json`;
31
+ // 确保 .claude 目录存在
32
+ await sandbox.exec(`mkdir -p '${claudeDir}'`);
33
+ // 写入 settings.json
34
+ await sandbox.writeFile(settingsPath, JSON.stringify(settings, null, 2));
35
+ // file 模式: 写入 handler 脚本并创建事件文件
36
+ if (config.endpoint.type === 'file') {
37
+ const eventsPath = config.endpoint.path ?? DEFAULT_EVENTS_FILE;
38
+ await writeHandlerScript(sandbox, eventsPath);
39
+ }
40
+ }
41
+ /**
42
+ * 从沙箱内的 JSONL 文件读取 hook 事件。
43
+ * 用于 file 模式下拉取事件。
44
+ */
45
+ export async function readHookEvents(sandbox, path) {
46
+ const filePath = path ?? DEFAULT_EVENTS_FILE;
47
+ const result = await sandbox.exec(`cat '${filePath}' 2>/dev/null || true`);
48
+ const output = result.stdout.trim();
49
+ if (!output)
50
+ return [];
51
+ return output
52
+ .split('\n')
53
+ .filter(line => line.trim())
54
+ .map(line => JSON.parse(line));
55
+ }
56
+ /**
57
+ * 在沙箱内自动化 `claude login`,捕获 OAuth 授权 URL。
58
+ *
59
+ * 使用 GNU screen 管理 PTY:
60
+ * - screen 提供真实 PTY,满足 claude login 的 TUI 需求
61
+ * - screen -X stuff 注入按键(导航 TUI)
62
+ * - screen -X hardcopy 截取屏幕纯文本(无 ANSI 转义码)
63
+ * - screen -X source 执行 stuff 命令文件(精确控制注入内容)
64
+ *
65
+ * 返回 URL 和 sendCode/waitForCredentials 回调。
66
+ */
67
+ export async function startClaudeLogin(sandbox, config) {
68
+ const enterInterval = config?.enterInterval ?? 2;
69
+ const maxRetries = config?.maxRetries ?? 30;
70
+ const installCmd = config?.installCommand
71
+ ?? 'apt-get update -qq && apt-get install -y -qq screen';
72
+ // 1. 确保 screen 已安装(需 root 权限安装包)
73
+ const checkScreen = await sandbox.exec('which screen 2>/dev/null');
74
+ if (checkScreen.exitCode !== 0) {
75
+ const installResult = await sandbox.exec(installCmd, { timeout: 60_000, asRoot: true });
76
+ if (installResult.exitCode !== 0) {
77
+ throw new Error(`Failed to install screen: ${installResult.stderr || installResult.stdout}`);
78
+ }
79
+ }
80
+ // 2. 清理旧文件和 screen 会话
81
+ await sandbox.exec(`screen -S ${SCREEN_SESSION} -X quit 2>/dev/null || true; `
82
+ + `rm -f '${SCREEN_OUTPUT}' /tmp/sandbank-code-debug /tmp/sandbank-screen-cmd`);
83
+ // 3. 在 screen 会话中启动 claude login
84
+ // **不要** stty columns 1000 — screen 虚拟终端固定 80 列,
85
+ // stty 改宽度会让 TUI 不换行,但超出 80 列的部分直接不可见(hardcopy 不捕获)。
86
+ // 保持默认 80 列让 URL 自然换行,extractUrlFromText 会 trimEnd+join 重组。
87
+ await sandbox.exec(`screen -dmS ${SCREEN_SESSION} bash -c 'exec claude login'`);
88
+ // 等待 screen 会话启动
89
+ await new Promise(r => setTimeout(r, 2000));
90
+ // 4. 反复检查屏幕并发送 Enter 直到出现 OAuth URL
91
+ // 关键: 先检查再发送 Enter,避免 URL 出现后多发一个 Enter 误提交空 code
92
+ let urlFound = false;
93
+ for (let i = 0; i < maxRetries; i++) {
94
+ await new Promise(r => setTimeout(r, enterInterval * 1000));
95
+ // 先检查当前屏幕(纯文本,无 ANSI 转义码)
96
+ await sandbox.exec(`screen -S ${SCREEN_SESSION} -X hardcopy ${SCREEN_OUTPUT}`);
97
+ const result = await sandbox.exec(`cat '${SCREEN_OUTPUT}' 2>/dev/null || true`);
98
+ if (result.stdout.includes('claude.ai/oauth')) {
99
+ urlFound = true;
100
+ break;
101
+ }
102
+ // URL 未找到,发送 Enter 导航 TUI
103
+ await sandbox.exec(`screen -S ${SCREEN_SESSION} -X stuff $'\\r'`);
104
+ }
105
+ if (!urlFound) {
106
+ const output = await sandbox.exec(`cat '${SCREEN_OUTPUT}' 2>/dev/null || true`);
107
+ throw new Error(`Failed to detect OAuth URL after ${maxRetries} retries.\n`
108
+ + `Screen output:\n${output.stdout.substring(0, 1000)}`);
109
+ }
110
+ // 5. 从 hardcopy 提取完整 URL(extractUrlFromText 处理 80 列断行)
111
+ const screenResult = await sandbox.exec(`cat '${SCREEN_OUTPUT}' 2>/dev/null || true`);
112
+ const url = extractUrlFromText(screenResult.stdout);
113
+ if (!url) {
114
+ throw new Error(`OAuth URL detected but failed to extract.\n`
115
+ + `Screen output:\n${screenResult.stdout.substring(0, 1000)}`);
116
+ }
117
+ // 6. sendCode: 用 screen source + stuff 注入 code
118
+ const sendCode = async (code) => {
119
+ // 检查当前 screen 状态 — 如果之前的 Enter 导致了 "Invalid code",先恢复
120
+ await sandbox.exec(`screen -S ${SCREEN_SESSION} -X hardcopy /tmp/sandbank-pre-send`);
121
+ const preState = await sandbox.exec('cat /tmp/sandbank-pre-send 2>/dev/null');
122
+ if (preState.stdout.match(/retry|try.again|Invalid/i)) {
123
+ // 发送 Enter 跳过 retry 提示,回到 code 输入
124
+ await sandbox.exec(`screen -S ${SCREEN_SESSION} -X stuff $'\\r'`);
125
+ await new Promise(r => setTimeout(r, 3000));
126
+ }
127
+ // 直接用 screen -X stuff 注入 code + CR
128
+ // 不能用 source 文件:auth code 含 # 字符,screen source 解析器会把 # 后内容当注释
129
+ // 用 $'...\r' 安全发送:$'...' 内 # 是字面量,\r 被 bash 解释为 CR
130
+ const escaped = code.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
131
+ await sandbox.exec(`screen -S ${SCREEN_SESSION} -X stuff $'${escaped}\\r'`);
132
+ };
133
+ // 7. waitForCredentials
134
+ const waitForCredentials = async (timeoutMs = 300_000) => {
135
+ const homeResult = await sandbox.exec('echo $HOME');
136
+ const home = homeResult.stdout.trim() || '/root';
137
+ const credPath = `${home}/.claude/.credentials.json`;
138
+ const start = Date.now();
139
+ const interval = 2000;
140
+ while (Date.now() - start < timeoutMs) {
141
+ const check = await sandbox.exec(`test -s '${credPath}' && echo OK || echo MISSING`);
142
+ if (check.stdout.trim() === 'OK') {
143
+ return;
144
+ }
145
+ await new Promise(r => setTimeout(r, interval));
146
+ }
147
+ // 收集诊断信息
148
+ const diag = [`Timed out waiting for credentials at ${credPath} (${timeoutMs}ms)`];
149
+ await sandbox.exec(`screen -S ${SCREEN_SESSION} -X hardcopy /tmp/sandbank-screen-final 2>/dev/null || true`);
150
+ const screenFinal = await sandbox.exec('cat /tmp/sandbank-screen-final 2>/dev/null');
151
+ if (screenFinal.stdout)
152
+ diag.push(`Screen (final):\n${screenFinal.stdout}`);
153
+ const codeDebug = await sandbox.exec('cat /tmp/sandbank-code-debug 2>/dev/null');
154
+ if (codeDebug.stdout)
155
+ diag.push(`Code debug:\n${codeDebug.stdout}`);
156
+ const screenCmd = await sandbox.exec('cat /tmp/sandbank-screen-cmd 2>/dev/null');
157
+ if (screenCmd.stdout)
158
+ diag.push(`Screen cmd:\n${screenCmd.stdout}`);
159
+ const psResult = await sandbox.exec('ps aux | grep -E "screen|claude" | grep -v grep 2>/dev/null');
160
+ if (psResult.stdout)
161
+ diag.push(`Processes:\n${psResult.stdout}`);
162
+ throw new Error(diag.join('\n\n'));
163
+ };
164
+ return { url, sendCode, waitForCredentials };
165
+ }
166
+ // --- Internal ---
167
+ function buildHookDef(event, config, isAsync) {
168
+ if (config.endpoint.type === 'http') {
169
+ return {
170
+ type: 'http',
171
+ url: config.endpoint.url,
172
+ ...(config.endpoint.headers ? { headers: config.endpoint.headers } : {}),
173
+ timeout: 10,
174
+ };
175
+ }
176
+ // file 模式: 使用 command hook 调用 handler 脚本
177
+ return {
178
+ type: 'command',
179
+ command: HANDLER_SCRIPT_PATH,
180
+ timeout: 5,
181
+ async: isAsync,
182
+ };
183
+ }
184
+ const URL_RE = /https?:\/\/[^\s'"><]+/g;
185
+ /**
186
+ * 从 screen hardcopy 纯文本中提取 OAuth URL。
187
+ *
188
+ * hardcopy 按 screen 虚拟终端宽度(默认 80 列)输出,
189
+ * 长 URL 会被断行,每行尾部填充空格到 80 列。
190
+ * 先 trimEnd 每行再拼接,消除断行产生的空格,重组完整 URL。
191
+ */
192
+ function extractUrlFromText(text) {
193
+ if (!text)
194
+ return null;
195
+ // 重组被 hardcopy 断行的长 URL
196
+ const joined = text.split('\n').map(line => line.trimEnd()).join('');
197
+ const urls = joined.match(URL_RE);
198
+ if (!urls)
199
+ return null;
200
+ const oauthUrls = urls.filter(u => u.includes('claude.ai/oauth'));
201
+ if (oauthUrls.length === 0)
202
+ return null;
203
+ return oauthUrls.reduce((a, b) => a.length >= b.length ? a : b);
204
+ }
205
+ async function writeHandlerScript(sandbox, eventsPath) {
206
+ // 使用纯 POSIX shell 以保证最大兼容性
207
+ // tr -d '\n' 确保多行 JSON 输入被压成单行 JSONL
208
+ const script = `#!/bin/sh
209
+ TS=$(($(date +%s) * 1000))
210
+ INPUT=$(cat | tr -d '\\n')
211
+ printf '{"ts":%d,"data":%s}\\n' "$TS" "$INPUT" >> '${eventsPath}'
212
+ `;
213
+ await sandbox.writeFile(HANDLER_SCRIPT_PATH, script);
214
+ // writeFile 以 root 写入,chmod 需 root 权限
215
+ await sandbox.exec(`chmod +x '${HANDLER_SCRIPT_PATH}'`, { asRoot: true });
216
+ // events 文件由 hook handler(以沙箱用户身份)追加写入,需用户可写
217
+ await sandbox.exec(`touch '${eventsPath}'`);
218
+ }
package/dist/index.d.ts CHANGED
@@ -1,10 +1,15 @@
1
- export type { SandboxProvider, Sandbox, CreateConfig, ExecOptions, ExecResult, SandboxState, SandboxInfo, ListFilter, Capability, StreamableSandbox, TerminalSandbox, TerminalOptions, TerminalInfo, TerminalSession, Disposable, SleepableSandbox, PortExposeSandbox, SnapshotSandbox, VolumeProvider, VolumeConfig, VolumeInfo, ServiceType, ServiceConfig, ServiceCredentials, ServiceInfo, ServiceProvider, ServiceBinding, SandboxAdapter, AdapterSandbox, SkillDefinition, } from './types.js';
1
+ export type { SandboxProvider, Sandbox, CreateConfig, ExecOptions, ExecResult, SandboxState, SandboxInfo, ListFilter, Capability, StreamableSandbox, TerminalSandbox, TerminalOptions, TerminalInfo, TerminalSession, Disposable, SleepableSandbox, PortExposeSandbox, SnapshotSandbox, VolumeProvider, VolumeConfig, VolumeInfo, ServiceType, ServiceConfig, ServiceCredentials, ServiceInfo, ServiceProvider, ServiceBinding, SandboxAdapter, AdapterSandbox, SkillDefinition, SandboxUser, SandboxUserInfo, } from './types.js';
2
2
  export { createProvider } from './provider.js';
3
3
  export { hasCapability, withStreaming, withTerminal, withSleep, withPortExpose, withSnapshot, withVolumes, withServices, } from './capabilities.js';
4
4
  export { SandboxError, SandboxNotFoundError, SandboxStateError, ExecTimeoutError, RateLimitError, ProviderError, CapabilityNotSupportedError, } from './errors.js';
5
5
  export { connectTerminal } from './terminal.js';
6
6
  export { injectSkills } from './skill-inject.js';
7
7
  export { writeFileViaExec, readFileViaExec, uploadArchiveViaExec, downloadArchiveViaExec } from './file-helpers.js';
8
+ export { setupSandboxUser, wrapAsUser } from './sandbox-user.js';
9
+ export type { SandboxEvent, SandboxEventType, SandboxObserver, ProviderOptions } from './observer.js';
10
+ export { emitEvent, createNoopObserver, createWebhookObserver } from './observer.js';
11
+ export type { ClaudeHookEvent, InjectHooksConfig, HookEventData, ClaudeLoginConfig, ClaudeLoginResult } from './hooks.js';
12
+ export { injectClaudeHooks, readHookEvents, startClaudeLogin, DEFAULT_EVENTS_FILE } from './hooks.js';
8
13
  export type { MessagePriority, SessionMessage, ContextStore, CompletionStatus, SandboxCompletion, SendOptions, Session, RelayConfig, CreateSessionConfig, JsonRpcRequest, JsonRpcResponse, JsonRpcNotification, JsonRpcError, Transport, } from './session-types.js';
9
14
  export { createSession } from './session.js';
10
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAEV,eAAe,EACf,OAAO,EACP,YAAY,EACZ,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EAEV,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,UAAU,EAEV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,cAAc,EAEd,cAAc,EACd,cAAc,EAEd,eAAe,GAChB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,WAAW,EACX,YAAY,GACb,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAGnH,YAAY,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,SAAS,GACV,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAEV,eAAe,EACf,OAAO,EACP,YAAY,EACZ,WAAW,EACX,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EAEV,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,UAAU,EAEV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,cAAc,EAEd,cAAc,EACd,cAAc,EAEd,eAAe,EAEf,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,EACT,cAAc,EACd,YAAY,EACZ,WAAW,EACX,YAAY,GACb,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAGnH,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAGhE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACrG,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAGpF,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACzH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGrG,YAAY,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,SAAS,GACV,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA"}
package/dist/index.js CHANGED
@@ -10,5 +10,9 @@ export { connectTerminal } from './terminal.js';
10
10
  export { injectSkills } from './skill-inject.js';
11
11
  // File helpers (for adapter authors)
12
12
  export { writeFileViaExec, readFileViaExec, uploadArchiveViaExec, downloadArchiveViaExec } from './file-helpers.js';
13
+ // Sandbox user
14
+ export { setupSandboxUser, wrapAsUser } from './sandbox-user.js';
15
+ export { emitEvent, createNoopObserver, createWebhookObserver } from './observer.js';
16
+ export { injectClaudeHooks, readHookEvents, startClaudeLogin, DEFAULT_EVENTS_FILE } from './hooks.js';
13
17
  // Session factory
14
18
  export { createSession } from './session.js';
@@ -0,0 +1,32 @@
1
+ export type SandboxEventType = 'sandbox:exec' | 'sandbox:writeFile' | 'sandbox:readFile' | 'sandbox:uploadArchive' | 'sandbox:downloadArchive';
2
+ export interface SandboxEvent {
3
+ /** 事件类型 */
4
+ type: SandboxEventType;
5
+ /** 沙箱 ID */
6
+ sandboxId: string;
7
+ /** 关联的任务 ID(可选) */
8
+ taskId?: string;
9
+ /** 事件时间戳(Unix ms) */
10
+ timestamp: number;
11
+ /** 事件数据(命令、路径、退出码等) */
12
+ data: Record<string, unknown>;
13
+ }
14
+ export interface SandboxObserver {
15
+ /** 接收一个沙箱事件。可以返回 Promise,但调用方不会等待。 */
16
+ onEvent(event: SandboxEvent): void | Promise<void>;
17
+ }
18
+ export interface ProviderOptions {
19
+ /** 可选的事件观察者。设置后,所有沙箱操作都会自动记录。 */
20
+ observer?: SandboxObserver;
21
+ /** 默认任务 ID,会附加到所有事件上 */
22
+ taskId?: string;
23
+ }
24
+ /** 安全地发射事件:不阻塞、不抛错 */
25
+ export declare function emitEvent(observer: SandboxObserver, event: SandboxEvent): void;
26
+ /** 空观察者,不做任何操作 */
27
+ export declare function createNoopObserver(): SandboxObserver;
28
+ /** Webhook 观察者,将事件 POST 到指定 URL */
29
+ export declare function createWebhookObserver(url: string, options?: {
30
+ headers?: Record<string, string>;
31
+ }): SandboxObserver;
32
+ //# sourceMappingURL=observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,mBAAmB,GACnB,kBAAkB,GAClB,uBAAuB,GACvB,yBAAyB,CAAA;AAE7B,MAAM,WAAW,YAAY;IAC3B,WAAW;IACX,IAAI,EAAE,gBAAgB,CAAA;IACtB,YAAY;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnD;AAED,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,QAAQ,CAAC,EAAE,eAAe,CAAA;IAC1B,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,sBAAsB;AACtB,wBAAgB,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAS9E;AAED,kBAAkB;AAClB,wBAAgB,kBAAkB,IAAI,eAAe,CAEpD;AAED,mCAAmC;AACnC,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAC7C,eAAe,CAajB"}
@@ -0,0 +1,33 @@
1
+ // --- Sandbox Observer ---
2
+ /** 安全地发射事件:不阻塞、不抛错 */
3
+ export function emitEvent(observer, event) {
4
+ try {
5
+ const result = observer.onEvent(event);
6
+ if (result && typeof result.catch === 'function') {
7
+ ;
8
+ result.catch(() => { });
9
+ }
10
+ }
11
+ catch {
12
+ // observer 报错不影响沙箱操作
13
+ }
14
+ }
15
+ /** 空观察者,不做任何操作 */
16
+ export function createNoopObserver() {
17
+ return { onEvent() { } };
18
+ }
19
+ /** Webhook 观察者,将事件 POST 到指定 URL */
20
+ export function createWebhookObserver(url, options) {
21
+ return {
22
+ onEvent(event) {
23
+ return fetch(url, {
24
+ method: 'POST',
25
+ headers: {
26
+ 'Content-Type': 'application/json',
27
+ ...options?.headers,
28
+ },
29
+ body: JSON.stringify(event),
30
+ }).then(() => { });
31
+ },
32
+ };
33
+ }
@@ -1,4 +1,8 @@
1
1
  import type { SandboxAdapter, SandboxProvider } from './types.js';
2
+ import type { SandboxObserver } from './observer.js';
2
3
  /** 创建一个 SandboxProvider */
3
- export declare function createProvider(adapter: SandboxAdapter): SandboxProvider;
4
+ export declare function createProvider(adapter: SandboxAdapter, options?: {
5
+ observer?: SandboxObserver;
6
+ taskId?: string;
7
+ }): SandboxProvider;
4
8
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAQV,cAAc,EAEd,eAAe,EAShB,MAAM,YAAY,CAAA;AAqGnB,2BAA2B;AAC3B,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,eAAe,CA0EvE"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAQV,cAAc,EAEd,eAAe,EAShB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,eAAe,CAAA;AA8ItE,2BAA2B;AAC3B,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,eAAe,CAmFjB"}
package/dist/provider.js CHANGED
@@ -1,37 +1,66 @@
1
+ import { emitEvent } from './observer.js';
1
2
  import { CapabilityNotSupportedError, ProviderError } from './errors.js';
2
3
  import { injectSkills } from './skill-inject.js';
3
4
  import { readFileViaExec, writeFileViaExec, uploadArchiveViaExec, downloadArchiveViaExec } from './file-helpers.js';
5
+ import { setupSandboxUser, wrapAsUser } from './sandbox-user.js';
4
6
  /**
5
7
  * 将 AdapterSandbox 包装为完整的 Sandbox 接口。
6
8
  * 自动补充缺失的 writeFile/readFile 默认实现。
9
+ * 若传入 observer,自动对所有操作发射事件。
7
10
  */
8
- function wrapSandbox(raw, providerName) {
11
+ function wrapSandbox(raw, providerName, observer, taskId, userInfo) {
12
+ function emit(type, data) {
13
+ if (!observer)
14
+ return;
15
+ emitEvent(observer, { type, sandboxId: raw.id, taskId, timestamp: Date.now(), data });
16
+ }
9
17
  const sandbox = {
10
18
  get id() { return raw.id; },
11
19
  get state() { return raw.state; },
12
20
  get createdAt() { return raw.createdAt; },
13
- exec(command, options) {
14
- return raw.exec(command, options);
21
+ get user() { return userInfo; },
22
+ async exec(command, options) {
23
+ let cmd = command;
24
+ let opts = options;
25
+ // 非 root 用户包装: 默认以该用户执行,asRoot 跳过
26
+ if (userInfo && !options?.asRoot) {
27
+ cmd = wrapAsUser(command, userInfo.name, options?.cwd);
28
+ // cwd 已包含在 wrapped command 中,不再传给 adapter
29
+ opts = options ? { ...options, cwd: undefined, asRoot: undefined } : undefined;
30
+ }
31
+ const start = Date.now();
32
+ try {
33
+ const result = await raw.exec(cmd, opts);
34
+ emit('sandbox:exec', { command, exitCode: result.exitCode, duration: Date.now() - start });
35
+ return result;
36
+ }
37
+ catch (err) {
38
+ emit('sandbox:exec', { command, error: err.message, duration: Date.now() - start });
39
+ throw err;
40
+ }
15
41
  },
16
- writeFile(path, content) {
17
- if (raw.writeFile)
18
- return raw.writeFile(path, content);
19
- return writeFileViaExec(raw, path, content);
42
+ async writeFile(path, content) {
43
+ const size = typeof content === 'string' ? content.length : content.byteLength;
44
+ const fn = raw.writeFile ? raw.writeFile.bind(raw) : (p, c) => writeFileViaExec(raw, p, c);
45
+ await fn(path, content);
46
+ emit('sandbox:writeFile', { path, size });
20
47
  },
21
- readFile(path) {
22
- if (raw.readFile)
23
- return raw.readFile(path);
24
- return readFileViaExec(raw, path);
48
+ async readFile(path) {
49
+ const fn = raw.readFile ? raw.readFile.bind(raw) : (p) => readFileViaExec(raw, p);
50
+ const result = await fn(path);
51
+ emit('sandbox:readFile', { path, size: result.byteLength });
52
+ return result;
25
53
  },
26
- uploadArchive(archive, destDir) {
27
- if (raw.uploadArchive)
28
- return raw.uploadArchive(archive, destDir);
29
- return uploadArchiveViaExec(raw, archive, destDir);
54
+ async uploadArchive(archive, destDir) {
55
+ const fn = raw.uploadArchive ? raw.uploadArchive.bind(raw) : (a, d) => uploadArchiveViaExec(raw, a, d);
56
+ await fn(archive, destDir);
57
+ emit('sandbox:uploadArchive', { destDir: destDir ?? '/' });
30
58
  },
31
- downloadArchive(srcDir) {
32
- if (raw.downloadArchive)
33
- return raw.downloadArchive(srcDir);
34
- return downloadArchiveViaExec(raw, srcDir);
59
+ async downloadArchive(srcDir) {
60
+ const fn = raw.downloadArchive ? raw.downloadArchive.bind(raw) : (s) => downloadArchiveViaExec(raw, s);
61
+ const result = await fn(srcDir);
62
+ emit('sandbox:downloadArchive', { srcDir: srcDir ?? '/' });
63
+ return result;
35
64
  },
36
65
  };
37
66
  // 转发可选能力方法(只有 adapter 真正实现的才转发)
@@ -89,8 +118,10 @@ function detectCapabilities(adapter) {
89
118
  return validated;
90
119
  }
91
120
  /** 创建一个 SandboxProvider */
92
- export function createProvider(adapter) {
121
+ export function createProvider(adapter, options) {
93
122
  const capabilities = detectCapabilities(adapter);
123
+ const observer = options?.observer;
124
+ const taskId = options?.taskId;
94
125
  const provider = {
95
126
  get name() { return adapter.name; },
96
127
  get capabilities() { return capabilities; },
@@ -115,7 +146,12 @@ export function createProvider(adapter) {
115
146
  config = { ...config, env: mergedEnv };
116
147
  }
117
148
  const raw = await adapter.createSandbox(config);
118
- const sandbox = wrapSandbox(raw, adapter.name);
149
+ // 创建非 root 用户(如果配置了)
150
+ let userInfo;
151
+ if (config.user) {
152
+ userInfo = await setupSandboxUser(raw, config.user);
153
+ }
154
+ const sandbox = wrapSandbox(raw, adapter.name, observer, taskId, userInfo);
119
155
  if (config.skills?.length) {
120
156
  try {
121
157
  await injectSkills(sandbox, config.skills);
@@ -129,7 +165,7 @@ export function createProvider(adapter) {
129
165
  },
130
166
  async get(id) {
131
167
  const raw = await adapter.getSandbox(id);
132
- return wrapSandbox(raw, adapter.name);
168
+ return wrapSandbox(raw, adapter.name, observer, taskId);
133
169
  },
134
170
  async list(filter) {
135
171
  return adapter.listSandboxes(filter);
@@ -0,0 +1,15 @@
1
+ import type { AdapterSandbox, SandboxUser, SandboxUserInfo } from './types.js';
2
+ /**
3
+ * 在沙箱中创建非 root 用户。
4
+ * 假设 Debian/Ubuntu 基础镜像(useradd)。
5
+ */
6
+ export declare function setupSandboxUser(sandbox: AdapterSandbox, config: string | SandboxUser): Promise<SandboxUserInfo>;
7
+ /**
8
+ * 将命令包装为指定用户执行。
9
+ * 使用 `su - <user> -c '...'` — 由 root 调用无需密码,`-` 设置完整环境。
10
+ *
11
+ * 构建 inner command(su 的 bash 将执行的内容),然后整体做一次
12
+ * 单引号转义放入外层 `'...'`。cwd 在 inner command 中用双引号包裹。
13
+ */
14
+ export declare function wrapAsUser(command: string, user: string, cwd?: string): string;
15
+ //# sourceMappingURL=sandbox-user.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-user.d.ts","sourceRoot":"","sources":["../src/sandbox-user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE9E;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,GAAG,WAAW,GAC3B,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ9E"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * 在沙箱中创建非 root 用户。
3
+ * 假设 Debian/Ubuntu 基础镜像(useradd)。
4
+ */
5
+ export async function setupSandboxUser(sandbox, config) {
6
+ const opts = typeof config === 'string' ? { name: config } : config;
7
+ const name = opts.name ?? 'sandbank';
8
+ const sudo = opts.sudo ?? true;
9
+ // 1. 创建用户(如果不存在)
10
+ const uidFlag = opts.uid != null ? `-u ${opts.uid}` : '';
11
+ const result = await sandbox.exec(`id ${name} >/dev/null 2>&1 || useradd -m -s /bin/bash ${uidFlag} ${name}`);
12
+ if (result.exitCode !== 0) {
13
+ throw new Error(`Failed to create user '${name}': ${result.stderr || result.stdout}`);
14
+ }
15
+ // 2. 获取 home 目录
16
+ const homeResult = await sandbox.exec(`eval echo ~${name}`);
17
+ const home = homeResult.stdout.trim();
18
+ if (!home || home === `~${name}`) {
19
+ throw new Error(`Failed to resolve home directory for user '${name}'`);
20
+ }
21
+ // 3. 配置 sudo(可选)
22
+ if (sudo) {
23
+ await sandbox.exec(`command -v sudo >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y -qq sudo) 2>/dev/null; `
24
+ + `echo '${name} ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/${name} && chmod 440 /etc/sudoers.d/${name}`);
25
+ }
26
+ return { name, home };
27
+ }
28
+ /**
29
+ * 将命令包装为指定用户执行。
30
+ * 使用 `su - <user> -c '...'` — 由 root 调用无需密码,`-` 设置完整环境。
31
+ *
32
+ * 构建 inner command(su 的 bash 将执行的内容),然后整体做一次
33
+ * 单引号转义放入外层 `'...'`。cwd 在 inner command 中用双引号包裹。
34
+ */
35
+ export function wrapAsUser(command, user, cwd) {
36
+ let innerCmd = command;
37
+ if (cwd) {
38
+ // 双引号包裹 cwd,转义双引号上下文中的特殊字符
39
+ const safeCwd = cwd.replace(/["$`\\]/g, '\\$&');
40
+ innerCmd = `cd "${safeCwd}" && ${command}`;
41
+ }
42
+ return `su - ${user} -c '${escapeSingleQuotes(innerCmd)}'`;
43
+ }
44
+ /** POSIX 单引号转义: ' → '\'' */
45
+ function escapeSingleQuotes(s) {
46
+ return s.replace(/'/g, "'\\''");
47
+ }
package/dist/types.d.ts CHANGED
@@ -47,11 +47,34 @@ export interface CreateConfig {
47
47
  skills?: SkillDefinition[];
48
48
  /** 绑定的服务。凭证自动注入为环境变量(需 provider 支持 'services' 能力) */
49
49
  services?: ServiceBinding[];
50
+ /** 端口映射 [hostPort, guestPort][]。本地模式使用,将容器端口转发到宿主机端口 */
51
+ ports?: [number, number][];
52
+ /**
53
+ * 创建非 root 用户并以该用户身份执行命令。
54
+ * - string: 用户名(等价于 { name: 'xxx' })
55
+ * - object: 完整配置
56
+ * - 未设置: 保持 root(向后兼容)
57
+ */
58
+ user?: string | SandboxUser;
50
59
  }
51
60
  export interface ListFilter {
52
61
  state?: SandboxState | SandboxState[];
53
62
  limit?: number;
54
63
  }
64
+ export interface SandboxUser {
65
+ /** 用户名。默认: 'sandbank' */
66
+ name?: string;
67
+ /** 指定 UID。默认: 自动分配 */
68
+ uid?: number;
69
+ /** 是否授予 sudo 权限。默认: true */
70
+ sudo?: boolean;
71
+ }
72
+ export interface SandboxUserInfo {
73
+ /** 用户名 */
74
+ name: string;
75
+ /** Home 目录路径 */
76
+ home: string;
77
+ }
55
78
  export interface Sandbox {
56
79
  /** 沙箱唯一 ID */
57
80
  readonly id: string;
@@ -59,6 +82,8 @@ export interface Sandbox {
59
82
  readonly state: SandboxState;
60
83
  /** 创建时间 */
61
84
  readonly createdAt: string;
85
+ /** 非 root 用户信息(如已配置) */
86
+ readonly user?: SandboxUserInfo;
62
87
  /** 执行命令,等待完成 */
63
88
  exec(command: string, options?: ExecOptions): Promise<ExecResult>;
64
89
  /** 写入单个文件 */
@@ -76,6 +101,8 @@ export interface ExecOptions {
76
101
  timeout?: number;
77
102
  /** 工作目录 */
78
103
  cwd?: string;
104
+ /** 以 root 身份执行(仅在配置了 user 时有意义)。默认: false */
105
+ asRoot?: boolean;
79
106
  }
80
107
  export interface ExecResult {
81
108
  stdout: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sandbank.dev/core",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Unified sandbox SDK for AI agents — provider abstraction, capability system, and error types",
5
5
  "license": "MIT",
6
6
  "type": "module",