@computesdk/beam 0.1.9 → 0.1.11
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/dist/index.d.mts +0 -16
- package/dist/index.d.ts +0 -16
- package/dist/index.js +29 -133
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +29 -133
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.d.mts
CHANGED
|
@@ -2,28 +2,12 @@ import * as _computesdk_provider from '@computesdk/provider';
|
|
|
2
2
|
import { SandboxInstance } from '@beamcloud/beam-js';
|
|
3
3
|
export { SandboxInstance as BeamSandboxInstance } from '@beamcloud/beam-js';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Beam-specific configuration options
|
|
7
|
-
*/
|
|
8
5
|
interface BeamConfig {
|
|
9
|
-
/** Beam API token - if not provided, will fallback to BEAM_TOKEN environment variable */
|
|
10
6
|
token?: string;
|
|
11
|
-
/** Beam workspace ID - if not provided, will fallback to BEAM_WORKSPACE_ID environment variable */
|
|
12
7
|
workspaceId?: string;
|
|
13
|
-
/** Gateway URL for custom/staging environments */
|
|
14
8
|
gatewayUrl?: string;
|
|
15
|
-
/** Request timeout in milliseconds */
|
|
16
9
|
timeout?: number;
|
|
17
10
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Create a Beam provider instance using the factory pattern
|
|
20
|
-
*
|
|
21
|
-
* Beam provides containerized sandbox environments with:
|
|
22
|
-
* - Process management (exec, runCode)
|
|
23
|
-
* - Filesystem access
|
|
24
|
-
* - Dynamic port exposure
|
|
25
|
-
* - Snapshot and image creation capabilities
|
|
26
|
-
*/
|
|
27
11
|
declare const beam: (config: BeamConfig) => _computesdk_provider.Provider<SandboxInstance, any, any>;
|
|
28
12
|
|
|
29
13
|
export { type BeamConfig, beam };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,28 +2,12 @@ import * as _computesdk_provider from '@computesdk/provider';
|
|
|
2
2
|
import { SandboxInstance } from '@beamcloud/beam-js';
|
|
3
3
|
export { SandboxInstance as BeamSandboxInstance } from '@beamcloud/beam-js';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Beam-specific configuration options
|
|
7
|
-
*/
|
|
8
5
|
interface BeamConfig {
|
|
9
|
-
/** Beam API token - if not provided, will fallback to BEAM_TOKEN environment variable */
|
|
10
6
|
token?: string;
|
|
11
|
-
/** Beam workspace ID - if not provided, will fallback to BEAM_WORKSPACE_ID environment variable */
|
|
12
7
|
workspaceId?: string;
|
|
13
|
-
/** Gateway URL for custom/staging environments */
|
|
14
8
|
gatewayUrl?: string;
|
|
15
|
-
/** Request timeout in milliseconds */
|
|
16
9
|
timeout?: number;
|
|
17
10
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Create a Beam provider instance using the factory pattern
|
|
20
|
-
*
|
|
21
|
-
* Beam provides containerized sandbox environments with:
|
|
22
|
-
* - Process management (exec, runCode)
|
|
23
|
-
* - Filesystem access
|
|
24
|
-
* - Dynamic port exposure
|
|
25
|
-
* - Snapshot and image creation capabilities
|
|
26
|
-
*/
|
|
27
11
|
declare const beam: (config: BeamConfig) => _computesdk_provider.Provider<SandboxInstance, any, any>;
|
|
28
12
|
|
|
29
13
|
export { type BeamConfig, beam };
|
package/dist/index.js
CHANGED
|
@@ -28,12 +28,8 @@ var import_provider = require("@computesdk/provider");
|
|
|
28
28
|
function configureBeamOpts(config) {
|
|
29
29
|
import_beam_js.beamOpts.token = config.token || typeof process !== "undefined" && process.env?.BEAM_TOKEN || "";
|
|
30
30
|
import_beam_js.beamOpts.workspaceId = config.workspaceId || typeof process !== "undefined" && process.env?.BEAM_WORKSPACE_ID || "";
|
|
31
|
-
if (config.gatewayUrl)
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
if (config.timeout) {
|
|
35
|
-
import_beam_js.beamOpts.timeout = config.timeout;
|
|
36
|
-
}
|
|
31
|
+
if (config.gatewayUrl) import_beam_js.beamOpts.gatewayUrl = config.gatewayUrl;
|
|
32
|
+
if (config.timeout) import_beam_js.beamOpts.timeout = config.timeout;
|
|
37
33
|
}
|
|
38
34
|
function shellEscape(arg) {
|
|
39
35
|
if (arg === "") return "''";
|
|
@@ -43,11 +39,6 @@ var beam = (0, import_provider.defineProvider)({
|
|
|
43
39
|
name: "beam",
|
|
44
40
|
methods: {
|
|
45
41
|
sandbox: {
|
|
46
|
-
/**
|
|
47
|
-
* Create a new Beam sandbox
|
|
48
|
-
*
|
|
49
|
-
* Uses Sandbox class from @beamcloud/beam-js to provision a container.
|
|
50
|
-
*/
|
|
51
42
|
create: async (config, options) => {
|
|
52
43
|
configureBeamOpts(config);
|
|
53
44
|
if (!import_beam_js.beamOpts.token) {
|
|
@@ -62,7 +53,6 @@ var beam = (0, import_provider.defineProvider)({
|
|
|
62
53
|
}
|
|
63
54
|
try {
|
|
64
55
|
const {
|
|
65
|
-
runtime: optRuntime,
|
|
66
56
|
timeout: optTimeout,
|
|
67
57
|
envs,
|
|
68
58
|
name,
|
|
@@ -74,16 +64,14 @@ var beam = (0, import_provider.defineProvider)({
|
|
|
74
64
|
directory: _directory,
|
|
75
65
|
...providerOptions
|
|
76
66
|
} = options || {};
|
|
67
|
+
const optRuntime = options?.runtime;
|
|
77
68
|
const sandboxConfig = {
|
|
78
69
|
name: name || `computesdk-${Date.now()}`,
|
|
79
70
|
keepWarmSeconds: 300,
|
|
80
71
|
...providerOptions
|
|
81
|
-
// Spread provider-specific options
|
|
82
72
|
};
|
|
83
73
|
const timeout = optTimeout ?? config.timeout;
|
|
84
|
-
if (timeout)
|
|
85
|
-
sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1e3);
|
|
86
|
-
}
|
|
74
|
+
if (timeout) sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1e3);
|
|
87
75
|
if (optRuntime === "node") {
|
|
88
76
|
sandboxConfig.image = import_beam_js.Image.fromRegistry("node:20-slim");
|
|
89
77
|
}
|
|
@@ -94,28 +82,19 @@ var beam = (0, import_provider.defineProvider)({
|
|
|
94
82
|
const instance = await sandbox.create();
|
|
95
83
|
return { sandbox: instance, sandboxId: instance.containerId };
|
|
96
84
|
} catch (error) {
|
|
97
|
-
if (error instanceof Error) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
);
|
|
102
|
-
}
|
|
85
|
+
if (error instanceof Error && (error.message.includes("unauthorized") || error.message.includes("401"))) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`Beam authentication failed. Please check your BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`
|
|
88
|
+
);
|
|
103
89
|
}
|
|
104
90
|
throw new Error(
|
|
105
91
|
`Failed to create Beam sandbox: ${error instanceof Error ? error.message : String(error)}`
|
|
106
92
|
);
|
|
107
93
|
}
|
|
108
94
|
},
|
|
109
|
-
/**
|
|
110
|
-
* Connect to an existing Beam sandbox by ID
|
|
111
|
-
*
|
|
112
|
-
* Uses Sandbox.connect() to reconnect to a running sandbox.
|
|
113
|
-
*/
|
|
114
95
|
getById: async (config, sandboxId) => {
|
|
115
96
|
configureBeamOpts(config);
|
|
116
|
-
if (!import_beam_js.beamOpts.token)
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
97
|
+
if (!import_beam_js.beamOpts.token) return null;
|
|
119
98
|
try {
|
|
120
99
|
const instance = await import_beam_js.Sandbox.connect(sandboxId);
|
|
121
100
|
return { sandbox: instance, sandboxId: instance.containerId };
|
|
@@ -123,40 +102,16 @@ var beam = (0, import_provider.defineProvider)({
|
|
|
123
102
|
return null;
|
|
124
103
|
}
|
|
125
104
|
},
|
|
126
|
-
|
|
127
|
-
* List all active Beam sandboxes
|
|
128
|
-
*
|
|
129
|
-
* Beam SDK has no sandbox list API; returns empty array.
|
|
130
|
-
*/
|
|
131
|
-
list: async (_config) => {
|
|
132
|
-
return [];
|
|
133
|
-
},
|
|
134
|
-
/**
|
|
135
|
-
* Destroy a Beam sandbox
|
|
136
|
-
*
|
|
137
|
-
* Connects to the sandbox and terminates it.
|
|
138
|
-
*/
|
|
105
|
+
list: async (_config) => [],
|
|
139
106
|
destroy: async (config, sandboxId) => {
|
|
140
107
|
configureBeamOpts(config);
|
|
141
|
-
if (!import_beam_js.beamOpts.token)
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
108
|
+
if (!import_beam_js.beamOpts.token) return;
|
|
144
109
|
try {
|
|
145
110
|
const instance = await import_beam_js.Sandbox.connect(sandboxId);
|
|
146
111
|
await instance.terminate();
|
|
147
112
|
} catch {
|
|
148
113
|
}
|
|
149
114
|
},
|
|
150
|
-
/**
|
|
151
|
-
* Execute code in the sandbox
|
|
152
|
-
*
|
|
153
|
-
* Auto-detects runtime (Python vs Node.js) and executes via sandbox.exec().
|
|
154
|
-
*/
|
|
155
|
-
/**
|
|
156
|
-
* Execute a shell command in the sandbox
|
|
157
|
-
*
|
|
158
|
-
* Uses sandbox.exec() with shell command string.
|
|
159
|
-
*/
|
|
160
115
|
runCommand: async (sandbox, command, options) => {
|
|
161
116
|
const startTime = Date.now();
|
|
162
117
|
try {
|
|
@@ -165,114 +120,62 @@ var beam = (0, import_provider.defineProvider)({
|
|
|
165
120
|
const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}="${(0, import_provider.escapeShellArg)(String(v))}"`).join(" ");
|
|
166
121
|
fullCommand = `${envPrefix} ${fullCommand}`;
|
|
167
122
|
}
|
|
168
|
-
if (options?.cwd) {
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
if (options?.background) {
|
|
172
|
-
fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
|
|
173
|
-
}
|
|
123
|
+
if (options?.cwd) fullCommand = `cd "${(0, import_provider.escapeShellArg)(options.cwd)}" && ${fullCommand}`;
|
|
124
|
+
if (options?.background) fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
|
|
174
125
|
const proc = await sandbox.exec(["sh", "-c", fullCommand]);
|
|
175
126
|
await proc.wait();
|
|
176
|
-
const [stdoutStr, stderrStr] = await Promise.all([
|
|
177
|
-
|
|
178
|
-
proc.stderr.read()
|
|
179
|
-
]);
|
|
180
|
-
return {
|
|
181
|
-
stdout: stdoutStr || "",
|
|
182
|
-
stderr: stderrStr || "",
|
|
183
|
-
exitCode: proc.exitCode || 0,
|
|
184
|
-
durationMs: Date.now() - startTime
|
|
185
|
-
};
|
|
127
|
+
const [stdoutStr, stderrStr] = await Promise.all([proc.stdout.read(), proc.stderr.read()]);
|
|
128
|
+
return { stdout: stdoutStr || "", stderr: stderrStr || "", exitCode: proc.exitCode || 0, durationMs: Date.now() - startTime };
|
|
186
129
|
} catch (error) {
|
|
187
|
-
return {
|
|
188
|
-
stdout: "",
|
|
189
|
-
stderr: error instanceof Error ? error.message : String(error),
|
|
190
|
-
exitCode: 127,
|
|
191
|
-
durationMs: Date.now() - startTime
|
|
192
|
-
};
|
|
130
|
+
return { stdout: "", stderr: error instanceof Error ? error.message : String(error), exitCode: 127, durationMs: Date.now() - startTime };
|
|
193
131
|
}
|
|
194
132
|
},
|
|
195
|
-
/**
|
|
196
|
-
* Get sandbox information
|
|
197
|
-
*/
|
|
198
133
|
getInfo: async (sandbox) => {
|
|
199
134
|
let runtime = "python";
|
|
200
135
|
const runtimeHint = sandbox;
|
|
201
136
|
if (typeof runtimeHint.runtime === "string") {
|
|
202
137
|
const lower = runtimeHint.runtime.toLowerCase();
|
|
203
|
-
if (lower.includes("node"))
|
|
204
|
-
|
|
205
|
-
} else if (lower.includes("python")) {
|
|
206
|
-
runtime = "python";
|
|
207
|
-
}
|
|
138
|
+
if (lower.includes("node")) runtime = "node";
|
|
139
|
+
else if (lower.includes("python")) runtime = "python";
|
|
208
140
|
} else if (typeof runtimeHint.image === "string") {
|
|
209
141
|
const imageStr = runtimeHint.image.toLowerCase();
|
|
210
|
-
if (imageStr.includes("node"))
|
|
211
|
-
|
|
212
|
-
} else if (imageStr.includes("python")) {
|
|
213
|
-
runtime = "python";
|
|
214
|
-
}
|
|
142
|
+
if (imageStr.includes("node")) runtime = "node";
|
|
143
|
+
else if (imageStr.includes("python")) runtime = "python";
|
|
215
144
|
} else if (typeof runtimeHint.imageName === "string") {
|
|
216
145
|
const imageNameStr = runtimeHint.imageName.toLowerCase();
|
|
217
|
-
if (imageNameStr.includes("node"))
|
|
218
|
-
|
|
219
|
-
} else if (imageNameStr.includes("python")) {
|
|
220
|
-
runtime = "python";
|
|
221
|
-
}
|
|
146
|
+
if (imageNameStr.includes("node")) runtime = "node";
|
|
147
|
+
else if (imageNameStr.includes("python")) runtime = "python";
|
|
222
148
|
}
|
|
223
149
|
return {
|
|
224
150
|
id: sandbox.containerId,
|
|
225
151
|
provider: "beam",
|
|
226
|
-
runtime,
|
|
227
152
|
status: "running",
|
|
228
153
|
createdAt: /* @__PURE__ */ new Date(),
|
|
229
154
|
timeout: 3e5,
|
|
230
|
-
metadata: {
|
|
231
|
-
containerId: sandbox.containerId
|
|
232
|
-
}
|
|
155
|
+
metadata: { containerId: sandbox.containerId, runtime }
|
|
233
156
|
};
|
|
234
157
|
},
|
|
235
|
-
/**
|
|
236
|
-
* Get public URL for a specific port
|
|
237
|
-
*
|
|
238
|
-
* Uses sandbox.exposePort() to dynamically expose a port.
|
|
239
|
-
*/
|
|
240
158
|
getUrl: async (sandbox, options) => {
|
|
241
159
|
try {
|
|
242
160
|
return await sandbox.exposePort(options.port);
|
|
243
161
|
} catch (error) {
|
|
244
|
-
throw new Error(
|
|
245
|
-
`Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`
|
|
246
|
-
);
|
|
162
|
+
throw new Error(`Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`);
|
|
247
163
|
}
|
|
248
164
|
},
|
|
249
|
-
/**
|
|
250
|
-
* Filesystem operations
|
|
251
|
-
*
|
|
252
|
-
* Most operations use shell commands via runCommand since Beam's file API
|
|
253
|
-
* is local-path oriented (uploadFile/downloadFile require local filesystem paths).
|
|
254
|
-
* readdir uses the native listFiles API since it returns structured data.
|
|
255
|
-
*/
|
|
256
165
|
filesystem: {
|
|
257
166
|
readFile: async (sandbox, path, runCommand) => {
|
|
258
167
|
const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);
|
|
259
|
-
if (result.exitCode !== 0) {
|
|
260
|
-
throw new Error(`Failed to read file ${path}: ${result.stderr}`);
|
|
261
|
-
}
|
|
168
|
+
if (result.exitCode !== 0) throw new Error(`Failed to read file ${path}: ${result.stderr}`);
|
|
262
169
|
return result.stdout;
|
|
263
170
|
},
|
|
264
171
|
writeFile: async (sandbox, path, content, runCommand) => {
|
|
265
172
|
const b64 = Buffer.from(content).toString("base64");
|
|
266
173
|
const result = await runCommand(sandbox, `echo '${b64}' | base64 -d > ${shellEscape(path)}`);
|
|
267
|
-
if (result.exitCode !== 0) {
|
|
268
|
-
throw new Error(`Failed to write file ${path}: ${result.stderr}`);
|
|
269
|
-
}
|
|
174
|
+
if (result.exitCode !== 0) throw new Error(`Failed to write file ${path}: ${result.stderr}`);
|
|
270
175
|
},
|
|
271
176
|
mkdir: async (sandbox, path, runCommand) => {
|
|
272
177
|
const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);
|
|
273
|
-
if (result.exitCode !== 0) {
|
|
274
|
-
throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
|
|
275
|
-
}
|
|
178
|
+
if (result.exitCode !== 0) throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
|
|
276
179
|
},
|
|
277
180
|
readdir: async (sandbox, path, _runCommand) => {
|
|
278
181
|
const files = await sandbox.fs.listFiles(path);
|
|
@@ -289,17 +192,10 @@ var beam = (0, import_provider.defineProvider)({
|
|
|
289
192
|
},
|
|
290
193
|
remove: async (sandbox, path, runCommand) => {
|
|
291
194
|
const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);
|
|
292
|
-
if (result.exitCode !== 0) {
|
|
293
|
-
throw new Error(`Failed to remove ${path}: ${result.stderr}`);
|
|
294
|
-
}
|
|
195
|
+
if (result.exitCode !== 0) throw new Error(`Failed to remove ${path}: ${result.stderr}`);
|
|
295
196
|
}
|
|
296
197
|
},
|
|
297
|
-
|
|
298
|
-
* Get the native SandboxInstance for advanced usage
|
|
299
|
-
*/
|
|
300
|
-
getInstance: (sandbox) => {
|
|
301
|
-
return sandbox;
|
|
302
|
-
}
|
|
198
|
+
getInstance: (sandbox) => sandbox
|
|
303
199
|
}
|
|
304
200
|
}
|
|
305
201
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Beam Provider - Factory-based Implementation\n *\n * Containerized sandbox environments using the Beam platform.\n * Beam provides sandboxes with process management, filesystem access,\n * and port exposure capabilities.\n *\n * Features:\n * - Process execution via sandbox.exec()\n * - Code execution in Python, JavaScript\n * - Shell command execution\n * - Filesystem operations (shell-based + native listFiles)\n * - Dynamic port exposure for accessing sandbox services\n */\n\nimport { Sandbox, SandboxInstance, beamOpts, Image } from '@beamcloud/beam-js';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\nimport type {\n CodeResult,\n CommandResult,\n SandboxInfo,\n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\n/** Type alias for the runCommand function passed to filesystem methods */\ntype RunCommandFn = (sandbox: SandboxInstance, command: string, options?: RunCommandOptions) => Promise<CommandResult>;\n\n/**\n * Beam-specific configuration options\n */\nexport interface BeamConfig {\n /** Beam API token - if not provided, will fallback to BEAM_TOKEN environment variable */\n token?: string;\n /** Beam workspace ID - if not provided, will fallback to BEAM_WORKSPACE_ID environment variable */\n workspaceId?: string;\n /** Gateway URL for custom/staging environments */\n gatewayUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n/**\n * Configure the global beamOpts singleton before each SDK call.\n * Beam uses a global config pattern rather than per-call config.\n */\nfunction configureBeamOpts(config: BeamConfig): void {\n beamOpts.token = config.token || (typeof process !== 'undefined' && process.env?.BEAM_TOKEN) || '';\n beamOpts.workspaceId = config.workspaceId || (typeof process !== 'undefined' && process.env?.BEAM_WORKSPACE_ID) || '';\n if (config.gatewayUrl) {\n beamOpts.gatewayUrl = config.gatewayUrl;\n }\n if (config.timeout) {\n (beamOpts as any).timeout = config.timeout;\n }\n}\n\n/**\n * Shell-escape a string using single quotes (POSIX).\n */\nfunction shellEscape(arg: string): string {\n if (arg === '') return \"''\";\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/**\n * Detect Node parser/compile failures while avoiding runtime SyntaxError matches.\n */\nfunction isNodeParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('Unexpected token') ||\n output.includes('Unexpected identifier') ||\n output.includes('Unexpected end of input') ||\n output.includes('Invalid or unexpected token');\n\n const hasCompileContext =\n output.includes('[eval]') ||\n output.includes('makeContextifyScript') ||\n output.includes('compileScript') ||\n output.includes('wrapSafe');\n\n const hasRuntimeSyntaxSignature =\n output.includes('at JSON.parse') ||\n output.includes('JSON.parse (<anonymous>)') ||\n output.includes('in JSON at position');\n\n return hasSyntaxMarker && hasCompileContext && !hasRuntimeSyntaxSignature;\n}\n\n/**\n * Detect Python parser failures (syntax/indentation/tab) emitted by python -c.\n */\nfunction isPythonParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('IndentationError') ||\n output.includes('TabError');\n\n const hasStringFileContext = output.includes('File \"<string>\"');\n const hasRuntimeTraceback = output.includes('Traceback (most recent call last)');\n\n return hasSyntaxMarker && hasStringFileContext && !hasRuntimeTraceback;\n}\n\n/**\n * Detect parser/compile failures that should throw instead of returning CodeResult.\n */\nfunction isParserFailure(output: string, runtime: Runtime): boolean {\n if (!output.trim()) return false;\n\n if (runtime === 'node') {\n return isNodeParserFailure(output);\n }\n\n if (runtime === 'python') {\n return isPythonParserFailure(output);\n }\n\n return false;\n}\n\n/**\n * Create a Beam provider instance using the factory pattern\n *\n * Beam provides containerized sandbox environments with:\n * - Process management (exec, runCode)\n * - Filesystem access\n * - Dynamic port exposure\n * - Snapshot and image creation capabilities\n */\nexport const beam = defineProvider<SandboxInstance, BeamConfig>({\n name: 'beam',\n methods: {\n sandbox: {\n /**\n * Create a new Beam sandbox\n *\n * Uses Sandbox class from @beamcloud/beam-js to provision a container.\n */\n create: async (config: BeamConfig, options?: CreateSandboxOptions) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n throw new Error(\n `Missing Beam token. Provide 'token' in config or set BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n\n if (!beamOpts.workspaceId) {\n throw new Error(\n `Missing Beam workspace ID. Provide 'workspaceId' in config or set BEAM_WORKSPACE_ID environment variable.`\n );\n }\n\n try {\n // Destructure known ComputeSDK fields, collect the rest for passthrough\n const {\n runtime: optRuntime,\n timeout: optTimeout,\n envs,\n name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: _sandboxId,\n namespace: _namespace,\n directory: _directory,\n ...providerOptions\n } = options || {};\n\n const sandboxConfig: any = {\n name: name || `computesdk-${Date.now()}`,\n keepWarmSeconds: 300,\n ...providerOptions, // Spread provider-specific options\n };\n\n // options.timeout takes precedence over config.timeout\n const timeout = optTimeout ?? config.timeout;\n if (timeout) {\n sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1000);\n }\n\n if (optRuntime === 'node') {\n sandboxConfig.image = Image.fromRegistry('node:20-slim');\n }\n\n if (envs) {\n sandboxConfig.envVars = Object.entries(envs).map(([name, value]) => `${name}=${value}`);\n }\n\n const sandbox = new Sandbox(sandboxConfig);\n const instance = await sandbox.create();\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('401')) {\n throw new Error(\n `Beam authentication failed. Please check your BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n }\n throw new Error(\n `Failed to create Beam sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n /**\n * Connect to an existing Beam sandbox by ID\n *\n * Uses Sandbox.connect() to reconnect to a running sandbox.\n */\n getById: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n return null;\n }\n\n try {\n const instance = await Sandbox.connect(sandboxId);\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch {\n return null;\n }\n },\n\n /**\n * List all active Beam sandboxes\n *\n * Beam SDK has no sandbox list API; returns empty array.\n */\n list: async (_config: BeamConfig) => {\n return [];\n },\n\n /**\n * Destroy a Beam sandbox\n *\n * Connects to the sandbox and terminates it.\n */\n destroy: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n return;\n }\n\n try {\n const instance = await Sandbox.connect(sandboxId);\n await instance.terminate();\n } catch {\n // Sandbox might already be destroyed\n }\n },\n\n /**\n * Execute code in the sandbox\n *\n * Auto-detects runtime (Python vs Node.js) and executes via sandbox.exec().\n */\n\n /**\n * Execute a shell command in the sandbox\n *\n * Uses sandbox.exec() with shell command string.\n */\n runCommand: async (sandbox: SandboxInstance, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n let fullCommand = command;\n\n if (options?.env && Object.keys(options.env).length > 0) {\n const envPrefix = Object.entries(options.env)\n .map(([k, v]) => `${k}=\"${escapeShellArg(String(v))}\"`)\n .join(' ');\n fullCommand = `${envPrefix} ${fullCommand}`;\n }\n\n if (options?.cwd) {\n fullCommand = `cd \"${escapeShellArg(options.cwd)}\" && ${fullCommand}`;\n }\n\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n // Wrap in sh -c to get shell parsing (pipes, redirects, etc.)\n const proc = await sandbox.exec(['sh', '-c', fullCommand]);\n await proc.wait();\n const [stdoutStr, stderrStr] = await Promise.all([\n proc.stdout.read(),\n proc.stderr.read(),\n ]);\n\n return {\n stdout: stdoutStr || '',\n stderr: stderrStr || '',\n exitCode: proc.exitCode || 0,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n /**\n * Get sandbox information\n */\n getInfo: async (sandbox: SandboxInstance): Promise<SandboxInfo> => {\n // Derive runtime from sandbox instance if available; otherwise default to 'python'\n let runtime: Runtime = 'python';\n const runtimeHint = sandbox as SandboxInstance & {\n runtime?: unknown;\n image?: unknown;\n imageName?: unknown;\n };\n\n if (typeof runtimeHint.runtime === 'string') {\n const lower = runtimeHint.runtime.toLowerCase();\n if (lower.includes('node')) {\n runtime = 'node';\n } else if (lower.includes('python')) {\n runtime = 'python';\n }\n } else if (typeof runtimeHint.image === 'string') {\n const imageStr = runtimeHint.image.toLowerCase();\n if (imageStr.includes('node')) {\n runtime = 'node';\n } else if (imageStr.includes('python')) {\n runtime = 'python';\n }\n } else if (typeof runtimeHint.imageName === 'string') {\n const imageNameStr = runtimeHint.imageName.toLowerCase();\n if (imageNameStr.includes('node')) {\n runtime = 'node';\n } else if (imageNameStr.includes('python')) {\n runtime = 'python';\n }\n }\n\n return {\n id: sandbox.containerId,\n provider: 'beam',\n runtime,\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n containerId: sandbox.containerId,\n },\n };\n },\n\n /**\n * Get public URL for a specific port\n *\n * Uses sandbox.exposePort() to dynamically expose a port.\n */\n getUrl: async (sandbox: SandboxInstance, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n return await sandbox.exposePort(options.port);\n } catch (error) {\n throw new Error(\n `Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n /**\n * Filesystem operations\n *\n * Most operations use shell commands via runCommand since Beam's file API\n * is local-path oriented (uploadFile/downloadFile require local filesystem paths).\n * readdir uses the native listFiles API since it returns structured data.\n */\n filesystem: {\n readFile: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<string> => {\n const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to read file ${path}: ${result.stderr}`);\n }\n return result.stdout;\n },\n\n writeFile: async (sandbox: SandboxInstance, path: string, content: string, runCommand: RunCommandFn): Promise<void> => {\n const b64 = Buffer.from(content).toString('base64');\n const result = await runCommand(sandbox, `echo '${b64}' | base64 -d > ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to write file ${path}: ${result.stderr}`);\n }\n },\n\n mkdir: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox: SandboxInstance, path: string, _runCommand: RunCommandFn): Promise<FileEntry[]> => {\n const files = await sandbox.fs.listFiles(path);\n return files.map((file: any) => ({\n name: file.name,\n type: file.isDir ? 'directory' as const : 'file' as const,\n size: Number(file.size) || 0,\n modified: file.modTime ? new Date(file.modTime * 1000) : new Date(),\n }));\n },\n\n exists: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<boolean> => {\n const result = await runCommand(sandbox, `test -f ${shellEscape(path)} || test -d ${shellEscape(path)}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n /**\n * Get the native SandboxInstance for advanced usage\n */\n getInstance: (sandbox: SandboxInstance): SandboxInstance => {\n return sandbox;\n },\n },\n },\n});\n\n// Export Beam sandbox type for explicit typing\nexport type { SandboxInstance as BeamSandboxInstance } from '@beamcloud/beam-js';\n"],"mappings":"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","names":["name"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Beam Provider - Factory-based Implementation\n *\n * Containerized sandbox environments using the Beam platform.\n * Beam provides sandboxes with process management, filesystem access,\n * and port exposure capabilities.\n */\n\nimport { Sandbox, SandboxInstance, beamOpts, Image } from '@beamcloud/beam-js';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\nimport type {\n CommandResult,\n SandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\ntype RunCommandFn = (sandbox: SandboxInstance, command: string, options?: RunCommandOptions) => Promise<CommandResult>;\n\nexport interface BeamConfig {\n token?: string;\n workspaceId?: string;\n gatewayUrl?: string;\n timeout?: number;\n}\n\nfunction configureBeamOpts(config: BeamConfig): void {\n beamOpts.token = config.token || (typeof process !== 'undefined' && process.env?.BEAM_TOKEN) || '';\n beamOpts.workspaceId = config.workspaceId || (typeof process !== 'undefined' && process.env?.BEAM_WORKSPACE_ID) || '';\n if (config.gatewayUrl) beamOpts.gatewayUrl = config.gatewayUrl;\n if (config.timeout) (beamOpts as any).timeout = config.timeout;\n}\n\nfunction shellEscape(arg: string): string {\n if (arg === '') return \"''\";\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nfunction isNodeParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('Unexpected token') ||\n output.includes('Unexpected identifier') ||\n output.includes('Unexpected end of input') ||\n output.includes('Invalid or unexpected token');\n\n const hasCompileContext =\n output.includes('[eval]') ||\n output.includes('makeContextifyScript') ||\n output.includes('compileScript') ||\n output.includes('wrapSafe');\n\n const hasRuntimeSyntaxSignature =\n output.includes('at JSON.parse') ||\n output.includes('JSON.parse (<anonymous>)') ||\n output.includes('in JSON at position');\n\n return hasSyntaxMarker && hasCompileContext && !hasRuntimeSyntaxSignature;\n}\n\nfunction isPythonParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('IndentationError') ||\n output.includes('TabError');\n\n const hasStringFileContext = output.includes('File \"<string>\"');\n const hasRuntimeTraceback = output.includes('Traceback (most recent call last)');\n\n return hasSyntaxMarker && hasStringFileContext && !hasRuntimeTraceback;\n}\n\nfunction isParserFailure(output: string, runtime: string): boolean {\n if (!output.trim()) return false;\n if (runtime === 'node') return isNodeParserFailure(output);\n if (runtime === 'python') return isPythonParserFailure(output);\n return false;\n}\n\nexport const beam = defineProvider<SandboxInstance, BeamConfig>({\n name: 'beam',\n methods: {\n sandbox: {\n create: async (config: BeamConfig, options?: CreateSandboxOptions) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n throw new Error(\n `Missing Beam token. Provide 'token' in config or set BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n\n if (!beamOpts.workspaceId) {\n throw new Error(\n `Missing Beam workspace ID. Provide 'workspaceId' in config or set BEAM_WORKSPACE_ID environment variable.`\n );\n }\n\n try {\n const {\n timeout: optTimeout,\n envs,\n name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: _sandboxId,\n namespace: _namespace,\n directory: _directory,\n ...providerOptions\n } = options || {};\n\n const optRuntime = (options as any)?.runtime as string | undefined;\n\n const sandboxConfig: any = {\n name: name || `computesdk-${Date.now()}`,\n keepWarmSeconds: 300,\n ...providerOptions,\n };\n\n const timeout = optTimeout ?? config.timeout;\n if (timeout) sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1000);\n\n if (optRuntime === 'node') {\n sandboxConfig.image = Image.fromRegistry('node:20-slim');\n }\n\n if (envs) {\n sandboxConfig.envVars = Object.entries(envs).map(([name, value]) => `${name}=${value}`);\n }\n\n const sandbox = new Sandbox(sandboxConfig);\n const instance = await sandbox.create();\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch (error) {\n if (error instanceof Error && (error.message.includes('unauthorized') || error.message.includes('401'))) {\n throw new Error(\n `Beam authentication failed. Please check your BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n throw new Error(\n `Failed to create Beam sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n if (!beamOpts.token) return null;\n try {\n const instance = await Sandbox.connect(sandboxId);\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch { return null; }\n },\n\n list: async (_config: BeamConfig) => [],\n\n destroy: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n if (!beamOpts.token) return;\n try {\n const instance = await Sandbox.connect(sandboxId);\n await instance.terminate();\n } catch { /* Sandbox might already be destroyed */ }\n },\n\n runCommand: async (sandbox: SandboxInstance, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n let fullCommand = command;\n if (options?.env && Object.keys(options.env).length > 0) {\n const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}=\"${escapeShellArg(String(v))}\"`).join(' ');\n fullCommand = `${envPrefix} ${fullCommand}`;\n }\n if (options?.cwd) fullCommand = `cd \"${escapeShellArg(options.cwd)}\" && ${fullCommand}`;\n if (options?.background) fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n\n const proc = await sandbox.exec(['sh', '-c', fullCommand]);\n await proc.wait();\n const [stdoutStr, stderrStr] = await Promise.all([proc.stdout.read(), proc.stderr.read()]);\n return { stdout: stdoutStr || '', stderr: stderrStr || '', exitCode: proc.exitCode || 0, durationMs: Date.now() - startTime };\n } catch (error) {\n return { stdout: '', stderr: error instanceof Error ? error.message : String(error), exitCode: 127, durationMs: Date.now() - startTime };\n }\n },\n\n getInfo: async (sandbox: SandboxInstance): Promise<SandboxInfo> => {\n let runtime = 'python';\n const runtimeHint = sandbox as SandboxInstance & { runtime?: unknown; image?: unknown; imageName?: unknown };\n if (typeof runtimeHint.runtime === 'string') {\n const lower = runtimeHint.runtime.toLowerCase();\n if (lower.includes('node')) runtime = 'node';\n else if (lower.includes('python')) runtime = 'python';\n } else if (typeof runtimeHint.image === 'string') {\n const imageStr = runtimeHint.image.toLowerCase();\n if (imageStr.includes('node')) runtime = 'node';\n else if (imageStr.includes('python')) runtime = 'python';\n } else if (typeof runtimeHint.imageName === 'string') {\n const imageNameStr = runtimeHint.imageName.toLowerCase();\n if (imageNameStr.includes('node')) runtime = 'node';\n else if (imageNameStr.includes('python')) runtime = 'python';\n }\n return {\n id: sandbox.containerId,\n provider: 'beam',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: { containerId: sandbox.containerId, runtime },\n };\n },\n\n getUrl: async (sandbox: SandboxInstance, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n return await sandbox.exposePort(options.port);\n } catch (error) {\n throw new Error(`Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n filesystem: {\n readFile: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<string> => {\n const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to read file ${path}: ${result.stderr}`);\n return result.stdout;\n },\n writeFile: async (sandbox: SandboxInstance, path: string, content: string, runCommand: RunCommandFn): Promise<void> => {\n const b64 = Buffer.from(content).toString('base64');\n const result = await runCommand(sandbox, `echo '${b64}' | base64 -d > ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to write file ${path}: ${result.stderr}`);\n },\n mkdir: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n },\n readdir: async (sandbox: SandboxInstance, path: string, _runCommand: RunCommandFn): Promise<FileEntry[]> => {\n const files = await sandbox.fs.listFiles(path);\n return files.map((file: any) => ({\n name: file.name,\n type: file.isDir ? 'directory' as const : 'file' as const,\n size: Number(file.size) || 0,\n modified: file.modTime ? new Date(file.modTime * 1000) : new Date(),\n }));\n },\n exists: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<boolean> => {\n const result = await runCommand(sandbox, `test -f ${shellEscape(path)} || test -d ${shellEscape(path)}`);\n return result.exitCode === 0;\n },\n remove: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n },\n },\n\n getInstance: (sandbox: SandboxInstance): SandboxInstance => sandbox,\n },\n },\n});\n\nexport type { SandboxInstance as BeamSandboxInstance } from '@beamcloud/beam-js';\n"],"mappings":"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","names":["name"]}
|
package/dist/index.mjs
CHANGED
|
@@ -4,12 +4,8 @@ import { defineProvider, escapeShellArg } from "@computesdk/provider";
|
|
|
4
4
|
function configureBeamOpts(config) {
|
|
5
5
|
beamOpts.token = config.token || typeof process !== "undefined" && process.env?.BEAM_TOKEN || "";
|
|
6
6
|
beamOpts.workspaceId = config.workspaceId || typeof process !== "undefined" && process.env?.BEAM_WORKSPACE_ID || "";
|
|
7
|
-
if (config.gatewayUrl)
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
if (config.timeout) {
|
|
11
|
-
beamOpts.timeout = config.timeout;
|
|
12
|
-
}
|
|
7
|
+
if (config.gatewayUrl) beamOpts.gatewayUrl = config.gatewayUrl;
|
|
8
|
+
if (config.timeout) beamOpts.timeout = config.timeout;
|
|
13
9
|
}
|
|
14
10
|
function shellEscape(arg) {
|
|
15
11
|
if (arg === "") return "''";
|
|
@@ -19,11 +15,6 @@ var beam = defineProvider({
|
|
|
19
15
|
name: "beam",
|
|
20
16
|
methods: {
|
|
21
17
|
sandbox: {
|
|
22
|
-
/**
|
|
23
|
-
* Create a new Beam sandbox
|
|
24
|
-
*
|
|
25
|
-
* Uses Sandbox class from @beamcloud/beam-js to provision a container.
|
|
26
|
-
*/
|
|
27
18
|
create: async (config, options) => {
|
|
28
19
|
configureBeamOpts(config);
|
|
29
20
|
if (!beamOpts.token) {
|
|
@@ -38,7 +29,6 @@ var beam = defineProvider({
|
|
|
38
29
|
}
|
|
39
30
|
try {
|
|
40
31
|
const {
|
|
41
|
-
runtime: optRuntime,
|
|
42
32
|
timeout: optTimeout,
|
|
43
33
|
envs,
|
|
44
34
|
name,
|
|
@@ -50,16 +40,14 @@ var beam = defineProvider({
|
|
|
50
40
|
directory: _directory,
|
|
51
41
|
...providerOptions
|
|
52
42
|
} = options || {};
|
|
43
|
+
const optRuntime = options?.runtime;
|
|
53
44
|
const sandboxConfig = {
|
|
54
45
|
name: name || `computesdk-${Date.now()}`,
|
|
55
46
|
keepWarmSeconds: 300,
|
|
56
47
|
...providerOptions
|
|
57
|
-
// Spread provider-specific options
|
|
58
48
|
};
|
|
59
49
|
const timeout = optTimeout ?? config.timeout;
|
|
60
|
-
if (timeout)
|
|
61
|
-
sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1e3);
|
|
62
|
-
}
|
|
50
|
+
if (timeout) sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1e3);
|
|
63
51
|
if (optRuntime === "node") {
|
|
64
52
|
sandboxConfig.image = Image.fromRegistry("node:20-slim");
|
|
65
53
|
}
|
|
@@ -70,28 +58,19 @@ var beam = defineProvider({
|
|
|
70
58
|
const instance = await sandbox.create();
|
|
71
59
|
return { sandbox: instance, sandboxId: instance.containerId };
|
|
72
60
|
} catch (error) {
|
|
73
|
-
if (error instanceof Error) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
);
|
|
78
|
-
}
|
|
61
|
+
if (error instanceof Error && (error.message.includes("unauthorized") || error.message.includes("401"))) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`Beam authentication failed. Please check your BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`
|
|
64
|
+
);
|
|
79
65
|
}
|
|
80
66
|
throw new Error(
|
|
81
67
|
`Failed to create Beam sandbox: ${error instanceof Error ? error.message : String(error)}`
|
|
82
68
|
);
|
|
83
69
|
}
|
|
84
70
|
},
|
|
85
|
-
/**
|
|
86
|
-
* Connect to an existing Beam sandbox by ID
|
|
87
|
-
*
|
|
88
|
-
* Uses Sandbox.connect() to reconnect to a running sandbox.
|
|
89
|
-
*/
|
|
90
71
|
getById: async (config, sandboxId) => {
|
|
91
72
|
configureBeamOpts(config);
|
|
92
|
-
if (!beamOpts.token)
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
73
|
+
if (!beamOpts.token) return null;
|
|
95
74
|
try {
|
|
96
75
|
const instance = await Sandbox.connect(sandboxId);
|
|
97
76
|
return { sandbox: instance, sandboxId: instance.containerId };
|
|
@@ -99,40 +78,16 @@ var beam = defineProvider({
|
|
|
99
78
|
return null;
|
|
100
79
|
}
|
|
101
80
|
},
|
|
102
|
-
|
|
103
|
-
* List all active Beam sandboxes
|
|
104
|
-
*
|
|
105
|
-
* Beam SDK has no sandbox list API; returns empty array.
|
|
106
|
-
*/
|
|
107
|
-
list: async (_config) => {
|
|
108
|
-
return [];
|
|
109
|
-
},
|
|
110
|
-
/**
|
|
111
|
-
* Destroy a Beam sandbox
|
|
112
|
-
*
|
|
113
|
-
* Connects to the sandbox and terminates it.
|
|
114
|
-
*/
|
|
81
|
+
list: async (_config) => [],
|
|
115
82
|
destroy: async (config, sandboxId) => {
|
|
116
83
|
configureBeamOpts(config);
|
|
117
|
-
if (!beamOpts.token)
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
84
|
+
if (!beamOpts.token) return;
|
|
120
85
|
try {
|
|
121
86
|
const instance = await Sandbox.connect(sandboxId);
|
|
122
87
|
await instance.terminate();
|
|
123
88
|
} catch {
|
|
124
89
|
}
|
|
125
90
|
},
|
|
126
|
-
/**
|
|
127
|
-
* Execute code in the sandbox
|
|
128
|
-
*
|
|
129
|
-
* Auto-detects runtime (Python vs Node.js) and executes via sandbox.exec().
|
|
130
|
-
*/
|
|
131
|
-
/**
|
|
132
|
-
* Execute a shell command in the sandbox
|
|
133
|
-
*
|
|
134
|
-
* Uses sandbox.exec() with shell command string.
|
|
135
|
-
*/
|
|
136
91
|
runCommand: async (sandbox, command, options) => {
|
|
137
92
|
const startTime = Date.now();
|
|
138
93
|
try {
|
|
@@ -141,114 +96,62 @@ var beam = defineProvider({
|
|
|
141
96
|
const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}="${escapeShellArg(String(v))}"`).join(" ");
|
|
142
97
|
fullCommand = `${envPrefix} ${fullCommand}`;
|
|
143
98
|
}
|
|
144
|
-
if (options?.cwd) {
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
if (options?.background) {
|
|
148
|
-
fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
|
|
149
|
-
}
|
|
99
|
+
if (options?.cwd) fullCommand = `cd "${escapeShellArg(options.cwd)}" && ${fullCommand}`;
|
|
100
|
+
if (options?.background) fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
|
|
150
101
|
const proc = await sandbox.exec(["sh", "-c", fullCommand]);
|
|
151
102
|
await proc.wait();
|
|
152
|
-
const [stdoutStr, stderrStr] = await Promise.all([
|
|
153
|
-
|
|
154
|
-
proc.stderr.read()
|
|
155
|
-
]);
|
|
156
|
-
return {
|
|
157
|
-
stdout: stdoutStr || "",
|
|
158
|
-
stderr: stderrStr || "",
|
|
159
|
-
exitCode: proc.exitCode || 0,
|
|
160
|
-
durationMs: Date.now() - startTime
|
|
161
|
-
};
|
|
103
|
+
const [stdoutStr, stderrStr] = await Promise.all([proc.stdout.read(), proc.stderr.read()]);
|
|
104
|
+
return { stdout: stdoutStr || "", stderr: stderrStr || "", exitCode: proc.exitCode || 0, durationMs: Date.now() - startTime };
|
|
162
105
|
} catch (error) {
|
|
163
|
-
return {
|
|
164
|
-
stdout: "",
|
|
165
|
-
stderr: error instanceof Error ? error.message : String(error),
|
|
166
|
-
exitCode: 127,
|
|
167
|
-
durationMs: Date.now() - startTime
|
|
168
|
-
};
|
|
106
|
+
return { stdout: "", stderr: error instanceof Error ? error.message : String(error), exitCode: 127, durationMs: Date.now() - startTime };
|
|
169
107
|
}
|
|
170
108
|
},
|
|
171
|
-
/**
|
|
172
|
-
* Get sandbox information
|
|
173
|
-
*/
|
|
174
109
|
getInfo: async (sandbox) => {
|
|
175
110
|
let runtime = "python";
|
|
176
111
|
const runtimeHint = sandbox;
|
|
177
112
|
if (typeof runtimeHint.runtime === "string") {
|
|
178
113
|
const lower = runtimeHint.runtime.toLowerCase();
|
|
179
|
-
if (lower.includes("node"))
|
|
180
|
-
|
|
181
|
-
} else if (lower.includes("python")) {
|
|
182
|
-
runtime = "python";
|
|
183
|
-
}
|
|
114
|
+
if (lower.includes("node")) runtime = "node";
|
|
115
|
+
else if (lower.includes("python")) runtime = "python";
|
|
184
116
|
} else if (typeof runtimeHint.image === "string") {
|
|
185
117
|
const imageStr = runtimeHint.image.toLowerCase();
|
|
186
|
-
if (imageStr.includes("node"))
|
|
187
|
-
|
|
188
|
-
} else if (imageStr.includes("python")) {
|
|
189
|
-
runtime = "python";
|
|
190
|
-
}
|
|
118
|
+
if (imageStr.includes("node")) runtime = "node";
|
|
119
|
+
else if (imageStr.includes("python")) runtime = "python";
|
|
191
120
|
} else if (typeof runtimeHint.imageName === "string") {
|
|
192
121
|
const imageNameStr = runtimeHint.imageName.toLowerCase();
|
|
193
|
-
if (imageNameStr.includes("node"))
|
|
194
|
-
|
|
195
|
-
} else if (imageNameStr.includes("python")) {
|
|
196
|
-
runtime = "python";
|
|
197
|
-
}
|
|
122
|
+
if (imageNameStr.includes("node")) runtime = "node";
|
|
123
|
+
else if (imageNameStr.includes("python")) runtime = "python";
|
|
198
124
|
}
|
|
199
125
|
return {
|
|
200
126
|
id: sandbox.containerId,
|
|
201
127
|
provider: "beam",
|
|
202
|
-
runtime,
|
|
203
128
|
status: "running",
|
|
204
129
|
createdAt: /* @__PURE__ */ new Date(),
|
|
205
130
|
timeout: 3e5,
|
|
206
|
-
metadata: {
|
|
207
|
-
containerId: sandbox.containerId
|
|
208
|
-
}
|
|
131
|
+
metadata: { containerId: sandbox.containerId, runtime }
|
|
209
132
|
};
|
|
210
133
|
},
|
|
211
|
-
/**
|
|
212
|
-
* Get public URL for a specific port
|
|
213
|
-
*
|
|
214
|
-
* Uses sandbox.exposePort() to dynamically expose a port.
|
|
215
|
-
*/
|
|
216
134
|
getUrl: async (sandbox, options) => {
|
|
217
135
|
try {
|
|
218
136
|
return await sandbox.exposePort(options.port);
|
|
219
137
|
} catch (error) {
|
|
220
|
-
throw new Error(
|
|
221
|
-
`Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`
|
|
222
|
-
);
|
|
138
|
+
throw new Error(`Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`);
|
|
223
139
|
}
|
|
224
140
|
},
|
|
225
|
-
/**
|
|
226
|
-
* Filesystem operations
|
|
227
|
-
*
|
|
228
|
-
* Most operations use shell commands via runCommand since Beam's file API
|
|
229
|
-
* is local-path oriented (uploadFile/downloadFile require local filesystem paths).
|
|
230
|
-
* readdir uses the native listFiles API since it returns structured data.
|
|
231
|
-
*/
|
|
232
141
|
filesystem: {
|
|
233
142
|
readFile: async (sandbox, path, runCommand) => {
|
|
234
143
|
const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);
|
|
235
|
-
if (result.exitCode !== 0) {
|
|
236
|
-
throw new Error(`Failed to read file ${path}: ${result.stderr}`);
|
|
237
|
-
}
|
|
144
|
+
if (result.exitCode !== 0) throw new Error(`Failed to read file ${path}: ${result.stderr}`);
|
|
238
145
|
return result.stdout;
|
|
239
146
|
},
|
|
240
147
|
writeFile: async (sandbox, path, content, runCommand) => {
|
|
241
148
|
const b64 = Buffer.from(content).toString("base64");
|
|
242
149
|
const result = await runCommand(sandbox, `echo '${b64}' | base64 -d > ${shellEscape(path)}`);
|
|
243
|
-
if (result.exitCode !== 0) {
|
|
244
|
-
throw new Error(`Failed to write file ${path}: ${result.stderr}`);
|
|
245
|
-
}
|
|
150
|
+
if (result.exitCode !== 0) throw new Error(`Failed to write file ${path}: ${result.stderr}`);
|
|
246
151
|
},
|
|
247
152
|
mkdir: async (sandbox, path, runCommand) => {
|
|
248
153
|
const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);
|
|
249
|
-
if (result.exitCode !== 0) {
|
|
250
|
-
throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
|
|
251
|
-
}
|
|
154
|
+
if (result.exitCode !== 0) throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
|
|
252
155
|
},
|
|
253
156
|
readdir: async (sandbox, path, _runCommand) => {
|
|
254
157
|
const files = await sandbox.fs.listFiles(path);
|
|
@@ -265,17 +168,10 @@ var beam = defineProvider({
|
|
|
265
168
|
},
|
|
266
169
|
remove: async (sandbox, path, runCommand) => {
|
|
267
170
|
const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);
|
|
268
|
-
if (result.exitCode !== 0) {
|
|
269
|
-
throw new Error(`Failed to remove ${path}: ${result.stderr}`);
|
|
270
|
-
}
|
|
171
|
+
if (result.exitCode !== 0) throw new Error(`Failed to remove ${path}: ${result.stderr}`);
|
|
271
172
|
}
|
|
272
173
|
},
|
|
273
|
-
|
|
274
|
-
* Get the native SandboxInstance for advanced usage
|
|
275
|
-
*/
|
|
276
|
-
getInstance: (sandbox) => {
|
|
277
|
-
return sandbox;
|
|
278
|
-
}
|
|
174
|
+
getInstance: (sandbox) => sandbox
|
|
279
175
|
}
|
|
280
176
|
}
|
|
281
177
|
});
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Beam Provider - Factory-based Implementation\n *\n * Containerized sandbox environments using the Beam platform.\n * Beam provides sandboxes with process management, filesystem access,\n * and port exposure capabilities.\n *\n * Features:\n * - Process execution via sandbox.exec()\n * - Code execution in Python, JavaScript\n * - Shell command execution\n * - Filesystem operations (shell-based + native listFiles)\n * - Dynamic port exposure for accessing sandbox services\n */\n\nimport { Sandbox, SandboxInstance, beamOpts, Image } from '@beamcloud/beam-js';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\nimport type {\n CodeResult,\n CommandResult,\n SandboxInfo,\n Runtime,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\n/** Type alias for the runCommand function passed to filesystem methods */\ntype RunCommandFn = (sandbox: SandboxInstance, command: string, options?: RunCommandOptions) => Promise<CommandResult>;\n\n/**\n * Beam-specific configuration options\n */\nexport interface BeamConfig {\n /** Beam API token - if not provided, will fallback to BEAM_TOKEN environment variable */\n token?: string;\n /** Beam workspace ID - if not provided, will fallback to BEAM_WORKSPACE_ID environment variable */\n workspaceId?: string;\n /** Gateway URL for custom/staging environments */\n gatewayUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n/**\n * Configure the global beamOpts singleton before each SDK call.\n * Beam uses a global config pattern rather than per-call config.\n */\nfunction configureBeamOpts(config: BeamConfig): void {\n beamOpts.token = config.token || (typeof process !== 'undefined' && process.env?.BEAM_TOKEN) || '';\n beamOpts.workspaceId = config.workspaceId || (typeof process !== 'undefined' && process.env?.BEAM_WORKSPACE_ID) || '';\n if (config.gatewayUrl) {\n beamOpts.gatewayUrl = config.gatewayUrl;\n }\n if (config.timeout) {\n (beamOpts as any).timeout = config.timeout;\n }\n}\n\n/**\n * Shell-escape a string using single quotes (POSIX).\n */\nfunction shellEscape(arg: string): string {\n if (arg === '') return \"''\";\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n\n/**\n * Detect Node parser/compile failures while avoiding runtime SyntaxError matches.\n */\nfunction isNodeParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('Unexpected token') ||\n output.includes('Unexpected identifier') ||\n output.includes('Unexpected end of input') ||\n output.includes('Invalid or unexpected token');\n\n const hasCompileContext =\n output.includes('[eval]') ||\n output.includes('makeContextifyScript') ||\n output.includes('compileScript') ||\n output.includes('wrapSafe');\n\n const hasRuntimeSyntaxSignature =\n output.includes('at JSON.parse') ||\n output.includes('JSON.parse (<anonymous>)') ||\n output.includes('in JSON at position');\n\n return hasSyntaxMarker && hasCompileContext && !hasRuntimeSyntaxSignature;\n}\n\n/**\n * Detect Python parser failures (syntax/indentation/tab) emitted by python -c.\n */\nfunction isPythonParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('IndentationError') ||\n output.includes('TabError');\n\n const hasStringFileContext = output.includes('File \"<string>\"');\n const hasRuntimeTraceback = output.includes('Traceback (most recent call last)');\n\n return hasSyntaxMarker && hasStringFileContext && !hasRuntimeTraceback;\n}\n\n/**\n * Detect parser/compile failures that should throw instead of returning CodeResult.\n */\nfunction isParserFailure(output: string, runtime: Runtime): boolean {\n if (!output.trim()) return false;\n\n if (runtime === 'node') {\n return isNodeParserFailure(output);\n }\n\n if (runtime === 'python') {\n return isPythonParserFailure(output);\n }\n\n return false;\n}\n\n/**\n * Create a Beam provider instance using the factory pattern\n *\n * Beam provides containerized sandbox environments with:\n * - Process management (exec, runCode)\n * - Filesystem access\n * - Dynamic port exposure\n * - Snapshot and image creation capabilities\n */\nexport const beam = defineProvider<SandboxInstance, BeamConfig>({\n name: 'beam',\n methods: {\n sandbox: {\n /**\n * Create a new Beam sandbox\n *\n * Uses Sandbox class from @beamcloud/beam-js to provision a container.\n */\n create: async (config: BeamConfig, options?: CreateSandboxOptions) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n throw new Error(\n `Missing Beam token. Provide 'token' in config or set BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n\n if (!beamOpts.workspaceId) {\n throw new Error(\n `Missing Beam workspace ID. Provide 'workspaceId' in config or set BEAM_WORKSPACE_ID environment variable.`\n );\n }\n\n try {\n // Destructure known ComputeSDK fields, collect the rest for passthrough\n const {\n runtime: optRuntime,\n timeout: optTimeout,\n envs,\n name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: _sandboxId,\n namespace: _namespace,\n directory: _directory,\n ...providerOptions\n } = options || {};\n\n const sandboxConfig: any = {\n name: name || `computesdk-${Date.now()}`,\n keepWarmSeconds: 300,\n ...providerOptions, // Spread provider-specific options\n };\n\n // options.timeout takes precedence over config.timeout\n const timeout = optTimeout ?? config.timeout;\n if (timeout) {\n sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1000);\n }\n\n if (optRuntime === 'node') {\n sandboxConfig.image = Image.fromRegistry('node:20-slim');\n }\n\n if (envs) {\n sandboxConfig.envVars = Object.entries(envs).map(([name, value]) => `${name}=${value}`);\n }\n\n const sandbox = new Sandbox(sandboxConfig);\n const instance = await sandbox.create();\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('401')) {\n throw new Error(\n `Beam authentication failed. Please check your BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n }\n throw new Error(\n `Failed to create Beam sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n /**\n * Connect to an existing Beam sandbox by ID\n *\n * Uses Sandbox.connect() to reconnect to a running sandbox.\n */\n getById: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n return null;\n }\n\n try {\n const instance = await Sandbox.connect(sandboxId);\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch {\n return null;\n }\n },\n\n /**\n * List all active Beam sandboxes\n *\n * Beam SDK has no sandbox list API; returns empty array.\n */\n list: async (_config: BeamConfig) => {\n return [];\n },\n\n /**\n * Destroy a Beam sandbox\n *\n * Connects to the sandbox and terminates it.\n */\n destroy: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n return;\n }\n\n try {\n const instance = await Sandbox.connect(sandboxId);\n await instance.terminate();\n } catch {\n // Sandbox might already be destroyed\n }\n },\n\n /**\n * Execute code in the sandbox\n *\n * Auto-detects runtime (Python vs Node.js) and executes via sandbox.exec().\n */\n\n /**\n * Execute a shell command in the sandbox\n *\n * Uses sandbox.exec() with shell command string.\n */\n runCommand: async (sandbox: SandboxInstance, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n let fullCommand = command;\n\n if (options?.env && Object.keys(options.env).length > 0) {\n const envPrefix = Object.entries(options.env)\n .map(([k, v]) => `${k}=\"${escapeShellArg(String(v))}\"`)\n .join(' ');\n fullCommand = `${envPrefix} ${fullCommand}`;\n }\n\n if (options?.cwd) {\n fullCommand = `cd \"${escapeShellArg(options.cwd)}\" && ${fullCommand}`;\n }\n\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n // Wrap in sh -c to get shell parsing (pipes, redirects, etc.)\n const proc = await sandbox.exec(['sh', '-c', fullCommand]);\n await proc.wait();\n const [stdoutStr, stderrStr] = await Promise.all([\n proc.stdout.read(),\n proc.stderr.read(),\n ]);\n\n return {\n stdout: stdoutStr || '',\n stderr: stderrStr || '',\n exitCode: proc.exitCode || 0,\n durationMs: Date.now() - startTime,\n };\n } catch (error) {\n return {\n stdout: '',\n stderr: error instanceof Error ? error.message : String(error),\n exitCode: 127,\n durationMs: Date.now() - startTime,\n };\n }\n },\n\n /**\n * Get sandbox information\n */\n getInfo: async (sandbox: SandboxInstance): Promise<SandboxInfo> => {\n // Derive runtime from sandbox instance if available; otherwise default to 'python'\n let runtime: Runtime = 'python';\n const runtimeHint = sandbox as SandboxInstance & {\n runtime?: unknown;\n image?: unknown;\n imageName?: unknown;\n };\n\n if (typeof runtimeHint.runtime === 'string') {\n const lower = runtimeHint.runtime.toLowerCase();\n if (lower.includes('node')) {\n runtime = 'node';\n } else if (lower.includes('python')) {\n runtime = 'python';\n }\n } else if (typeof runtimeHint.image === 'string') {\n const imageStr = runtimeHint.image.toLowerCase();\n if (imageStr.includes('node')) {\n runtime = 'node';\n } else if (imageStr.includes('python')) {\n runtime = 'python';\n }\n } else if (typeof runtimeHint.imageName === 'string') {\n const imageNameStr = runtimeHint.imageName.toLowerCase();\n if (imageNameStr.includes('node')) {\n runtime = 'node';\n } else if (imageNameStr.includes('python')) {\n runtime = 'python';\n }\n }\n\n return {\n id: sandbox.containerId,\n provider: 'beam',\n runtime,\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n containerId: sandbox.containerId,\n },\n };\n },\n\n /**\n * Get public URL for a specific port\n *\n * Uses sandbox.exposePort() to dynamically expose a port.\n */\n getUrl: async (sandbox: SandboxInstance, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n return await sandbox.exposePort(options.port);\n } catch (error) {\n throw new Error(\n `Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n /**\n * Filesystem operations\n *\n * Most operations use shell commands via runCommand since Beam's file API\n * is local-path oriented (uploadFile/downloadFile require local filesystem paths).\n * readdir uses the native listFiles API since it returns structured data.\n */\n filesystem: {\n readFile: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<string> => {\n const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to read file ${path}: ${result.stderr}`);\n }\n return result.stdout;\n },\n\n writeFile: async (sandbox: SandboxInstance, path: string, content: string, runCommand: RunCommandFn): Promise<void> => {\n const b64 = Buffer.from(content).toString('base64');\n const result = await runCommand(sandbox, `echo '${b64}' | base64 -d > ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to write file ${path}: ${result.stderr}`);\n }\n },\n\n mkdir: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n }\n },\n\n readdir: async (sandbox: SandboxInstance, path: string, _runCommand: RunCommandFn): Promise<FileEntry[]> => {\n const files = await sandbox.fs.listFiles(path);\n return files.map((file: any) => ({\n name: file.name,\n type: file.isDir ? 'directory' as const : 'file' as const,\n size: Number(file.size) || 0,\n modified: file.modTime ? new Date(file.modTime * 1000) : new Date(),\n }));\n },\n\n exists: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<boolean> => {\n const result = await runCommand(sandbox, `test -f ${shellEscape(path)} || test -d ${shellEscape(path)}`);\n return result.exitCode === 0;\n },\n\n remove: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);\n if (result.exitCode !== 0) {\n throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n }\n },\n },\n\n /**\n * Get the native SandboxInstance for advanced usage\n */\n getInstance: (sandbox: SandboxInstance): SandboxInstance => {\n return sandbox;\n },\n },\n },\n});\n\n// Export Beam sandbox type for explicit typing\nexport type { SandboxInstance as BeamSandboxInstance } from '@beamcloud/beam-js';\n"],"mappings":"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","names":["name"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Beam Provider - Factory-based Implementation\n *\n * Containerized sandbox environments using the Beam platform.\n * Beam provides sandboxes with process management, filesystem access,\n * and port exposure capabilities.\n */\n\nimport { Sandbox, SandboxInstance, beamOpts, Image } from '@beamcloud/beam-js';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\nimport type {\n CommandResult,\n SandboxInfo,\n CreateSandboxOptions,\n FileEntry,\n RunCommandOptions,\n} from 'computesdk';\n\ntype RunCommandFn = (sandbox: SandboxInstance, command: string, options?: RunCommandOptions) => Promise<CommandResult>;\n\nexport interface BeamConfig {\n token?: string;\n workspaceId?: string;\n gatewayUrl?: string;\n timeout?: number;\n}\n\nfunction configureBeamOpts(config: BeamConfig): void {\n beamOpts.token = config.token || (typeof process !== 'undefined' && process.env?.BEAM_TOKEN) || '';\n beamOpts.workspaceId = config.workspaceId || (typeof process !== 'undefined' && process.env?.BEAM_WORKSPACE_ID) || '';\n if (config.gatewayUrl) beamOpts.gatewayUrl = config.gatewayUrl;\n if (config.timeout) (beamOpts as any).timeout = config.timeout;\n}\n\nfunction shellEscape(arg: string): string {\n if (arg === '') return \"''\";\n return `'${arg.replace(/'/g, \"'\\\\''\")}'`;\n}\n\nfunction isNodeParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('Unexpected token') ||\n output.includes('Unexpected identifier') ||\n output.includes('Unexpected end of input') ||\n output.includes('Invalid or unexpected token');\n\n const hasCompileContext =\n output.includes('[eval]') ||\n output.includes('makeContextifyScript') ||\n output.includes('compileScript') ||\n output.includes('wrapSafe');\n\n const hasRuntimeSyntaxSignature =\n output.includes('at JSON.parse') ||\n output.includes('JSON.parse (<anonymous>)') ||\n output.includes('in JSON at position');\n\n return hasSyntaxMarker && hasCompileContext && !hasRuntimeSyntaxSignature;\n}\n\nfunction isPythonParserFailure(output: string): boolean {\n const hasSyntaxMarker =\n output.includes('SyntaxError') ||\n output.includes('IndentationError') ||\n output.includes('TabError');\n\n const hasStringFileContext = output.includes('File \"<string>\"');\n const hasRuntimeTraceback = output.includes('Traceback (most recent call last)');\n\n return hasSyntaxMarker && hasStringFileContext && !hasRuntimeTraceback;\n}\n\nfunction isParserFailure(output: string, runtime: string): boolean {\n if (!output.trim()) return false;\n if (runtime === 'node') return isNodeParserFailure(output);\n if (runtime === 'python') return isPythonParserFailure(output);\n return false;\n}\n\nexport const beam = defineProvider<SandboxInstance, BeamConfig>({\n name: 'beam',\n methods: {\n sandbox: {\n create: async (config: BeamConfig, options?: CreateSandboxOptions) => {\n configureBeamOpts(config);\n\n if (!beamOpts.token) {\n throw new Error(\n `Missing Beam token. Provide 'token' in config or set BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n\n if (!beamOpts.workspaceId) {\n throw new Error(\n `Missing Beam workspace ID. Provide 'workspaceId' in config or set BEAM_WORKSPACE_ID environment variable.`\n );\n }\n\n try {\n const {\n timeout: optTimeout,\n envs,\n name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: _sandboxId,\n namespace: _namespace,\n directory: _directory,\n ...providerOptions\n } = options || {};\n\n const optRuntime = (options as any)?.runtime as string | undefined;\n\n const sandboxConfig: any = {\n name: name || `computesdk-${Date.now()}`,\n keepWarmSeconds: 300,\n ...providerOptions,\n };\n\n const timeout = optTimeout ?? config.timeout;\n if (timeout) sandboxConfig.keepWarmSeconds = Math.ceil(timeout / 1000);\n\n if (optRuntime === 'node') {\n sandboxConfig.image = Image.fromRegistry('node:20-slim');\n }\n\n if (envs) {\n sandboxConfig.envVars = Object.entries(envs).map(([name, value]) => `${name}=${value}`);\n }\n\n const sandbox = new Sandbox(sandboxConfig);\n const instance = await sandbox.create();\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch (error) {\n if (error instanceof Error && (error.message.includes('unauthorized') || error.message.includes('401'))) {\n throw new Error(\n `Beam authentication failed. Please check your BEAM_TOKEN environment variable. Get your token from https://app.beam.cloud`\n );\n }\n throw new Error(\n `Failed to create Beam sandbox: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n },\n\n getById: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n if (!beamOpts.token) return null;\n try {\n const instance = await Sandbox.connect(sandboxId);\n return { sandbox: instance, sandboxId: instance.containerId };\n } catch { return null; }\n },\n\n list: async (_config: BeamConfig) => [],\n\n destroy: async (config: BeamConfig, sandboxId: string) => {\n configureBeamOpts(config);\n if (!beamOpts.token) return;\n try {\n const instance = await Sandbox.connect(sandboxId);\n await instance.terminate();\n } catch { /* Sandbox might already be destroyed */ }\n },\n\n runCommand: async (sandbox: SandboxInstance, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n let fullCommand = command;\n if (options?.env && Object.keys(options.env).length > 0) {\n const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}=\"${escapeShellArg(String(v))}\"`).join(' ');\n fullCommand = `${envPrefix} ${fullCommand}`;\n }\n if (options?.cwd) fullCommand = `cd \"${escapeShellArg(options.cwd)}\" && ${fullCommand}`;\n if (options?.background) fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n\n const proc = await sandbox.exec(['sh', '-c', fullCommand]);\n await proc.wait();\n const [stdoutStr, stderrStr] = await Promise.all([proc.stdout.read(), proc.stderr.read()]);\n return { stdout: stdoutStr || '', stderr: stderrStr || '', exitCode: proc.exitCode || 0, durationMs: Date.now() - startTime };\n } catch (error) {\n return { stdout: '', stderr: error instanceof Error ? error.message : String(error), exitCode: 127, durationMs: Date.now() - startTime };\n }\n },\n\n getInfo: async (sandbox: SandboxInstance): Promise<SandboxInfo> => {\n let runtime = 'python';\n const runtimeHint = sandbox as SandboxInstance & { runtime?: unknown; image?: unknown; imageName?: unknown };\n if (typeof runtimeHint.runtime === 'string') {\n const lower = runtimeHint.runtime.toLowerCase();\n if (lower.includes('node')) runtime = 'node';\n else if (lower.includes('python')) runtime = 'python';\n } else if (typeof runtimeHint.image === 'string') {\n const imageStr = runtimeHint.image.toLowerCase();\n if (imageStr.includes('node')) runtime = 'node';\n else if (imageStr.includes('python')) runtime = 'python';\n } else if (typeof runtimeHint.imageName === 'string') {\n const imageNameStr = runtimeHint.imageName.toLowerCase();\n if (imageNameStr.includes('node')) runtime = 'node';\n else if (imageNameStr.includes('python')) runtime = 'python';\n }\n return {\n id: sandbox.containerId,\n provider: 'beam',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: { containerId: sandbox.containerId, runtime },\n };\n },\n\n getUrl: async (sandbox: SandboxInstance, options: { port: number; protocol?: string }): Promise<string> => {\n try {\n return await sandbox.exposePort(options.port);\n } catch (error) {\n throw new Error(`Failed to get Beam URL for port ${options.port}: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n filesystem: {\n readFile: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<string> => {\n const result = await runCommand(sandbox, `cat ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to read file ${path}: ${result.stderr}`);\n return result.stdout;\n },\n writeFile: async (sandbox: SandboxInstance, path: string, content: string, runCommand: RunCommandFn): Promise<void> => {\n const b64 = Buffer.from(content).toString('base64');\n const result = await runCommand(sandbox, `echo '${b64}' | base64 -d > ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to write file ${path}: ${result.stderr}`);\n },\n mkdir: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `mkdir -p ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to create directory ${path}: ${result.stderr}`);\n },\n readdir: async (sandbox: SandboxInstance, path: string, _runCommand: RunCommandFn): Promise<FileEntry[]> => {\n const files = await sandbox.fs.listFiles(path);\n return files.map((file: any) => ({\n name: file.name,\n type: file.isDir ? 'directory' as const : 'file' as const,\n size: Number(file.size) || 0,\n modified: file.modTime ? new Date(file.modTime * 1000) : new Date(),\n }));\n },\n exists: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<boolean> => {\n const result = await runCommand(sandbox, `test -f ${shellEscape(path)} || test -d ${shellEscape(path)}`);\n return result.exitCode === 0;\n },\n remove: async (sandbox: SandboxInstance, path: string, runCommand: RunCommandFn): Promise<void> => {\n const result = await runCommand(sandbox, `rm -rf ${shellEscape(path)}`);\n if (result.exitCode !== 0) throw new Error(`Failed to remove ${path}: ${result.stderr}`);\n },\n },\n\n getInstance: (sandbox: SandboxInstance): SandboxInstance => sandbox,\n },\n },\n});\n\nexport type { SandboxInstance as BeamSandboxInstance } from '@beamcloud/beam-js';\n"],"mappings":"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","names":["name"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@computesdk/beam",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Beam provider for ComputeSDK - containerized sandbox environments with process management and filesystem access",
|
|
5
5
|
"author": "ComputeSDK",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@beamcloud/beam-js": "1.0.0-rc.30",
|
|
22
|
-
"computesdk": "
|
|
23
|
-
"@computesdk/provider": "1.
|
|
22
|
+
"computesdk": "4.1.0",
|
|
23
|
+
"@computesdk/provider": "2.1.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^20.0.0",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"tsup": "^8.0.0",
|
|
31
31
|
"typescript": "^5.0.0",
|
|
32
32
|
"vitest": "^1.0.0",
|
|
33
|
-
"@computesdk/test-utils": "
|
|
33
|
+
"@computesdk/test-utils": "2.0.0"
|
|
34
34
|
},
|
|
35
35
|
"keywords": [
|
|
36
36
|
"computesdk",
|