@opencoredev/sandbox-sdk 0.1.1 → 1.0.0-beta.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/CHANGELOG.md +34 -7
- package/README.md +350 -23
- package/dist/ai.d.ts +5 -0
- package/dist/ai.js +1 -0
- package/dist/chunk-59t3rqja.js +2 -0
- package/dist/chunk-cwx6cc31.js +2 -0
- package/dist/chunk-exv1kf89.js +60 -0
- package/dist/chunk-gc8zdxyb.js +2 -0
- package/dist/chunk-hjzhc3qg.js +40 -0
- package/dist/chunk-md6fmprc.js +1 -0
- package/dist/chunk-t5vr9nd8.js +8 -0
- package/dist/chunk-v6y7eqxw.js +27 -0
- package/dist/chunk-yed8mvs7.js +2 -0
- package/dist/chunk-yrsb6hws.js +5 -0
- package/dist/chunk-z9rjzn28.js +2 -0
- package/dist/errors.d.ts +60 -0
- package/dist/files.d.ts +57 -0
- package/dist/git.d.ts +28 -0
- package/dist/handle.d.ts +4 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +1 -0
- package/dist/keys.d.ts +5 -0
- package/dist/logs.d.ts +8 -0
- package/dist/mastra.d.ts +43 -0
- package/dist/mastra.js +1 -0
- package/dist/memory.d.ts +34 -0
- package/dist/memory.js +11 -0
- package/dist/openai.d.ts +39 -0
- package/dist/openai.js +1 -0
- package/dist/peer.d.ts +5 -0
- package/dist/processes.d.ts +71 -0
- package/dist/provider.d.ts +138 -0
- package/dist/provider.js +0 -0
- package/dist/providers/agentos/errors.d.ts +4 -0
- package/dist/providers/agentos/index.d.ts +11 -0
- package/dist/providers/agentos/index.js +2 -0
- package/dist/providers/boat/index.d.ts +23 -0
- package/dist/providers/boat/index.js +1 -0
- package/dist/providers/boat-api/errors.d.ts +6 -0
- package/dist/providers/boat-api/exec.d.ts +11 -0
- package/dist/providers/boat-api/index.d.ts +22 -0
- package/dist/providers/boxd/errors.d.ts +3 -0
- package/dist/providers/boxd/execute.d.ts +3 -0
- package/dist/providers/boxd/guest.d.ts +14 -0
- package/dist/providers/boxd/index.d.ts +23 -0
- package/dist/providers/boxd/index.js +85 -0
- package/dist/providers/boxd/transfers.d.ts +19 -0
- package/dist/providers/daytona/buffered.d.ts +3 -0
- package/dist/providers/daytona/errors.d.ts +3 -0
- package/dist/providers/daytona/exec.d.ts +14 -0
- package/dist/providers/daytona/index.d.ts +24 -0
- package/dist/providers/daytona/index.js +88 -0
- package/dist/providers/e2b/errors.d.ts +3 -0
- package/dist/providers/e2b/index.d.ts +15 -0
- package/dist/providers/e2b/index.js +1 -0
- package/dist/providers/freestyle/deadline.d.ts +4 -0
- package/dist/providers/freestyle/errors.d.ts +16 -0
- package/dist/providers/freestyle/execute.d.ts +12 -0
- package/dist/providers/freestyle/index.d.ts +14 -0
- package/dist/providers/freestyle/index.js +133 -0
- package/dist/providers/freestyle/wire.d.ts +10 -0
- package/dist/providers/local/docker.d.ts +32 -0
- package/dist/providers/local/index.d.ts +17 -0
- package/dist/providers/local/index.js +2 -0
- package/dist/providers/railway/errors.d.ts +4 -0
- package/dist/providers/railway/index.d.ts +24 -0
- package/dist/providers/railway/index.js +1 -0
- package/dist/providers/sandboxer/index.d.ts +33 -0
- package/dist/providers/sandboxer/index.js +1 -0
- package/dist/providers/superserve/bootstrap.d.ts +11 -0
- package/dist/providers/superserve/errors.d.ts +3 -0
- package/dist/providers/superserve/execute.d.ts +13 -0
- package/dist/providers/superserve/index.d.ts +23 -0
- package/dist/providers/superserve/index.js +126 -0
- package/dist/providers/tenki/deadline.d.ts +2 -0
- package/dist/providers/tenki/errors.d.ts +10 -0
- package/dist/providers/tenki/exec.d.ts +4 -0
- package/dist/providers/tenki/files.d.ts +3 -0
- package/dist/providers/tenki/index.d.ts +28 -0
- package/dist/providers/tenki/index.js +172 -0
- package/dist/providers/tenki/ready.d.ts +7 -0
- package/dist/providers/tenki/stream.d.ts +3 -0
- package/dist/providers/upstash/buffered.d.ts +3 -0
- package/dist/providers/upstash/errors.d.ts +3 -0
- package/dist/providers/upstash/exec.d.ts +18 -0
- package/dist/providers/upstash/files.d.ts +15 -0
- package/dist/providers/upstash/index.d.ts +38 -0
- package/dist/providers/upstash/index.js +111 -0
- package/dist/providers/vercel/errors.d.ts +3 -0
- package/dist/providers/vercel/index.d.ts +14 -0
- package/dist/providers/vercel/index.js +1 -0
- package/dist/providers/vercel/provider.d.ts +10 -0
- package/dist/providers/vercel/transport.d.ts +40 -0
- package/dist/run.d.ts +41 -0
- package/dist/testing.d.ts +17 -0
- package/dist/testing.js +6 -0
- package/dist/tool-security.d.ts +9 -0
- package/dist/tools.d.ts +117 -0
- package/dist/tools.js +1 -0
- package/dist/types.d.ts +189 -0
- package/package.json +170 -92
- package/dist/agentos-DFJ4TFaY.mjs +0 -389
- package/dist/agentos-DFJ4TFaY.mjs.map +0 -1
- package/dist/ai/harness.d.mts +0 -16
- package/dist/ai/harness.mjs +0 -69
- package/dist/ai/harness.mjs.map +0 -1
- package/dist/ai/index.d.mts +0 -54
- package/dist/ai/index.mjs +0 -4
- package/dist/ai-DhfwIZdL.mjs +0 -243
- package/dist/ai-DhfwIZdL.mjs.map +0 -1
- package/dist/capabilities-CEowrzRM.mjs +0 -99
- package/dist/capabilities-CEowrzRM.mjs.map +0 -1
- package/dist/capabilities-COKpwoFH.mjs +0 -28
- package/dist/capabilities-COKpwoFH.mjs.map +0 -1
- package/dist/capabilities-DftdOpIu.d.mts +0 -13
- package/dist/errors-Ch9PHKTd.mjs +0 -61
- package/dist/errors-Ch9PHKTd.mjs.map +0 -1
- package/dist/eve/index.d.mts +0 -19
- package/dist/eve/index.mjs +0 -155
- package/dist/eve/index.mjs.map +0 -1
- package/dist/index-Bk6GmoEt.d.mts +0 -25
- package/dist/index-BufLdrbp.d.mts +0 -31
- package/dist/index.d.mts +0 -5
- package/dist/index.mjs +0 -38
- package/dist/index.mjs.map +0 -1
- package/dist/mastra/index.d.mts +0 -118
- package/dist/mastra/index.mjs +0 -662
- package/dist/mastra/index.mjs.map +0 -1
- package/dist/metadata.d.mts +0 -34
- package/dist/metadata.mjs +0 -103
- package/dist/metadata.mjs.map +0 -1
- package/dist/provider-BzzkIVmv.d.mts +0 -91
- package/dist/provider-utils-BjOSWNsh.mjs +0 -201
- package/dist/provider-utils-BjOSWNsh.mjs.map +0 -1
- package/dist/providers/agentos/index.d.mts +0 -7
- package/dist/providers/agentos/index.mjs +0 -8
- package/dist/providers/daytona/index.d.mts +0 -21
- package/dist/providers/daytona/index.mjs +0 -205
- package/dist/providers/daytona/index.mjs.map +0 -1
- package/dist/providers/e2b/index.d.mts +0 -17
- package/dist/providers/e2b/index.mjs +0 -168
- package/dist/providers/e2b/index.mjs.map +0 -1
- package/dist/providers/local/index.d.mts +0 -22
- package/dist/providers/local/index.mjs +0 -21
- package/dist/providers/local/index.mjs.map +0 -1
- package/dist/providers/upstash/index.d.mts +0 -17
- package/dist/providers/upstash/index.mjs +0 -210
- package/dist/providers/upstash/index.mjs.map +0 -1
- package/dist/providers/vercel/index.d.mts +0 -28
- package/dist/providers/vercel/index.mjs +0 -185
- package/dist/providers/vercel/index.mjs.map +0 -1
- package/dist/sandbox-Dco6z9aB.d.mts +0 -26
- package/dist/sandbox-rIOcbhtM.mjs +0 -112
- package/dist/sandbox-rIOcbhtM.mjs.map +0 -1
- package/dist/testing/index.d.mts +0 -27
- package/dist/testing/index.mjs +0 -173
- package/dist/testing/index.mjs.map +0 -1
- package/dist/types-DEi_dfRR.d.mts +0 -103
package/dist/mastra/index.mjs
DELETED
|
@@ -1,662 +0,0 @@
|
|
|
1
|
-
import { n as isSandboxError, t as SandboxError } from "../errors-Ch9PHKTd.mjs";
|
|
2
|
-
import { DirectoryNotEmptyError, DirectoryNotFoundError, FileExistsError, FileNotFoundError, IsDirectoryError, MastraFilesystem, MastraSandbox, NotDirectoryError, PermissionError, ProcessHandle, SandboxNotReadyError, SandboxProcessManager, StaleFileError, Workspace, WorkspaceReadOnlyError } from "@mastra/core/workspace";
|
|
3
|
-
|
|
4
|
-
//#region src/mastra/index.ts
|
|
5
|
-
/** Create a Mastra sandbox backed by any managed Sandbox SDK provider. */
|
|
6
|
-
function createMastraSandbox(options) {
|
|
7
|
-
return new SandboxSDKMastraSandbox(options);
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Create a Mastra workspace whose filesystem and commands share one Sandbox SDK
|
|
11
|
-
* session. The workspace owns and destroys the session.
|
|
12
|
-
*/
|
|
13
|
-
function createMastraWorkspace(options) {
|
|
14
|
-
const sandbox = createMastraSandbox(options);
|
|
15
|
-
const filesystem = new SandboxSDKMastraFilesystem({
|
|
16
|
-
...options.filesystem,
|
|
17
|
-
sandbox
|
|
18
|
-
});
|
|
19
|
-
return new Workspace({
|
|
20
|
-
...options.workspace,
|
|
21
|
-
filesystem,
|
|
22
|
-
sandbox
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
/** Mastra WorkspaceSandbox implementation for Sandbox SDK providers. */
|
|
26
|
-
var SandboxSDKMastraSandbox = class extends MastraSandbox {
|
|
27
|
-
id;
|
|
28
|
-
name;
|
|
29
|
-
provider;
|
|
30
|
-
cwd;
|
|
31
|
-
processes;
|
|
32
|
-
status = "pending";
|
|
33
|
-
managed;
|
|
34
|
-
identity;
|
|
35
|
-
env;
|
|
36
|
-
ports;
|
|
37
|
-
instructions;
|
|
38
|
-
onFirstCreate;
|
|
39
|
-
createdAt = /* @__PURE__ */ new Date();
|
|
40
|
-
session;
|
|
41
|
-
constructor(options) {
|
|
42
|
-
const processes = new SandboxSDKProcessManager({ env: options.env });
|
|
43
|
-
super({
|
|
44
|
-
...options,
|
|
45
|
-
name: "Sandbox SDK",
|
|
46
|
-
processes
|
|
47
|
-
});
|
|
48
|
-
this.managed = requireManaged(options.provider);
|
|
49
|
-
this.id = options.id ?? `mastra-${options.provider.id}-${crypto.randomUUID()}`;
|
|
50
|
-
this.name = `Sandbox SDK (${options.provider.id})`;
|
|
51
|
-
this.provider = options.provider.id;
|
|
52
|
-
this.cwd = normalizeCwd(options.cwd ?? "/workspace");
|
|
53
|
-
this.env = options.env ?? {};
|
|
54
|
-
this.ports = options.ports ?? [];
|
|
55
|
-
this.identity = options.identity;
|
|
56
|
-
this.instructions = options.instructions;
|
|
57
|
-
this.onFirstCreate = options.onFirstCreate;
|
|
58
|
-
this.processes = processes;
|
|
59
|
-
}
|
|
60
|
-
/** The live normalized Sandbox SDK session. */
|
|
61
|
-
get sandboxSdk() {
|
|
62
|
-
if (!this.session) throw new SandboxNotReadyError(this.id);
|
|
63
|
-
return this.session.sandbox;
|
|
64
|
-
}
|
|
65
|
-
async start() {
|
|
66
|
-
if (this.session) {
|
|
67
|
-
await this.session.resume();
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
this.session = await this.managed.create({
|
|
71
|
-
sessionId: this.id,
|
|
72
|
-
identity: this.identity,
|
|
73
|
-
cwd: this.cwd,
|
|
74
|
-
env: this.env,
|
|
75
|
-
ports: this.ports,
|
|
76
|
-
onFirstCreate: this.onFirstCreate
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
async stop() {
|
|
80
|
-
if (!this.session) return;
|
|
81
|
-
await this.killTrackedProcesses();
|
|
82
|
-
await this.session.stop();
|
|
83
|
-
}
|
|
84
|
-
async destroy() {
|
|
85
|
-
if (!this.session) return;
|
|
86
|
-
await this.killTrackedProcesses();
|
|
87
|
-
const session = this.session;
|
|
88
|
-
this.session = void 0;
|
|
89
|
-
await session.destroy();
|
|
90
|
-
}
|
|
91
|
-
async getPortUrl(port, protocol) {
|
|
92
|
-
await this.ensureRunning();
|
|
93
|
-
return this.session.getPortUrl({
|
|
94
|
-
port,
|
|
95
|
-
protocol
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
getInfo() {
|
|
99
|
-
return {
|
|
100
|
-
id: this.id,
|
|
101
|
-
name: this.name,
|
|
102
|
-
provider: this.provider,
|
|
103
|
-
status: this.status,
|
|
104
|
-
createdAt: this.createdAt,
|
|
105
|
-
metadata: {
|
|
106
|
-
sandboxId: this.session?.sandbox.id,
|
|
107
|
-
sandboxProvider: this.provider,
|
|
108
|
-
cwd: this.cwd,
|
|
109
|
-
capabilities: this.session?.sandbox.capabilities
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
getInstructions(options) {
|
|
114
|
-
const defaultInstructions = `Commands run in an isolated ${this.provider} sandbox. The default working directory is ${this.cwd}.`;
|
|
115
|
-
if (this.instructions === void 0) return defaultInstructions;
|
|
116
|
-
if (typeof this.instructions === "string") return this.instructions;
|
|
117
|
-
return this.instructions({
|
|
118
|
-
defaultInstructions,
|
|
119
|
-
requestContext: options?.requestContext
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
/** @deprecated Use `status === "running"` instead. */
|
|
123
|
-
isReady() {
|
|
124
|
-
return this.status === "running" && this.session !== void 0;
|
|
125
|
-
}
|
|
126
|
-
async killTrackedProcesses() {
|
|
127
|
-
const processes = await this.processes.list().catch(() => []);
|
|
128
|
-
await Promise.all(processes.filter((process) => process.running).map((process) => this.processes.kill(process.pid).catch(() => false)));
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
/** Mastra background-process bridge for normalized Sandbox SDK processes. */
|
|
132
|
-
var SandboxSDKProcessManager = class extends SandboxProcessManager {
|
|
133
|
-
async spawn(command, options = {}) {
|
|
134
|
-
const env = Object.fromEntries(Object.entries({
|
|
135
|
-
...this.env,
|
|
136
|
-
...options.env
|
|
137
|
-
}).filter((entry) => entry[1] !== void 0));
|
|
138
|
-
const handle = new SandboxSDKProcessHandle(await this.sandbox.sandboxSdk.processes.start(parseSimpleCommand(command) ?? command, {
|
|
139
|
-
cwd: options.cwd,
|
|
140
|
-
env,
|
|
141
|
-
timeout: options.timeout,
|
|
142
|
-
signal: options.abortSignal
|
|
143
|
-
}), options);
|
|
144
|
-
this._tracked.set(handle.pid, handle);
|
|
145
|
-
return handle;
|
|
146
|
-
}
|
|
147
|
-
async list() {
|
|
148
|
-
return Promise.all([...this._tracked.values()].map(async (handle) => {
|
|
149
|
-
const adapter = handle;
|
|
150
|
-
return {
|
|
151
|
-
pid: handle.pid,
|
|
152
|
-
command: handle.command,
|
|
153
|
-
running: await adapter.isRunning(),
|
|
154
|
-
...handle.exitCode === void 0 ? {} : { exitCode: handle.exitCode }
|
|
155
|
-
};
|
|
156
|
-
}));
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
var SandboxSDKProcessHandle = class extends ProcessHandle {
|
|
160
|
-
pid;
|
|
161
|
-
process;
|
|
162
|
-
startedAt = performance.now();
|
|
163
|
-
completed;
|
|
164
|
-
currentExitCode;
|
|
165
|
-
killed = false;
|
|
166
|
-
timedOut = false;
|
|
167
|
-
timeoutId;
|
|
168
|
-
constructor(process, options) {
|
|
169
|
-
super(options);
|
|
170
|
-
this.process = process;
|
|
171
|
-
this.pid = process.id;
|
|
172
|
-
if (options.timeout !== void 0 && options.timeout > 0) this.timeoutId = setTimeout(() => {
|
|
173
|
-
this.timedOut = true;
|
|
174
|
-
this.kill();
|
|
175
|
-
}, options.timeout);
|
|
176
|
-
this.completed = this.collect();
|
|
177
|
-
}
|
|
178
|
-
get exitCode() {
|
|
179
|
-
return this.currentExitCode;
|
|
180
|
-
}
|
|
181
|
-
async wait() {
|
|
182
|
-
return this.completed;
|
|
183
|
-
}
|
|
184
|
-
async kill() {
|
|
185
|
-
if (this.currentExitCode !== void 0) return false;
|
|
186
|
-
this.killed = true;
|
|
187
|
-
await this.process.kill();
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
async sendStdin(data) {
|
|
191
|
-
if (this.currentExitCode !== void 0) throw new Error(`Process ${this.pid} has already exited with code ${this.currentExitCode}`);
|
|
192
|
-
await this.process.write(data);
|
|
193
|
-
}
|
|
194
|
-
async isRunning() {
|
|
195
|
-
if (this.currentExitCode !== void 0) return false;
|
|
196
|
-
const status = await this.process.status();
|
|
197
|
-
return status === "starting" || status === "running";
|
|
198
|
-
}
|
|
199
|
-
async collect() {
|
|
200
|
-
const output = this.pumpOutput();
|
|
201
|
-
try {
|
|
202
|
-
const result = await this.process.wait();
|
|
203
|
-
this.currentExitCode = this.timedOut ? 124 : result.exitCode;
|
|
204
|
-
await output;
|
|
205
|
-
} catch (error) {
|
|
206
|
-
await output.catch(() => void 0);
|
|
207
|
-
if (isSandboxError(error) && error.code === "timeout") this.timedOut = true;
|
|
208
|
-
this.currentExitCode = this.timedOut ? 124 : 1;
|
|
209
|
-
this.emitStderr(error instanceof Error ? error.message : String(error));
|
|
210
|
-
} finally {
|
|
211
|
-
if (this.timeoutId) clearTimeout(this.timeoutId);
|
|
212
|
-
}
|
|
213
|
-
return {
|
|
214
|
-
success: this.currentExitCode === 0,
|
|
215
|
-
exitCode: this.currentExitCode,
|
|
216
|
-
stdout: this.stdout,
|
|
217
|
-
stderr: this.stderr,
|
|
218
|
-
executionTimeMs: Math.round(performance.now() - this.startedAt),
|
|
219
|
-
...this.killed ? { killed: true } : {},
|
|
220
|
-
...this.timedOut ? { timedOut: true } : {}
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
async pumpOutput() {
|
|
224
|
-
const decoders = {
|
|
225
|
-
stdout: new TextDecoder(),
|
|
226
|
-
stderr: new TextDecoder()
|
|
227
|
-
};
|
|
228
|
-
try {
|
|
229
|
-
for await (const event of this.process.output()) {
|
|
230
|
-
const data = typeof event.data === "string" ? event.data : decoders[event.stream].decode(event.data, { stream: true });
|
|
231
|
-
if (data) if (event.stream === "stdout") this.emitStdout(data);
|
|
232
|
-
else this.emitStderr(data);
|
|
233
|
-
}
|
|
234
|
-
} finally {
|
|
235
|
-
const stdout = decoders.stdout.decode();
|
|
236
|
-
const stderr = decoders.stderr.decode();
|
|
237
|
-
if (stdout) this.emitStdout(stdout);
|
|
238
|
-
if (stderr) this.emitStderr(stderr);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
/** Mastra WorkspaceFilesystem implementation sharing a Mastra sandbox session. */
|
|
243
|
-
var SandboxSDKMastraFilesystem = class extends MastraFilesystem {
|
|
244
|
-
id;
|
|
245
|
-
name = "Sandbox SDK Filesystem";
|
|
246
|
-
provider = "sandbox-sdk";
|
|
247
|
-
readOnly;
|
|
248
|
-
basePath;
|
|
249
|
-
status = "pending";
|
|
250
|
-
sandbox;
|
|
251
|
-
instructions;
|
|
252
|
-
constructor(options) {
|
|
253
|
-
super({
|
|
254
|
-
...options,
|
|
255
|
-
name: "Sandbox SDK Filesystem"
|
|
256
|
-
});
|
|
257
|
-
this.sandbox = options.sandbox;
|
|
258
|
-
this.id = `${options.sandbox.id}-filesystem`;
|
|
259
|
-
this.basePath = options.sandbox.cwd;
|
|
260
|
-
this.readOnly = options.readOnly ?? false;
|
|
261
|
-
this.instructions = options.instructions;
|
|
262
|
-
}
|
|
263
|
-
async init() {}
|
|
264
|
-
async destroy() {}
|
|
265
|
-
getInfo() {
|
|
266
|
-
return {
|
|
267
|
-
id: this.id,
|
|
268
|
-
name: this.name,
|
|
269
|
-
provider: this.provider,
|
|
270
|
-
status: this.status,
|
|
271
|
-
readOnly: this.readOnly,
|
|
272
|
-
metadata: {
|
|
273
|
-
sandboxId: this.sandbox.id,
|
|
274
|
-
sandboxProvider: this.sandbox.provider,
|
|
275
|
-
basePath: this.basePath
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
getInstructions(options) {
|
|
280
|
-
const defaultInstructions = `Files are stored in the same ${this.sandbox.provider} sandbox used for commands. Filesystem path / maps to ${this.basePath} inside the sandbox.`;
|
|
281
|
-
if (this.instructions === void 0) return defaultInstructions;
|
|
282
|
-
if (typeof this.instructions === "string") return this.instructions;
|
|
283
|
-
return this.instructions({
|
|
284
|
-
defaultInstructions,
|
|
285
|
-
requestContext: options?.requestContext
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
async realpath(path) {
|
|
289
|
-
await this.ready();
|
|
290
|
-
const virtual = toVirtualPath(this.basePath, path);
|
|
291
|
-
const result = await this.sandbox.sandboxSdk.run({
|
|
292
|
-
command: "realpath",
|
|
293
|
-
args: ["-m", toSandboxPath(this.basePath, virtual)]
|
|
294
|
-
});
|
|
295
|
-
if (!result.success) return virtual;
|
|
296
|
-
const resolved = result.stdout.trim();
|
|
297
|
-
if (!isWithin(this.basePath, resolved)) throw new PermissionError(path, "realpath");
|
|
298
|
-
return fromSandboxPath(this.basePath, resolved);
|
|
299
|
-
}
|
|
300
|
-
async readFile(path, options) {
|
|
301
|
-
await this.ready();
|
|
302
|
-
if ((await this.stat(path)).type === "directory") throw new IsDirectoryError(path);
|
|
303
|
-
try {
|
|
304
|
-
const content = Buffer.from(await this.sandbox.sandboxSdk.files.read(toSandboxPath(this.basePath, path)));
|
|
305
|
-
return options?.encoding ? content.toString(options.encoding) : content;
|
|
306
|
-
} catch (error) {
|
|
307
|
-
throw mapFileError(path, "read", error);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
async writeFile(path, content, options) {
|
|
311
|
-
await this.ready();
|
|
312
|
-
this.assertWritable("writeFile");
|
|
313
|
-
const target = toSandboxPath(this.basePath, path);
|
|
314
|
-
const exists = await this.exists(path);
|
|
315
|
-
if (exists && options?.overwrite === false) throw new FileExistsError(path);
|
|
316
|
-
if (exists) {
|
|
317
|
-
const current = await this.stat(path);
|
|
318
|
-
if (current.type === "directory") throw new IsDirectoryError(path);
|
|
319
|
-
if (options?.expectedMtime && current.modifiedAt.getTime() !== options.expectedMtime.getTime()) throw new StaleFileError(path, options.expectedMtime, current.modifiedAt);
|
|
320
|
-
}
|
|
321
|
-
await this.ensureParent(path, options?.recursive !== false);
|
|
322
|
-
try {
|
|
323
|
-
await this.sandbox.sandboxSdk.files.write(target, toBytes(content));
|
|
324
|
-
} catch (error) {
|
|
325
|
-
throw mapFileError(path, "write", error);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
async appendFile(path, content) {
|
|
329
|
-
await this.ready();
|
|
330
|
-
this.assertWritable("appendFile");
|
|
331
|
-
const current = await this.exists(path) ? Buffer.from(await this.readFile(path)) : Buffer.alloc(0);
|
|
332
|
-
const added = Buffer.from(toBytes(content));
|
|
333
|
-
const combined = new Uint8Array(current.byteLength + added.byteLength);
|
|
334
|
-
combined.set(current);
|
|
335
|
-
combined.set(added, current.byteLength);
|
|
336
|
-
await this.writeFile(path, combined);
|
|
337
|
-
}
|
|
338
|
-
async deleteFile(path, options) {
|
|
339
|
-
await this.ready();
|
|
340
|
-
this.assertWritable("deleteFile");
|
|
341
|
-
if (!await this.exists(path)) {
|
|
342
|
-
if (options?.force) return;
|
|
343
|
-
throw new FileNotFoundError(path);
|
|
344
|
-
}
|
|
345
|
-
if ((await this.stat(path)).type === "directory") throw new IsDirectoryError(path);
|
|
346
|
-
try {
|
|
347
|
-
await this.sandbox.sandboxSdk.files.remove(toSandboxPath(this.basePath, path));
|
|
348
|
-
} catch (error) {
|
|
349
|
-
throw mapFileError(path, "delete", error);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
async copyFile(src, dest, options) {
|
|
353
|
-
await this.ready();
|
|
354
|
-
this.assertWritable("copyFile");
|
|
355
|
-
if (!await this.exists(src)) throw new FileNotFoundError(src);
|
|
356
|
-
if (await this.exists(dest) && options?.overwrite === false) throw new FileExistsError(dest);
|
|
357
|
-
if ((await this.stat(src)).type === "directory") {
|
|
358
|
-
if (!options?.recursive) throw new IsDirectoryError(src);
|
|
359
|
-
await this.mkdir(dest, { recursive: true });
|
|
360
|
-
for (const entry of await this.readdir(src)) await this.copyFile(joinVirtual(src, entry.name), joinVirtual(dest, entry.name), options);
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
await this.writeFile(dest, await this.readFile(src), {
|
|
364
|
-
recursive: true,
|
|
365
|
-
overwrite: options?.overwrite
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
async moveFile(src, dest, options) {
|
|
369
|
-
this.assertWritable("moveFile");
|
|
370
|
-
const source = await this.stat(src);
|
|
371
|
-
await this.copyFile(src, dest, {
|
|
372
|
-
...options,
|
|
373
|
-
recursive: source.type === "directory" ? true : options?.recursive
|
|
374
|
-
});
|
|
375
|
-
if (source.type === "directory") await this.rmdir(src, { recursive: true });
|
|
376
|
-
else await this.deleteFile(src);
|
|
377
|
-
}
|
|
378
|
-
async mkdir(path, options) {
|
|
379
|
-
await this.ready();
|
|
380
|
-
this.assertWritable("mkdir");
|
|
381
|
-
if (await this.exists(path)) {
|
|
382
|
-
if ((await this.stat(path)).type !== "directory") throw new FileExistsError(path);
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
if (options?.recursive === false) await this.requireParent(path);
|
|
386
|
-
try {
|
|
387
|
-
await this.sandbox.sandboxSdk.files.mkdir(toSandboxPath(this.basePath, path));
|
|
388
|
-
} catch (error) {
|
|
389
|
-
throw mapFileError(path, "mkdir", error);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
async rmdir(path, options) {
|
|
393
|
-
await this.ready();
|
|
394
|
-
this.assertWritable("rmdir");
|
|
395
|
-
if (!await this.exists(path)) {
|
|
396
|
-
if (options?.force) return;
|
|
397
|
-
throw new DirectoryNotFoundError(path);
|
|
398
|
-
}
|
|
399
|
-
if ((await this.stat(path)).type !== "directory") throw new NotDirectoryError(path);
|
|
400
|
-
if (!options?.recursive && (await this.readdir(path)).length > 0) throw new DirectoryNotEmptyError(path);
|
|
401
|
-
try {
|
|
402
|
-
await this.sandbox.sandboxSdk.files.remove(toSandboxPath(this.basePath, path));
|
|
403
|
-
} catch (error) {
|
|
404
|
-
throw mapFileError(path, "rmdir", error);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
async readdir(path, options) {
|
|
408
|
-
await this.ready();
|
|
409
|
-
if (!await this.exists(path)) throw new DirectoryNotFoundError(path);
|
|
410
|
-
if ((await this.stat(path)).type !== "directory") throw new NotDirectoryError(path);
|
|
411
|
-
const extensions = options?.extension ? new Set((Array.isArray(options.extension) ? options.extension : [options.extension]).map((extension$1) => extension$1.startsWith(".") ? extension$1 : `.${extension$1}`)) : void 0;
|
|
412
|
-
return this.listDirectory(path, options?.recursive ? options.maxDepth ?? 100 : 0, extensions);
|
|
413
|
-
}
|
|
414
|
-
async exists(path) {
|
|
415
|
-
await this.ready();
|
|
416
|
-
return this.sandbox.sandboxSdk.files.exists(toSandboxPath(this.basePath, path));
|
|
417
|
-
}
|
|
418
|
-
async stat(path) {
|
|
419
|
-
await this.ready();
|
|
420
|
-
const virtual = toVirtualPath(this.basePath, path);
|
|
421
|
-
const target = toSandboxPath(this.basePath, virtual);
|
|
422
|
-
if (virtual === "/") return directoryStat("", "/");
|
|
423
|
-
if (!await this.sandbox.sandboxSdk.files.exists(target)) throw new FileNotFoundError(path);
|
|
424
|
-
const native = await this.nativeStat(target);
|
|
425
|
-
if (native) return {
|
|
426
|
-
name: basename(virtual),
|
|
427
|
-
path: virtual,
|
|
428
|
-
type: native.type,
|
|
429
|
-
size: native.size,
|
|
430
|
-
createdAt: native.createdAt,
|
|
431
|
-
modifiedAt: native.modifiedAt
|
|
432
|
-
};
|
|
433
|
-
const entry = await this.findEntry(target);
|
|
434
|
-
if (!entry) throw new FileNotFoundError(path);
|
|
435
|
-
const timestamp = /* @__PURE__ */ new Date(0);
|
|
436
|
-
return {
|
|
437
|
-
name: entry.name,
|
|
438
|
-
path: virtual,
|
|
439
|
-
type: entry.type === "directory" ? "directory" : "file",
|
|
440
|
-
size: entry.size ?? 0,
|
|
441
|
-
createdAt: timestamp,
|
|
442
|
-
modifiedAt: timestamp
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
async ready() {
|
|
446
|
-
await this.ensureReady();
|
|
447
|
-
await this.sandbox.ensureRunning();
|
|
448
|
-
}
|
|
449
|
-
assertWritable(operation) {
|
|
450
|
-
if (this.readOnly) throw new WorkspaceReadOnlyError(operation);
|
|
451
|
-
}
|
|
452
|
-
async ensureParent(path, recursive) {
|
|
453
|
-
const parent = dirname(toVirtualPath(this.basePath, path));
|
|
454
|
-
if (parent === "/") return;
|
|
455
|
-
if (recursive) await this.mkdir(parent, { recursive: true });
|
|
456
|
-
else await this.requireParent(path);
|
|
457
|
-
}
|
|
458
|
-
async requireParent(path) {
|
|
459
|
-
const parent = dirname(toVirtualPath(this.basePath, path));
|
|
460
|
-
if (!await this.exists(parent)) throw new DirectoryNotFoundError(parent);
|
|
461
|
-
if ((await this.stat(parent)).type !== "directory") throw new NotDirectoryError(parent);
|
|
462
|
-
}
|
|
463
|
-
async listDirectory(path, depth, extensions) {
|
|
464
|
-
const entries = await this.sandbox.sandboxSdk.files.list(toSandboxPath(this.basePath, path));
|
|
465
|
-
const result = [];
|
|
466
|
-
for (const entry of entries) {
|
|
467
|
-
const type = entry.type === "directory" ? "directory" : "file";
|
|
468
|
-
if (type === "file" && extensions && !extensions.has(extension(entry.name))) continue;
|
|
469
|
-
result.push({
|
|
470
|
-
name: entry.name,
|
|
471
|
-
type,
|
|
472
|
-
...entry.size === void 0 ? {} : { size: entry.size },
|
|
473
|
-
...entry.type === "symlink" ? { isSymlink: true } : {}
|
|
474
|
-
});
|
|
475
|
-
if (depth > 0 && type === "directory") {
|
|
476
|
-
const childPath = joinVirtual(path, entry.name);
|
|
477
|
-
const children = await this.listDirectory(childPath, depth - 1, extensions);
|
|
478
|
-
result.push(...children.map((child) => ({
|
|
479
|
-
...child,
|
|
480
|
-
name: `${entry.name}/${child.name}`
|
|
481
|
-
})));
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
return result;
|
|
485
|
-
}
|
|
486
|
-
async findEntry(target) {
|
|
487
|
-
const parent = dirname(target);
|
|
488
|
-
return (await this.sandbox.sandboxSdk.files.list(parent)).find((entry) => entry.path === target);
|
|
489
|
-
}
|
|
490
|
-
async nativeStat(target) {
|
|
491
|
-
try {
|
|
492
|
-
const result = await this.sandbox.sandboxSdk.run({
|
|
493
|
-
command: "stat",
|
|
494
|
-
args: [
|
|
495
|
-
"-c",
|
|
496
|
-
"%F|%s|%W|%Y",
|
|
497
|
-
target
|
|
498
|
-
]
|
|
499
|
-
});
|
|
500
|
-
if (!result.success) return void 0;
|
|
501
|
-
const [kind, sizeValue, createdValue, modifiedValue] = result.stdout.trim().split("|");
|
|
502
|
-
if (!kind || !sizeValue || !createdValue || !modifiedValue) return;
|
|
503
|
-
const modified = Number(modifiedValue) * 1e3;
|
|
504
|
-
const createdSeconds = Number(createdValue);
|
|
505
|
-
return {
|
|
506
|
-
type: kind.includes("directory") ? "directory" : "file",
|
|
507
|
-
size: Number(sizeValue),
|
|
508
|
-
createdAt: /* @__PURE__ */ new Date((createdSeconds > 0 ? createdSeconds : Number(modifiedValue)) * 1e3),
|
|
509
|
-
modifiedAt: new Date(modified)
|
|
510
|
-
};
|
|
511
|
-
} catch {
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
};
|
|
516
|
-
function requireManaged(provider) {
|
|
517
|
-
if (!provider.managed) throw new SandboxError({
|
|
518
|
-
code: "unsupported",
|
|
519
|
-
provider: provider.id,
|
|
520
|
-
operation: "mastra.createSandbox",
|
|
521
|
-
message: `Provider ${provider.id} does not implement managed sandbox sessions`
|
|
522
|
-
});
|
|
523
|
-
return provider.managed;
|
|
524
|
-
}
|
|
525
|
-
function normalizeCwd(value) {
|
|
526
|
-
if (!value.startsWith("/") || value.includes("\0")) throw new SandboxError({
|
|
527
|
-
code: "invalid_input",
|
|
528
|
-
provider: "mastra",
|
|
529
|
-
operation: "cwd",
|
|
530
|
-
message: "cwd must be an absolute path"
|
|
531
|
-
});
|
|
532
|
-
return value.replace(/\/$/, "") || "/";
|
|
533
|
-
}
|
|
534
|
-
function toVirtualPath(cwd, value) {
|
|
535
|
-
assertPath(value);
|
|
536
|
-
if (value === cwd) return "/";
|
|
537
|
-
if (value.startsWith(`${cwd}/`)) return `/${value.slice(cwd.length + 1)}`;
|
|
538
|
-
return (value.startsWith("/") ? value : `/${value}`).replace(/\/{2,}/g, "/").replace(/\/$/, "") || "/";
|
|
539
|
-
}
|
|
540
|
-
function toSandboxPath(cwd, value) {
|
|
541
|
-
const virtual = toVirtualPath(cwd, value);
|
|
542
|
-
return virtual === "/" ? cwd : `${cwd}${virtual}`;
|
|
543
|
-
}
|
|
544
|
-
function fromSandboxPath(cwd, value) {
|
|
545
|
-
if (value === cwd) return "/";
|
|
546
|
-
if (!value.startsWith(`${cwd}/`)) throw new PermissionError(value, "access");
|
|
547
|
-
return `/${value.slice(cwd.length + 1)}`;
|
|
548
|
-
}
|
|
549
|
-
function assertPath(value) {
|
|
550
|
-
if (!value || value.includes("\0") || value.split("/").includes("..")) throw new PermissionError(value, "access");
|
|
551
|
-
}
|
|
552
|
-
function isWithin(root, path) {
|
|
553
|
-
return path === root || path.startsWith(`${root}/`);
|
|
554
|
-
}
|
|
555
|
-
function toBytes(content) {
|
|
556
|
-
return typeof content === "string" ? new TextEncoder().encode(content) : new Uint8Array(content);
|
|
557
|
-
}
|
|
558
|
-
function basename(path) {
|
|
559
|
-
return path.split("/").filter(Boolean).at(-1) ?? "";
|
|
560
|
-
}
|
|
561
|
-
function dirname(path) {
|
|
562
|
-
const parts = path.split("/").filter(Boolean);
|
|
563
|
-
parts.pop();
|
|
564
|
-
return `/${parts.join("/")}`.replace(/\/$/, "") || "/";
|
|
565
|
-
}
|
|
566
|
-
function joinVirtual(parent, child) {
|
|
567
|
-
return `${parent.replace(/\/$/, "")}/${child}`.replace(/\/{2,}/g, "/");
|
|
568
|
-
}
|
|
569
|
-
function extension(path) {
|
|
570
|
-
const name = basename(path);
|
|
571
|
-
const index = name.lastIndexOf(".");
|
|
572
|
-
return index <= 0 ? "" : name.slice(index);
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Preserve argument boundaries for ordinary commands. Commands that use shell
|
|
576
|
-
* syntax deliberately fall back to the provider's shell-string execution path.
|
|
577
|
-
*/
|
|
578
|
-
function parseSimpleCommand(value) {
|
|
579
|
-
const parts = [];
|
|
580
|
-
let current = "";
|
|
581
|
-
let tokenStarted = false;
|
|
582
|
-
let quote;
|
|
583
|
-
const finish = () => {
|
|
584
|
-
if (!tokenStarted) return;
|
|
585
|
-
parts.push(current);
|
|
586
|
-
current = "";
|
|
587
|
-
tokenStarted = false;
|
|
588
|
-
};
|
|
589
|
-
for (let index = 0; index < value.length; index++) {
|
|
590
|
-
const character = value[index];
|
|
591
|
-
if (quote === "single") {
|
|
592
|
-
if (character === "'") quote = void 0;
|
|
593
|
-
else current += character;
|
|
594
|
-
tokenStarted = true;
|
|
595
|
-
continue;
|
|
596
|
-
}
|
|
597
|
-
if (quote === "double") {
|
|
598
|
-
if (character === "\"") quote = void 0;
|
|
599
|
-
else if (character === "\\") {
|
|
600
|
-
const next = value[++index];
|
|
601
|
-
if (next === void 0) return void 0;
|
|
602
|
-
current += next;
|
|
603
|
-
} else if (character === "$" || character === "`") return;
|
|
604
|
-
else current += character;
|
|
605
|
-
tokenStarted = true;
|
|
606
|
-
continue;
|
|
607
|
-
}
|
|
608
|
-
if (/\s/.test(character)) {
|
|
609
|
-
finish();
|
|
610
|
-
continue;
|
|
611
|
-
}
|
|
612
|
-
if (character === "'") {
|
|
613
|
-
quote = "single";
|
|
614
|
-
tokenStarted = true;
|
|
615
|
-
continue;
|
|
616
|
-
}
|
|
617
|
-
if (character === "\"") {
|
|
618
|
-
quote = "double";
|
|
619
|
-
tokenStarted = true;
|
|
620
|
-
continue;
|
|
621
|
-
}
|
|
622
|
-
if (character === "\\") {
|
|
623
|
-
const next = value[++index];
|
|
624
|
-
if (next === void 0) return void 0;
|
|
625
|
-
current += next;
|
|
626
|
-
tokenStarted = true;
|
|
627
|
-
continue;
|
|
628
|
-
}
|
|
629
|
-
if ("|&;<>()$`*?[]{}~#\n\r".includes(character)) return void 0;
|
|
630
|
-
current += character;
|
|
631
|
-
tokenStarted = true;
|
|
632
|
-
}
|
|
633
|
-
if (quote) return void 0;
|
|
634
|
-
finish();
|
|
635
|
-
const [command, ...args] = parts;
|
|
636
|
-
return command ? {
|
|
637
|
-
command,
|
|
638
|
-
args
|
|
639
|
-
} : void 0;
|
|
640
|
-
}
|
|
641
|
-
function directoryStat(name, path) {
|
|
642
|
-
const timestamp = /* @__PURE__ */ new Date(0);
|
|
643
|
-
return {
|
|
644
|
-
name,
|
|
645
|
-
path,
|
|
646
|
-
type: "directory",
|
|
647
|
-
size: 0,
|
|
648
|
-
createdAt: timestamp,
|
|
649
|
-
modifiedAt: timestamp
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
function mapFileError(path, operation, error) {
|
|
653
|
-
if (!isSandboxError(error)) return error instanceof Error ? error : new Error(String(error));
|
|
654
|
-
if (error.code === "not_found") return new FileNotFoundError(path);
|
|
655
|
-
if (error.code === "permission") return new PermissionError(path, operation);
|
|
656
|
-
if (error.code === "conflict") return new FileExistsError(path);
|
|
657
|
-
return error;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
//#endregion
|
|
661
|
-
export { SandboxSDKMastraFilesystem, SandboxSDKMastraSandbox, SandboxSDKProcessManager, createMastraSandbox, createMastraWorkspace };
|
|
662
|
-
//# sourceMappingURL=index.mjs.map
|