sbox-sdk 0.0.2
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/LICENSE +21 -0
- package/README.md +137 -0
- package/dist/adapter/index.d.ts +22 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +16 -0
- package/dist/agent-tools/index.d.ts +13 -0
- package/dist/agent-tools/index.d.ts.map +1 -0
- package/dist/agent-tools/index.js +9 -0
- package/dist/agent-tools/policy.d.ts +48 -0
- package/dist/agent-tools/policy.d.ts.map +1 -0
- package/dist/agent-tools/policy.js +51 -0
- package/dist/agent-tools/registry.d.ts +9 -0
- package/dist/agent-tools/registry.d.ts.map +1 -0
- package/dist/agent-tools/registry.js +412 -0
- package/dist/agent-tools/result.d.ts +32 -0
- package/dist/agent-tools/result.d.ts.map +1 -0
- package/dist/agent-tools/result.js +14 -0
- package/dist/agent-tools/types.d.ts +76 -0
- package/dist/agent-tools/types.d.ts.map +1 -0
- package/dist/agent-tools/types.js +1 -0
- package/dist/ai/index.d.ts +36 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +40 -0
- package/dist/ai-sdk/index.d.ts +31 -0
- package/dist/ai-sdk/index.d.ts.map +1 -0
- package/dist/ai-sdk/index.js +80 -0
- package/dist/anthropic/index.d.ts +42 -0
- package/dist/anthropic/index.d.ts.map +1 -0
- package/dist/anthropic/index.js +64 -0
- package/dist/aws-lambda/index.d.ts +87 -0
- package/dist/aws-lambda/index.d.ts.map +1 -0
- package/dist/aws-lambda/index.js +290 -0
- package/dist/beam/index.d.ts +92 -0
- package/dist/beam/index.d.ts.map +1 -0
- package/dist/beam/index.js +222 -0
- package/dist/blaxel/index.d.ts +125 -0
- package/dist/blaxel/index.d.ts.map +1 -0
- package/dist/blaxel/index.js +220 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +249 -0
- package/dist/cloudflare/index.d.ts +64 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +259 -0
- package/dist/codesandbox/index.d.ts +100 -0
- package/dist/codesandbox/index.d.ts.map +1 -0
- package/dist/codesandbox/index.js +227 -0
- package/dist/conformance/index.d.ts +20 -0
- package/dist/conformance/index.d.ts.map +1 -0
- package/dist/conformance/index.js +189 -0
- package/dist/daytona/index.d.ts +64 -0
- package/dist/daytona/index.d.ts.map +1 -0
- package/dist/daytona/index.js +258 -0
- package/dist/e2b/index.d.ts +63 -0
- package/dist/e2b/index.d.ts.map +1 -0
- package/dist/e2b/index.js +411 -0
- package/dist/fly/index.d.ts +75 -0
- package/dist/fly/index.d.ts.map +1 -0
- package/dist/fly/index.js +222 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/internal/capabilities.d.ts +57 -0
- package/dist/internal/capabilities.d.ts.map +1 -0
- package/dist/internal/capabilities.js +68 -0
- package/dist/internal/client.d.ts +9 -0
- package/dist/internal/client.d.ts.map +1 -0
- package/dist/internal/client.js +126 -0
- package/dist/internal/encoding.d.ts +8 -0
- package/dist/internal/encoding.d.ts.map +1 -0
- package/dist/internal/encoding.js +20 -0
- package/dist/internal/errors.d.ts +45 -0
- package/dist/internal/errors.d.ts.map +1 -0
- package/dist/internal/errors.js +79 -0
- package/dist/internal/exec.d.ts +19 -0
- package/dist/internal/exec.d.ts.map +1 -0
- package/dist/internal/exec.js +208 -0
- package/dist/internal/plugin.d.ts +38 -0
- package/dist/internal/plugin.d.ts.map +1 -0
- package/dist/internal/plugin.js +1 -0
- package/dist/internal/runtime.d.ts +8 -0
- package/dist/internal/runtime.d.ts.map +1 -0
- package/dist/internal/runtime.js +21 -0
- package/dist/internal/sandbox.d.ts +12 -0
- package/dist/internal/sandbox.d.ts.map +1 -0
- package/dist/internal/sandbox.js +438 -0
- package/dist/internal/shell.d.ts +36 -0
- package/dist/internal/shell.d.ts.map +1 -0
- package/dist/internal/shell.js +88 -0
- package/dist/internal/stream.d.ts +15 -0
- package/dist/internal/stream.d.ts.map +1 -0
- package/dist/internal/stream.js +58 -0
- package/dist/internal/types.d.ts +381 -0
- package/dist/internal/types.d.ts.map +1 -0
- package/dist/internal/types.js +1 -0
- package/dist/langchain/index.d.ts +25 -0
- package/dist/langchain/index.d.ts.map +1 -0
- package/dist/langchain/index.js +61 -0
- package/dist/mastra/index.d.ts +43 -0
- package/dist/mastra/index.d.ts.map +1 -0
- package/dist/mastra/index.js +69 -0
- package/dist/memory/index.d.ts +57 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +573 -0
- package/dist/modal/index.d.ts +67 -0
- package/dist/modal/index.d.ts.map +1 -0
- package/dist/modal/index.js +223 -0
- package/dist/morph/index.d.ts +91 -0
- package/dist/morph/index.d.ts.map +1 -0
- package/dist/morph/index.js +221 -0
- package/dist/northflank/index.d.ts +74 -0
- package/dist/northflank/index.d.ts.map +1 -0
- package/dist/northflank/index.js +265 -0
- package/dist/openai/index.d.ts +25 -0
- package/dist/openai/index.d.ts.map +1 -0
- package/dist/openai/index.js +71 -0
- package/dist/railway/index.d.ts +109 -0
- package/dist/railway/index.d.ts.map +1 -0
- package/dist/railway/index.js +219 -0
- package/dist/runloop/index.d.ts +69 -0
- package/dist/runloop/index.d.ts.map +1 -0
- package/dist/runloop/index.js +226 -0
- package/dist/testing/index.d.ts +44 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +61 -0
- package/dist/vercel/index.d.ts +63 -0
- package/dist/vercel/index.d.ts.map +1 -0
- package/dist/vercel/index.js +241 -0
- package/package.json +252 -0
- package/src/aws-lambda/runner/Dockerfile +15 -0
- package/src/aws-lambda/runner/README.md +59 -0
- package/src/aws-lambda/runner/server.mjs +91 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sbox-sdk/beam` — adapter for Beam Cloud sandboxes (`@beamcloud/beam-js`).
|
|
3
|
+
* A "sandbox" is a Beam sandboxed container (real Linux + coreutils), with
|
|
4
|
+
* first-class GPU. exec uses `instance.exec(cmd, { cwd, env })` and buffers the
|
|
5
|
+
* process streams (`streaming` emulated). The SDK's filesystem helpers are
|
|
6
|
+
* local-path based, so `readFile`/`writeFile` go through exec + base64 (binary
|
|
7
|
+
* safe, portable). Ports are public SSL endpoints (`exposePort`). `snapshot()`
|
|
8
|
+
* maps to `instance.snapshot()` and `fork()` snapshots then boots N sandboxes
|
|
9
|
+
* from it. `setTimeout()` maps to `updateTtl`. Requires the optional peer
|
|
10
|
+
* dependency `@beamcloud/beam-js`.
|
|
11
|
+
*/
|
|
12
|
+
import { AsyncQueue, base64ToBytes, bytesToBase64, defineProvider, SandboxError, shellQuote as sq, } from "../adapter/index.js";
|
|
13
|
+
export const BEAM_CAPS = {
|
|
14
|
+
background: "unsupported",
|
|
15
|
+
codeInterpreter: "unsupported",
|
|
16
|
+
egressControl: "unsupported",
|
|
17
|
+
exposePort: "native",
|
|
18
|
+
filesUpload: "native",
|
|
19
|
+
filesWatch: "unsupported",
|
|
20
|
+
fork: "native",
|
|
21
|
+
gpu: "native",
|
|
22
|
+
killProcess: "unsupported",
|
|
23
|
+
list: "unsupported",
|
|
24
|
+
metrics: "unsupported",
|
|
25
|
+
pause: "unsupported",
|
|
26
|
+
privatePreview: "unsupported",
|
|
27
|
+
proxiedFetch: "unsupported",
|
|
28
|
+
pty: "unsupported",
|
|
29
|
+
region: "unsupported",
|
|
30
|
+
secretsVault: "unsupported",
|
|
31
|
+
setTimeout: "native",
|
|
32
|
+
snapshot: "native",
|
|
33
|
+
ssh: "unsupported",
|
|
34
|
+
statefulKernel: "unsupported",
|
|
35
|
+
stdin: "unsupported",
|
|
36
|
+
stop: "unsupported",
|
|
37
|
+
streaming: "emulated",
|
|
38
|
+
volumes: "unsupported",
|
|
39
|
+
};
|
|
40
|
+
const BEAM_FLAGS = {
|
|
41
|
+
exitCodeNative: true,
|
|
42
|
+
perCommandEnvCwd: true, // exec accepts { cwd, env }
|
|
43
|
+
preservesDiskOnStop: false,
|
|
44
|
+
preservesMemoryOnPause: false,
|
|
45
|
+
previewModel: "subdomain",
|
|
46
|
+
};
|
|
47
|
+
let cached = null;
|
|
48
|
+
async function loadBeam() {
|
|
49
|
+
if (!cached) {
|
|
50
|
+
cached = (await import("@beamcloud/beam-js"));
|
|
51
|
+
}
|
|
52
|
+
return cached;
|
|
53
|
+
}
|
|
54
|
+
async function readAll(stream) {
|
|
55
|
+
if (!stream) {
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
if (typeof stream === "string") {
|
|
59
|
+
return stream;
|
|
60
|
+
}
|
|
61
|
+
const decode = (c) => typeof c === "string" ? c : new TextDecoder().decode(c);
|
|
62
|
+
if (typeof stream[Symbol.asyncIterator] === "function") {
|
|
63
|
+
let s = "";
|
|
64
|
+
for await (const c of stream) {
|
|
65
|
+
s += decode(c);
|
|
66
|
+
}
|
|
67
|
+
return s;
|
|
68
|
+
}
|
|
69
|
+
if (typeof stream.read === "function") {
|
|
70
|
+
let s = "";
|
|
71
|
+
for (;;) {
|
|
72
|
+
const c = await stream.read();
|
|
73
|
+
if (c === null || c === undefined) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
s += decode(c);
|
|
77
|
+
}
|
|
78
|
+
return s;
|
|
79
|
+
}
|
|
80
|
+
return "";
|
|
81
|
+
}
|
|
82
|
+
export const beam = defineProvider((opts) => {
|
|
83
|
+
const configure = async () => {
|
|
84
|
+
const mod = await loadBeam();
|
|
85
|
+
if (opts.token) {
|
|
86
|
+
mod.beamOpts.token = opts.token;
|
|
87
|
+
}
|
|
88
|
+
if (opts.workspaceId) {
|
|
89
|
+
mod.beamOpts.workspaceId = opts.workspaceId;
|
|
90
|
+
}
|
|
91
|
+
return mod;
|
|
92
|
+
};
|
|
93
|
+
// Buffered exec: run the command, drain stdout/stderr, then resolve the code.
|
|
94
|
+
const runBuffered = async (inst, cmd, options) => {
|
|
95
|
+
const proc = await inst.exec(cmd, {
|
|
96
|
+
cwd: options.cwd,
|
|
97
|
+
env: options.env,
|
|
98
|
+
});
|
|
99
|
+
const [stdout, stderr] = await Promise.all([
|
|
100
|
+
readAll(proc.stdout),
|
|
101
|
+
readAll(proc.stderr),
|
|
102
|
+
]);
|
|
103
|
+
const exitCode = await proc.wait();
|
|
104
|
+
return { stdout, stderr, exitCode: exitCode ?? 0 };
|
|
105
|
+
};
|
|
106
|
+
const makeHandle = (inst) => {
|
|
107
|
+
const id = inst.sandboxId();
|
|
108
|
+
// base64 fs uses a bare exec (no cwd/env) so it is independent of options.
|
|
109
|
+
const fsExec = (cmd) => runBuffered(inst, cmd, {});
|
|
110
|
+
return {
|
|
111
|
+
id,
|
|
112
|
+
raw: inst,
|
|
113
|
+
getInfo() {
|
|
114
|
+
return {
|
|
115
|
+
id,
|
|
116
|
+
state: "running",
|
|
117
|
+
provider: "beam",
|
|
118
|
+
metadata: {},
|
|
119
|
+
raw: inst,
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
async destroy() {
|
|
123
|
+
await inst.terminate();
|
|
124
|
+
},
|
|
125
|
+
async setTimeout(ttlMs) {
|
|
126
|
+
await inst.updateTtl(Math.max(1, Math.ceil(ttlMs / 1000)));
|
|
127
|
+
},
|
|
128
|
+
exec(cmd, options) {
|
|
129
|
+
const queue = new AsyncQueue();
|
|
130
|
+
void runBuffered(inst, cmd, options)
|
|
131
|
+
.then((r) => {
|
|
132
|
+
if (r.stdout) {
|
|
133
|
+
queue.push({ type: "stdout", data: r.stdout });
|
|
134
|
+
}
|
|
135
|
+
if (r.stderr) {
|
|
136
|
+
queue.push({ type: "stderr", data: r.stderr });
|
|
137
|
+
}
|
|
138
|
+
queue.push({ type: "exit", exitCode: r.exitCode });
|
|
139
|
+
queue.close();
|
|
140
|
+
})
|
|
141
|
+
.catch((error) => queue.fail(error instanceof SandboxError
|
|
142
|
+
? error
|
|
143
|
+
: SandboxError.wrap(error, "beam")));
|
|
144
|
+
return {
|
|
145
|
+
pid: Promise.resolve(""),
|
|
146
|
+
async kill() {
|
|
147
|
+
/* buffered exec; use the native process API for control */
|
|
148
|
+
},
|
|
149
|
+
[Symbol.asyncIterator]: () => queue.iterator(),
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
async readFile(path) {
|
|
153
|
+
const r = await fsExec(`base64 ${sq(path)}`);
|
|
154
|
+
if (r.exitCode !== 0) {
|
|
155
|
+
throw new SandboxError("NotFound", `no such file: '${path}'`, {
|
|
156
|
+
provider: "beam",
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return base64ToBytes(r.stdout);
|
|
160
|
+
},
|
|
161
|
+
async writeFile(path, data) {
|
|
162
|
+
const b64 = bytesToBase64(data);
|
|
163
|
+
const r = await fsExec(`mkdir -p "$(dirname ${sq(path)})" && printf %s ${sq(b64)} | base64 -d > ${sq(path)}`);
|
|
164
|
+
if (r.exitCode !== 0) {
|
|
165
|
+
throw new SandboxError("Provider", `write failed: '${path}'`, {
|
|
166
|
+
provider: "beam",
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
async exposePort(port) {
|
|
171
|
+
return { url: await inst.exposePort(port), port };
|
|
172
|
+
},
|
|
173
|
+
async snapshot(snapOpts) {
|
|
174
|
+
const snapshotId = await inst.snapshot();
|
|
175
|
+
return {
|
|
176
|
+
id: snapshotId,
|
|
177
|
+
name: snapOpts.name,
|
|
178
|
+
provider: "beam",
|
|
179
|
+
raw: snapshotId,
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
async fork(count) {
|
|
183
|
+
const snapshotId = await inst.snapshot();
|
|
184
|
+
const mod = await configure();
|
|
185
|
+
const forks = await Promise.all(Array.from({ length: count }, () => mod.Sandbox.createFromSnapshot(snapshotId)));
|
|
186
|
+
return forks.map((f) => makeHandle(f));
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
const provider = {
|
|
191
|
+
name: "beam",
|
|
192
|
+
capabilities: BEAM_CAPS,
|
|
193
|
+
flags: BEAM_FLAGS,
|
|
194
|
+
async create(spec) {
|
|
195
|
+
const mod = await configure();
|
|
196
|
+
const image = spec.template ?? opts.image;
|
|
197
|
+
const sandbox = new mod.Sandbox({
|
|
198
|
+
name: spec.name,
|
|
199
|
+
cpu: spec.resources?.vcpus ?? opts.cpu ?? 1,
|
|
200
|
+
memory: (spec.resources?.memoryMB
|
|
201
|
+
? `${spec.resources.memoryMB}Mi`
|
|
202
|
+
: undefined) ??
|
|
203
|
+
opts.memory ??
|
|
204
|
+
"1Gi",
|
|
205
|
+
gpu: spec.resources?.gpu,
|
|
206
|
+
ports: spec.ports,
|
|
207
|
+
keepWarmSeconds: spec.ttlMs
|
|
208
|
+
? Math.ceil(spec.ttlMs / 1000)
|
|
209
|
+
: undefined,
|
|
210
|
+
image: image && mod.Image
|
|
211
|
+
? new mod.Image({ baseImage: image })
|
|
212
|
+
: undefined,
|
|
213
|
+
});
|
|
214
|
+
return makeHandle(await sandbox.create());
|
|
215
|
+
},
|
|
216
|
+
async connect(id) {
|
|
217
|
+
const mod = await configure();
|
|
218
|
+
return makeHandle(await mod.Sandbox.connect(id));
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
return provider;
|
|
222
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { SandboxProvider } from "../adapter/index.js";
|
|
2
|
+
export interface BlaxelOptions {
|
|
3
|
+
/** Blaxel API key (falls back to BL_API_KEY in the environment). */
|
|
4
|
+
apiKey?: string;
|
|
5
|
+
/** Blaxel workspace (falls back to BL_WORKSPACE in the environment). */
|
|
6
|
+
workspace?: string;
|
|
7
|
+
/** Default sandbox image when a spec omits `template`. */
|
|
8
|
+
image?: string;
|
|
9
|
+
/** Default memory (MB) for new sandboxes. */
|
|
10
|
+
memory?: number;
|
|
11
|
+
region?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const BLAXEL_CAPS: {
|
|
14
|
+
readonly background: "unsupported";
|
|
15
|
+
readonly codeInterpreter: "unsupported";
|
|
16
|
+
readonly egressControl: "unsupported";
|
|
17
|
+
readonly exposePort: "native";
|
|
18
|
+
readonly filesUpload: "native";
|
|
19
|
+
readonly filesWatch: "unsupported";
|
|
20
|
+
readonly fork: "unsupported";
|
|
21
|
+
readonly gpu: "unsupported";
|
|
22
|
+
readonly killProcess: "unsupported";
|
|
23
|
+
readonly list: "native";
|
|
24
|
+
readonly metrics: "unsupported";
|
|
25
|
+
readonly pause: "unsupported";
|
|
26
|
+
readonly privatePreview: "native";
|
|
27
|
+
readonly proxiedFetch: "unsupported";
|
|
28
|
+
readonly pty: "unsupported";
|
|
29
|
+
readonly region: "native";
|
|
30
|
+
readonly secretsVault: "unsupported";
|
|
31
|
+
readonly setTimeout: "unsupported";
|
|
32
|
+
readonly snapshot: "unsupported";
|
|
33
|
+
readonly ssh: "unsupported";
|
|
34
|
+
readonly statefulKernel: "unsupported";
|
|
35
|
+
readonly stdin: "unsupported";
|
|
36
|
+
readonly stop: "unsupported";
|
|
37
|
+
readonly streaming: "emulated";
|
|
38
|
+
readonly volumes: "native";
|
|
39
|
+
};
|
|
40
|
+
export type BlaxelCaps = typeof BLAXEL_CAPS;
|
|
41
|
+
interface BlaxelProcessResult {
|
|
42
|
+
pid?: string;
|
|
43
|
+
exitCode?: number;
|
|
44
|
+
status?: string;
|
|
45
|
+
logs?: string;
|
|
46
|
+
stdout?: string;
|
|
47
|
+
}
|
|
48
|
+
interface BlaxelLs {
|
|
49
|
+
subdirectories?: ({
|
|
50
|
+
path?: string;
|
|
51
|
+
name?: string;
|
|
52
|
+
} | string)[];
|
|
53
|
+
files?: ({
|
|
54
|
+
path?: string;
|
|
55
|
+
name?: string;
|
|
56
|
+
} | string)[];
|
|
57
|
+
}
|
|
58
|
+
interface BlaxelInstance {
|
|
59
|
+
metadata?: {
|
|
60
|
+
name?: string;
|
|
61
|
+
status?: string;
|
|
62
|
+
};
|
|
63
|
+
status?: string;
|
|
64
|
+
process: {
|
|
65
|
+
exec(opts: {
|
|
66
|
+
command: string;
|
|
67
|
+
workingDir?: string;
|
|
68
|
+
waitForCompletion?: boolean;
|
|
69
|
+
timeout?: number;
|
|
70
|
+
}): Promise<BlaxelProcessResult>;
|
|
71
|
+
kill(name: string): Promise<void>;
|
|
72
|
+
};
|
|
73
|
+
fs: {
|
|
74
|
+
readBinary(path: string): Promise<Blob | Uint8Array | ArrayBuffer>;
|
|
75
|
+
writeBinary(path: string, data: Uint8Array): Promise<void>;
|
|
76
|
+
mkdir(path: string): Promise<void>;
|
|
77
|
+
ls(path: string): Promise<BlaxelLs>;
|
|
78
|
+
};
|
|
79
|
+
previews: {
|
|
80
|
+
createIfNotExists(opts: {
|
|
81
|
+
metadata: {
|
|
82
|
+
name: string;
|
|
83
|
+
};
|
|
84
|
+
spec: {
|
|
85
|
+
port: number;
|
|
86
|
+
public: boolean;
|
|
87
|
+
prefixUrl?: string;
|
|
88
|
+
};
|
|
89
|
+
}): Promise<{
|
|
90
|
+
spec?: {
|
|
91
|
+
url?: string;
|
|
92
|
+
};
|
|
93
|
+
}>;
|
|
94
|
+
};
|
|
95
|
+
delete(): Promise<void>;
|
|
96
|
+
}
|
|
97
|
+
export declare const blaxel: (opts: BlaxelOptions) => SandboxProvider<{
|
|
98
|
+
readonly background: "unsupported";
|
|
99
|
+
readonly codeInterpreter: "unsupported";
|
|
100
|
+
readonly egressControl: "unsupported";
|
|
101
|
+
readonly exposePort: "native";
|
|
102
|
+
readonly filesUpload: "native";
|
|
103
|
+
readonly filesWatch: "unsupported";
|
|
104
|
+
readonly fork: "unsupported";
|
|
105
|
+
readonly gpu: "unsupported";
|
|
106
|
+
readonly killProcess: "unsupported";
|
|
107
|
+
readonly list: "native";
|
|
108
|
+
readonly metrics: "unsupported";
|
|
109
|
+
readonly pause: "unsupported";
|
|
110
|
+
readonly privatePreview: "native";
|
|
111
|
+
readonly proxiedFetch: "unsupported";
|
|
112
|
+
readonly pty: "unsupported";
|
|
113
|
+
readonly region: "native";
|
|
114
|
+
readonly secretsVault: "unsupported";
|
|
115
|
+
readonly setTimeout: "unsupported";
|
|
116
|
+
readonly snapshot: "unsupported";
|
|
117
|
+
readonly ssh: "unsupported";
|
|
118
|
+
readonly statefulKernel: "unsupported";
|
|
119
|
+
readonly stdin: "unsupported";
|
|
120
|
+
readonly stop: "unsupported";
|
|
121
|
+
readonly streaming: "emulated";
|
|
122
|
+
readonly volumes: "native";
|
|
123
|
+
}, BlaxelInstance>;
|
|
124
|
+
export {};
|
|
125
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/blaxel/index.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EASV,eAAe,EAGhB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BU,CAAC;AAEnC,MAAM,MAAM,UAAU,GAAG,OAAO,WAAW,CAAC;AAW5C,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AACD,UAAU,QAAQ;IAChB,cAAc,CAAC,EAAE,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IAC/D,KAAK,CAAC,EAAE,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,EAAE,CAAC;CACvD;AACD,UAAU,cAAc;IACtB,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,IAAI,CAAC,IAAI,EAAE;YACT,OAAO,EAAE,MAAM,CAAC;YAChB,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;YAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KACnC,CAAC;IACF,EAAE,EAAE;QACF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,UAAU,GAAG,WAAW,CAAC,CAAC;QACnE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;KACrC,CAAC;IACF,QAAQ,EAAE;QACR,iBAAiB,CAAC,IAAI,EAAE;YACtB,QAAQ,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAA;aAAE,CAAC;YAC3B,IAAI,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,OAAO,CAAC;gBAAC,SAAS,CAAC,EAAE,MAAM,CAAA;aAAE,CAAC;SAC7D,GAAG,OAAO,CAAC;YAAE,IAAI,CAAC,EAAE;gBAAE,GAAG,CAAC,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAC,CAAC;KAC1C,CAAC;IACF,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AA6DD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;kBAoJlB,CAAC"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sbox-sdk/blaxel` — adapter for Blaxel (`@blaxel/core`, `SandboxInstance`).
|
|
3
|
+
* Blaxel is the "perpetual sandbox" platform: a sandbox stays in standby
|
|
4
|
+
* indefinitely and resumes in sub-25ms on the next request, so there is no
|
|
5
|
+
* explicit pause/resume — `destroy()` deletes it. exec is the buffered
|
|
6
|
+
* `process.exec({ command, waitForCompletion: true })`; it has no per-command env
|
|
7
|
+
* (only `workingDir`), so the core folds cwd+env into a `cd … && KEY=v …` wrapper
|
|
8
|
+
* (`perCommandEnvCwd: false`). Filesystem uses the binary-safe `fs.readBinary` /
|
|
9
|
+
* `fs.writeBinary`; directory ops the core can't get from those are polyfilled via
|
|
10
|
+
* exec. Ports are preview URLs (`previews.createIfNotExists`, public or private).
|
|
11
|
+
* Requires the optional peer dependency `@blaxel/core`.
|
|
12
|
+
*/
|
|
13
|
+
import { AsyncQueue, defineProvider, SandboxError } from "../adapter/index.js";
|
|
14
|
+
export const BLAXEL_CAPS = {
|
|
15
|
+
background: "unsupported",
|
|
16
|
+
codeInterpreter: "unsupported",
|
|
17
|
+
egressControl: "unsupported",
|
|
18
|
+
exposePort: "native",
|
|
19
|
+
filesUpload: "native",
|
|
20
|
+
filesWatch: "unsupported",
|
|
21
|
+
fork: "unsupported",
|
|
22
|
+
gpu: "unsupported",
|
|
23
|
+
killProcess: "unsupported",
|
|
24
|
+
list: "native",
|
|
25
|
+
metrics: "unsupported",
|
|
26
|
+
pause: "unsupported",
|
|
27
|
+
privatePreview: "native",
|
|
28
|
+
proxiedFetch: "unsupported",
|
|
29
|
+
pty: "unsupported",
|
|
30
|
+
region: "native",
|
|
31
|
+
secretsVault: "unsupported",
|
|
32
|
+
setTimeout: "unsupported",
|
|
33
|
+
snapshot: "unsupported",
|
|
34
|
+
ssh: "unsupported",
|
|
35
|
+
statefulKernel: "unsupported",
|
|
36
|
+
stdin: "unsupported",
|
|
37
|
+
stop: "unsupported",
|
|
38
|
+
streaming: "emulated",
|
|
39
|
+
volumes: "native",
|
|
40
|
+
};
|
|
41
|
+
const BLAXEL_FLAGS = {
|
|
42
|
+
exitCodeNative: true,
|
|
43
|
+
perCommandEnvCwd: false, // process.exec has no per-call env — core wraps it
|
|
44
|
+
preservesDiskOnStop: true, // standby preserves disk + memory automatically
|
|
45
|
+
preservesMemoryOnPause: true,
|
|
46
|
+
previewModel: "subdomain",
|
|
47
|
+
};
|
|
48
|
+
let cached = null;
|
|
49
|
+
async function loadBlaxel() {
|
|
50
|
+
if (!cached) {
|
|
51
|
+
cached = (await import("@blaxel/core"));
|
|
52
|
+
}
|
|
53
|
+
return cached;
|
|
54
|
+
}
|
|
55
|
+
function mapState(state) {
|
|
56
|
+
switch ((state ?? "").toUpperCase()) {
|
|
57
|
+
case "DEPLOYED":
|
|
58
|
+
case "RUNNING": {
|
|
59
|
+
return "running";
|
|
60
|
+
}
|
|
61
|
+
case "STANDBY":
|
|
62
|
+
case "SUSPENDED": {
|
|
63
|
+
return "paused";
|
|
64
|
+
}
|
|
65
|
+
case "DEPLOYING":
|
|
66
|
+
case "PENDING": {
|
|
67
|
+
return "creating";
|
|
68
|
+
}
|
|
69
|
+
case "DELETED": {
|
|
70
|
+
return "destroyed";
|
|
71
|
+
}
|
|
72
|
+
default: {
|
|
73
|
+
return "unknown";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function toBytes(data) {
|
|
78
|
+
if (data instanceof Uint8Array) {
|
|
79
|
+
return data;
|
|
80
|
+
}
|
|
81
|
+
if (data instanceof ArrayBuffer) {
|
|
82
|
+
return new Uint8Array(data);
|
|
83
|
+
}
|
|
84
|
+
return new Uint8Array(await data.arrayBuffer());
|
|
85
|
+
}
|
|
86
|
+
function entryName(e) {
|
|
87
|
+
if (typeof e === "string") {
|
|
88
|
+
return e;
|
|
89
|
+
}
|
|
90
|
+
return e.name ?? (e.path ? (e.path.split("/").pop() ?? e.path) : "");
|
|
91
|
+
}
|
|
92
|
+
export const blaxel = defineProvider((opts) => {
|
|
93
|
+
const ensureAuth = () => {
|
|
94
|
+
if (opts.apiKey) {
|
|
95
|
+
process.env.BL_API_KEY ??= opts.apiKey;
|
|
96
|
+
}
|
|
97
|
+
if (opts.workspace) {
|
|
98
|
+
process.env.BL_WORKSPACE ??= opts.workspace;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const makeHandle = (inst) => {
|
|
102
|
+
const name = inst.metadata?.name ?? "";
|
|
103
|
+
return {
|
|
104
|
+
id: name,
|
|
105
|
+
name,
|
|
106
|
+
raw: inst,
|
|
107
|
+
getInfo() {
|
|
108
|
+
return {
|
|
109
|
+
id: name,
|
|
110
|
+
name,
|
|
111
|
+
state: mapState(inst.metadata?.status ?? inst.status),
|
|
112
|
+
provider: "blaxel",
|
|
113
|
+
metadata: {},
|
|
114
|
+
raw: inst,
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
async destroy() {
|
|
118
|
+
await inst.delete();
|
|
119
|
+
},
|
|
120
|
+
exec(cmd) {
|
|
121
|
+
const queue = new AsyncQueue();
|
|
122
|
+
void inst.process
|
|
123
|
+
.exec({ command: cmd, waitForCompletion: true })
|
|
124
|
+
.then((r) => {
|
|
125
|
+
const out = r.logs ?? r.stdout ?? "";
|
|
126
|
+
if (out) {
|
|
127
|
+
queue.push({ type: "stdout", data: out });
|
|
128
|
+
}
|
|
129
|
+
queue.push({ type: "exit", exitCode: r.exitCode ?? 0 });
|
|
130
|
+
queue.close();
|
|
131
|
+
})
|
|
132
|
+
.catch((error) => queue.fail(error instanceof SandboxError
|
|
133
|
+
? error
|
|
134
|
+
: SandboxError.wrap(error, "blaxel")));
|
|
135
|
+
return {
|
|
136
|
+
pid: Promise.resolve(""),
|
|
137
|
+
async kill() {
|
|
138
|
+
/* exec runs with waitForCompletion; no kill handle */
|
|
139
|
+
},
|
|
140
|
+
[Symbol.asyncIterator]: () => queue.iterator(),
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
async readFile(path) {
|
|
144
|
+
return toBytes(await inst.fs.readBinary(path));
|
|
145
|
+
},
|
|
146
|
+
async writeFile(path, data) {
|
|
147
|
+
await inst.fs.writeBinary(path, data);
|
|
148
|
+
},
|
|
149
|
+
async mkdir(path) {
|
|
150
|
+
await inst.fs.mkdir(path);
|
|
151
|
+
},
|
|
152
|
+
async listDir(path) {
|
|
153
|
+
const ls = await inst.fs.ls(path);
|
|
154
|
+
const base = path.replace(/\/$/, "");
|
|
155
|
+
const dirs = (ls.subdirectories ?? []).map((d) => {
|
|
156
|
+
const nm = entryName(d);
|
|
157
|
+
return { name: nm, path: `${base}/${nm}`, type: "dir" };
|
|
158
|
+
});
|
|
159
|
+
const files = (ls.files ?? []).map((f) => {
|
|
160
|
+
const nm = entryName(f);
|
|
161
|
+
return { name: nm, path: `${base}/${nm}`, type: "file" };
|
|
162
|
+
});
|
|
163
|
+
return [...dirs, ...files];
|
|
164
|
+
},
|
|
165
|
+
async exposePort(port, portOpts) {
|
|
166
|
+
const preview = await inst.previews.createIfNotExists({
|
|
167
|
+
metadata: { name: `sbox-${port}` },
|
|
168
|
+
spec: { port, public: !portOpts.private },
|
|
169
|
+
});
|
|
170
|
+
return { url: preview.spec?.url ?? "", port };
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
const provider = {
|
|
175
|
+
name: "blaxel",
|
|
176
|
+
capabilities: BLAXEL_CAPS,
|
|
177
|
+
flags: BLAXEL_FLAGS,
|
|
178
|
+
async create(spec) {
|
|
179
|
+
ensureAuth();
|
|
180
|
+
const mod = await loadBlaxel();
|
|
181
|
+
const name = spec.name ?? `sbox-${globalThis.crypto.randomUUID().slice(0, 8)}`;
|
|
182
|
+
const inst = await mod.SandboxInstance.createIfNotExists({
|
|
183
|
+
name,
|
|
184
|
+
image: spec.template ?? opts.image ?? "blaxel/prod-base:latest",
|
|
185
|
+
memory: spec.resources?.memoryMB ?? opts.memory ?? 2048,
|
|
186
|
+
region: spec.region ?? opts.region,
|
|
187
|
+
ports: spec.ports?.map((p) => ({ target: p, protocol: "HTTP" })),
|
|
188
|
+
labels: spec.metadata,
|
|
189
|
+
ttl: spec.ttlMs ? `${Math.ceil(spec.ttlMs / 1000)}s` : undefined,
|
|
190
|
+
volumes: spec.volumes?.map((v) => ({
|
|
191
|
+
name: v.id,
|
|
192
|
+
mountPath: v.mountPath,
|
|
193
|
+
readOnly: v.readOnly ?? false,
|
|
194
|
+
})),
|
|
195
|
+
});
|
|
196
|
+
return makeHandle(inst);
|
|
197
|
+
},
|
|
198
|
+
async connect(id) {
|
|
199
|
+
ensureAuth();
|
|
200
|
+
const mod = await loadBlaxel();
|
|
201
|
+
return makeHandle(await mod.SandboxInstance.get(id));
|
|
202
|
+
},
|
|
203
|
+
async *list() {
|
|
204
|
+
ensureAuth();
|
|
205
|
+
const mod = await loadBlaxel();
|
|
206
|
+
for (const inst of await mod.SandboxInstance.list()) {
|
|
207
|
+
const name = inst.metadata?.name ?? "";
|
|
208
|
+
yield {
|
|
209
|
+
id: name,
|
|
210
|
+
name,
|
|
211
|
+
state: mapState(inst.metadata?.status ?? inst.status),
|
|
212
|
+
provider: "blaxel",
|
|
213
|
+
metadata: {},
|
|
214
|
+
raw: inst,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
return provider;
|
|
220
|
+
});
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|