@computesdk/cloudflare 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -26,6 +26,8 @@ interface CloudflareSandbox {
26
26
  remote: boolean;
27
27
  sandboxUrl?: string;
28
28
  sandboxSecret?: string;
29
+ pendingEnvVars?: Record<string, string>;
30
+ remoteInitialized?: boolean;
29
31
  sandbox?: any;
30
32
  }
31
33
  declare const cloudflare: (config: CloudflareConfig) => _computesdk_provider.Provider<CloudflareSandbox, any, any>;
package/dist/index.d.ts CHANGED
@@ -26,6 +26,8 @@ interface CloudflareSandbox {
26
26
  remote: boolean;
27
27
  sandboxUrl?: string;
28
28
  sandboxSecret?: string;
29
+ pendingEnvVars?: Record<string, string>;
30
+ remoteInitialized?: boolean;
29
31
  sandbox?: any;
30
32
  }
31
33
  declare const cloudflare: (config: CloudflareConfig) => _computesdk_provider.Provider<CloudflareSandbox, any, any>;
package/dist/index.js CHANGED
@@ -68,6 +68,9 @@ function runtimeToLanguage(runtime) {
68
68
  return "python";
69
69
  }
70
70
  }
71
+ function createSandboxId() {
72
+ return `cf-sandbox-${crypto.randomUUID()}`;
73
+ }
71
74
  async function workerRequest(cfSandbox, path, body = {}) {
72
75
  const res = await fetch(`${cfSandbox.sandboxUrl}${path}`, {
73
76
  method: "POST",
@@ -89,6 +92,17 @@ async function workerRequest(cfSandbox, path, body = {}) {
89
92
  }
90
93
  return data;
91
94
  }
95
+ async function workerRequestWithInit(cfSandbox, path, body = {}) {
96
+ if (!cfSandbox.remote || cfSandbox.remoteInitialized) {
97
+ return workerRequest(cfSandbox, path, body);
98
+ }
99
+ const initEnvVars = cfSandbox.pendingEnvVars;
100
+ const requestBody = initEnvVars && Object.keys(initEnvVars).length > 0 ? { ...body, initEnvVars } : body;
101
+ const data = await workerRequest(cfSandbox, path, requestBody);
102
+ cfSandbox.pendingEnvVars = void 0;
103
+ cfSandbox.remoteInitialized = true;
104
+ return data;
105
+ }
92
106
  function shellEscape(s) {
93
107
  return s.replace(/["$`\\!]/g, "\\$&");
94
108
  }
@@ -158,26 +172,19 @@ var cloudflare = (0, import_provider.defineProvider)({
158
172
  ports: _ports,
159
173
  ...rest
160
174
  } = options || {};
161
- const sandboxId = optSandboxId || `cf-sandbox-${Date.now()}`;
175
+ const sandboxId = optSandboxId || createSandboxId();
162
176
  const envVars = { ...config.envVars, ...envs };
163
177
  const timeout = optTimeout ?? config.timeout;
178
+ const sleepAfter = timeout ? `${Math.ceil(timeout / 1e3)}s` : void 0;
164
179
  if (isRemote(config)) {
165
- await workerRequest(
166
- { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: /* @__PURE__ */ new Map() },
167
- "/v1/sandbox/create",
168
- {
169
- envVars: Object.keys(envVars).length > 0 ? envVars : void 0,
170
- ...timeout ? { timeout } : {},
171
- ...rest
172
- // Pass through provider-specific options
173
- }
174
- );
175
180
  return {
176
181
  sandbox: {
177
182
  sandboxId,
178
183
  remote: true,
179
184
  sandboxUrl: config.sandboxUrl,
180
185
  sandboxSecret: config.sandboxSecret,
186
+ pendingEnvVars: Object.keys(envVars).length > 0 ? envVars : void 0,
187
+ remoteInitialized: false,
181
188
  exposedPorts: /* @__PURE__ */ new Map()
182
189
  },
183
190
  sandboxId
@@ -189,7 +196,11 @@ var cloudflare = (0, import_provider.defineProvider)({
189
196
  );
190
197
  }
191
198
  try {
192
- const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);
199
+ const sandboxOpts = { ...config.sandboxOptions };
200
+ if (sleepAfter) {
201
+ sandboxOpts.sleepAfter = sleepAfter;
202
+ }
203
+ const sandbox = await getSandbox(config.sandboxBinding, sandboxId, sandboxOpts);
193
204
  if (Object.keys(envVars).length > 0) {
194
205
  await sandbox.setEnvVars(envVars);
195
206
  }
@@ -224,6 +235,7 @@ var cloudflare = (0, import_provider.defineProvider)({
224
235
  remote: true,
225
236
  sandboxUrl: config.sandboxUrl,
226
237
  sandboxSecret: config.sandboxSecret,
238
+ remoteInitialized: true,
227
239
  exposedPorts: /* @__PURE__ */ new Map()
228
240
  };
229
241
  await workerRequest(cfSandbox, "/v1/sandbox/exec", { command: "true" });
@@ -270,7 +282,7 @@ var cloudflare = (0, import_provider.defineProvider)({
270
282
  const detectedRuntime = runtime || detectRuntime(code);
271
283
  const language = runtimeToLanguage(detectedRuntime);
272
284
  if (cfSandbox.remote) {
273
- const execution = await workerRequest(cfSandbox, "/v1/sandbox/runCode", { code, language });
285
+ const execution = await workerRequestWithInit(cfSandbox, "/v1/sandbox/runCode", { code, language });
274
286
  return processExecution(execution, detectedRuntime);
275
287
  }
276
288
  try {
@@ -289,7 +301,7 @@ var cloudflare = (0, import_provider.defineProvider)({
289
301
  if (options?.background) {
290
302
  fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
291
303
  }
292
- const result = await workerRequest(cfSandbox, "/v1/sandbox/exec", {
304
+ const result = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exec", {
293
305
  command: fullCommand,
294
306
  cwd: options?.cwd,
295
307
  env: options?.env,
@@ -338,7 +350,7 @@ var cloudflare = (0, import_provider.defineProvider)({
338
350
  getInfo: async (cfSandbox) => {
339
351
  try {
340
352
  if (cfSandbox.remote) {
341
- await workerRequest(cfSandbox, "/v1/sandbox/info");
353
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/info");
342
354
  } else {
343
355
  await cfSandbox.sandbox.exec("true");
344
356
  }
@@ -377,7 +389,7 @@ var cloudflare = (0, import_provider.defineProvider)({
377
389
  }
378
390
  let preview;
379
391
  if (cfSandbox.remote) {
380
- preview = await workerRequest(cfSandbox, "/v1/sandbox/exposePort", { port, options: {} });
392
+ preview = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exposePort", { port, options: {} });
381
393
  } else {
382
394
  preview = await cfSandbox.sandbox.exposePort(port, {});
383
395
  }
@@ -389,7 +401,7 @@ var cloudflare = (0, import_provider.defineProvider)({
389
401
  filesystem: {
390
402
  readFile: async (cfSandbox, path) => {
391
403
  if (cfSandbox.remote) {
392
- const file2 = await workerRequest(cfSandbox, "/v1/sandbox/readFile", { path });
404
+ const file2 = await workerRequestWithInit(cfSandbox, "/v1/sandbox/readFile", { path });
393
405
  return file2.content || "";
394
406
  }
395
407
  const file = await cfSandbox.sandbox.readFile(path);
@@ -397,14 +409,14 @@ var cloudflare = (0, import_provider.defineProvider)({
397
409
  },
398
410
  writeFile: async (cfSandbox, path, content) => {
399
411
  if (cfSandbox.remote) {
400
- await workerRequest(cfSandbox, "/v1/sandbox/writeFile", { path, content });
412
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/writeFile", { path, content });
401
413
  return;
402
414
  }
403
415
  await cfSandbox.sandbox.writeFile(path, content);
404
416
  },
405
417
  mkdir: async (cfSandbox, path) => {
406
418
  if (cfSandbox.remote) {
407
- await workerRequest(cfSandbox, "/v1/sandbox/mkdir", { path });
419
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/mkdir", { path });
408
420
  return;
409
421
  }
410
422
  await cfSandbox.sandbox.mkdir(path, { recursive: true });
@@ -412,7 +424,7 @@ var cloudflare = (0, import_provider.defineProvider)({
412
424
  readdir: async (cfSandbox, path) => {
413
425
  let result;
414
426
  if (cfSandbox.remote) {
415
- result = await workerRequest(cfSandbox, "/v1/sandbox/exec", {
427
+ result = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exec", {
416
428
  command: `ls -la "${shellEscape(path)}"`,
417
429
  cwd: "/"
418
430
  });
@@ -426,7 +438,7 @@ var cloudflare = (0, import_provider.defineProvider)({
426
438
  },
427
439
  exists: async (cfSandbox, path) => {
428
440
  if (cfSandbox.remote) {
429
- const result2 = await workerRequest(cfSandbox, "/v1/sandbox/exists", { path });
441
+ const result2 = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exists", { path });
430
442
  return result2.exists;
431
443
  }
432
444
  const result = await cfSandbox.sandbox.exists(path);
@@ -434,7 +446,7 @@ var cloudflare = (0, import_provider.defineProvider)({
434
446
  },
435
447
  remove: async (cfSandbox, path) => {
436
448
  if (cfSandbox.remote) {
437
- await workerRequest(cfSandbox, "/v1/sandbox/deleteFile", { path });
449
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/deleteFile", { path });
438
450
  return;
439
451
  }
440
452
  await cfSandbox.sandbox.deleteFile(path);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Cloudflare Provider - Factory-based Implementation (Dual-Mode)\n *\n * Supports two connection modes:\n *\n * 1. **Remote mode** — User deploys a gateway Worker to their Cloudflare account\n * via `npx @computesdk/cloudflare`, then connects from anywhere using\n * CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET.\n *\n * 2. **Direct mode** — User's code runs inside a Cloudflare Worker with the\n * Durable Object binding available. Uses the @cloudflare/sandbox SDK directly.\n *\n * The mode is selected automatically based on which config fields are provided.\n */\n\nimport { defineProvider } from '@computesdk/provider';\n\n/**\n * Lazy-load @cloudflare/sandbox to avoid importing it in Node.js environments.\n * The SDK only works inside the Cloudflare Workers runtime (its transitive dep\n * @cloudflare/containers uses extensionless ESM imports that break in Node).\n * Remote mode never needs this import.\n */\nlet _getSandboxFn: ((binding: any, id: string, options?: any) => any) | null = null;\nasync function getSandbox(binding: any, id: string, options?: any): Promise<any> {\n if (!_getSandboxFn) {\n const mod = await import('@cloudflare/sandbox');\n _getSandboxFn = mod.getSandbox as (binding: any, id: string, options?: any) => any;\n }\n return _getSandboxFn(binding, id, options);\n}\n\nimport type { Runtime, CodeResult, CommandResult, SandboxInfo, CreateSandboxOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\n// ─── Config ──────────────────────────────────────────────────────────────────\n\nexport interface CloudflareConfig {\n // Remote mode (from anywhere — talks to deployed gateway Worker)\n /** URL of the deployed gateway Worker (e.g. https://computesdk-sandbox.user.workers.dev) */\n sandboxUrl?: string;\n /** Shared secret for authenticating with the gateway Worker */\n sandboxSecret?: string;\n\n // Direct mode (inside a Cloudflare Worker — uses DO binding)\n /** Cloudflare Sandbox Durable Object binding from Workers environment */\n sandboxBinding?: any;\n\n // Shared options\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Environment variables to pass to sandbox */\n envVars?: Record<string, string>;\n /** Options passed to getSandbox() for lifecycle control (direct mode only) */\n sandboxOptions?: {\n sleepAfter?: string | number;\n keepAlive?: boolean;\n };\n}\n\n// ─── Internal types ──────────────────────────────────────────────────────────\n\ninterface CloudflareSandbox {\n sandboxId: string;\n exposedPorts: Map<number, string>;\n // Remote mode fields\n remote: boolean;\n sandboxUrl?: string;\n sandboxSecret?: string;\n // Direct mode fields\n sandbox?: any; // The @cloudflare/sandbox instance\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction isRemote(config: CloudflareConfig): boolean {\n return !!(config.sandboxUrl && config.sandboxSecret);\n}\n\nfunction detectRuntime(code: string): Runtime {\n if (code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n if (code.includes('console.log') ||\n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename')) {\n return 'node';\n }\n return 'python';\n}\n\nfunction runtimeToLanguage(runtime: Runtime): 'python' | 'javascript' | 'typescript' {\n switch (runtime) {\n case 'python': return 'python';\n case 'node': return 'javascript';\n case 'bun': return 'javascript';\n case 'deno': return 'typescript';\n default: return 'python';\n }\n}\n\n/**\n * Make an authenticated request to the remote gateway Worker\n */\nasync function workerRequest(\n cfSandbox: CloudflareSandbox,\n path: string,\n body: Record<string, any> = {}\n): Promise<any> {\n const res = await fetch(`${cfSandbox.sandboxUrl}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${cfSandbox.sandboxSecret}`,\n },\n body: JSON.stringify({ sandboxId: cfSandbox.sandboxId, ...body }),\n });\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n const text = await res.text().catch(() => '(unreadable)');\n throw new Error(`Worker request failed: ${res.status} - ${text.slice(0, 200)}`);\n }\n\n if (!res.ok) {\n throw new Error(data.error || `Worker request failed: ${res.status}`);\n }\n\n return data;\n}\n\n/**\n * Escape a string for safe use inside double-quoted shell arguments.\n */\nfunction shellEscape(s: string): string {\n return s.replace(/[\"$`\\\\!]/g, '\\\\$&');\n}\n\n/**\n * Process code execution results into a CodeResult (shared by remote and direct modes)\n */\nfunction processExecution(execution: any, detectedRuntime: Runtime): CodeResult {\n const stdoutParts: string[] = [];\n const stderrParts: string[] = [];\n\n if (execution.logs) {\n if (execution.logs.stdout) stdoutParts.push(...execution.logs.stdout);\n if (execution.logs.stderr) stderrParts.push(...execution.logs.stderr);\n }\n if (execution.results && Array.isArray(execution.results)) {\n for (const res of execution.results) {\n if (res.text) stdoutParts.push(res.text);\n }\n }\n if (execution.error) {\n const errorMsg = execution.error.message || execution.error.name || 'Execution error';\n if (errorMsg.includes('SyntaxError') || errorMsg.includes('invalid syntax')) {\n throw new Error(`Syntax error: ${errorMsg}`);\n }\n stderrParts.push(errorMsg);\n }\n\n const stdout = stdoutParts.join('\\n');\n const stderr = stderrParts.join('\\n');\n\n return {\n output: stderr ? `${stdout}${stdout && stderr ? '\\n' : ''}${stderr}` : stdout,\n exitCode: execution.error ? 1 : 0,\n language: detectedRuntime\n };\n}\n\n/**\n * Parse ls -la output into FileEntry objects (used by both modes for readdir)\n */\nfunction parseLsOutput(stdout: string): FileEntry[] {\n const lines = stdout.split('\\n').filter((line: string) => line.trim() && !line.startsWith('total'));\n\n return lines.map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n type: permissions.startsWith('d') ? 'directory' as const : 'file' as const,\n size,\n modified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n}\n\n// ─── Provider ────────────────────────────────────────────────────────────────\n\nexport const cloudflare = defineProvider<CloudflareSandbox, CloudflareConfig>({\n name: 'cloudflare',\n methods: {\n sandbox: {\n // ─── Collection operations ───────────────────────────────────────\n\n create: async (config: CloudflareConfig, options?: CreateSandboxOptions) => {\n // Destructure known ComputeSDK fields, collect the rest for passthrough\n const {\n runtime: _runtime,\n timeout: optTimeout,\n envs,\n name: _name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: optSandboxId,\n namespace: _namespace,\n directory: _directory,\n overlays: _overlays,\n servers: _servers,\n ports: _ports,\n ...rest\n } = options || {};\n\n const sandboxId = optSandboxId || `cf-sandbox-${Date.now()}`;\n const envVars = { ...config.envVars, ...envs };\n // options.timeout takes precedence over config.timeout\n const timeout = optTimeout ?? config.timeout;\n\n // Remote mode\n if (isRemote(config)) {\n await workerRequest(\n { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: new Map() },\n '/v1/sandbox/create',\n {\n envVars: Object.keys(envVars).length > 0 ? envVars : undefined,\n ...(timeout ? { timeout } : {}),\n ...rest, // Pass through provider-specific options\n }\n );\n\n return {\n sandbox: {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n }\n\n // Direct mode\n if (!config.sandboxBinding) {\n throw new Error(\n 'Missing Cloudflare config. Either:\\n' +\n ' 1. Set CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET (remote mode)\\n' +\n ' 2. Provide sandboxBinding from your Workers environment (direct mode)\\n' +\n 'Run `npx @computesdk/cloudflare` to deploy a gateway Worker.'\n );\n }\n\n try {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);\n\n if (Object.keys(envVars).length > 0) {\n await sandbox.setEnvVars(envVars);\n }\n\n return {\n sandbox: {\n sandbox,\n sandboxId,\n remote: false,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('binding')) {\n throw new Error(\n 'Cloudflare Sandbox binding failed. Ensure your Durable Object binding is properly configured in wrangler.toml. ' +\n 'See https://developers.cloudflare.com/sandbox/get-started/ for setup instructions.'\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error('Cloudflare resource limits exceeded. Check your usage at https://dash.cloudflare.com/');\n }\n }\n throw new Error(`Failed to create Cloudflare sandbox: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getById: async (config: CloudflareConfig, sandboxId: string) => {\n // Remote mode\n if (isRemote(config)) {\n try {\n const cfSandbox: CloudflareSandbox = {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n exposedPorts: new Map(),\n };\n // Verify sandbox is alive\n await workerRequest(cfSandbox, '/v1/sandbox/exec', { command: 'true' });\n return { sandbox: cfSandbox, sandboxId };\n } catch {\n return null;\n }\n }\n\n // Direct mode\n if (!config.sandboxBinding) return null;\n\n try {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);\n await sandbox.exec('true');\n return {\n sandbox: { sandbox, sandboxId, remote: false, exposedPorts: new Map() },\n sandboxId\n };\n } catch {\n return null;\n }\n },\n\n list: async (_config: CloudflareConfig) => {\n throw new Error(\n 'Cloudflare provider does not support listing sandboxes. ' +\n 'Durable Objects do not have a native list API. ' +\n 'Use getById to reconnect to specific sandboxes by ID.'\n );\n },\n\n destroy: async (config: CloudflareConfig, sandboxId: string) => {\n try {\n if (isRemote(config)) {\n await workerRequest(\n { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: new Map() },\n '/v1/sandbox/destroy'\n );\n return;\n }\n\n if (config.sandboxBinding) {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId);\n await sandbox.destroy();\n }\n } catch {\n // Sandbox might already be destroyed\n }\n },\n\n // ─── Instance operations ─────────────────────────────────────────\n\n runCode: async (cfSandbox: CloudflareSandbox, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const detectedRuntime = runtime || detectRuntime(code);\n const language = runtimeToLanguage(detectedRuntime);\n\n // Remote mode\n if (cfSandbox.remote) {\n const execution = await workerRequest(cfSandbox, '/v1/sandbox/runCode', { code, language });\n return processExecution(execution, detectedRuntime);\n }\n\n // Direct mode\n try {\n const execution = await cfSandbox.sandbox.runCode(code, { language });\n return processExecution(execution, detectedRuntime);\n } catch (error) {\n if (error instanceof Error && error.message.includes('Syntax error')) throw error;\n throw new Error(`Cloudflare execution failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n runCommand: async (cfSandbox: CloudflareSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n\n // Remote mode\n if (cfSandbox.remote) {\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const result = await workerRequest(cfSandbox, '/v1/sandbox/exec', {\n command: fullCommand,\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode,\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 // Direct mode\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const execResult = await cfSandbox.sandbox.exec(fullCommand, {\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: execResult.stdout || '',\n stderr: execResult.stderr || '',\n exitCode: execResult.exitCode,\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 getInfo: async (cfSandbox: CloudflareSandbox): Promise<SandboxInfo> => {\n try {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/info');\n } else {\n await cfSandbox.sandbox.exec('true');\n }\n\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n }\n };\n } catch (error) {\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'error',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n error: error instanceof Error ? error.message : String(error)\n }\n };\n }\n },\n\n getUrl: async (cfSandbox: CloudflareSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const { port, protocol = 'https' } = options;\n\n if (cfSandbox.exposedPorts.has(port)) {\n return cfSandbox.exposedPorts.get(port)!;\n }\n\n let preview: any;\n if (cfSandbox.remote) {\n preview = await workerRequest(cfSandbox, '/v1/sandbox/exposePort', { port, options: {} });\n } else {\n preview = await cfSandbox.sandbox.exposePort(port, {});\n }\n\n const url = `${protocol}://${preview.url}`;\n cfSandbox.exposedPorts.set(port, url);\n return url;\n },\n\n // ─── Filesystem ────────────────────────────────────────────────\n\n filesystem: {\n readFile: async (cfSandbox: CloudflareSandbox, path: string): Promise<string> => {\n if (cfSandbox.remote) {\n const file = await workerRequest(cfSandbox, '/v1/sandbox/readFile', { path });\n return file.content || '';\n }\n const file = await cfSandbox.sandbox.readFile(path);\n return file.content || '';\n },\n\n writeFile: async (cfSandbox: CloudflareSandbox, path: string, content: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/writeFile', { path, content });\n return;\n }\n await cfSandbox.sandbox.writeFile(path, content);\n },\n\n mkdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/mkdir', { path });\n return;\n }\n await cfSandbox.sandbox.mkdir(path, { recursive: true });\n },\n\n readdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<FileEntry[]> => {\n // Both modes use ls -la since there's no native readdir\n let result: any;\n if (cfSandbox.remote) {\n result = await workerRequest(cfSandbox, '/v1/sandbox/exec', {\n command: `ls -la \"${shellEscape(path)}\"`,\n cwd: '/',\n });\n } else {\n result = await cfSandbox.sandbox.exec(`ls -la \"${shellEscape(path)}\"`, { cwd: '/' });\n }\n\n if (result.exitCode !== 0) {\n throw new Error(`Directory listing failed: ${result.stderr}`);\n }\n\n return parseLsOutput(result.stdout);\n },\n\n exists: async (cfSandbox: CloudflareSandbox, path: string): Promise<boolean> => {\n if (cfSandbox.remote) {\n const result = await workerRequest(cfSandbox, '/v1/sandbox/exists', { path });\n return result.exists;\n }\n const result = await cfSandbox.sandbox.exists(path);\n return result.exists;\n },\n\n remove: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/deleteFile', { path });\n return;\n }\n await cfSandbox.sandbox.deleteFile(path);\n }\n }\n }\n }\n});\n"],"mappings":"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","names":["file","result"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Cloudflare Provider - Factory-based Implementation (Dual-Mode)\n *\n * Supports two connection modes:\n *\n * 1. **Remote mode** — User deploys a gateway Worker to their Cloudflare account\n * via `npx @computesdk/cloudflare`, then connects from anywhere using\n * CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET.\n *\n * 2. **Direct mode** — User's code runs inside a Cloudflare Worker with the\n * Durable Object binding available. Uses the @cloudflare/sandbox SDK directly.\n *\n * The mode is selected automatically based on which config fields are provided.\n */\n\nimport { defineProvider } from '@computesdk/provider';\n\n/**\n * Lazy-load @cloudflare/sandbox to avoid importing it in Node.js environments.\n * The SDK only works inside the Cloudflare Workers runtime (its transitive dep\n * @cloudflare/containers uses extensionless ESM imports that break in Node).\n * Remote mode never needs this import.\n */\nlet _getSandboxFn: ((binding: any, id: string, options?: any) => any) | null = null;\nasync function getSandbox(binding: any, id: string, options?: any): Promise<any> {\n if (!_getSandboxFn) {\n const mod = await import('@cloudflare/sandbox');\n _getSandboxFn = mod.getSandbox as (binding: any, id: string, options?: any) => any;\n }\n return _getSandboxFn(binding, id, options);\n}\n\nimport type { Runtime, CodeResult, CommandResult, SandboxInfo, CreateSandboxOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\n// ─── Config ──────────────────────────────────────────────────────────────────\n\nexport interface CloudflareConfig {\n // Remote mode (from anywhere — talks to deployed gateway Worker)\n /** URL of the deployed gateway Worker (e.g. https://computesdk-sandbox.user.workers.dev) */\n sandboxUrl?: string;\n /** Shared secret for authenticating with the gateway Worker */\n sandboxSecret?: string;\n\n // Direct mode (inside a Cloudflare Worker — uses DO binding)\n /** Cloudflare Sandbox Durable Object binding from Workers environment */\n sandboxBinding?: any;\n\n // Shared options\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Environment variables to pass to sandbox */\n envVars?: Record<string, string>;\n /** Options passed to getSandbox() for lifecycle control (direct mode only) */\n sandboxOptions?: {\n sleepAfter?: string | number;\n keepAlive?: boolean;\n };\n}\n\n// ─── Internal types ──────────────────────────────────────────────────────────\n\ninterface CloudflareSandbox {\n sandboxId: string;\n exposedPorts: Map<number, string>;\n // Remote mode fields\n remote: boolean;\n sandboxUrl?: string;\n sandboxSecret?: string;\n pendingEnvVars?: Record<string, string>;\n remoteInitialized?: boolean;\n // Direct mode fields\n sandbox?: any; // The @cloudflare/sandbox instance\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction isRemote(config: CloudflareConfig): boolean {\n return !!(config.sandboxUrl && config.sandboxSecret);\n}\n\nfunction detectRuntime(code: string): Runtime {\n if (code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n if (code.includes('console.log') ||\n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename')) {\n return 'node';\n }\n return 'python';\n}\n\nfunction runtimeToLanguage(runtime: Runtime): 'python' | 'javascript' | 'typescript' {\n switch (runtime) {\n case 'python': return 'python';\n case 'node': return 'javascript';\n case 'bun': return 'javascript';\n case 'deno': return 'typescript';\n default: return 'python';\n }\n}\n\nfunction createSandboxId(): string {\n return `cf-sandbox-${crypto.randomUUID()}`;\n}\n\n/**\n * Make an authenticated request to the remote gateway Worker\n */\nasync function workerRequest(\n cfSandbox: CloudflareSandbox,\n path: string,\n body: Record<string, any> = {}\n): Promise<any> {\n const res = await fetch(`${cfSandbox.sandboxUrl}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${cfSandbox.sandboxSecret}`,\n },\n body: JSON.stringify({ sandboxId: cfSandbox.sandboxId, ...body }),\n });\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n const text = await res.text().catch(() => '(unreadable)');\n throw new Error(`Worker request failed: ${res.status} - ${text.slice(0, 200)}`);\n }\n\n if (!res.ok) {\n throw new Error(data.error || `Worker request failed: ${res.status}`);\n }\n\n return data;\n}\n\nasync function workerRequestWithInit(\n cfSandbox: CloudflareSandbox,\n path: string,\n body: Record<string, any> = {}\n): Promise<any> {\n if (!cfSandbox.remote || cfSandbox.remoteInitialized) {\n return workerRequest(cfSandbox, path, body);\n }\n\n const initEnvVars = cfSandbox.pendingEnvVars;\n const requestBody = initEnvVars && Object.keys(initEnvVars).length > 0\n ? { ...body, initEnvVars }\n : body;\n\n const data = await workerRequest(cfSandbox, path, requestBody);\n cfSandbox.pendingEnvVars = undefined;\n cfSandbox.remoteInitialized = true;\n return data;\n}\n\n/**\n * Escape a string for safe use inside double-quoted shell arguments.\n */\nfunction shellEscape(s: string): string {\n return s.replace(/[\"$`\\\\!]/g, '\\\\$&');\n}\n\n/**\n * Process code execution results into a CodeResult (shared by remote and direct modes)\n */\nfunction processExecution(execution: any, detectedRuntime: Runtime): CodeResult {\n const stdoutParts: string[] = [];\n const stderrParts: string[] = [];\n\n if (execution.logs) {\n if (execution.logs.stdout) stdoutParts.push(...execution.logs.stdout);\n if (execution.logs.stderr) stderrParts.push(...execution.logs.stderr);\n }\n if (execution.results && Array.isArray(execution.results)) {\n for (const res of execution.results) {\n if (res.text) stdoutParts.push(res.text);\n }\n }\n if (execution.error) {\n const errorMsg = execution.error.message || execution.error.name || 'Execution error';\n if (errorMsg.includes('SyntaxError') || errorMsg.includes('invalid syntax')) {\n throw new Error(`Syntax error: ${errorMsg}`);\n }\n stderrParts.push(errorMsg);\n }\n\n const stdout = stdoutParts.join('\\n');\n const stderr = stderrParts.join('\\n');\n\n return {\n output: stderr ? `${stdout}${stdout && stderr ? '\\n' : ''}${stderr}` : stdout,\n exitCode: execution.error ? 1 : 0,\n language: detectedRuntime\n };\n}\n\n/**\n * Parse ls -la output into FileEntry objects (used by both modes for readdir)\n */\nfunction parseLsOutput(stdout: string): FileEntry[] {\n const lines = stdout.split('\\n').filter((line: string) => line.trim() && !line.startsWith('total'));\n\n return lines.map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n type: permissions.startsWith('d') ? 'directory' as const : 'file' as const,\n size,\n modified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n}\n\n// ─── Provider ────────────────────────────────────────────────────────────────\n\nexport const cloudflare = defineProvider<CloudflareSandbox, CloudflareConfig>({\n name: 'cloudflare',\n methods: {\n sandbox: {\n // ─── Collection operations ───────────────────────────────────────\n\n create: async (config: CloudflareConfig, options?: CreateSandboxOptions) => {\n // Destructure known ComputeSDK fields, collect the rest for passthrough\n const {\n runtime: _runtime,\n timeout: optTimeout,\n envs,\n name: _name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: optSandboxId,\n namespace: _namespace,\n directory: _directory,\n overlays: _overlays,\n servers: _servers,\n ports: _ports,\n ...rest\n } = options || {};\n\n const sandboxId = optSandboxId || createSandboxId();\n const envVars = { ...config.envVars, ...envs };\n // options.timeout takes precedence over config.timeout\n const timeout = optTimeout ?? config.timeout;\n const sleepAfter = timeout ? `${Math.ceil(timeout / 1000)}s` : undefined;\n\n // Remote mode\n if (isRemote(config)) {\n return {\n sandbox: {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n pendingEnvVars: Object.keys(envVars).length > 0 ? envVars : undefined,\n remoteInitialized: false,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n }\n\n // Direct mode\n if (!config.sandboxBinding) {\n throw new Error(\n 'Missing Cloudflare config. Either:\\n' +\n ' 1. Set CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET (remote mode)\\n' +\n ' 2. Provide sandboxBinding from your Workers environment (direct mode)\\n' +\n 'Run `npx @computesdk/cloudflare` to deploy a gateway Worker.'\n );\n }\n\n try {\n const sandboxOpts = { ...config.sandboxOptions };\n if (sleepAfter) {\n sandboxOpts.sleepAfter = sleepAfter;\n }\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, sandboxOpts);\n\n if (Object.keys(envVars).length > 0) {\n await sandbox.setEnvVars(envVars);\n }\n\n return {\n sandbox: {\n sandbox,\n sandboxId,\n remote: false,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('binding')) {\n throw new Error(\n 'Cloudflare Sandbox binding failed. Ensure your Durable Object binding is properly configured in wrangler.toml. ' +\n 'See https://developers.cloudflare.com/sandbox/get-started/ for setup instructions.'\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error('Cloudflare resource limits exceeded. Check your usage at https://dash.cloudflare.com/');\n }\n }\n throw new Error(`Failed to create Cloudflare sandbox: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getById: async (config: CloudflareConfig, sandboxId: string) => {\n // Remote mode\n if (isRemote(config)) {\n try {\n const cfSandbox: CloudflareSandbox = {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n remoteInitialized: true,\n exposedPorts: new Map(),\n };\n // Verify sandbox is alive\n await workerRequest(cfSandbox, '/v1/sandbox/exec', { command: 'true' });\n return { sandbox: cfSandbox, sandboxId };\n } catch {\n return null;\n }\n }\n\n // Direct mode\n if (!config.sandboxBinding) return null;\n\n try {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);\n await sandbox.exec('true');\n return {\n sandbox: { sandbox, sandboxId, remote: false, exposedPorts: new Map() },\n sandboxId\n };\n } catch {\n return null;\n }\n },\n\n list: async (_config: CloudflareConfig) => {\n throw new Error(\n 'Cloudflare provider does not support listing sandboxes. ' +\n 'Durable Objects do not have a native list API. ' +\n 'Use getById to reconnect to specific sandboxes by ID.'\n );\n },\n\n destroy: async (config: CloudflareConfig, sandboxId: string) => {\n try {\n if (isRemote(config)) {\n await workerRequest(\n { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: new Map() },\n '/v1/sandbox/destroy'\n );\n return;\n }\n\n if (config.sandboxBinding) {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId);\n await sandbox.destroy();\n }\n } catch {\n // Sandbox might already be destroyed\n }\n },\n\n // ─── Instance operations ─────────────────────────────────────────\n\n runCode: async (cfSandbox: CloudflareSandbox, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const detectedRuntime = runtime || detectRuntime(code);\n const language = runtimeToLanguage(detectedRuntime);\n\n // Remote mode\n if (cfSandbox.remote) {\n const execution = await workerRequestWithInit(cfSandbox, '/v1/sandbox/runCode', { code, language });\n return processExecution(execution, detectedRuntime);\n }\n\n // Direct mode\n try {\n const execution = await cfSandbox.sandbox.runCode(code, { language });\n return processExecution(execution, detectedRuntime);\n } catch (error) {\n if (error instanceof Error && error.message.includes('Syntax error')) throw error;\n throw new Error(`Cloudflare execution failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n runCommand: async (cfSandbox: CloudflareSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n\n // Remote mode\n if (cfSandbox.remote) {\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const result = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exec', {\n command: fullCommand,\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode,\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 // Direct mode\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const execResult = await cfSandbox.sandbox.exec(fullCommand, {\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: execResult.stdout || '',\n stderr: execResult.stderr || '',\n exitCode: execResult.exitCode,\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 getInfo: async (cfSandbox: CloudflareSandbox): Promise<SandboxInfo> => {\n try {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/info');\n } else {\n await cfSandbox.sandbox.exec('true');\n }\n\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n }\n };\n } catch (error) {\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'error',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n error: error instanceof Error ? error.message : String(error)\n }\n };\n }\n },\n\n getUrl: async (cfSandbox: CloudflareSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const { port, protocol = 'https' } = options;\n\n if (cfSandbox.exposedPorts.has(port)) {\n return cfSandbox.exposedPorts.get(port)!;\n }\n\n let preview: any;\n if (cfSandbox.remote) {\n preview = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exposePort', { port, options: {} });\n } else {\n preview = await cfSandbox.sandbox.exposePort(port, {});\n }\n\n const url = `${protocol}://${preview.url}`;\n cfSandbox.exposedPorts.set(port, url);\n return url;\n },\n\n // ─── Filesystem ────────────────────────────────────────────────\n\n filesystem: {\n readFile: async (cfSandbox: CloudflareSandbox, path: string): Promise<string> => {\n if (cfSandbox.remote) {\n const file = await workerRequestWithInit(cfSandbox, '/v1/sandbox/readFile', { path });\n return file.content || '';\n }\n const file = await cfSandbox.sandbox.readFile(path);\n return file.content || '';\n },\n\n writeFile: async (cfSandbox: CloudflareSandbox, path: string, content: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/writeFile', { path, content });\n return;\n }\n await cfSandbox.sandbox.writeFile(path, content);\n },\n\n mkdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/mkdir', { path });\n return;\n }\n await cfSandbox.sandbox.mkdir(path, { recursive: true });\n },\n\n readdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<FileEntry[]> => {\n // Both modes use ls -la since there's no native readdir\n let result: any;\n if (cfSandbox.remote) {\n result = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exec', {\n command: `ls -la \"${shellEscape(path)}\"`,\n cwd: '/',\n });\n } else {\n result = await cfSandbox.sandbox.exec(`ls -la \"${shellEscape(path)}\"`, { cwd: '/' });\n }\n\n if (result.exitCode !== 0) {\n throw new Error(`Directory listing failed: ${result.stderr}`);\n }\n\n return parseLsOutput(result.stdout);\n },\n\n exists: async (cfSandbox: CloudflareSandbox, path: string): Promise<boolean> => {\n if (cfSandbox.remote) {\n const result = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exists', { path });\n return result.exists;\n }\n const result = await cfSandbox.sandbox.exists(path);\n return result.exists;\n },\n\n remove: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/deleteFile', { path });\n return;\n }\n await cfSandbox.sandbox.deleteFile(path);\n }\n }\n }\n }\n});"],"mappings":"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","names":["file","result"]}
package/dist/index.mjs CHANGED
@@ -34,6 +34,9 @@ function runtimeToLanguage(runtime) {
34
34
  return "python";
35
35
  }
36
36
  }
37
+ function createSandboxId() {
38
+ return `cf-sandbox-${crypto.randomUUID()}`;
39
+ }
37
40
  async function workerRequest(cfSandbox, path, body = {}) {
38
41
  const res = await fetch(`${cfSandbox.sandboxUrl}${path}`, {
39
42
  method: "POST",
@@ -55,6 +58,17 @@ async function workerRequest(cfSandbox, path, body = {}) {
55
58
  }
56
59
  return data;
57
60
  }
61
+ async function workerRequestWithInit(cfSandbox, path, body = {}) {
62
+ if (!cfSandbox.remote || cfSandbox.remoteInitialized) {
63
+ return workerRequest(cfSandbox, path, body);
64
+ }
65
+ const initEnvVars = cfSandbox.pendingEnvVars;
66
+ const requestBody = initEnvVars && Object.keys(initEnvVars).length > 0 ? { ...body, initEnvVars } : body;
67
+ const data = await workerRequest(cfSandbox, path, requestBody);
68
+ cfSandbox.pendingEnvVars = void 0;
69
+ cfSandbox.remoteInitialized = true;
70
+ return data;
71
+ }
58
72
  function shellEscape(s) {
59
73
  return s.replace(/["$`\\!]/g, "\\$&");
60
74
  }
@@ -124,26 +138,19 @@ var cloudflare = defineProvider({
124
138
  ports: _ports,
125
139
  ...rest
126
140
  } = options || {};
127
- const sandboxId = optSandboxId || `cf-sandbox-${Date.now()}`;
141
+ const sandboxId = optSandboxId || createSandboxId();
128
142
  const envVars = { ...config.envVars, ...envs };
129
143
  const timeout = optTimeout ?? config.timeout;
144
+ const sleepAfter = timeout ? `${Math.ceil(timeout / 1e3)}s` : void 0;
130
145
  if (isRemote(config)) {
131
- await workerRequest(
132
- { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: /* @__PURE__ */ new Map() },
133
- "/v1/sandbox/create",
134
- {
135
- envVars: Object.keys(envVars).length > 0 ? envVars : void 0,
136
- ...timeout ? { timeout } : {},
137
- ...rest
138
- // Pass through provider-specific options
139
- }
140
- );
141
146
  return {
142
147
  sandbox: {
143
148
  sandboxId,
144
149
  remote: true,
145
150
  sandboxUrl: config.sandboxUrl,
146
151
  sandboxSecret: config.sandboxSecret,
152
+ pendingEnvVars: Object.keys(envVars).length > 0 ? envVars : void 0,
153
+ remoteInitialized: false,
147
154
  exposedPorts: /* @__PURE__ */ new Map()
148
155
  },
149
156
  sandboxId
@@ -155,7 +162,11 @@ var cloudflare = defineProvider({
155
162
  );
156
163
  }
157
164
  try {
158
- const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);
165
+ const sandboxOpts = { ...config.sandboxOptions };
166
+ if (sleepAfter) {
167
+ sandboxOpts.sleepAfter = sleepAfter;
168
+ }
169
+ const sandbox = await getSandbox(config.sandboxBinding, sandboxId, sandboxOpts);
159
170
  if (Object.keys(envVars).length > 0) {
160
171
  await sandbox.setEnvVars(envVars);
161
172
  }
@@ -190,6 +201,7 @@ var cloudflare = defineProvider({
190
201
  remote: true,
191
202
  sandboxUrl: config.sandboxUrl,
192
203
  sandboxSecret: config.sandboxSecret,
204
+ remoteInitialized: true,
193
205
  exposedPorts: /* @__PURE__ */ new Map()
194
206
  };
195
207
  await workerRequest(cfSandbox, "/v1/sandbox/exec", { command: "true" });
@@ -236,7 +248,7 @@ var cloudflare = defineProvider({
236
248
  const detectedRuntime = runtime || detectRuntime(code);
237
249
  const language = runtimeToLanguage(detectedRuntime);
238
250
  if (cfSandbox.remote) {
239
- const execution = await workerRequest(cfSandbox, "/v1/sandbox/runCode", { code, language });
251
+ const execution = await workerRequestWithInit(cfSandbox, "/v1/sandbox/runCode", { code, language });
240
252
  return processExecution(execution, detectedRuntime);
241
253
  }
242
254
  try {
@@ -255,7 +267,7 @@ var cloudflare = defineProvider({
255
267
  if (options?.background) {
256
268
  fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
257
269
  }
258
- const result = await workerRequest(cfSandbox, "/v1/sandbox/exec", {
270
+ const result = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exec", {
259
271
  command: fullCommand,
260
272
  cwd: options?.cwd,
261
273
  env: options?.env,
@@ -304,7 +316,7 @@ var cloudflare = defineProvider({
304
316
  getInfo: async (cfSandbox) => {
305
317
  try {
306
318
  if (cfSandbox.remote) {
307
- await workerRequest(cfSandbox, "/v1/sandbox/info");
319
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/info");
308
320
  } else {
309
321
  await cfSandbox.sandbox.exec("true");
310
322
  }
@@ -343,7 +355,7 @@ var cloudflare = defineProvider({
343
355
  }
344
356
  let preview;
345
357
  if (cfSandbox.remote) {
346
- preview = await workerRequest(cfSandbox, "/v1/sandbox/exposePort", { port, options: {} });
358
+ preview = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exposePort", { port, options: {} });
347
359
  } else {
348
360
  preview = await cfSandbox.sandbox.exposePort(port, {});
349
361
  }
@@ -355,7 +367,7 @@ var cloudflare = defineProvider({
355
367
  filesystem: {
356
368
  readFile: async (cfSandbox, path) => {
357
369
  if (cfSandbox.remote) {
358
- const file2 = await workerRequest(cfSandbox, "/v1/sandbox/readFile", { path });
370
+ const file2 = await workerRequestWithInit(cfSandbox, "/v1/sandbox/readFile", { path });
359
371
  return file2.content || "";
360
372
  }
361
373
  const file = await cfSandbox.sandbox.readFile(path);
@@ -363,14 +375,14 @@ var cloudflare = defineProvider({
363
375
  },
364
376
  writeFile: async (cfSandbox, path, content) => {
365
377
  if (cfSandbox.remote) {
366
- await workerRequest(cfSandbox, "/v1/sandbox/writeFile", { path, content });
378
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/writeFile", { path, content });
367
379
  return;
368
380
  }
369
381
  await cfSandbox.sandbox.writeFile(path, content);
370
382
  },
371
383
  mkdir: async (cfSandbox, path) => {
372
384
  if (cfSandbox.remote) {
373
- await workerRequest(cfSandbox, "/v1/sandbox/mkdir", { path });
385
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/mkdir", { path });
374
386
  return;
375
387
  }
376
388
  await cfSandbox.sandbox.mkdir(path, { recursive: true });
@@ -378,7 +390,7 @@ var cloudflare = defineProvider({
378
390
  readdir: async (cfSandbox, path) => {
379
391
  let result;
380
392
  if (cfSandbox.remote) {
381
- result = await workerRequest(cfSandbox, "/v1/sandbox/exec", {
393
+ result = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exec", {
382
394
  command: `ls -la "${shellEscape(path)}"`,
383
395
  cwd: "/"
384
396
  });
@@ -392,7 +404,7 @@ var cloudflare = defineProvider({
392
404
  },
393
405
  exists: async (cfSandbox, path) => {
394
406
  if (cfSandbox.remote) {
395
- const result2 = await workerRequest(cfSandbox, "/v1/sandbox/exists", { path });
407
+ const result2 = await workerRequestWithInit(cfSandbox, "/v1/sandbox/exists", { path });
396
408
  return result2.exists;
397
409
  }
398
410
  const result = await cfSandbox.sandbox.exists(path);
@@ -400,7 +412,7 @@ var cloudflare = defineProvider({
400
412
  },
401
413
  remove: async (cfSandbox, path) => {
402
414
  if (cfSandbox.remote) {
403
- await workerRequest(cfSandbox, "/v1/sandbox/deleteFile", { path });
415
+ await workerRequestWithInit(cfSandbox, "/v1/sandbox/deleteFile", { path });
404
416
  return;
405
417
  }
406
418
  await cfSandbox.sandbox.deleteFile(path);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Cloudflare Provider - Factory-based Implementation (Dual-Mode)\n *\n * Supports two connection modes:\n *\n * 1. **Remote mode** — User deploys a gateway Worker to their Cloudflare account\n * via `npx @computesdk/cloudflare`, then connects from anywhere using\n * CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET.\n *\n * 2. **Direct mode** — User's code runs inside a Cloudflare Worker with the\n * Durable Object binding available. Uses the @cloudflare/sandbox SDK directly.\n *\n * The mode is selected automatically based on which config fields are provided.\n */\n\nimport { defineProvider } from '@computesdk/provider';\n\n/**\n * Lazy-load @cloudflare/sandbox to avoid importing it in Node.js environments.\n * The SDK only works inside the Cloudflare Workers runtime (its transitive dep\n * @cloudflare/containers uses extensionless ESM imports that break in Node).\n * Remote mode never needs this import.\n */\nlet _getSandboxFn: ((binding: any, id: string, options?: any) => any) | null = null;\nasync function getSandbox(binding: any, id: string, options?: any): Promise<any> {\n if (!_getSandboxFn) {\n const mod = await import('@cloudflare/sandbox');\n _getSandboxFn = mod.getSandbox as (binding: any, id: string, options?: any) => any;\n }\n return _getSandboxFn(binding, id, options);\n}\n\nimport type { Runtime, CodeResult, CommandResult, SandboxInfo, CreateSandboxOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\n// ─── Config ──────────────────────────────────────────────────────────────────\n\nexport interface CloudflareConfig {\n // Remote mode (from anywhere — talks to deployed gateway Worker)\n /** URL of the deployed gateway Worker (e.g. https://computesdk-sandbox.user.workers.dev) */\n sandboxUrl?: string;\n /** Shared secret for authenticating with the gateway Worker */\n sandboxSecret?: string;\n\n // Direct mode (inside a Cloudflare Worker — uses DO binding)\n /** Cloudflare Sandbox Durable Object binding from Workers environment */\n sandboxBinding?: any;\n\n // Shared options\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Environment variables to pass to sandbox */\n envVars?: Record<string, string>;\n /** Options passed to getSandbox() for lifecycle control (direct mode only) */\n sandboxOptions?: {\n sleepAfter?: string | number;\n keepAlive?: boolean;\n };\n}\n\n// ─── Internal types ──────────────────────────────────────────────────────────\n\ninterface CloudflareSandbox {\n sandboxId: string;\n exposedPorts: Map<number, string>;\n // Remote mode fields\n remote: boolean;\n sandboxUrl?: string;\n sandboxSecret?: string;\n // Direct mode fields\n sandbox?: any; // The @cloudflare/sandbox instance\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction isRemote(config: CloudflareConfig): boolean {\n return !!(config.sandboxUrl && config.sandboxSecret);\n}\n\nfunction detectRuntime(code: string): Runtime {\n if (code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n if (code.includes('console.log') ||\n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename')) {\n return 'node';\n }\n return 'python';\n}\n\nfunction runtimeToLanguage(runtime: Runtime): 'python' | 'javascript' | 'typescript' {\n switch (runtime) {\n case 'python': return 'python';\n case 'node': return 'javascript';\n case 'bun': return 'javascript';\n case 'deno': return 'typescript';\n default: return 'python';\n }\n}\n\n/**\n * Make an authenticated request to the remote gateway Worker\n */\nasync function workerRequest(\n cfSandbox: CloudflareSandbox,\n path: string,\n body: Record<string, any> = {}\n): Promise<any> {\n const res = await fetch(`${cfSandbox.sandboxUrl}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${cfSandbox.sandboxSecret}`,\n },\n body: JSON.stringify({ sandboxId: cfSandbox.sandboxId, ...body }),\n });\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n const text = await res.text().catch(() => '(unreadable)');\n throw new Error(`Worker request failed: ${res.status} - ${text.slice(0, 200)}`);\n }\n\n if (!res.ok) {\n throw new Error(data.error || `Worker request failed: ${res.status}`);\n }\n\n return data;\n}\n\n/**\n * Escape a string for safe use inside double-quoted shell arguments.\n */\nfunction shellEscape(s: string): string {\n return s.replace(/[\"$`\\\\!]/g, '\\\\$&');\n}\n\n/**\n * Process code execution results into a CodeResult (shared by remote and direct modes)\n */\nfunction processExecution(execution: any, detectedRuntime: Runtime): CodeResult {\n const stdoutParts: string[] = [];\n const stderrParts: string[] = [];\n\n if (execution.logs) {\n if (execution.logs.stdout) stdoutParts.push(...execution.logs.stdout);\n if (execution.logs.stderr) stderrParts.push(...execution.logs.stderr);\n }\n if (execution.results && Array.isArray(execution.results)) {\n for (const res of execution.results) {\n if (res.text) stdoutParts.push(res.text);\n }\n }\n if (execution.error) {\n const errorMsg = execution.error.message || execution.error.name || 'Execution error';\n if (errorMsg.includes('SyntaxError') || errorMsg.includes('invalid syntax')) {\n throw new Error(`Syntax error: ${errorMsg}`);\n }\n stderrParts.push(errorMsg);\n }\n\n const stdout = stdoutParts.join('\\n');\n const stderr = stderrParts.join('\\n');\n\n return {\n output: stderr ? `${stdout}${stdout && stderr ? '\\n' : ''}${stderr}` : stdout,\n exitCode: execution.error ? 1 : 0,\n language: detectedRuntime\n };\n}\n\n/**\n * Parse ls -la output into FileEntry objects (used by both modes for readdir)\n */\nfunction parseLsOutput(stdout: string): FileEntry[] {\n const lines = stdout.split('\\n').filter((line: string) => line.trim() && !line.startsWith('total'));\n\n return lines.map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n type: permissions.startsWith('d') ? 'directory' as const : 'file' as const,\n size,\n modified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n}\n\n// ─── Provider ────────────────────────────────────────────────────────────────\n\nexport const cloudflare = defineProvider<CloudflareSandbox, CloudflareConfig>({\n name: 'cloudflare',\n methods: {\n sandbox: {\n // ─── Collection operations ───────────────────────────────────────\n\n create: async (config: CloudflareConfig, options?: CreateSandboxOptions) => {\n // Destructure known ComputeSDK fields, collect the rest for passthrough\n const {\n runtime: _runtime,\n timeout: optTimeout,\n envs,\n name: _name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: optSandboxId,\n namespace: _namespace,\n directory: _directory,\n overlays: _overlays,\n servers: _servers,\n ports: _ports,\n ...rest\n } = options || {};\n\n const sandboxId = optSandboxId || `cf-sandbox-${Date.now()}`;\n const envVars = { ...config.envVars, ...envs };\n // options.timeout takes precedence over config.timeout\n const timeout = optTimeout ?? config.timeout;\n\n // Remote mode\n if (isRemote(config)) {\n await workerRequest(\n { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: new Map() },\n '/v1/sandbox/create',\n {\n envVars: Object.keys(envVars).length > 0 ? envVars : undefined,\n ...(timeout ? { timeout } : {}),\n ...rest, // Pass through provider-specific options\n }\n );\n\n return {\n sandbox: {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n }\n\n // Direct mode\n if (!config.sandboxBinding) {\n throw new Error(\n 'Missing Cloudflare config. Either:\\n' +\n ' 1. Set CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET (remote mode)\\n' +\n ' 2. Provide sandboxBinding from your Workers environment (direct mode)\\n' +\n 'Run `npx @computesdk/cloudflare` to deploy a gateway Worker.'\n );\n }\n\n try {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);\n\n if (Object.keys(envVars).length > 0) {\n await sandbox.setEnvVars(envVars);\n }\n\n return {\n sandbox: {\n sandbox,\n sandboxId,\n remote: false,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('binding')) {\n throw new Error(\n 'Cloudflare Sandbox binding failed. Ensure your Durable Object binding is properly configured in wrangler.toml. ' +\n 'See https://developers.cloudflare.com/sandbox/get-started/ for setup instructions.'\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error('Cloudflare resource limits exceeded. Check your usage at https://dash.cloudflare.com/');\n }\n }\n throw new Error(`Failed to create Cloudflare sandbox: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getById: async (config: CloudflareConfig, sandboxId: string) => {\n // Remote mode\n if (isRemote(config)) {\n try {\n const cfSandbox: CloudflareSandbox = {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n exposedPorts: new Map(),\n };\n // Verify sandbox is alive\n await workerRequest(cfSandbox, '/v1/sandbox/exec', { command: 'true' });\n return { sandbox: cfSandbox, sandboxId };\n } catch {\n return null;\n }\n }\n\n // Direct mode\n if (!config.sandboxBinding) return null;\n\n try {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);\n await sandbox.exec('true');\n return {\n sandbox: { sandbox, sandboxId, remote: false, exposedPorts: new Map() },\n sandboxId\n };\n } catch {\n return null;\n }\n },\n\n list: async (_config: CloudflareConfig) => {\n throw new Error(\n 'Cloudflare provider does not support listing sandboxes. ' +\n 'Durable Objects do not have a native list API. ' +\n 'Use getById to reconnect to specific sandboxes by ID.'\n );\n },\n\n destroy: async (config: CloudflareConfig, sandboxId: string) => {\n try {\n if (isRemote(config)) {\n await workerRequest(\n { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: new Map() },\n '/v1/sandbox/destroy'\n );\n return;\n }\n\n if (config.sandboxBinding) {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId);\n await sandbox.destroy();\n }\n } catch {\n // Sandbox might already be destroyed\n }\n },\n\n // ─── Instance operations ─────────────────────────────────────────\n\n runCode: async (cfSandbox: CloudflareSandbox, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const detectedRuntime = runtime || detectRuntime(code);\n const language = runtimeToLanguage(detectedRuntime);\n\n // Remote mode\n if (cfSandbox.remote) {\n const execution = await workerRequest(cfSandbox, '/v1/sandbox/runCode', { code, language });\n return processExecution(execution, detectedRuntime);\n }\n\n // Direct mode\n try {\n const execution = await cfSandbox.sandbox.runCode(code, { language });\n return processExecution(execution, detectedRuntime);\n } catch (error) {\n if (error instanceof Error && error.message.includes('Syntax error')) throw error;\n throw new Error(`Cloudflare execution failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n runCommand: async (cfSandbox: CloudflareSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n\n // Remote mode\n if (cfSandbox.remote) {\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const result = await workerRequest(cfSandbox, '/v1/sandbox/exec', {\n command: fullCommand,\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode,\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 // Direct mode\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const execResult = await cfSandbox.sandbox.exec(fullCommand, {\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: execResult.stdout || '',\n stderr: execResult.stderr || '',\n exitCode: execResult.exitCode,\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 getInfo: async (cfSandbox: CloudflareSandbox): Promise<SandboxInfo> => {\n try {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/info');\n } else {\n await cfSandbox.sandbox.exec('true');\n }\n\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n }\n };\n } catch (error) {\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'error',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n error: error instanceof Error ? error.message : String(error)\n }\n };\n }\n },\n\n getUrl: async (cfSandbox: CloudflareSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const { port, protocol = 'https' } = options;\n\n if (cfSandbox.exposedPorts.has(port)) {\n return cfSandbox.exposedPorts.get(port)!;\n }\n\n let preview: any;\n if (cfSandbox.remote) {\n preview = await workerRequest(cfSandbox, '/v1/sandbox/exposePort', { port, options: {} });\n } else {\n preview = await cfSandbox.sandbox.exposePort(port, {});\n }\n\n const url = `${protocol}://${preview.url}`;\n cfSandbox.exposedPorts.set(port, url);\n return url;\n },\n\n // ─── Filesystem ────────────────────────────────────────────────\n\n filesystem: {\n readFile: async (cfSandbox: CloudflareSandbox, path: string): Promise<string> => {\n if (cfSandbox.remote) {\n const file = await workerRequest(cfSandbox, '/v1/sandbox/readFile', { path });\n return file.content || '';\n }\n const file = await cfSandbox.sandbox.readFile(path);\n return file.content || '';\n },\n\n writeFile: async (cfSandbox: CloudflareSandbox, path: string, content: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/writeFile', { path, content });\n return;\n }\n await cfSandbox.sandbox.writeFile(path, content);\n },\n\n mkdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/mkdir', { path });\n return;\n }\n await cfSandbox.sandbox.mkdir(path, { recursive: true });\n },\n\n readdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<FileEntry[]> => {\n // Both modes use ls -la since there's no native readdir\n let result: any;\n if (cfSandbox.remote) {\n result = await workerRequest(cfSandbox, '/v1/sandbox/exec', {\n command: `ls -la \"${shellEscape(path)}\"`,\n cwd: '/',\n });\n } else {\n result = await cfSandbox.sandbox.exec(`ls -la \"${shellEscape(path)}\"`, { cwd: '/' });\n }\n\n if (result.exitCode !== 0) {\n throw new Error(`Directory listing failed: ${result.stderr}`);\n }\n\n return parseLsOutput(result.stdout);\n },\n\n exists: async (cfSandbox: CloudflareSandbox, path: string): Promise<boolean> => {\n if (cfSandbox.remote) {\n const result = await workerRequest(cfSandbox, '/v1/sandbox/exists', { path });\n return result.exists;\n }\n const result = await cfSandbox.sandbox.exists(path);\n return result.exists;\n },\n\n remove: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequest(cfSandbox, '/v1/sandbox/deleteFile', { path });\n return;\n }\n await cfSandbox.sandbox.deleteFile(path);\n }\n }\n }\n }\n});\n"],"mappings":"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","names":["file","result"]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Cloudflare Provider - Factory-based Implementation (Dual-Mode)\n *\n * Supports two connection modes:\n *\n * 1. **Remote mode** — User deploys a gateway Worker to their Cloudflare account\n * via `npx @computesdk/cloudflare`, then connects from anywhere using\n * CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET.\n *\n * 2. **Direct mode** — User's code runs inside a Cloudflare Worker with the\n * Durable Object binding available. Uses the @cloudflare/sandbox SDK directly.\n *\n * The mode is selected automatically based on which config fields are provided.\n */\n\nimport { defineProvider } from '@computesdk/provider';\n\n/**\n * Lazy-load @cloudflare/sandbox to avoid importing it in Node.js environments.\n * The SDK only works inside the Cloudflare Workers runtime (its transitive dep\n * @cloudflare/containers uses extensionless ESM imports that break in Node).\n * Remote mode never needs this import.\n */\nlet _getSandboxFn: ((binding: any, id: string, options?: any) => any) | null = null;\nasync function getSandbox(binding: any, id: string, options?: any): Promise<any> {\n if (!_getSandboxFn) {\n const mod = await import('@cloudflare/sandbox');\n _getSandboxFn = mod.getSandbox as (binding: any, id: string, options?: any) => any;\n }\n return _getSandboxFn(binding, id, options);\n}\n\nimport type { Runtime, CodeResult, CommandResult, SandboxInfo, CreateSandboxOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\n// ─── Config ──────────────────────────────────────────────────────────────────\n\nexport interface CloudflareConfig {\n // Remote mode (from anywhere — talks to deployed gateway Worker)\n /** URL of the deployed gateway Worker (e.g. https://computesdk-sandbox.user.workers.dev) */\n sandboxUrl?: string;\n /** Shared secret for authenticating with the gateway Worker */\n sandboxSecret?: string;\n\n // Direct mode (inside a Cloudflare Worker — uses DO binding)\n /** Cloudflare Sandbox Durable Object binding from Workers environment */\n sandboxBinding?: any;\n\n // Shared options\n /** Default runtime environment */\n runtime?: Runtime;\n /** Execution timeout in milliseconds */\n timeout?: number;\n /** Environment variables to pass to sandbox */\n envVars?: Record<string, string>;\n /** Options passed to getSandbox() for lifecycle control (direct mode only) */\n sandboxOptions?: {\n sleepAfter?: string | number;\n keepAlive?: boolean;\n };\n}\n\n// ─── Internal types ──────────────────────────────────────────────────────────\n\ninterface CloudflareSandbox {\n sandboxId: string;\n exposedPorts: Map<number, string>;\n // Remote mode fields\n remote: boolean;\n sandboxUrl?: string;\n sandboxSecret?: string;\n pendingEnvVars?: Record<string, string>;\n remoteInitialized?: boolean;\n // Direct mode fields\n sandbox?: any; // The @cloudflare/sandbox instance\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction isRemote(config: CloudflareConfig): boolean {\n return !!(config.sandboxUrl && config.sandboxSecret);\n}\n\nfunction detectRuntime(code: string): Runtime {\n if (code.includes('print(') ||\n code.includes('import ') ||\n code.includes('def ') ||\n code.includes('sys.') ||\n code.includes('json.') ||\n code.includes('__') ||\n code.includes('f\"') ||\n code.includes(\"f'\") ||\n code.includes('raise ')) {\n return 'python';\n }\n if (code.includes('console.log') ||\n code.includes('process.') ||\n code.includes('require(') ||\n code.includes('module.exports') ||\n code.includes('__dirname') ||\n code.includes('__filename')) {\n return 'node';\n }\n return 'python';\n}\n\nfunction runtimeToLanguage(runtime: Runtime): 'python' | 'javascript' | 'typescript' {\n switch (runtime) {\n case 'python': return 'python';\n case 'node': return 'javascript';\n case 'bun': return 'javascript';\n case 'deno': return 'typescript';\n default: return 'python';\n }\n}\n\nfunction createSandboxId(): string {\n return `cf-sandbox-${crypto.randomUUID()}`;\n}\n\n/**\n * Make an authenticated request to the remote gateway Worker\n */\nasync function workerRequest(\n cfSandbox: CloudflareSandbox,\n path: string,\n body: Record<string, any> = {}\n): Promise<any> {\n const res = await fetch(`${cfSandbox.sandboxUrl}${path}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${cfSandbox.sandboxSecret}`,\n },\n body: JSON.stringify({ sandboxId: cfSandbox.sandboxId, ...body }),\n });\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n const text = await res.text().catch(() => '(unreadable)');\n throw new Error(`Worker request failed: ${res.status} - ${text.slice(0, 200)}`);\n }\n\n if (!res.ok) {\n throw new Error(data.error || `Worker request failed: ${res.status}`);\n }\n\n return data;\n}\n\nasync function workerRequestWithInit(\n cfSandbox: CloudflareSandbox,\n path: string,\n body: Record<string, any> = {}\n): Promise<any> {\n if (!cfSandbox.remote || cfSandbox.remoteInitialized) {\n return workerRequest(cfSandbox, path, body);\n }\n\n const initEnvVars = cfSandbox.pendingEnvVars;\n const requestBody = initEnvVars && Object.keys(initEnvVars).length > 0\n ? { ...body, initEnvVars }\n : body;\n\n const data = await workerRequest(cfSandbox, path, requestBody);\n cfSandbox.pendingEnvVars = undefined;\n cfSandbox.remoteInitialized = true;\n return data;\n}\n\n/**\n * Escape a string for safe use inside double-quoted shell arguments.\n */\nfunction shellEscape(s: string): string {\n return s.replace(/[\"$`\\\\!]/g, '\\\\$&');\n}\n\n/**\n * Process code execution results into a CodeResult (shared by remote and direct modes)\n */\nfunction processExecution(execution: any, detectedRuntime: Runtime): CodeResult {\n const stdoutParts: string[] = [];\n const stderrParts: string[] = [];\n\n if (execution.logs) {\n if (execution.logs.stdout) stdoutParts.push(...execution.logs.stdout);\n if (execution.logs.stderr) stderrParts.push(...execution.logs.stderr);\n }\n if (execution.results && Array.isArray(execution.results)) {\n for (const res of execution.results) {\n if (res.text) stdoutParts.push(res.text);\n }\n }\n if (execution.error) {\n const errorMsg = execution.error.message || execution.error.name || 'Execution error';\n if (errorMsg.includes('SyntaxError') || errorMsg.includes('invalid syntax')) {\n throw new Error(`Syntax error: ${errorMsg}`);\n }\n stderrParts.push(errorMsg);\n }\n\n const stdout = stdoutParts.join('\\n');\n const stderr = stderrParts.join('\\n');\n\n return {\n output: stderr ? `${stdout}${stdout && stderr ? '\\n' : ''}${stderr}` : stdout,\n exitCode: execution.error ? 1 : 0,\n language: detectedRuntime\n };\n}\n\n/**\n * Parse ls -la output into FileEntry objects (used by both modes for readdir)\n */\nfunction parseLsOutput(stdout: string): FileEntry[] {\n const lines = stdout.split('\\n').filter((line: string) => line.trim() && !line.startsWith('total'));\n\n return lines.map((line: string) => {\n const parts = line.trim().split(/\\s+/);\n const permissions = parts[0] || '';\n const size = parseInt(parts[4]) || 0;\n const dateStr = (parts[5] || '') + ' ' + (parts[6] || '');\n const date = dateStr.trim() ? new Date(dateStr) : new Date();\n const name = parts.slice(8).join(' ') || parts[parts.length - 1] || 'unknown';\n\n return {\n name,\n type: permissions.startsWith('d') ? 'directory' as const : 'file' as const,\n size,\n modified: isNaN(date.getTime()) ? new Date() : date\n };\n });\n}\n\n// ─── Provider ────────────────────────────────────────────────────────────────\n\nexport const cloudflare = defineProvider<CloudflareSandbox, CloudflareConfig>({\n name: 'cloudflare',\n methods: {\n sandbox: {\n // ─── Collection operations ───────────────────────────────────────\n\n create: async (config: CloudflareConfig, options?: CreateSandboxOptions) => {\n // Destructure known ComputeSDK fields, collect the rest for passthrough\n const {\n runtime: _runtime,\n timeout: optTimeout,\n envs,\n name: _name,\n metadata: _metadata,\n templateId: _templateId,\n snapshotId: _snapshotId,\n sandboxId: optSandboxId,\n namespace: _namespace,\n directory: _directory,\n overlays: _overlays,\n servers: _servers,\n ports: _ports,\n ...rest\n } = options || {};\n\n const sandboxId = optSandboxId || createSandboxId();\n const envVars = { ...config.envVars, ...envs };\n // options.timeout takes precedence over config.timeout\n const timeout = optTimeout ?? config.timeout;\n const sleepAfter = timeout ? `${Math.ceil(timeout / 1000)}s` : undefined;\n\n // Remote mode\n if (isRemote(config)) {\n return {\n sandbox: {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n pendingEnvVars: Object.keys(envVars).length > 0 ? envVars : undefined,\n remoteInitialized: false,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n }\n\n // Direct mode\n if (!config.sandboxBinding) {\n throw new Error(\n 'Missing Cloudflare config. Either:\\n' +\n ' 1. Set CLOUDFLARE_SANDBOX_URL + CLOUDFLARE_SANDBOX_SECRET (remote mode)\\n' +\n ' 2. Provide sandboxBinding from your Workers environment (direct mode)\\n' +\n 'Run `npx @computesdk/cloudflare` to deploy a gateway Worker.'\n );\n }\n\n try {\n const sandboxOpts = { ...config.sandboxOptions };\n if (sleepAfter) {\n sandboxOpts.sleepAfter = sleepAfter;\n }\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, sandboxOpts);\n\n if (Object.keys(envVars).length > 0) {\n await sandbox.setEnvVars(envVars);\n }\n\n return {\n sandbox: {\n sandbox,\n sandboxId,\n remote: false,\n exposedPorts: new Map(),\n },\n sandboxId\n };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('binding')) {\n throw new Error(\n 'Cloudflare Sandbox binding failed. Ensure your Durable Object binding is properly configured in wrangler.toml. ' +\n 'See https://developers.cloudflare.com/sandbox/get-started/ for setup instructions.'\n );\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error('Cloudflare resource limits exceeded. Check your usage at https://dash.cloudflare.com/');\n }\n }\n throw new Error(`Failed to create Cloudflare sandbox: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getById: async (config: CloudflareConfig, sandboxId: string) => {\n // Remote mode\n if (isRemote(config)) {\n try {\n const cfSandbox: CloudflareSandbox = {\n sandboxId,\n remote: true,\n sandboxUrl: config.sandboxUrl,\n sandboxSecret: config.sandboxSecret,\n remoteInitialized: true,\n exposedPorts: new Map(),\n };\n // Verify sandbox is alive\n await workerRequest(cfSandbox, '/v1/sandbox/exec', { command: 'true' });\n return { sandbox: cfSandbox, sandboxId };\n } catch {\n return null;\n }\n }\n\n // Direct mode\n if (!config.sandboxBinding) return null;\n\n try {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId, config.sandboxOptions);\n await sandbox.exec('true');\n return {\n sandbox: { sandbox, sandboxId, remote: false, exposedPorts: new Map() },\n sandboxId\n };\n } catch {\n return null;\n }\n },\n\n list: async (_config: CloudflareConfig) => {\n throw new Error(\n 'Cloudflare provider does not support listing sandboxes. ' +\n 'Durable Objects do not have a native list API. ' +\n 'Use getById to reconnect to specific sandboxes by ID.'\n );\n },\n\n destroy: async (config: CloudflareConfig, sandboxId: string) => {\n try {\n if (isRemote(config)) {\n await workerRequest(\n { sandboxId, remote: true, sandboxUrl: config.sandboxUrl, sandboxSecret: config.sandboxSecret, exposedPorts: new Map() },\n '/v1/sandbox/destroy'\n );\n return;\n }\n\n if (config.sandboxBinding) {\n const sandbox = await getSandbox(config.sandboxBinding, sandboxId);\n await sandbox.destroy();\n }\n } catch {\n // Sandbox might already be destroyed\n }\n },\n\n // ─── Instance operations ─────────────────────────────────────────\n\n runCode: async (cfSandbox: CloudflareSandbox, code: string, runtime?: Runtime): Promise<CodeResult> => {\n const detectedRuntime = runtime || detectRuntime(code);\n const language = runtimeToLanguage(detectedRuntime);\n\n // Remote mode\n if (cfSandbox.remote) {\n const execution = await workerRequestWithInit(cfSandbox, '/v1/sandbox/runCode', { code, language });\n return processExecution(execution, detectedRuntime);\n }\n\n // Direct mode\n try {\n const execution = await cfSandbox.sandbox.runCode(code, { language });\n return processExecution(execution, detectedRuntime);\n } catch (error) {\n if (error instanceof Error && error.message.includes('Syntax error')) throw error;\n throw new Error(`Cloudflare execution failed: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n runCommand: async (cfSandbox: CloudflareSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n\n // Remote mode\n if (cfSandbox.remote) {\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const result = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exec', {\n command: fullCommand,\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: result.stdout || '',\n stderr: result.stderr || '',\n exitCode: result.exitCode,\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 // Direct mode\n try {\n let fullCommand = command;\n if (options?.background) {\n fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;\n }\n\n const execResult = await cfSandbox.sandbox.exec(fullCommand, {\n cwd: options?.cwd,\n env: options?.env,\n timeout: options?.timeout,\n });\n\n return {\n stdout: execResult.stdout || '',\n stderr: execResult.stderr || '',\n exitCode: execResult.exitCode,\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 getInfo: async (cfSandbox: CloudflareSandbox): Promise<SandboxInfo> => {\n try {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/info');\n } else {\n await cfSandbox.sandbox.exec('true');\n }\n\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n }\n };\n } catch (error) {\n return {\n id: cfSandbox.sandboxId,\n provider: 'cloudflare',\n runtime: 'python',\n status: 'error',\n createdAt: new Date(),\n timeout: 300000,\n metadata: {\n cloudflareSandboxId: cfSandbox.sandboxId,\n mode: cfSandbox.remote ? 'remote' : 'direct',\n error: error instanceof Error ? error.message : String(error)\n }\n };\n }\n },\n\n getUrl: async (cfSandbox: CloudflareSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const { port, protocol = 'https' } = options;\n\n if (cfSandbox.exposedPorts.has(port)) {\n return cfSandbox.exposedPorts.get(port)!;\n }\n\n let preview: any;\n if (cfSandbox.remote) {\n preview = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exposePort', { port, options: {} });\n } else {\n preview = await cfSandbox.sandbox.exposePort(port, {});\n }\n\n const url = `${protocol}://${preview.url}`;\n cfSandbox.exposedPorts.set(port, url);\n return url;\n },\n\n // ─── Filesystem ────────────────────────────────────────────────\n\n filesystem: {\n readFile: async (cfSandbox: CloudflareSandbox, path: string): Promise<string> => {\n if (cfSandbox.remote) {\n const file = await workerRequestWithInit(cfSandbox, '/v1/sandbox/readFile', { path });\n return file.content || '';\n }\n const file = await cfSandbox.sandbox.readFile(path);\n return file.content || '';\n },\n\n writeFile: async (cfSandbox: CloudflareSandbox, path: string, content: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/writeFile', { path, content });\n return;\n }\n await cfSandbox.sandbox.writeFile(path, content);\n },\n\n mkdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/mkdir', { path });\n return;\n }\n await cfSandbox.sandbox.mkdir(path, { recursive: true });\n },\n\n readdir: async (cfSandbox: CloudflareSandbox, path: string): Promise<FileEntry[]> => {\n // Both modes use ls -la since there's no native readdir\n let result: any;\n if (cfSandbox.remote) {\n result = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exec', {\n command: `ls -la \"${shellEscape(path)}\"`,\n cwd: '/',\n });\n } else {\n result = await cfSandbox.sandbox.exec(`ls -la \"${shellEscape(path)}\"`, { cwd: '/' });\n }\n\n if (result.exitCode !== 0) {\n throw new Error(`Directory listing failed: ${result.stderr}`);\n }\n\n return parseLsOutput(result.stdout);\n },\n\n exists: async (cfSandbox: CloudflareSandbox, path: string): Promise<boolean> => {\n if (cfSandbox.remote) {\n const result = await workerRequestWithInit(cfSandbox, '/v1/sandbox/exists', { path });\n return result.exists;\n }\n const result = await cfSandbox.sandbox.exists(path);\n return result.exists;\n },\n\n remove: async (cfSandbox: CloudflareSandbox, path: string): Promise<void> => {\n if (cfSandbox.remote) {\n await workerRequestWithInit(cfSandbox, '/v1/sandbox/deleteFile', { path });\n return;\n }\n await cfSandbox.sandbox.deleteFile(path);\n }\n }\n }\n }\n});"],"mappings":"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","names":["file","result"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/cloudflare",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "Cloudflare provider for ComputeSDK - edge code execution using Cloudflare Workers and Durable Objects",
5
5
  "author": "Garrison",
6
6
  "license": "MIT",
@@ -22,9 +22,9 @@
22
22
  "src/worker"
23
23
  ],
24
24
  "dependencies": {
25
- "@cloudflare/sandbox": "^0.7.0",
26
- "computesdk": "2.5.1",
27
- "@computesdk/provider": "1.0.31"
25
+ "@cloudflare/sandbox": "^0.7.18",
26
+ "@computesdk/provider": "1.0.31",
27
+ "computesdk": "2.5.1"
28
28
  },
29
29
  "keywords": [
30
30
  "computesdk",
@@ -1 +1 @@
1
- FROM docker.io/cloudflare/sandbox:0.7.17
1
+ FROM docker.io/cloudflare/sandbox:0.7.18
@@ -50,12 +50,14 @@ export default {
50
50
  try {
51
51
  const sandbox = getSandbox(env.Sandbox, sandboxId);
52
52
 
53
+ if (body.initEnvVars) {
54
+ await sandbox.setEnvVars(body.initEnvVars);
55
+ }
56
+
53
57
  // --- Sandbox lifecycle ---
54
58
 
55
59
  if (url.pathname === '/v1/sandbox/create') {
56
60
  if (body.envVars) await sandbox.setEnvVars(body.envVars);
57
- // Trigger lazy container start
58
- await sandbox.exec('true');
59
61
  return Response.json({ sandboxId, status: 'running' });
60
62
  }
61
63
 
@@ -139,4 +141,4 @@ export default {
139
141
  return Response.json({ error: message }, { status: 500 });
140
142
  }
141
143
  },
142
- };
144
+ };
@@ -3,6 +3,6 @@
3
3
  "private": true,
4
4
  "type": "module",
5
5
  "dependencies": {
6
- "@cloudflare/sandbox": "^0.7.0"
6
+ "@cloudflare/sandbox": "^0.7.18"
7
7
  }
8
8
  }
@@ -7,7 +7,7 @@
7
7
  {
8
8
  "class_name": "Sandbox",
9
9
  "image": "./Dockerfile",
10
- "max_instances": 10
10
+ "max_instances": 1000
11
11
  }
12
12
  ],
13
13
  "durable_objects": {