@computesdk/codesandbox 1.5.68 → 1.5.70

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
@@ -1,5 +1,5 @@
1
- import * as _computesdk_provider from '@computesdk/provider';
2
1
  import * as computesdk from 'computesdk';
2
+ import * as _computesdk_provider from '@computesdk/provider';
3
3
  import { Sandbox } from '@codesandbox/sdk';
4
4
 
5
5
  interface CodesandboxConfig {
@@ -12,6 +12,16 @@ interface CodesandboxConfig {
12
12
  /** Execution timeout in milliseconds */
13
13
  timeout?: number;
14
14
  }
15
- declare const codesandbox: (config: CodesandboxConfig) => _computesdk_provider.Provider<Sandbox, any, any, computesdk.Volume>;
15
+ /**
16
+ * The CodeSandbox SDK sandbox, plus `pause()` (hibernate: memory and disk are
17
+ * kept) and `resume()` (wake the same sandbox id).
18
+ */
19
+ type CodesandboxSandbox = Sandbox & {
20
+ pause(): Promise<void>;
21
+ resume(): Promise<void>;
22
+ };
23
+ declare const codesandbox: (config: CodesandboxConfig & _computesdk_provider.ProcessRuntimeOptions) => _computesdk_provider.Provider<CodesandboxSandbox, any, any, computesdk.Volume> & {
24
+ readonly sizes: computesdk.InstanceSizeManager;
25
+ };
16
26
 
17
- export { type CodesandboxConfig, codesandbox };
27
+ export { type CodesandboxConfig, type CodesandboxSandbox, codesandbox };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import * as _computesdk_provider from '@computesdk/provider';
2
1
  import * as computesdk from 'computesdk';
2
+ import * as _computesdk_provider from '@computesdk/provider';
3
3
  import { Sandbox } from '@codesandbox/sdk';
4
4
 
5
5
  interface CodesandboxConfig {
@@ -12,6 +12,16 @@ interface CodesandboxConfig {
12
12
  /** Execution timeout in milliseconds */
13
13
  timeout?: number;
14
14
  }
15
- declare const codesandbox: (config: CodesandboxConfig) => _computesdk_provider.Provider<Sandbox, any, any, computesdk.Volume>;
15
+ /**
16
+ * The CodeSandbox SDK sandbox, plus `pause()` (hibernate: memory and disk are
17
+ * kept) and `resume()` (wake the same sandbox id).
18
+ */
19
+ type CodesandboxSandbox = Sandbox & {
20
+ pause(): Promise<void>;
21
+ resume(): Promise<void>;
22
+ };
23
+ declare const codesandbox: (config: CodesandboxConfig & _computesdk_provider.ProcessRuntimeOptions) => _computesdk_provider.Provider<CodesandboxSandbox, any, any, computesdk.Volume> & {
24
+ readonly sizes: computesdk.InstanceSizeManager;
25
+ };
16
26
 
17
- export { type CodesandboxConfig, codesandbox };
27
+ export { type CodesandboxConfig, type CodesandboxSandbox, codesandbox };
package/dist/index.js CHANGED
@@ -25,62 +25,189 @@ __export(index_exports, {
25
25
  module.exports = __toCommonJS(index_exports);
26
26
  var import_sdk = require("@codesandbox/sdk");
27
27
  var import_provider = require("@computesdk/provider");
28
+ var SNAPSHOT_TAG = "computesdk-snapshot";
29
+ var states = /* @__PURE__ */ new WeakMap();
30
+ var statesById = /* @__PURE__ */ new Map();
31
+ var openClients = /* @__PURE__ */ new Map();
32
+ function resolveApiKey(config) {
33
+ const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
34
+ if (!apiKey) {
35
+ throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);
36
+ }
37
+ return apiKey;
38
+ }
39
+ function sdkFor(config) {
40
+ return new import_sdk.CodeSandbox(resolveApiKey(config));
41
+ }
42
+ async function closeClient(sandboxId) {
43
+ const client = openClients.get(sandboxId);
44
+ if (!client) return;
45
+ openClients.delete(sandboxId);
46
+ try {
47
+ const open = await client;
48
+ await open.disconnect().catch(() => void 0);
49
+ open.dispose();
50
+ } catch {
51
+ }
52
+ }
53
+ function track(sdk, native) {
54
+ const state = { sdk, current: native };
55
+ states.set(native, state);
56
+ statesById.set(native.id, state);
57
+ const sandbox = native;
58
+ Object.defineProperty(sandbox, "pause", {
59
+ configurable: true,
60
+ value: async () => {
61
+ await closeClient(sandbox.id);
62
+ state.client = void 0;
63
+ await sdk.sandboxes.hibernate(sandbox.id);
64
+ }
65
+ });
66
+ Object.defineProperty(sandbox, "resume", {
67
+ configurable: true,
68
+ value: async () => {
69
+ await closeClient(sandbox.id);
70
+ state.client = void 0;
71
+ state.current = await sdk.sandboxes.resume(sandbox.id);
72
+ }
73
+ });
74
+ return sandbox;
75
+ }
76
+ async function refreshSession(sandboxId) {
77
+ await closeClient(sandboxId);
78
+ const state = statesById.get(sandboxId);
79
+ if (!state) return;
80
+ state.client = void 0;
81
+ state.current = await state.sdk.sandboxes.resume(sandboxId);
82
+ }
83
+ function getClient(sandbox) {
84
+ const state = states.get(sandbox);
85
+ if (!state) return sandbox.connect();
86
+ if (state.client && openClients.get(sandbox.id) !== state.client) state.client = void 0;
87
+ if (!state.client) {
88
+ const client = state.current.connect();
89
+ state.client = client;
90
+ openClients.set(sandbox.id, client);
91
+ client.catch(() => {
92
+ if (state.client === client) state.client = void 0;
93
+ if (openClients.get(sandbox.id) === client) openClients.delete(sandbox.id);
94
+ });
95
+ }
96
+ return state.client;
97
+ }
98
+ function shQuote(value) {
99
+ return `'${value.replace(/'/g, `'\\''`)}'`;
100
+ }
101
+ function randomToken() {
102
+ return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
103
+ }
104
+ var TIMEOUT_EXIT_CODE = 124;
105
+ function wrapCommand(command, token, timeoutMs) {
106
+ const out = `/tmp/.computesdk-${token}.out`;
107
+ const err = `/tmp/.computesdk-${token}.err`;
108
+ const marker = `'__CSDK_' '${token}__'`;
109
+ const body = timeoutMs && timeoutMs > 0 ? `if command -v timeout >/dev/null 2>&1; then timeout -k 2 ${Math.max(1, Math.ceil(timeoutMs / 1e3))} bash -c ${shQuote(command)}; else bash -c ${shQuote(command)}; fi` : command;
110
+ return [
111
+ `(
112
+ ${body}
113
+ ) </dev/null >${out} 2>${err}; __csdk_ec=$?`,
114
+ `{ printf '%s%s%s:' ${marker} "$__csdk_ec"; base64 ${out} | tr -d '\\n'; printf ':'; base64 ${err} | tr -d '\\n'; printf '%s%s' ${marker}; } >${resultPath(token)}.tmp`,
115
+ `mv -f ${resultPath(token)}.tmp ${resultPath(token)}; rm -f ${out} ${err}; cat ${resultPath(token)}`
116
+ ].join("; ");
117
+ }
118
+ function resultPath(token) {
119
+ return `/tmp/.computesdk-${token}.res`;
120
+ }
121
+ function parseWrapped(output, marker) {
122
+ const flat = output.replace(/[\r\n]/g, "");
123
+ const start = flat.indexOf(marker);
124
+ if (start === -1) return void 0;
125
+ const end = flat.indexOf(marker, start + marker.length);
126
+ if (end === -1) return void 0;
127
+ const [code, out = "", err = ""] = flat.slice(start + marker.length, end).split(":");
128
+ const exitCode = Number.parseInt(code, 10);
129
+ if (!Number.isFinite(exitCode)) return void 0;
130
+ return {
131
+ stdout: Buffer.from(out, "base64").toString("utf8"),
132
+ stderr: Buffer.from(err, "base64").toString("utf8"),
133
+ exitCode
134
+ };
135
+ }
136
+ var SessionError = class extends Error {
137
+ constructor(cause) {
138
+ super(cause instanceof Error ? cause.message : String(cause));
139
+ }
140
+ };
141
+ async function runToCompletion(client, wrapped, runOpts, resultFile, timeoutMs) {
142
+ const cmd = await client.commands.runBackground(wrapped, runOpts).catch((error) => {
143
+ throw new SessionError(error);
144
+ });
145
+ let settled = false;
146
+ const finished = cmd.waitUntilComplete().then(
147
+ (output) => output,
148
+ (error) => typeof error?.output === "string" ? error.output : ""
149
+ );
150
+ const polled = (async () => {
151
+ for (let delay = 100; !settled; delay = Math.min(delay * 2, 1e3)) {
152
+ await new Promise((resolve) => setTimeout(resolve, delay));
153
+ if (settled) break;
154
+ const exists = await client.fs.stat(resultFile).then(() => true, () => false);
155
+ if (exists) {
156
+ cmd.kill().catch(() => void 0);
157
+ return "";
158
+ }
159
+ }
160
+ return "";
161
+ })();
162
+ let timer;
163
+ const deadline = timeoutMs === void 0 ? void 0 : new Promise((resolve) => {
164
+ timer = setTimeout(() => resolve(void 0), timeoutMs);
165
+ });
166
+ try {
167
+ return await Promise.race([finished, polled, ...deadline ? [deadline] : []]);
168
+ } finally {
169
+ settled = true;
170
+ clearTimeout(timer);
171
+ }
172
+ }
28
173
  var codesandbox = (0, import_provider.defineProvider)({
29
174
  name: "codesandbox",
30
175
  methods: {
31
176
  instances: {
32
177
  create: async (config, options) => {
33
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
34
- if (!apiKey) {
35
- throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);
36
- }
37
- const sdk = new import_sdk.CodeSandbox(apiKey);
178
+ const sdk = sdkFor(config);
38
179
  try {
39
- let sandbox;
40
- let sandboxId;
41
- if (options?.snapshotId) {
42
- sandbox = await sdk.sandboxes.resume(options.snapshotId);
43
- sandboxId = options.snapshotId;
44
- } else {
45
- const {
46
- timeout: _timeout,
47
- envs,
48
- name: _name,
49
- metadata: _metadata,
50
- templateId: optTemplateId,
51
- snapshotId: _snapshotId,
52
- sandboxId: _sandboxId,
53
- namespace: _namespace,
54
- directory: _directory,
55
- ...providerOptions
56
- } = options || {};
57
- const createOptions = { ...providerOptions };
58
- const templateId = optTemplateId || config.templateId;
59
- if (templateId) createOptions.id = templateId;
60
- if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;
61
- sandbox = await sdk.sandboxes.create(createOptions);
62
- sandboxId = sandbox.id;
63
- }
64
- return { instance: sandbox, instanceId: sandboxId };
180
+ const {
181
+ timeout: _timeout,
182
+ envs,
183
+ name: _name,
184
+ metadata: _metadata,
185
+ templateId: optTemplateId,
186
+ snapshotId,
187
+ sandboxId: _sandboxId,
188
+ namespace: _namespace,
189
+ directory: _directory,
190
+ ...providerOptions
191
+ } = options || {};
192
+ const createOptions = { ...providerOptions };
193
+ const templateId = snapshotId || optTemplateId || config.templateId;
194
+ if (templateId) createOptions.id = templateId;
195
+ if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;
196
+ const sandbox = await sdk.sandboxes.create(createOptions);
197
+ return { instance: track(sdk, sandbox), instanceId: sandbox.id };
65
198
  } catch (error) {
66
- if (error instanceof Error) {
67
- if (error.message.includes("unauthorized") || error.message.includes("API key")) {
68
- throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable.`);
69
- }
70
- if (error.message.includes("quota") || error.message.includes("limit")) {
71
- throw new Error(`CodeSandbox quota exceeded. Please check your usage at https://codesandbox.io/dashboard`);
72
- }
199
+ const message = error instanceof Error ? error.message : String(error);
200
+ if (/unauthori[sz]ed|API key/i.test(message)) {
201
+ throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable. (${message})`);
73
202
  }
74
- throw new Error(`Failed to create CodeSandbox sandbox: ${error instanceof Error ? error.message : String(error)}`);
203
+ throw new Error(`Failed to create CodeSandbox sandbox: ${message}`);
75
204
  }
76
205
  },
77
206
  getById: async (config, sandboxId) => {
78
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
79
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
80
- const sdk = new import_sdk.CodeSandbox(apiKey);
207
+ const sdk = sdkFor(config);
81
208
  try {
82
209
  const sandbox = await sdk.sandboxes.resume(sandboxId);
83
- return { instance: sandbox, instanceId: sandboxId };
210
+ return { instance: track(sdk, sandbox), instanceId: sandboxId };
84
211
  } catch {
85
212
  return null;
86
213
  }
@@ -89,49 +216,72 @@ var codesandbox = (0, import_provider.defineProvider)({
89
216
  throw new Error(`CodeSandbox provider does not support listing sandboxes.`);
90
217
  },
91
218
  destroy: async (config, sandboxId) => {
92
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
93
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
94
- const sdk = new import_sdk.CodeSandbox(apiKey);
219
+ const sdk = sdkFor(config);
220
+ await closeClient(sandboxId);
221
+ statesById.delete(sandboxId);
95
222
  try {
96
223
  await sdk.sandboxes.shutdown(sandboxId);
97
224
  } catch {
98
225
  }
99
- try {
100
- await sdk.sandboxes.delete(sandboxId);
101
- } catch (error) {
102
- const message = error instanceof Error ? error.message : String(error);
103
- if (!message.includes("not found") && !message.includes("404")) {
104
- throw new Error(`Failed to delete CodeSandbox sandbox "${sandboxId}": ${message}`);
226
+ let lastError;
227
+ for (let attempt = 0; attempt < 3; attempt++) {
228
+ try {
229
+ await sdk.sandboxes.delete(sandboxId);
230
+ return;
231
+ } catch (error) {
232
+ const message2 = error instanceof Error ? error.message : String(error);
233
+ if (/not found|404/i.test(message2)) return;
234
+ lastError = error;
235
+ await new Promise((resolve) => setTimeout(resolve, 2e3 * (attempt + 1)));
105
236
  }
106
237
  }
238
+ const message = lastError instanceof Error ? lastError.message : String(lastError);
239
+ throw new Error(`Failed to delete CodeSandbox sandbox "${sandboxId}": ${message}`);
107
240
  },
108
241
  runCommand: async (sandbox, command, options) => {
109
242
  const startTime = Date.now();
110
- try {
111
- const client = await sandbox.connect();
112
- let fullCommand = command;
113
- if (options?.env && Object.keys(options.env).length > 0) {
114
- const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}="${(0, import_provider.escapeShellArg)(v)}"`).join(" ");
115
- fullCommand = `${envPrefix} ${fullCommand}`;
243
+ const runOpts = {};
244
+ if (options?.env && Object.keys(options.env).length > 0) runOpts.env = options.env;
245
+ if (options?.cwd) runOpts.cwd = options.cwd;
246
+ const run = async () => {
247
+ const client = await getClient(sandbox).catch((error) => {
248
+ throw new SessionError(error);
249
+ });
250
+ if (options?.background) {
251
+ await client.commands.runBackground(`setsid bash -c ${shQuote(command)} </dev/null >/dev/null 2>&1 &`, runOpts).catch((error) => {
252
+ throw new SessionError(error);
253
+ });
254
+ return { stdout: "", stderr: "", exitCode: 0, durationMs: Date.now() - startTime };
255
+ }
256
+ const token = randomToken();
257
+ const marker = `__CSDK_${token}__`;
258
+ const clientTimeoutMs = options?.timeout && options.timeout > 0 ? options.timeout + 1e4 : void 0;
259
+ const output = await runToCompletion(client, wrapCommand(command, token, options?.timeout), runOpts, resultPath(token), clientTimeoutMs);
260
+ if (output === void 0) {
261
+ return { stdout: "", stderr: `Command timed out after ${options.timeout}ms`, exitCode: TIMEOUT_EXIT_CODE, durationMs: Date.now() - startTime };
262
+ }
263
+ let parsed = parseWrapped(output, marker);
264
+ if (!parsed) {
265
+ const saved = await client.fs.readTextFile(resultPath(token)).catch(() => void 0);
266
+ parsed = saved === void 0 ? void 0 : parseWrapped(saved, marker);
116
267
  }
117
- if (options?.cwd) fullCommand = `cd "${(0, import_provider.escapeShellArg)(options.cwd)}" && ${fullCommand}`;
118
- if (options?.background) fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
119
- const errFile = `/tmp/.computesdk-stderr-${Date.now()}-${Math.random().toString(36).slice(2)}`;
120
- const delim = `__COMPUTESDK_EXIT_${Date.now()}_${Math.random().toString(36).slice(2)}__`;
121
- const wrapped = `{ ${fullCommand} ; } 2>${(0, import_provider.escapeShellArg)(errFile)}; __cs_ec=$?; echo "${delim}$__cs_ec"; cat ${(0, import_provider.escapeShellArg)(errFile)} 2>/dev/null; rm -f ${(0, import_provider.escapeShellArg)(errFile)}`;
122
- const output = await client.commands.run(wrapped);
123
- const delimIdx = output.lastIndexOf(delim);
124
- if (delimIdx === -1) {
125
- return { stdout: output, stderr: "", exitCode: 0, durationMs: Date.now() - startTime };
268
+ client.fs.remove(resultPath(token)).catch(() => void 0);
269
+ if (!parsed) {
270
+ return { stdout: output.replace(/\r\n/g, "\n"), stderr: "", exitCode: 0, durationMs: Date.now() - startTime };
271
+ }
272
+ return { ...parsed, durationMs: Date.now() - startTime };
273
+ };
274
+ try {
275
+ try {
276
+ return await run();
277
+ } catch (error) {
278
+ if (!(error instanceof SessionError)) throw error;
279
+ await refreshSession(sandbox.id);
280
+ return await run();
126
281
  }
127
- const after = output.substring(delimIdx + delim.length);
128
- const newlineIdx = after.indexOf("\n");
129
- const exitCode = parseInt(newlineIdx === -1 ? after : after.substring(0, newlineIdx), 10) || 0;
130
- const stderr = newlineIdx === -1 ? "" : after.substring(newlineIdx + 1);
131
- const stdout = output.substring(0, delimIdx).replace(/\n$/, "");
132
- return { stdout, stderr, exitCode, durationMs: Date.now() - startTime };
133
282
  } catch (error) {
134
- return { stdout: "", stderr: error instanceof Error ? error.message : String(error), exitCode: 127, durationMs: Date.now() - startTime };
283
+ const exitCode = typeof error?.exitCode === "number" ? error.exitCode : 127;
284
+ return { stdout: "", stderr: error instanceof Error ? error.message : String(error), exitCode, durationMs: Date.now() - startTime };
135
285
  }
136
286
  },
137
287
  getInfo: async (sandbox) => ({
@@ -148,68 +298,84 @@ var codesandbox = (0, import_provider.defineProvider)({
148
298
  },
149
299
  filesystem: {
150
300
  readFile: async (sandbox, path) => {
151
- const client = await sandbox.connect();
301
+ const client = await getClient(sandbox);
152
302
  return client.fs.readTextFile(path);
153
303
  },
154
304
  writeFile: async (sandbox, path, content) => {
155
- const client = await sandbox.connect();
305
+ const client = await getClient(sandbox);
156
306
  await client.fs.writeTextFile(path, content);
157
307
  },
158
308
  mkdir: async (sandbox, path) => {
159
- const client = await sandbox.connect();
160
- await client.commands.run(`mkdir -p "${path}"`);
309
+ const client = await getClient(sandbox);
310
+ await client.fs.mkdir(path, true);
161
311
  },
162
312
  readdir: async (sandbox, path) => {
163
- const client = await sandbox.connect();
313
+ const client = await getClient(sandbox);
164
314
  const entries = await client.fs.readdir(path);
165
315
  return entries.map((entry) => ({
166
316
  name: entry.name,
167
- type: entry.isDirectory ? "directory" : "file",
168
- size: entry.size || 0,
169
- modified: entry.lastModified ? new Date(entry.lastModified) : /* @__PURE__ */ new Date()
317
+ type: entry.type === "directory" ? "directory" : "file",
318
+ size: 0,
319
+ modified: /* @__PURE__ */ new Date()
170
320
  }));
171
321
  },
172
322
  exists: async (sandbox, path) => {
173
- const client = await sandbox.connect();
323
+ const client = await getClient(sandbox);
174
324
  try {
175
- await client.commands.run(`ls "${path}"`);
325
+ await client.fs.stat(path);
176
326
  return true;
177
327
  } catch {
178
328
  return false;
179
329
  }
180
330
  },
181
331
  remove: async (sandbox, path) => {
182
- const client = await sandbox.connect();
183
- await client.fs.remove(path);
332
+ const client = await getClient(sandbox);
333
+ await client.fs.remove(path, true);
184
334
  }
185
335
  },
336
+ // Hibernate keeps the VM's memory and disk; resume wakes the same sandbox id.
337
+ pause: (sandbox) => sandbox.pause(),
338
+ resume: (sandbox) => sandbox.resume(),
339
+ pauseCapabilities: { memory: true },
186
340
  getInstance: (sandbox) => sandbox
187
341
  },
188
342
  snapshot: {
343
+ // A fork of the running sandbox (memory, processes and disk), hibernated
344
+ // so it persists as a restore point independent of the source.
189
345
  create: async (config, sandboxId, options) => {
190
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
191
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
192
- const sdk = new import_sdk.CodeSandbox(apiKey);
346
+ const sdk = sdkFor(config);
193
347
  try {
194
- const sandbox = await sdk.sandboxes.resume(sandboxId);
195
- await sdk.sandboxes.hibernate(sandboxId);
196
- return { id: sandbox.id, provider: "codesandbox", createdAt: /* @__PURE__ */ new Date(), metadata: { name: options?.name, bootupType: sandbox.bootupType } };
348
+ const fork = await sdk.sandboxes.create({
349
+ id: sandboxId,
350
+ tags: [SNAPSHOT_TAG],
351
+ ...options?.name ? { title: options.name } : {}
352
+ });
353
+ await sdk.sandboxes.hibernate(fork.id);
354
+ await refreshSession(sandboxId);
355
+ return { id: fork.id, provider: "codesandbox", createdAt: /* @__PURE__ */ new Date(), metadata: { name: options?.name, sourceSandboxId: sandboxId } };
197
356
  } catch (error) {
198
357
  throw new Error(`Failed to create CodeSandbox snapshot: ${error instanceof Error ? error.message : String(error)}`);
199
358
  }
200
359
  },
201
- list: async (_config) => {
202
- throw new Error(`CodeSandbox provider does not support listing snapshots.`);
360
+ list: async (config) => {
361
+ const sdk = sdkFor(config);
362
+ const { sandboxes } = await sdk.sandboxes.list({ tags: [SNAPSHOT_TAG] });
363
+ return sandboxes.filter((s) => s.tags?.includes(SNAPSHOT_TAG)).map((s) => ({ id: s.id, provider: "codesandbox", createdAt: s.createdAt, metadata: { name: s.title } }));
203
364
  },
204
365
  delete: async (config, snapshotId) => {
205
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
206
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
207
- const sdk = new import_sdk.CodeSandbox(apiKey);
366
+ const sdk = sdkFor(config);
208
367
  try {
209
- await sdk.sandboxes.shutdown(snapshotId);
210
- } catch {
368
+ await sdk.sandboxes.delete(snapshotId);
369
+ } catch (error) {
370
+ const message = error instanceof Error ? error.message : String(error);
371
+ if (!/not found|404/i.test(message)) {
372
+ throw new Error(`Failed to delete CodeSandbox snapshot "${snapshotId}": ${message}`);
373
+ }
211
374
  }
212
- }
375
+ },
376
+ // Forks keep the whole VM, memory and /tmp included; the source keeps
377
+ // running, and each restore is an independent fork of the snapshot.
378
+ capabilities: { scope: "rootfs", memory: true, destroysSource: false, source: "kept", fork: true, readiness: "immediate" }
213
379
  },
214
380
  template: {
215
381
  create: async (_config, _options) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Codesandbox Provider - Factory-based Implementation\n */\n\nimport { CodeSandbox } from '@codesandbox/sdk';\nimport type { Sandbox as CodesandboxSandbox } from '@codesandbox/sdk';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\n\nimport type { CommandResult, InstanceInfo, CreateInstanceOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\nexport interface CodesandboxConfig {\n /** CodeSandbox API key - if not provided, will fallback to CSB_API_KEY environment variable */\n apiKey?: string;\n /** Template to use for new sandboxes */\n templateId?: string;\n /** Default runtime environment (e.g. 'node', 'python') */\n runtime?: string;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\nexport const codesandbox = defineProvider<CodesandboxSandbox, CodesandboxConfig, any, any>({\n name: 'codesandbox',\n methods: {\n instances: {\n create: async (config: CodesandboxConfig, options?: CreateInstanceOptions) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) {\n throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);\n }\n const sdk = new CodeSandbox(apiKey);\n try {\n let sandbox: CodesandboxSandbox;\n let sandboxId: string;\n if (options?.snapshotId) {\n sandbox = await sdk.sandboxes.resume(options.snapshotId);\n sandboxId = options.snapshotId;\n } else {\n const {\n timeout: _timeout, envs, name: _name, metadata: _metadata,\n templateId: optTemplateId, snapshotId: _snapshotId, sandboxId: _sandboxId,\n namespace: _namespace, directory: _directory, ...providerOptions\n } = options || {};\n const createOptions: any = { ...providerOptions };\n const templateId = optTemplateId || config.templateId;\n if (templateId) createOptions.id = templateId;\n if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;\n sandbox = await sdk.sandboxes.create(createOptions);\n sandboxId = sandbox.id;\n }\n return { instance: sandbox, instanceId: sandboxId };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('API key')) {\n throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable.`);\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(`CodeSandbox quota exceeded. Please check your usage at https://codesandbox.io/dashboard`);\n }\n }\n throw new Error(`Failed to create CodeSandbox sandbox: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getById: async (config: CodesandboxConfig, sandboxId: string) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try {\n const sandbox = await sdk.sandboxes.resume(sandboxId);\n return { instance: sandbox, instanceId: sandboxId };\n } catch { return null; }\n },\n\n list: async (_config: CodesandboxConfig) => {\n throw new Error(`CodeSandbox provider does not support listing sandboxes.`);\n },\n\n destroy: async (config: CodesandboxConfig, sandboxId: string) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try { await sdk.sandboxes.shutdown(sandboxId); } catch { /* ignore */ }\n try {\n await sdk.sandboxes.delete(sandboxId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!message.includes('not found') && !message.includes('404')) {\n throw new Error(`Failed to delete CodeSandbox sandbox \"${sandboxId}\": ${message}`);\n }\n }\n },\n\n runCommand: async (sandbox: CodesandboxSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const client = await sandbox.connect();\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(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 // commands.run returns a bare output string — capture the real exit\n // code and stderr in-band via a delimiter + stderr file.\n const errFile = `/tmp/.computesdk-stderr-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const delim = `__COMPUTESDK_EXIT_${Date.now()}_${Math.random().toString(36).slice(2)}__`;\n const wrapped = `{ ${fullCommand} ; } 2>${escapeShellArg(errFile)}; __cs_ec=$?; echo \"${delim}$__cs_ec\"; cat ${escapeShellArg(errFile)} 2>/dev/null; rm -f ${escapeShellArg(errFile)}`;\n const output = await client.commands.run(wrapped);\n const delimIdx = output.lastIndexOf(delim);\n if (delimIdx === -1) {\n return { stdout: output, stderr: '', exitCode: 0, durationMs: Date.now() - startTime };\n }\n const after = output.substring(delimIdx + delim.length);\n const newlineIdx = after.indexOf('\\n');\n const exitCode = parseInt(newlineIdx === -1 ? after : after.substring(0, newlineIdx), 10) || 0;\n const stderr = newlineIdx === -1 ? '' : after.substring(newlineIdx + 1);\n const stdout = output.substring(0, delimIdx).replace(/\\n$/, '');\n return { stdout, stderr, exitCode, 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: CodesandboxSandbox): Promise<InstanceInfo> => ({\n id: sandbox.id,\n provider: 'codesandbox',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: { cluster: sandbox.cluster, bootupType: sandbox.bootupType, isUpToDate: sandbox.isUpToDate }\n }),\n\n getUrl: async (sandbox: CodesandboxSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const protocol = options.protocol || 'https';\n return `${protocol}://${sandbox.id}.${sandbox.cluster}.csb.app:${options.port}`;\n },\n\n filesystem: {\n readFile: async (sandbox: CodesandboxSandbox, path: string): Promise<string> => {\n const client = await sandbox.connect();\n return client.fs.readTextFile(path);\n },\n writeFile: async (sandbox: CodesandboxSandbox, path: string, content: string): Promise<void> => {\n const client = await sandbox.connect();\n await client.fs.writeTextFile(path, content);\n },\n mkdir: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await sandbox.connect();\n await client.commands.run(`mkdir -p \"${path}\"`);\n },\n readdir: async (sandbox: CodesandboxSandbox, path: string): Promise<FileEntry[]> => {\n const client = await sandbox.connect();\n const entries = await client.fs.readdir(path);\n return entries.map((entry: any) => ({\n name: entry.name,\n type: entry.isDirectory ? 'directory' as const : 'file' as const,\n size: entry.size || 0,\n modified: entry.lastModified ? new Date(entry.lastModified) : new Date()\n }));\n },\n exists: async (sandbox: CodesandboxSandbox, path: string): Promise<boolean> => {\n const client = await sandbox.connect();\n try { await client.commands.run(`ls \"${path}\"`); return true; } catch { return false; }\n },\n remove: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await sandbox.connect();\n await client.fs.remove(path);\n }\n },\n\n getInstance: (sandbox: CodesandboxSandbox): CodesandboxSandbox => sandbox,\n },\n\n snapshot: {\n create: async (config: CodesandboxConfig, sandboxId: string, options?: { name?: string }) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try {\n const sandbox = await sdk.sandboxes.resume(sandboxId);\n await sdk.sandboxes.hibernate(sandboxId);\n return { id: sandbox.id, provider: 'codesandbox', createdAt: new Date(), metadata: { name: options?.name, bootupType: sandbox.bootupType } };\n } catch (error) {\n throw new Error(`Failed to create CodeSandbox snapshot: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n list: async (_config: CodesandboxConfig) => { throw new Error(`CodeSandbox provider does not support listing snapshots.`); },\n delete: async (config: CodesandboxConfig, snapshotId: string) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try { await sdk.sandboxes.shutdown(snapshotId); } catch { /* ignore */ }\n }\n },\n\n template: {\n create: async (_config: CodesandboxConfig, _options: { name: string }) => {\n throw new Error(`CodeSandbox templates must be created via the dashboard.`);\n },\n list: async (_config: CodesandboxConfig) => { throw new Error(`CodeSandbox provider does not support listing templates via API.`); },\n delete: async (_config: CodesandboxConfig, _templateId: string) => { throw new Error(`CodeSandbox templates must be deleted via the dashboard.`); }\n }\n }\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Codesandbox Provider - Factory-based Implementation\n */\n\nimport { CodeSandbox } from '@codesandbox/sdk';\nimport type { Sandbox as CodesandboxNativeSandbox, SandboxClient } from '@codesandbox/sdk';\nimport { defineProvider } from '@computesdk/provider';\n\nimport type { CommandResult, InstanceInfo, CreateInstanceOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\nexport interface CodesandboxConfig {\n /** CodeSandbox API key - if not provided, will fallback to CSB_API_KEY environment variable */\n apiKey?: string;\n /** Template to use for new sandboxes */\n templateId?: string;\n /** Default runtime environment (e.g. 'node', 'python') */\n runtime?: string;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\n/**\n * The CodeSandbox SDK sandbox, plus `pause()` (hibernate: memory and disk are\n * kept) and `resume()` (wake the same sandbox id).\n */\nexport type CodesandboxSandbox = CodesandboxNativeSandbox & {\n pause(): Promise<void>;\n resume(): Promise<void>;\n};\n\n/** Tag carried by sandboxes that serve as snapshots (hibernated forks). */\nconst SNAPSHOT_TAG = 'computesdk-snapshot';\n\ninterface SandboxState {\n sdk: CodeSandbox;\n /** Latest SDK handle for this sandbox id (replaced on resume). */\n current: CodesandboxNativeSandbox;\n client?: Promise<SandboxClient>;\n}\n\nconst states = new WeakMap<CodesandboxNativeSandbox, SandboxState>();\n/** Tracked states by sandbox id, so a snapshot can refresh its source's session. */\nconst statesById = new Map<string, SandboxState>();\n/** Open clients by sandbox id, so destroy can close the session before deleting. */\nconst openClients = new Map<string, Promise<SandboxClient>>();\n\nfunction resolveApiKey(config: CodesandboxConfig): string {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) {\n throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);\n }\n return apiKey;\n}\n\nfunction sdkFor(config: CodesandboxConfig): CodeSandbox {\n return new CodeSandbox(resolveApiKey(config));\n}\n\nasync function closeClient(sandboxId: string): Promise<void> {\n const client = openClients.get(sandboxId);\n if (!client) return;\n openClients.delete(sandboxId);\n try {\n const open = await client;\n await open.disconnect().catch(() => undefined);\n open.dispose();\n } catch { /* already gone */ }\n}\n\nfunction track(sdk: CodeSandbox, native: CodesandboxNativeSandbox): CodesandboxSandbox {\n const state: SandboxState = { sdk, current: native };\n states.set(native, state);\n statesById.set(native.id, state);\n const sandbox = native as CodesandboxSandbox;\n Object.defineProperty(sandbox, 'pause', {\n configurable: true,\n value: async () => {\n await closeClient(sandbox.id);\n state.client = undefined;\n await sdk.sandboxes.hibernate(sandbox.id);\n },\n });\n Object.defineProperty(sandbox, 'resume', {\n configurable: true,\n value: async () => {\n await closeClient(sandbox.id);\n state.client = undefined;\n state.current = await sdk.sandboxes.resume(sandbox.id);\n },\n });\n return sandbox;\n}\n\n/** Reopens a running sandbox's session with fresh connection details. */\nasync function refreshSession(sandboxId: string): Promise<void> {\n await closeClient(sandboxId);\n const state = statesById.get(sandboxId);\n if (!state) return;\n state.client = undefined;\n state.current = await state.sdk.sandboxes.resume(sandboxId);\n}\n\nfunction getClient(sandbox: CodesandboxNativeSandbox): Promise<SandboxClient> {\n const state = states.get(sandbox);\n if (!state) return sandbox.connect();\n if (state.client && openClients.get(sandbox.id) !== state.client) state.client = undefined;\n if (!state.client) {\n const client = state.current.connect();\n state.client = client;\n openClients.set(sandbox.id, client);\n client.catch(() => {\n if (state.client === client) state.client = undefined;\n if (openClients.get(sandbox.id) === client) openClients.delete(sandbox.id);\n });\n }\n return state.client;\n}\n\nfunction shQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction randomToken(): string {\n return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Exit code `timeout(1)` reports when it stops a command. */\nconst TIMEOUT_EXIT_CODE = 124;\n\n/**\n * `commands.run` executes in a terminal: stdout and stdin are a TTY, stdout and\n * stderr are merged with CRLF line endings, a non-zero exit throws with the\n * output dropped, and a command that finishes before the SDK subscribes to it\n * can lose its output or never report its exit. So the\n * command runs with stdin from /dev/null and stdout and stderr captured to\n * files; the exit code and base64 of both streams are written between two\n * markers to a result file, which is printed and, if the printed copy is\n * missing, read back; the file appearing also counts as completion. The marker is printed in two pieces so it never appears\n * verbatim in the command text.\n */\nfunction wrapCommand(command: string, token: string, timeoutMs?: number): string {\n const out = `/tmp/.computesdk-${token}.out`;\n const err = `/tmp/.computesdk-${token}.err`;\n const marker = `'__CSDK_' '${token}__'`;\n const body = timeoutMs && timeoutMs > 0\n ? `if command -v timeout >/dev/null 2>&1; then timeout -k 2 ${Math.max(1, Math.ceil(timeoutMs / 1000))} bash -c ${shQuote(command)}; else bash -c ${shQuote(command)}; fi`\n : command;\n return [\n `(\\n${body}\\n) </dev/null >${out} 2>${err}; __csdk_ec=$?`,\n `{ printf '%s%s%s:' ${marker} \"$__csdk_ec\"; base64 ${out} | tr -d '\\\\n'; printf ':'; base64 ${err} | tr -d '\\\\n'; printf '%s%s' ${marker}; } >${resultPath(token)}.tmp`,\n `mv -f ${resultPath(token)}.tmp ${resultPath(token)}; rm -f ${out} ${err}; cat ${resultPath(token)}`,\n ].join('; ');\n}\n\nfunction resultPath(token: string): string {\n return `/tmp/.computesdk-${token}.res`;\n}\n\nfunction parseWrapped(output: string, marker: string): { stdout: string; stderr: string; exitCode: number } | undefined {\n const flat = output.replace(/[\\r\\n]/g, '');\n const start = flat.indexOf(marker);\n if (start === -1) return undefined;\n const end = flat.indexOf(marker, start + marker.length);\n if (end === -1) return undefined;\n const [code, out = '', err = ''] = flat.slice(start + marker.length, end).split(':');\n const exitCode = Number.parseInt(code, 10);\n if (!Number.isFinite(exitCode)) return undefined;\n return {\n stdout: Buffer.from(out, 'base64').toString('utf8'),\n stderr: Buffer.from(err, 'base64').toString('utf8'),\n exitCode,\n };\n}\n\n/** The session failed before the command started, so it is safe to retry. */\nclass SessionError extends Error {\n constructor(cause: unknown) {\n super(cause instanceof Error ? cause.message : String(cause));\n }\n}\n\n/**\n * Runs a wrapped command and resolves with its printed output once the SDK\n * reports it finished or its result file exists (`''` if only the file did),\n * or `undefined` past `timeoutMs`.\n */\nasync function runToCompletion(\n client: SandboxClient,\n wrapped: string,\n runOpts: { env?: Record<string, string>; cwd?: string },\n resultFile: string,\n timeoutMs?: number,\n): Promise<string | undefined> {\n const cmd = await client.commands.runBackground(wrapped, runOpts).catch((error) => { throw new SessionError(error); });\n let settled = false;\n const finished = cmd.waitUntilComplete().then(\n (output) => output,\n (error) => (typeof (error as any)?.output === 'string' ? (error as any).output : ''),\n );\n const polled = (async () => {\n for (let delay = 100; !settled; delay = Math.min(delay * 2, 1000)) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n if (settled) break;\n const exists = await client.fs.stat(resultFile).then(() => true, () => false);\n if (exists) {\n // The SDK missed the exit; drop its shell so its listeners go too.\n cmd.kill().catch(() => undefined);\n return '';\n }\n }\n return '';\n })();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = timeoutMs === undefined\n ? undefined\n : new Promise<undefined>((resolve) => { timer = setTimeout(() => resolve(undefined), timeoutMs); });\n try {\n return await Promise.race([finished, polled, ...(deadline ? [deadline] : [])]);\n } finally {\n settled = true;\n clearTimeout(timer);\n }\n}\n\nexport const codesandbox = defineProvider<CodesandboxSandbox, CodesandboxConfig, any, any>({\n name: 'codesandbox',\n methods: {\n instances: {\n create: async (config: CodesandboxConfig, options?: CreateInstanceOptions) => {\n const sdk = sdkFor(config);\n try {\n const {\n timeout: _timeout, envs, name: _name, metadata: _metadata,\n templateId: optTemplateId, snapshotId, sandboxId: _sandboxId,\n namespace: _namespace, directory: _directory, ...providerOptions\n } = options || {};\n const createOptions: any = { ...providerOptions };\n // A snapshot is a hibernated fork: restoring forks it again, so the\n // snapshot stays reusable and every restore is a new sandbox.\n const templateId = snapshotId || optTemplateId || config.templateId;\n if (templateId) createOptions.id = templateId;\n if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;\n const sandbox = await sdk.sandboxes.create(createOptions);\n return { instance: track(sdk, sandbox), instanceId: sandbox.id };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/unauthori[sz]ed|API key/i.test(message)) {\n throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable. (${message})`);\n }\n throw new Error(`Failed to create CodeSandbox sandbox: ${message}`);\n }\n },\n\n getById: async (config: CodesandboxConfig, sandboxId: string) => {\n const sdk = sdkFor(config);\n try {\n const sandbox = await sdk.sandboxes.resume(sandboxId);\n return { instance: track(sdk, sandbox), instanceId: sandboxId };\n } catch { return null; }\n },\n\n list: async (_config: CodesandboxConfig) => {\n throw new Error(`CodeSandbox provider does not support listing sandboxes.`);\n },\n\n destroy: async (config: CodesandboxConfig, sandboxId: string) => {\n const sdk = sdkFor(config);\n // Deleting a running VM intermittently fails with \"An unexpected error\n // occurred\", so close our session and shut the VM down first, then retry.\n await closeClient(sandboxId);\n statesById.delete(sandboxId);\n try { await sdk.sandboxes.shutdown(sandboxId); } catch { /* delete reports the real error */ }\n let lastError: unknown;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n await sdk.sandboxes.delete(sandboxId);\n return;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/not found|404/i.test(message)) return;\n lastError = error;\n await new Promise((resolve) => setTimeout(resolve, 2000 * (attempt + 1)));\n }\n }\n const message = lastError instanceof Error ? lastError.message : String(lastError);\n throw new Error(`Failed to delete CodeSandbox sandbox \"${sandboxId}\": ${message}`);\n },\n\n runCommand: async (sandbox: CodesandboxSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n const runOpts: { env?: Record<string, string>; cwd?: string } = {};\n if (options?.env && Object.keys(options.env).length > 0) runOpts.env = options.env;\n if (options?.cwd) runOpts.cwd = options.cwd;\n const run = async (): Promise<CommandResult> => {\n const client = await getClient(sandbox).catch((error) => { throw new SessionError(error); });\n if (options?.background) {\n await client.commands.runBackground(`setsid bash -c ${shQuote(command)} </dev/null >/dev/null 2>&1 &`, runOpts)\n .catch((error) => { throw new SessionError(error); });\n return { stdout: '', stderr: '', exitCode: 0, durationMs: Date.now() - startTime };\n }\n const token = randomToken();\n const marker = `__CSDK_${token}__`;\n const clientTimeoutMs = options?.timeout && options.timeout > 0 ? options.timeout + 10_000 : undefined;\n const output = await runToCompletion(client, wrapCommand(command, token, options?.timeout), runOpts, resultPath(token), clientTimeoutMs);\n if (output === undefined) {\n return { stdout: '', stderr: `Command timed out after ${options!.timeout}ms`, exitCode: TIMEOUT_EXIT_CODE, durationMs: Date.now() - startTime };\n }\n let parsed = parseWrapped(output, marker);\n if (!parsed) {\n const saved = await client.fs.readTextFile(resultPath(token)).catch(() => undefined);\n parsed = saved === undefined ? undefined : parseWrapped(saved, marker);\n }\n client.fs.remove(resultPath(token)).catch(() => undefined);\n if (!parsed) {\n return { stdout: output.replace(/\\r\\n/g, '\\n'), stderr: '', exitCode: 0, durationMs: Date.now() - startTime };\n }\n return { ...parsed, durationMs: Date.now() - startTime };\n };\n try {\n try {\n return await run();\n } catch (error) {\n if (!(error instanceof SessionError)) throw error;\n // A stale session, e.g. after the VM was suspended: reconnect once.\n await refreshSession(sandbox.id);\n return await run();\n }\n } catch (error) {\n const exitCode = typeof (error as any)?.exitCode === 'number' ? (error as any).exitCode : 127;\n return { stdout: '', stderr: error instanceof Error ? error.message : String(error), exitCode, durationMs: Date.now() - startTime };\n }\n },\n\n getInfo: async (sandbox: CodesandboxSandbox): Promise<InstanceInfo> => ({\n id: sandbox.id,\n provider: 'codesandbox',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: { cluster: sandbox.cluster, bootupType: sandbox.bootupType, isUpToDate: sandbox.isUpToDate }\n }),\n\n getUrl: async (sandbox: CodesandboxSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const protocol = options.protocol || 'https';\n return `${protocol}://${sandbox.id}.${sandbox.cluster}.csb.app:${options.port}`;\n },\n\n filesystem: {\n readFile: async (sandbox: CodesandboxSandbox, path: string): Promise<string> => {\n const client = await getClient(sandbox);\n return client.fs.readTextFile(path);\n },\n writeFile: async (sandbox: CodesandboxSandbox, path: string, content: string): Promise<void> => {\n const client = await getClient(sandbox);\n await client.fs.writeTextFile(path, content);\n },\n mkdir: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await getClient(sandbox);\n await client.fs.mkdir(path, true);\n },\n readdir: async (sandbox: CodesandboxSandbox, path: string): Promise<FileEntry[]> => {\n const client = await getClient(sandbox);\n const entries = await client.fs.readdir(path);\n return entries.map((entry) => ({\n name: entry.name,\n type: entry.type === 'directory' ? 'directory' as const : 'file' as const,\n size: 0,\n modified: new Date()\n }));\n },\n exists: async (sandbox: CodesandboxSandbox, path: string): Promise<boolean> => {\n const client = await getClient(sandbox);\n try { await client.fs.stat(path); return true; } catch { return false; }\n },\n remove: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await getClient(sandbox);\n await client.fs.remove(path, true);\n }\n },\n\n // Hibernate keeps the VM's memory and disk; resume wakes the same sandbox id.\n pause: (sandbox: CodesandboxSandbox) => sandbox.pause(),\n resume: (sandbox: CodesandboxSandbox) => sandbox.resume(),\n pauseCapabilities: { memory: true },\n\n getInstance: (sandbox: CodesandboxSandbox): CodesandboxSandbox => sandbox,\n },\n\n snapshot: {\n // A fork of the running sandbox (memory, processes and disk), hibernated\n // so it persists as a restore point independent of the source.\n create: async (config: CodesandboxConfig, sandboxId: string, options?: { name?: string }) => {\n const sdk = sdkFor(config);\n try {\n const fork = await sdk.sandboxes.create({\n id: sandboxId,\n tags: [SNAPSHOT_TAG],\n ...(options?.name ? { title: options.name } : {}),\n });\n await sdk.sandboxes.hibernate(fork.id);\n // Forking suspends and resumes the source VM, which can drop its session.\n await refreshSession(sandboxId);\n return { id: fork.id, provider: 'codesandbox', createdAt: new Date(), metadata: { name: options?.name, sourceSandboxId: sandboxId } };\n } catch (error) {\n throw new Error(`Failed to create CodeSandbox snapshot: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n list: async (config: CodesandboxConfig) => {\n const sdk = sdkFor(config);\n const { sandboxes } = await sdk.sandboxes.list({ tags: [SNAPSHOT_TAG] });\n return sandboxes\n .filter((s) => s.tags?.includes(SNAPSHOT_TAG))\n .map((s) => ({ id: s.id, provider: 'codesandbox', createdAt: s.createdAt, metadata: { name: s.title } }));\n },\n delete: async (config: CodesandboxConfig, snapshotId: string) => {\n const sdk = sdkFor(config);\n try {\n await sdk.sandboxes.delete(snapshotId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!/not found|404/i.test(message)) {\n throw new Error(`Failed to delete CodeSandbox snapshot \"${snapshotId}\": ${message}`);\n }\n }\n },\n // Forks keep the whole VM, memory and /tmp included; the source keeps\n // running, and each restore is an independent fork of the snapshot.\n capabilities: { scope: 'rootfs', memory: true, destroysSource: false, source: 'kept', fork: true, readiness: 'immediate' },\n },\n\n template: {\n create: async (_config: CodesandboxConfig, _options: { name: string }) => {\n throw new Error(`CodeSandbox templates must be created via the dashboard.`);\n },\n list: async (_config: CodesandboxConfig) => { throw new Error(`CodeSandbox provider does not support listing templates via API.`); },\n delete: async (_config: CodesandboxConfig, _templateId: string) => { throw new Error(`CodeSandbox templates must be deleted via the dashboard.`); }\n }\n }\n});\n"],"mappings":"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","names":["message"]}
package/dist/index.mjs CHANGED
@@ -1,62 +1,189 @@
1
1
  // src/index.ts
2
2
  import { CodeSandbox } from "@codesandbox/sdk";
3
- import { defineProvider, escapeShellArg } from "@computesdk/provider";
3
+ import { defineProvider } from "@computesdk/provider";
4
+ var SNAPSHOT_TAG = "computesdk-snapshot";
5
+ var states = /* @__PURE__ */ new WeakMap();
6
+ var statesById = /* @__PURE__ */ new Map();
7
+ var openClients = /* @__PURE__ */ new Map();
8
+ function resolveApiKey(config) {
9
+ const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
10
+ if (!apiKey) {
11
+ throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);
12
+ }
13
+ return apiKey;
14
+ }
15
+ function sdkFor(config) {
16
+ return new CodeSandbox(resolveApiKey(config));
17
+ }
18
+ async function closeClient(sandboxId) {
19
+ const client = openClients.get(sandboxId);
20
+ if (!client) return;
21
+ openClients.delete(sandboxId);
22
+ try {
23
+ const open = await client;
24
+ await open.disconnect().catch(() => void 0);
25
+ open.dispose();
26
+ } catch {
27
+ }
28
+ }
29
+ function track(sdk, native) {
30
+ const state = { sdk, current: native };
31
+ states.set(native, state);
32
+ statesById.set(native.id, state);
33
+ const sandbox = native;
34
+ Object.defineProperty(sandbox, "pause", {
35
+ configurable: true,
36
+ value: async () => {
37
+ await closeClient(sandbox.id);
38
+ state.client = void 0;
39
+ await sdk.sandboxes.hibernate(sandbox.id);
40
+ }
41
+ });
42
+ Object.defineProperty(sandbox, "resume", {
43
+ configurable: true,
44
+ value: async () => {
45
+ await closeClient(sandbox.id);
46
+ state.client = void 0;
47
+ state.current = await sdk.sandboxes.resume(sandbox.id);
48
+ }
49
+ });
50
+ return sandbox;
51
+ }
52
+ async function refreshSession(sandboxId) {
53
+ await closeClient(sandboxId);
54
+ const state = statesById.get(sandboxId);
55
+ if (!state) return;
56
+ state.client = void 0;
57
+ state.current = await state.sdk.sandboxes.resume(sandboxId);
58
+ }
59
+ function getClient(sandbox) {
60
+ const state = states.get(sandbox);
61
+ if (!state) return sandbox.connect();
62
+ if (state.client && openClients.get(sandbox.id) !== state.client) state.client = void 0;
63
+ if (!state.client) {
64
+ const client = state.current.connect();
65
+ state.client = client;
66
+ openClients.set(sandbox.id, client);
67
+ client.catch(() => {
68
+ if (state.client === client) state.client = void 0;
69
+ if (openClients.get(sandbox.id) === client) openClients.delete(sandbox.id);
70
+ });
71
+ }
72
+ return state.client;
73
+ }
74
+ function shQuote(value) {
75
+ return `'${value.replace(/'/g, `'\\''`)}'`;
76
+ }
77
+ function randomToken() {
78
+ return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
79
+ }
80
+ var TIMEOUT_EXIT_CODE = 124;
81
+ function wrapCommand(command, token, timeoutMs) {
82
+ const out = `/tmp/.computesdk-${token}.out`;
83
+ const err = `/tmp/.computesdk-${token}.err`;
84
+ const marker = `'__CSDK_' '${token}__'`;
85
+ const body = timeoutMs && timeoutMs > 0 ? `if command -v timeout >/dev/null 2>&1; then timeout -k 2 ${Math.max(1, Math.ceil(timeoutMs / 1e3))} bash -c ${shQuote(command)}; else bash -c ${shQuote(command)}; fi` : command;
86
+ return [
87
+ `(
88
+ ${body}
89
+ ) </dev/null >${out} 2>${err}; __csdk_ec=$?`,
90
+ `{ printf '%s%s%s:' ${marker} "$__csdk_ec"; base64 ${out} | tr -d '\\n'; printf ':'; base64 ${err} | tr -d '\\n'; printf '%s%s' ${marker}; } >${resultPath(token)}.tmp`,
91
+ `mv -f ${resultPath(token)}.tmp ${resultPath(token)}; rm -f ${out} ${err}; cat ${resultPath(token)}`
92
+ ].join("; ");
93
+ }
94
+ function resultPath(token) {
95
+ return `/tmp/.computesdk-${token}.res`;
96
+ }
97
+ function parseWrapped(output, marker) {
98
+ const flat = output.replace(/[\r\n]/g, "");
99
+ const start = flat.indexOf(marker);
100
+ if (start === -1) return void 0;
101
+ const end = flat.indexOf(marker, start + marker.length);
102
+ if (end === -1) return void 0;
103
+ const [code, out = "", err = ""] = flat.slice(start + marker.length, end).split(":");
104
+ const exitCode = Number.parseInt(code, 10);
105
+ if (!Number.isFinite(exitCode)) return void 0;
106
+ return {
107
+ stdout: Buffer.from(out, "base64").toString("utf8"),
108
+ stderr: Buffer.from(err, "base64").toString("utf8"),
109
+ exitCode
110
+ };
111
+ }
112
+ var SessionError = class extends Error {
113
+ constructor(cause) {
114
+ super(cause instanceof Error ? cause.message : String(cause));
115
+ }
116
+ };
117
+ async function runToCompletion(client, wrapped, runOpts, resultFile, timeoutMs) {
118
+ const cmd = await client.commands.runBackground(wrapped, runOpts).catch((error) => {
119
+ throw new SessionError(error);
120
+ });
121
+ let settled = false;
122
+ const finished = cmd.waitUntilComplete().then(
123
+ (output) => output,
124
+ (error) => typeof error?.output === "string" ? error.output : ""
125
+ );
126
+ const polled = (async () => {
127
+ for (let delay = 100; !settled; delay = Math.min(delay * 2, 1e3)) {
128
+ await new Promise((resolve) => setTimeout(resolve, delay));
129
+ if (settled) break;
130
+ const exists = await client.fs.stat(resultFile).then(() => true, () => false);
131
+ if (exists) {
132
+ cmd.kill().catch(() => void 0);
133
+ return "";
134
+ }
135
+ }
136
+ return "";
137
+ })();
138
+ let timer;
139
+ const deadline = timeoutMs === void 0 ? void 0 : new Promise((resolve) => {
140
+ timer = setTimeout(() => resolve(void 0), timeoutMs);
141
+ });
142
+ try {
143
+ return await Promise.race([finished, polled, ...deadline ? [deadline] : []]);
144
+ } finally {
145
+ settled = true;
146
+ clearTimeout(timer);
147
+ }
148
+ }
4
149
  var codesandbox = defineProvider({
5
150
  name: "codesandbox",
6
151
  methods: {
7
152
  instances: {
8
153
  create: async (config, options) => {
9
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
10
- if (!apiKey) {
11
- throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);
12
- }
13
- const sdk = new CodeSandbox(apiKey);
154
+ const sdk = sdkFor(config);
14
155
  try {
15
- let sandbox;
16
- let sandboxId;
17
- if (options?.snapshotId) {
18
- sandbox = await sdk.sandboxes.resume(options.snapshotId);
19
- sandboxId = options.snapshotId;
20
- } else {
21
- const {
22
- timeout: _timeout,
23
- envs,
24
- name: _name,
25
- metadata: _metadata,
26
- templateId: optTemplateId,
27
- snapshotId: _snapshotId,
28
- sandboxId: _sandboxId,
29
- namespace: _namespace,
30
- directory: _directory,
31
- ...providerOptions
32
- } = options || {};
33
- const createOptions = { ...providerOptions };
34
- const templateId = optTemplateId || config.templateId;
35
- if (templateId) createOptions.id = templateId;
36
- if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;
37
- sandbox = await sdk.sandboxes.create(createOptions);
38
- sandboxId = sandbox.id;
39
- }
40
- return { instance: sandbox, instanceId: sandboxId };
156
+ const {
157
+ timeout: _timeout,
158
+ envs,
159
+ name: _name,
160
+ metadata: _metadata,
161
+ templateId: optTemplateId,
162
+ snapshotId,
163
+ sandboxId: _sandboxId,
164
+ namespace: _namespace,
165
+ directory: _directory,
166
+ ...providerOptions
167
+ } = options || {};
168
+ const createOptions = { ...providerOptions };
169
+ const templateId = snapshotId || optTemplateId || config.templateId;
170
+ if (templateId) createOptions.id = templateId;
171
+ if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;
172
+ const sandbox = await sdk.sandboxes.create(createOptions);
173
+ return { instance: track(sdk, sandbox), instanceId: sandbox.id };
41
174
  } catch (error) {
42
- if (error instanceof Error) {
43
- if (error.message.includes("unauthorized") || error.message.includes("API key")) {
44
- throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable.`);
45
- }
46
- if (error.message.includes("quota") || error.message.includes("limit")) {
47
- throw new Error(`CodeSandbox quota exceeded. Please check your usage at https://codesandbox.io/dashboard`);
48
- }
175
+ const message = error instanceof Error ? error.message : String(error);
176
+ if (/unauthori[sz]ed|API key/i.test(message)) {
177
+ throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable. (${message})`);
49
178
  }
50
- throw new Error(`Failed to create CodeSandbox sandbox: ${error instanceof Error ? error.message : String(error)}`);
179
+ throw new Error(`Failed to create CodeSandbox sandbox: ${message}`);
51
180
  }
52
181
  },
53
182
  getById: async (config, sandboxId) => {
54
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
55
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
56
- const sdk = new CodeSandbox(apiKey);
183
+ const sdk = sdkFor(config);
57
184
  try {
58
185
  const sandbox = await sdk.sandboxes.resume(sandboxId);
59
- return { instance: sandbox, instanceId: sandboxId };
186
+ return { instance: track(sdk, sandbox), instanceId: sandboxId };
60
187
  } catch {
61
188
  return null;
62
189
  }
@@ -65,49 +192,72 @@ var codesandbox = defineProvider({
65
192
  throw new Error(`CodeSandbox provider does not support listing sandboxes.`);
66
193
  },
67
194
  destroy: async (config, sandboxId) => {
68
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
69
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
70
- const sdk = new CodeSandbox(apiKey);
195
+ const sdk = sdkFor(config);
196
+ await closeClient(sandboxId);
197
+ statesById.delete(sandboxId);
71
198
  try {
72
199
  await sdk.sandboxes.shutdown(sandboxId);
73
200
  } catch {
74
201
  }
75
- try {
76
- await sdk.sandboxes.delete(sandboxId);
77
- } catch (error) {
78
- const message = error instanceof Error ? error.message : String(error);
79
- if (!message.includes("not found") && !message.includes("404")) {
80
- throw new Error(`Failed to delete CodeSandbox sandbox "${sandboxId}": ${message}`);
202
+ let lastError;
203
+ for (let attempt = 0; attempt < 3; attempt++) {
204
+ try {
205
+ await sdk.sandboxes.delete(sandboxId);
206
+ return;
207
+ } catch (error) {
208
+ const message2 = error instanceof Error ? error.message : String(error);
209
+ if (/not found|404/i.test(message2)) return;
210
+ lastError = error;
211
+ await new Promise((resolve) => setTimeout(resolve, 2e3 * (attempt + 1)));
81
212
  }
82
213
  }
214
+ const message = lastError instanceof Error ? lastError.message : String(lastError);
215
+ throw new Error(`Failed to delete CodeSandbox sandbox "${sandboxId}": ${message}`);
83
216
  },
84
217
  runCommand: async (sandbox, command, options) => {
85
218
  const startTime = Date.now();
86
- try {
87
- const client = await sandbox.connect();
88
- let fullCommand = command;
89
- if (options?.env && Object.keys(options.env).length > 0) {
90
- const envPrefix = Object.entries(options.env).map(([k, v]) => `${k}="${escapeShellArg(v)}"`).join(" ");
91
- fullCommand = `${envPrefix} ${fullCommand}`;
219
+ const runOpts = {};
220
+ if (options?.env && Object.keys(options.env).length > 0) runOpts.env = options.env;
221
+ if (options?.cwd) runOpts.cwd = options.cwd;
222
+ const run = async () => {
223
+ const client = await getClient(sandbox).catch((error) => {
224
+ throw new SessionError(error);
225
+ });
226
+ if (options?.background) {
227
+ await client.commands.runBackground(`setsid bash -c ${shQuote(command)} </dev/null >/dev/null 2>&1 &`, runOpts).catch((error) => {
228
+ throw new SessionError(error);
229
+ });
230
+ return { stdout: "", stderr: "", exitCode: 0, durationMs: Date.now() - startTime };
231
+ }
232
+ const token = randomToken();
233
+ const marker = `__CSDK_${token}__`;
234
+ const clientTimeoutMs = options?.timeout && options.timeout > 0 ? options.timeout + 1e4 : void 0;
235
+ const output = await runToCompletion(client, wrapCommand(command, token, options?.timeout), runOpts, resultPath(token), clientTimeoutMs);
236
+ if (output === void 0) {
237
+ return { stdout: "", stderr: `Command timed out after ${options.timeout}ms`, exitCode: TIMEOUT_EXIT_CODE, durationMs: Date.now() - startTime };
238
+ }
239
+ let parsed = parseWrapped(output, marker);
240
+ if (!parsed) {
241
+ const saved = await client.fs.readTextFile(resultPath(token)).catch(() => void 0);
242
+ parsed = saved === void 0 ? void 0 : parseWrapped(saved, marker);
92
243
  }
93
- if (options?.cwd) fullCommand = `cd "${escapeShellArg(options.cwd)}" && ${fullCommand}`;
94
- if (options?.background) fullCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
95
- const errFile = `/tmp/.computesdk-stderr-${Date.now()}-${Math.random().toString(36).slice(2)}`;
96
- const delim = `__COMPUTESDK_EXIT_${Date.now()}_${Math.random().toString(36).slice(2)}__`;
97
- const wrapped = `{ ${fullCommand} ; } 2>${escapeShellArg(errFile)}; __cs_ec=$?; echo "${delim}$__cs_ec"; cat ${escapeShellArg(errFile)} 2>/dev/null; rm -f ${escapeShellArg(errFile)}`;
98
- const output = await client.commands.run(wrapped);
99
- const delimIdx = output.lastIndexOf(delim);
100
- if (delimIdx === -1) {
101
- return { stdout: output, stderr: "", exitCode: 0, durationMs: Date.now() - startTime };
244
+ client.fs.remove(resultPath(token)).catch(() => void 0);
245
+ if (!parsed) {
246
+ return { stdout: output.replace(/\r\n/g, "\n"), stderr: "", exitCode: 0, durationMs: Date.now() - startTime };
247
+ }
248
+ return { ...parsed, durationMs: Date.now() - startTime };
249
+ };
250
+ try {
251
+ try {
252
+ return await run();
253
+ } catch (error) {
254
+ if (!(error instanceof SessionError)) throw error;
255
+ await refreshSession(sandbox.id);
256
+ return await run();
102
257
  }
103
- const after = output.substring(delimIdx + delim.length);
104
- const newlineIdx = after.indexOf("\n");
105
- const exitCode = parseInt(newlineIdx === -1 ? after : after.substring(0, newlineIdx), 10) || 0;
106
- const stderr = newlineIdx === -1 ? "" : after.substring(newlineIdx + 1);
107
- const stdout = output.substring(0, delimIdx).replace(/\n$/, "");
108
- return { stdout, stderr, exitCode, durationMs: Date.now() - startTime };
109
258
  } catch (error) {
110
- return { stdout: "", stderr: error instanceof Error ? error.message : String(error), exitCode: 127, durationMs: Date.now() - startTime };
259
+ const exitCode = typeof error?.exitCode === "number" ? error.exitCode : 127;
260
+ return { stdout: "", stderr: error instanceof Error ? error.message : String(error), exitCode, durationMs: Date.now() - startTime };
111
261
  }
112
262
  },
113
263
  getInfo: async (sandbox) => ({
@@ -124,68 +274,84 @@ var codesandbox = defineProvider({
124
274
  },
125
275
  filesystem: {
126
276
  readFile: async (sandbox, path) => {
127
- const client = await sandbox.connect();
277
+ const client = await getClient(sandbox);
128
278
  return client.fs.readTextFile(path);
129
279
  },
130
280
  writeFile: async (sandbox, path, content) => {
131
- const client = await sandbox.connect();
281
+ const client = await getClient(sandbox);
132
282
  await client.fs.writeTextFile(path, content);
133
283
  },
134
284
  mkdir: async (sandbox, path) => {
135
- const client = await sandbox.connect();
136
- await client.commands.run(`mkdir -p "${path}"`);
285
+ const client = await getClient(sandbox);
286
+ await client.fs.mkdir(path, true);
137
287
  },
138
288
  readdir: async (sandbox, path) => {
139
- const client = await sandbox.connect();
289
+ const client = await getClient(sandbox);
140
290
  const entries = await client.fs.readdir(path);
141
291
  return entries.map((entry) => ({
142
292
  name: entry.name,
143
- type: entry.isDirectory ? "directory" : "file",
144
- size: entry.size || 0,
145
- modified: entry.lastModified ? new Date(entry.lastModified) : /* @__PURE__ */ new Date()
293
+ type: entry.type === "directory" ? "directory" : "file",
294
+ size: 0,
295
+ modified: /* @__PURE__ */ new Date()
146
296
  }));
147
297
  },
148
298
  exists: async (sandbox, path) => {
149
- const client = await sandbox.connect();
299
+ const client = await getClient(sandbox);
150
300
  try {
151
- await client.commands.run(`ls "${path}"`);
301
+ await client.fs.stat(path);
152
302
  return true;
153
303
  } catch {
154
304
  return false;
155
305
  }
156
306
  },
157
307
  remove: async (sandbox, path) => {
158
- const client = await sandbox.connect();
159
- await client.fs.remove(path);
308
+ const client = await getClient(sandbox);
309
+ await client.fs.remove(path, true);
160
310
  }
161
311
  },
312
+ // Hibernate keeps the VM's memory and disk; resume wakes the same sandbox id.
313
+ pause: (sandbox) => sandbox.pause(),
314
+ resume: (sandbox) => sandbox.resume(),
315
+ pauseCapabilities: { memory: true },
162
316
  getInstance: (sandbox) => sandbox
163
317
  },
164
318
  snapshot: {
319
+ // A fork of the running sandbox (memory, processes and disk), hibernated
320
+ // so it persists as a restore point independent of the source.
165
321
  create: async (config, sandboxId, options) => {
166
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
167
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
168
- const sdk = new CodeSandbox(apiKey);
322
+ const sdk = sdkFor(config);
169
323
  try {
170
- const sandbox = await sdk.sandboxes.resume(sandboxId);
171
- await sdk.sandboxes.hibernate(sandboxId);
172
- return { id: sandbox.id, provider: "codesandbox", createdAt: /* @__PURE__ */ new Date(), metadata: { name: options?.name, bootupType: sandbox.bootupType } };
324
+ const fork = await sdk.sandboxes.create({
325
+ id: sandboxId,
326
+ tags: [SNAPSHOT_TAG],
327
+ ...options?.name ? { title: options.name } : {}
328
+ });
329
+ await sdk.sandboxes.hibernate(fork.id);
330
+ await refreshSession(sandboxId);
331
+ return { id: fork.id, provider: "codesandbox", createdAt: /* @__PURE__ */ new Date(), metadata: { name: options?.name, sourceSandboxId: sandboxId } };
173
332
  } catch (error) {
174
333
  throw new Error(`Failed to create CodeSandbox snapshot: ${error instanceof Error ? error.message : String(error)}`);
175
334
  }
176
335
  },
177
- list: async (_config) => {
178
- throw new Error(`CodeSandbox provider does not support listing snapshots.`);
336
+ list: async (config) => {
337
+ const sdk = sdkFor(config);
338
+ const { sandboxes } = await sdk.sandboxes.list({ tags: [SNAPSHOT_TAG] });
339
+ return sandboxes.filter((s) => s.tags?.includes(SNAPSHOT_TAG)).map((s) => ({ id: s.id, provider: "codesandbox", createdAt: s.createdAt, metadata: { name: s.title } }));
179
340
  },
180
341
  delete: async (config, snapshotId) => {
181
- const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.CSB_API_KEY || "";
182
- if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);
183
- const sdk = new CodeSandbox(apiKey);
342
+ const sdk = sdkFor(config);
184
343
  try {
185
- await sdk.sandboxes.shutdown(snapshotId);
186
- } catch {
344
+ await sdk.sandboxes.delete(snapshotId);
345
+ } catch (error) {
346
+ const message = error instanceof Error ? error.message : String(error);
347
+ if (!/not found|404/i.test(message)) {
348
+ throw new Error(`Failed to delete CodeSandbox snapshot "${snapshotId}": ${message}`);
349
+ }
187
350
  }
188
- }
351
+ },
352
+ // Forks keep the whole VM, memory and /tmp included; the source keeps
353
+ // running, and each restore is an independent fork of the snapshot.
354
+ capabilities: { scope: "rootfs", memory: true, destroysSource: false, source: "kept", fork: true, readiness: "immediate" }
189
355
  },
190
356
  template: {
191
357
  create: async (_config, _options) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Codesandbox Provider - Factory-based Implementation\n */\n\nimport { CodeSandbox } from '@codesandbox/sdk';\nimport type { Sandbox as CodesandboxSandbox } from '@codesandbox/sdk';\nimport { defineProvider, escapeShellArg } from '@computesdk/provider';\n\nimport type { CommandResult, InstanceInfo, CreateInstanceOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\nexport interface CodesandboxConfig {\n /** CodeSandbox API key - if not provided, will fallback to CSB_API_KEY environment variable */\n apiKey?: string;\n /** Template to use for new sandboxes */\n templateId?: string;\n /** Default runtime environment (e.g. 'node', 'python') */\n runtime?: string;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\nexport const codesandbox = defineProvider<CodesandboxSandbox, CodesandboxConfig, any, any>({\n name: 'codesandbox',\n methods: {\n instances: {\n create: async (config: CodesandboxConfig, options?: CreateInstanceOptions) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) {\n throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);\n }\n const sdk = new CodeSandbox(apiKey);\n try {\n let sandbox: CodesandboxSandbox;\n let sandboxId: string;\n if (options?.snapshotId) {\n sandbox = await sdk.sandboxes.resume(options.snapshotId);\n sandboxId = options.snapshotId;\n } else {\n const {\n timeout: _timeout, envs, name: _name, metadata: _metadata,\n templateId: optTemplateId, snapshotId: _snapshotId, sandboxId: _sandboxId,\n namespace: _namespace, directory: _directory, ...providerOptions\n } = options || {};\n const createOptions: any = { ...providerOptions };\n const templateId = optTemplateId || config.templateId;\n if (templateId) createOptions.id = templateId;\n if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;\n sandbox = await sdk.sandboxes.create(createOptions);\n sandboxId = sandbox.id;\n }\n return { instance: sandbox, instanceId: sandboxId };\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('unauthorized') || error.message.includes('API key')) {\n throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable.`);\n }\n if (error.message.includes('quota') || error.message.includes('limit')) {\n throw new Error(`CodeSandbox quota exceeded. Please check your usage at https://codesandbox.io/dashboard`);\n }\n }\n throw new Error(`Failed to create CodeSandbox sandbox: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n\n getById: async (config: CodesandboxConfig, sandboxId: string) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try {\n const sandbox = await sdk.sandboxes.resume(sandboxId);\n return { instance: sandbox, instanceId: sandboxId };\n } catch { return null; }\n },\n\n list: async (_config: CodesandboxConfig) => {\n throw new Error(`CodeSandbox provider does not support listing sandboxes.`);\n },\n\n destroy: async (config: CodesandboxConfig, sandboxId: string) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try { await sdk.sandboxes.shutdown(sandboxId); } catch { /* ignore */ }\n try {\n await sdk.sandboxes.delete(sandboxId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!message.includes('not found') && !message.includes('404')) {\n throw new Error(`Failed to delete CodeSandbox sandbox \"${sandboxId}\": ${message}`);\n }\n }\n },\n\n runCommand: async (sandbox: CodesandboxSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n try {\n const client = await sandbox.connect();\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(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 // commands.run returns a bare output string — capture the real exit\n // code and stderr in-band via a delimiter + stderr file.\n const errFile = `/tmp/.computesdk-stderr-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n const delim = `__COMPUTESDK_EXIT_${Date.now()}_${Math.random().toString(36).slice(2)}__`;\n const wrapped = `{ ${fullCommand} ; } 2>${escapeShellArg(errFile)}; __cs_ec=$?; echo \"${delim}$__cs_ec\"; cat ${escapeShellArg(errFile)} 2>/dev/null; rm -f ${escapeShellArg(errFile)}`;\n const output = await client.commands.run(wrapped);\n const delimIdx = output.lastIndexOf(delim);\n if (delimIdx === -1) {\n return { stdout: output, stderr: '', exitCode: 0, durationMs: Date.now() - startTime };\n }\n const after = output.substring(delimIdx + delim.length);\n const newlineIdx = after.indexOf('\\n');\n const exitCode = parseInt(newlineIdx === -1 ? after : after.substring(0, newlineIdx), 10) || 0;\n const stderr = newlineIdx === -1 ? '' : after.substring(newlineIdx + 1);\n const stdout = output.substring(0, delimIdx).replace(/\\n$/, '');\n return { stdout, stderr, exitCode, 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: CodesandboxSandbox): Promise<InstanceInfo> => ({\n id: sandbox.id,\n provider: 'codesandbox',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: { cluster: sandbox.cluster, bootupType: sandbox.bootupType, isUpToDate: sandbox.isUpToDate }\n }),\n\n getUrl: async (sandbox: CodesandboxSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const protocol = options.protocol || 'https';\n return `${protocol}://${sandbox.id}.${sandbox.cluster}.csb.app:${options.port}`;\n },\n\n filesystem: {\n readFile: async (sandbox: CodesandboxSandbox, path: string): Promise<string> => {\n const client = await sandbox.connect();\n return client.fs.readTextFile(path);\n },\n writeFile: async (sandbox: CodesandboxSandbox, path: string, content: string): Promise<void> => {\n const client = await sandbox.connect();\n await client.fs.writeTextFile(path, content);\n },\n mkdir: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await sandbox.connect();\n await client.commands.run(`mkdir -p \"${path}\"`);\n },\n readdir: async (sandbox: CodesandboxSandbox, path: string): Promise<FileEntry[]> => {\n const client = await sandbox.connect();\n const entries = await client.fs.readdir(path);\n return entries.map((entry: any) => ({\n name: entry.name,\n type: entry.isDirectory ? 'directory' as const : 'file' as const,\n size: entry.size || 0,\n modified: entry.lastModified ? new Date(entry.lastModified) : new Date()\n }));\n },\n exists: async (sandbox: CodesandboxSandbox, path: string): Promise<boolean> => {\n const client = await sandbox.connect();\n try { await client.commands.run(`ls \"${path}\"`); return true; } catch { return false; }\n },\n remove: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await sandbox.connect();\n await client.fs.remove(path);\n }\n },\n\n getInstance: (sandbox: CodesandboxSandbox): CodesandboxSandbox => sandbox,\n },\n\n snapshot: {\n create: async (config: CodesandboxConfig, sandboxId: string, options?: { name?: string }) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try {\n const sandbox = await sdk.sandboxes.resume(sandboxId);\n await sdk.sandboxes.hibernate(sandboxId);\n return { id: sandbox.id, provider: 'codesandbox', createdAt: new Date(), metadata: { name: options?.name, bootupType: sandbox.bootupType } };\n } catch (error) {\n throw new Error(`Failed to create CodeSandbox snapshot: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n list: async (_config: CodesandboxConfig) => { throw new Error(`CodeSandbox provider does not support listing snapshots.`); },\n delete: async (config: CodesandboxConfig, snapshotId: string) => {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) throw new Error(`Missing CodeSandbox API key.`);\n const sdk = new CodeSandbox(apiKey);\n try { await sdk.sandboxes.shutdown(snapshotId); } catch { /* ignore */ }\n }\n },\n\n template: {\n create: async (_config: CodesandboxConfig, _options: { name: string }) => {\n throw new Error(`CodeSandbox templates must be created via the dashboard.`);\n },\n list: async (_config: CodesandboxConfig) => { throw new Error(`CodeSandbox provider does not support listing templates via API.`); },\n delete: async (_config: CodesandboxConfig, _templateId: string) => { throw new Error(`CodeSandbox templates must be deleted via the dashboard.`); }\n }\n }\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Codesandbox Provider - Factory-based Implementation\n */\n\nimport { CodeSandbox } from '@codesandbox/sdk';\nimport type { Sandbox as CodesandboxNativeSandbox, SandboxClient } from '@codesandbox/sdk';\nimport { defineProvider } from '@computesdk/provider';\n\nimport type { CommandResult, InstanceInfo, CreateInstanceOptions, FileEntry, RunCommandOptions } from '@computesdk/provider';\n\nexport interface CodesandboxConfig {\n /** CodeSandbox API key - if not provided, will fallback to CSB_API_KEY environment variable */\n apiKey?: string;\n /** Template to use for new sandboxes */\n templateId?: string;\n /** Default runtime environment (e.g. 'node', 'python') */\n runtime?: string;\n /** Execution timeout in milliseconds */\n timeout?: number;\n}\n\n/**\n * The CodeSandbox SDK sandbox, plus `pause()` (hibernate: memory and disk are\n * kept) and `resume()` (wake the same sandbox id).\n */\nexport type CodesandboxSandbox = CodesandboxNativeSandbox & {\n pause(): Promise<void>;\n resume(): Promise<void>;\n};\n\n/** Tag carried by sandboxes that serve as snapshots (hibernated forks). */\nconst SNAPSHOT_TAG = 'computesdk-snapshot';\n\ninterface SandboxState {\n sdk: CodeSandbox;\n /** Latest SDK handle for this sandbox id (replaced on resume). */\n current: CodesandboxNativeSandbox;\n client?: Promise<SandboxClient>;\n}\n\nconst states = new WeakMap<CodesandboxNativeSandbox, SandboxState>();\n/** Tracked states by sandbox id, so a snapshot can refresh its source's session. */\nconst statesById = new Map<string, SandboxState>();\n/** Open clients by sandbox id, so destroy can close the session before deleting. */\nconst openClients = new Map<string, Promise<SandboxClient>>();\n\nfunction resolveApiKey(config: CodesandboxConfig): string {\n const apiKey = config.apiKey || (typeof process !== 'undefined' && process.env?.CSB_API_KEY) || '';\n if (!apiKey) {\n throw new Error(`Missing CodeSandbox API key. Provide 'apiKey' in config or set CSB_API_KEY environment variable.`);\n }\n return apiKey;\n}\n\nfunction sdkFor(config: CodesandboxConfig): CodeSandbox {\n return new CodeSandbox(resolveApiKey(config));\n}\n\nasync function closeClient(sandboxId: string): Promise<void> {\n const client = openClients.get(sandboxId);\n if (!client) return;\n openClients.delete(sandboxId);\n try {\n const open = await client;\n await open.disconnect().catch(() => undefined);\n open.dispose();\n } catch { /* already gone */ }\n}\n\nfunction track(sdk: CodeSandbox, native: CodesandboxNativeSandbox): CodesandboxSandbox {\n const state: SandboxState = { sdk, current: native };\n states.set(native, state);\n statesById.set(native.id, state);\n const sandbox = native as CodesandboxSandbox;\n Object.defineProperty(sandbox, 'pause', {\n configurable: true,\n value: async () => {\n await closeClient(sandbox.id);\n state.client = undefined;\n await sdk.sandboxes.hibernate(sandbox.id);\n },\n });\n Object.defineProperty(sandbox, 'resume', {\n configurable: true,\n value: async () => {\n await closeClient(sandbox.id);\n state.client = undefined;\n state.current = await sdk.sandboxes.resume(sandbox.id);\n },\n });\n return sandbox;\n}\n\n/** Reopens a running sandbox's session with fresh connection details. */\nasync function refreshSession(sandboxId: string): Promise<void> {\n await closeClient(sandboxId);\n const state = statesById.get(sandboxId);\n if (!state) return;\n state.client = undefined;\n state.current = await state.sdk.sandboxes.resume(sandboxId);\n}\n\nfunction getClient(sandbox: CodesandboxNativeSandbox): Promise<SandboxClient> {\n const state = states.get(sandbox);\n if (!state) return sandbox.connect();\n if (state.client && openClients.get(sandbox.id) !== state.client) state.client = undefined;\n if (!state.client) {\n const client = state.current.connect();\n state.client = client;\n openClients.set(sandbox.id, client);\n client.catch(() => {\n if (state.client === client) state.client = undefined;\n if (openClients.get(sandbox.id) === client) openClients.delete(sandbox.id);\n });\n }\n return state.client;\n}\n\nfunction shQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\nfunction randomToken(): string {\n return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Exit code `timeout(1)` reports when it stops a command. */\nconst TIMEOUT_EXIT_CODE = 124;\n\n/**\n * `commands.run` executes in a terminal: stdout and stdin are a TTY, stdout and\n * stderr are merged with CRLF line endings, a non-zero exit throws with the\n * output dropped, and a command that finishes before the SDK subscribes to it\n * can lose its output or never report its exit. So the\n * command runs with stdin from /dev/null and stdout and stderr captured to\n * files; the exit code and base64 of both streams are written between two\n * markers to a result file, which is printed and, if the printed copy is\n * missing, read back; the file appearing also counts as completion. The marker is printed in two pieces so it never appears\n * verbatim in the command text.\n */\nfunction wrapCommand(command: string, token: string, timeoutMs?: number): string {\n const out = `/tmp/.computesdk-${token}.out`;\n const err = `/tmp/.computesdk-${token}.err`;\n const marker = `'__CSDK_' '${token}__'`;\n const body = timeoutMs && timeoutMs > 0\n ? `if command -v timeout >/dev/null 2>&1; then timeout -k 2 ${Math.max(1, Math.ceil(timeoutMs / 1000))} bash -c ${shQuote(command)}; else bash -c ${shQuote(command)}; fi`\n : command;\n return [\n `(\\n${body}\\n) </dev/null >${out} 2>${err}; __csdk_ec=$?`,\n `{ printf '%s%s%s:' ${marker} \"$__csdk_ec\"; base64 ${out} | tr -d '\\\\n'; printf ':'; base64 ${err} | tr -d '\\\\n'; printf '%s%s' ${marker}; } >${resultPath(token)}.tmp`,\n `mv -f ${resultPath(token)}.tmp ${resultPath(token)}; rm -f ${out} ${err}; cat ${resultPath(token)}`,\n ].join('; ');\n}\n\nfunction resultPath(token: string): string {\n return `/tmp/.computesdk-${token}.res`;\n}\n\nfunction parseWrapped(output: string, marker: string): { stdout: string; stderr: string; exitCode: number } | undefined {\n const flat = output.replace(/[\\r\\n]/g, '');\n const start = flat.indexOf(marker);\n if (start === -1) return undefined;\n const end = flat.indexOf(marker, start + marker.length);\n if (end === -1) return undefined;\n const [code, out = '', err = ''] = flat.slice(start + marker.length, end).split(':');\n const exitCode = Number.parseInt(code, 10);\n if (!Number.isFinite(exitCode)) return undefined;\n return {\n stdout: Buffer.from(out, 'base64').toString('utf8'),\n stderr: Buffer.from(err, 'base64').toString('utf8'),\n exitCode,\n };\n}\n\n/** The session failed before the command started, so it is safe to retry. */\nclass SessionError extends Error {\n constructor(cause: unknown) {\n super(cause instanceof Error ? cause.message : String(cause));\n }\n}\n\n/**\n * Runs a wrapped command and resolves with its printed output once the SDK\n * reports it finished or its result file exists (`''` if only the file did),\n * or `undefined` past `timeoutMs`.\n */\nasync function runToCompletion(\n client: SandboxClient,\n wrapped: string,\n runOpts: { env?: Record<string, string>; cwd?: string },\n resultFile: string,\n timeoutMs?: number,\n): Promise<string | undefined> {\n const cmd = await client.commands.runBackground(wrapped, runOpts).catch((error) => { throw new SessionError(error); });\n let settled = false;\n const finished = cmd.waitUntilComplete().then(\n (output) => output,\n (error) => (typeof (error as any)?.output === 'string' ? (error as any).output : ''),\n );\n const polled = (async () => {\n for (let delay = 100; !settled; delay = Math.min(delay * 2, 1000)) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n if (settled) break;\n const exists = await client.fs.stat(resultFile).then(() => true, () => false);\n if (exists) {\n // The SDK missed the exit; drop its shell so its listeners go too.\n cmd.kill().catch(() => undefined);\n return '';\n }\n }\n return '';\n })();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = timeoutMs === undefined\n ? undefined\n : new Promise<undefined>((resolve) => { timer = setTimeout(() => resolve(undefined), timeoutMs); });\n try {\n return await Promise.race([finished, polled, ...(deadline ? [deadline] : [])]);\n } finally {\n settled = true;\n clearTimeout(timer);\n }\n}\n\nexport const codesandbox = defineProvider<CodesandboxSandbox, CodesandboxConfig, any, any>({\n name: 'codesandbox',\n methods: {\n instances: {\n create: async (config: CodesandboxConfig, options?: CreateInstanceOptions) => {\n const sdk = sdkFor(config);\n try {\n const {\n timeout: _timeout, envs, name: _name, metadata: _metadata,\n templateId: optTemplateId, snapshotId, sandboxId: _sandboxId,\n namespace: _namespace, directory: _directory, ...providerOptions\n } = options || {};\n const createOptions: any = { ...providerOptions };\n // A snapshot is a hibernated fork: restoring forks it again, so the\n // snapshot stays reusable and every restore is a new sandbox.\n const templateId = snapshotId || optTemplateId || config.templateId;\n if (templateId) createOptions.id = templateId;\n if (envs && Object.keys(envs).length > 0) createOptions.envVars = envs;\n const sandbox = await sdk.sandboxes.create(createOptions);\n return { instance: track(sdk, sandbox), instanceId: sandbox.id };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/unauthori[sz]ed|API key/i.test(message)) {\n throw new Error(`CodeSandbox authentication failed. Please check your CSB_API_KEY environment variable. (${message})`);\n }\n throw new Error(`Failed to create CodeSandbox sandbox: ${message}`);\n }\n },\n\n getById: async (config: CodesandboxConfig, sandboxId: string) => {\n const sdk = sdkFor(config);\n try {\n const sandbox = await sdk.sandboxes.resume(sandboxId);\n return { instance: track(sdk, sandbox), instanceId: sandboxId };\n } catch { return null; }\n },\n\n list: async (_config: CodesandboxConfig) => {\n throw new Error(`CodeSandbox provider does not support listing sandboxes.`);\n },\n\n destroy: async (config: CodesandboxConfig, sandboxId: string) => {\n const sdk = sdkFor(config);\n // Deleting a running VM intermittently fails with \"An unexpected error\n // occurred\", so close our session and shut the VM down first, then retry.\n await closeClient(sandboxId);\n statesById.delete(sandboxId);\n try { await sdk.sandboxes.shutdown(sandboxId); } catch { /* delete reports the real error */ }\n let lastError: unknown;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n await sdk.sandboxes.delete(sandboxId);\n return;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/not found|404/i.test(message)) return;\n lastError = error;\n await new Promise((resolve) => setTimeout(resolve, 2000 * (attempt + 1)));\n }\n }\n const message = lastError instanceof Error ? lastError.message : String(lastError);\n throw new Error(`Failed to delete CodeSandbox sandbox \"${sandboxId}\": ${message}`);\n },\n\n runCommand: async (sandbox: CodesandboxSandbox, command: string, options?: RunCommandOptions): Promise<CommandResult> => {\n const startTime = Date.now();\n const runOpts: { env?: Record<string, string>; cwd?: string } = {};\n if (options?.env && Object.keys(options.env).length > 0) runOpts.env = options.env;\n if (options?.cwd) runOpts.cwd = options.cwd;\n const run = async (): Promise<CommandResult> => {\n const client = await getClient(sandbox).catch((error) => { throw new SessionError(error); });\n if (options?.background) {\n await client.commands.runBackground(`setsid bash -c ${shQuote(command)} </dev/null >/dev/null 2>&1 &`, runOpts)\n .catch((error) => { throw new SessionError(error); });\n return { stdout: '', stderr: '', exitCode: 0, durationMs: Date.now() - startTime };\n }\n const token = randomToken();\n const marker = `__CSDK_${token}__`;\n const clientTimeoutMs = options?.timeout && options.timeout > 0 ? options.timeout + 10_000 : undefined;\n const output = await runToCompletion(client, wrapCommand(command, token, options?.timeout), runOpts, resultPath(token), clientTimeoutMs);\n if (output === undefined) {\n return { stdout: '', stderr: `Command timed out after ${options!.timeout}ms`, exitCode: TIMEOUT_EXIT_CODE, durationMs: Date.now() - startTime };\n }\n let parsed = parseWrapped(output, marker);\n if (!parsed) {\n const saved = await client.fs.readTextFile(resultPath(token)).catch(() => undefined);\n parsed = saved === undefined ? undefined : parseWrapped(saved, marker);\n }\n client.fs.remove(resultPath(token)).catch(() => undefined);\n if (!parsed) {\n return { stdout: output.replace(/\\r\\n/g, '\\n'), stderr: '', exitCode: 0, durationMs: Date.now() - startTime };\n }\n return { ...parsed, durationMs: Date.now() - startTime };\n };\n try {\n try {\n return await run();\n } catch (error) {\n if (!(error instanceof SessionError)) throw error;\n // A stale session, e.g. after the VM was suspended: reconnect once.\n await refreshSession(sandbox.id);\n return await run();\n }\n } catch (error) {\n const exitCode = typeof (error as any)?.exitCode === 'number' ? (error as any).exitCode : 127;\n return { stdout: '', stderr: error instanceof Error ? error.message : String(error), exitCode, durationMs: Date.now() - startTime };\n }\n },\n\n getInfo: async (sandbox: CodesandboxSandbox): Promise<InstanceInfo> => ({\n id: sandbox.id,\n provider: 'codesandbox',\n status: 'running',\n createdAt: new Date(),\n timeout: 300000,\n metadata: { cluster: sandbox.cluster, bootupType: sandbox.bootupType, isUpToDate: sandbox.isUpToDate }\n }),\n\n getUrl: async (sandbox: CodesandboxSandbox, options: { port: number; protocol?: string }): Promise<string> => {\n const protocol = options.protocol || 'https';\n return `${protocol}://${sandbox.id}.${sandbox.cluster}.csb.app:${options.port}`;\n },\n\n filesystem: {\n readFile: async (sandbox: CodesandboxSandbox, path: string): Promise<string> => {\n const client = await getClient(sandbox);\n return client.fs.readTextFile(path);\n },\n writeFile: async (sandbox: CodesandboxSandbox, path: string, content: string): Promise<void> => {\n const client = await getClient(sandbox);\n await client.fs.writeTextFile(path, content);\n },\n mkdir: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await getClient(sandbox);\n await client.fs.mkdir(path, true);\n },\n readdir: async (sandbox: CodesandboxSandbox, path: string): Promise<FileEntry[]> => {\n const client = await getClient(sandbox);\n const entries = await client.fs.readdir(path);\n return entries.map((entry) => ({\n name: entry.name,\n type: entry.type === 'directory' ? 'directory' as const : 'file' as const,\n size: 0,\n modified: new Date()\n }));\n },\n exists: async (sandbox: CodesandboxSandbox, path: string): Promise<boolean> => {\n const client = await getClient(sandbox);\n try { await client.fs.stat(path); return true; } catch { return false; }\n },\n remove: async (sandbox: CodesandboxSandbox, path: string): Promise<void> => {\n const client = await getClient(sandbox);\n await client.fs.remove(path, true);\n }\n },\n\n // Hibernate keeps the VM's memory and disk; resume wakes the same sandbox id.\n pause: (sandbox: CodesandboxSandbox) => sandbox.pause(),\n resume: (sandbox: CodesandboxSandbox) => sandbox.resume(),\n pauseCapabilities: { memory: true },\n\n getInstance: (sandbox: CodesandboxSandbox): CodesandboxSandbox => sandbox,\n },\n\n snapshot: {\n // A fork of the running sandbox (memory, processes and disk), hibernated\n // so it persists as a restore point independent of the source.\n create: async (config: CodesandboxConfig, sandboxId: string, options?: { name?: string }) => {\n const sdk = sdkFor(config);\n try {\n const fork = await sdk.sandboxes.create({\n id: sandboxId,\n tags: [SNAPSHOT_TAG],\n ...(options?.name ? { title: options.name } : {}),\n });\n await sdk.sandboxes.hibernate(fork.id);\n // Forking suspends and resumes the source VM, which can drop its session.\n await refreshSession(sandboxId);\n return { id: fork.id, provider: 'codesandbox', createdAt: new Date(), metadata: { name: options?.name, sourceSandboxId: sandboxId } };\n } catch (error) {\n throw new Error(`Failed to create CodeSandbox snapshot: ${error instanceof Error ? error.message : String(error)}`);\n }\n },\n list: async (config: CodesandboxConfig) => {\n const sdk = sdkFor(config);\n const { sandboxes } = await sdk.sandboxes.list({ tags: [SNAPSHOT_TAG] });\n return sandboxes\n .filter((s) => s.tags?.includes(SNAPSHOT_TAG))\n .map((s) => ({ id: s.id, provider: 'codesandbox', createdAt: s.createdAt, metadata: { name: s.title } }));\n },\n delete: async (config: CodesandboxConfig, snapshotId: string) => {\n const sdk = sdkFor(config);\n try {\n await sdk.sandboxes.delete(snapshotId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!/not found|404/i.test(message)) {\n throw new Error(`Failed to delete CodeSandbox snapshot \"${snapshotId}\": ${message}`);\n }\n }\n },\n // Forks keep the whole VM, memory and /tmp included; the source keeps\n // running, and each restore is an independent fork of the snapshot.\n capabilities: { scope: 'rootfs', memory: true, destroysSource: false, source: 'kept', fork: true, readiness: 'immediate' },\n },\n\n template: {\n create: async (_config: CodesandboxConfig, _options: { name: string }) => {\n throw new Error(`CodeSandbox templates must be created via the dashboard.`);\n },\n list: async (_config: CodesandboxConfig) => { throw new Error(`CodeSandbox provider does not support listing templates via API.`); },\n delete: async (_config: CodesandboxConfig, _templateId: string) => { throw new Error(`CodeSandbox templates must be deleted via the dashboard.`); }\n }\n }\n});\n"],"mappings":"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","names":["message"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@computesdk/codesandbox",
3
- "version": "1.5.68",
3
+ "version": "1.5.70",
4
4
  "description": "CodeSandbox provider for ComputeSDK - fast browser-compatible sandboxes with npm and Python support",
5
5
  "author": "Garrison",
6
6
  "license": "MIT",
@@ -19,8 +19,8 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "@codesandbox/sdk": "^2.4.2",
22
- "computesdk": "4.1.14",
23
- "@computesdk/provider": "2.1.20"
22
+ "@computesdk/provider": "2.1.22",
23
+ "computesdk": "4.1.16"
24
24
  },
25
25
  "keywords": [
26
26
  "computesdk",
@@ -51,7 +51,7 @@
51
51
  "tsup": "^8.0.0",
52
52
  "typescript": "^5.0.0",
53
53
  "vitest": "^1.0.0",
54
- "@computesdk/test-utils": "2.0.4"
54
+ "@computesdk/test-utils": "2.0.6"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "tsup",