computesdk 1.8.6 → 1.8.8

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.mjs CHANGED
@@ -10,11 +10,10 @@ function isCommandExitError(error) {
10
10
  return typeof error === "object" && error !== null && "name" in error && error.name === "CommandExitError" && "result" in error;
11
11
  }
12
12
 
13
- // src/compute.ts
14
- import { ComputeClient } from "@computesdk/client";
13
+ // src/auth/license.ts
15
14
  async function authorizeApiKey(apiKey) {
16
15
  try {
17
- const response = await fetch("https://preview.computesdk.com/__api/license/authorize", {
16
+ const response = await fetch("https://sandbox.computesdk.com/__api/license/authorize", {
18
17
  method: "POST",
19
18
  headers: {
20
19
  "Content-Type": "application/json"
@@ -50,6 +49,8 @@ async function authorizeApiKey(apiKey) {
50
49
  throw new Error(`Failed to authorize API key (network error): ${error instanceof Error ? error.message : String(error)}`);
51
50
  }
52
51
  }
52
+
53
+ // src/compute-daemon/dependencies.ts
53
54
  async function isCommandAvailable(sandbox, command) {
54
55
  const result = await sandbox.runCommand("sh", ["-c", `command -v ${command}`]);
55
56
  return result.exitCode === 0;
@@ -91,6 +92,8 @@ Please install curl and bash manually or use a different sandbox image.`
91
92
  );
92
93
  }
93
94
  }
95
+
96
+ // src/compute-daemon/installer.ts
94
97
  async function isComputeInstalled(sandbox) {
95
98
  const result = await sandbox.runCommand("sh", ["-c", 'test -f /usr/local/bin/compute && echo "exists" || echo "missing"']);
96
99
  return result.stdout?.trim() === "exists";
@@ -109,18 +112,12 @@ async function runInstallScript(sandbox, accessToken) {
109
112
  const installResult = await sandbox.runCommand("bash", ["-c", installCommand]);
110
113
  if (installResult.exitCode !== 0) {
111
114
  const errorOutput = installResult.stderr || installResult.stdout || "unknown error";
112
- throw new Error(`Failed to install compute CLI: ${errorOutput}`);
115
+ throw new Error(`Failed to install compute daemon: ${errorOutput}`);
113
116
  }
114
117
  }
115
- async function installComputeInSandbox(sandbox, config) {
116
- let authResponse = null;
117
- let accessToken = config?.accessToken;
118
- if (config?.apiKey && !accessToken) {
119
- authResponse = await authorizeApiKey(config.apiKey);
120
- accessToken = authResponse.access_token;
121
- }
118
+ async function installComputeDaemon(sandbox, accessToken) {
122
119
  if (await isComputeInstalled(sandbox)) {
123
- return authResponse;
120
+ return;
124
121
  }
125
122
  await ensureDependencies(sandbox);
126
123
  await downloadInstallScript(sandbox);
@@ -128,8 +125,12 @@ async function installComputeInSandbox(sandbox, config) {
128
125
  if (!await isComputeInstalled(sandbox)) {
129
126
  throw new Error("Compute binary not found at /usr/local/bin/compute after installation");
130
127
  }
131
- return authResponse;
132
128
  }
129
+
130
+ // src/sandbox/wrapper.ts
131
+ import { ComputeClient } from "@computesdk/client";
132
+
133
+ // src/compute-daemon/lifecycle.ts
133
134
  async function waitForComputeReady(client, maxRetries = 30, delayMs = 2e3) {
134
135
  let lastError = null;
135
136
  for (let i = 0; i < maxRetries; i++) {
@@ -140,7 +141,7 @@ async function waitForComputeReady(client, maxRetries = 30, delayMs = 2e3) {
140
141
  lastError = error instanceof Error ? error : new Error(String(error));
141
142
  if (i === maxRetries - 1) {
142
143
  throw new Error(
143
- `Compute CLI failed to start after ${maxRetries} attempts (${maxRetries * delayMs / 1e3}s).
144
+ `Compute daemon failed to start after ${maxRetries} attempts (${maxRetries * delayMs / 1e3}s).
144
145
  Last error: ${lastError.message}
145
146
  This could indicate:
146
147
  1. The compute daemon failed to start in the sandbox
@@ -152,6 +153,28 @@ This could indicate:
152
153
  }
153
154
  }
154
155
  }
156
+
157
+ // src/sandbox/wrapper.ts
158
+ async function wrapWithComputeClient(originalSandbox, authResponse) {
159
+ const client = new ComputeClient({
160
+ sandboxUrl: authResponse.sandbox_url,
161
+ sandboxId: originalSandbox.sandboxId,
162
+ provider: originalSandbox.provider,
163
+ token: authResponse.access_token,
164
+ WebSocket: globalThis.WebSocket
165
+ });
166
+ await waitForComputeReady(client);
167
+ const wrappedSandbox = Object.assign(client, {
168
+ __originalSandbox: originalSandbox,
169
+ // Override getInstance to return the original provider's instance
170
+ getInstance: () => originalSandbox.getInstance(),
171
+ // Override getProvider to return the original provider
172
+ getProvider: () => originalSandbox.getProvider()
173
+ });
174
+ return wrappedSandbox;
175
+ }
176
+
177
+ // src/compute.ts
155
178
  var ComputeManager = class {
156
179
  constructor() {
157
180
  this.config = null;
@@ -181,9 +204,22 @@ var ComputeManager = class {
181
204
  const options = params?.options;
182
205
  const sandbox = await provider.sandbox.create(options);
183
206
  if (this.computeAuth.apiKey || this.computeAuth.accessToken) {
184
- const authResponse = await installComputeInSandbox(sandbox, this.computeAuth);
207
+ let authResponse = null;
208
+ let accessToken = this.computeAuth.accessToken;
209
+ if (this.computeAuth.apiKey && !accessToken) {
210
+ authResponse = await authorizeApiKey(this.computeAuth.apiKey);
211
+ accessToken = authResponse.access_token;
212
+ }
213
+ await installComputeDaemon(sandbox, accessToken);
185
214
  if (authResponse) {
186
- return await this.wrapWithComputeClient(sandbox, authResponse);
215
+ return await wrapWithComputeClient(sandbox, authResponse);
216
+ } else if (accessToken) {
217
+ const defaultAuthResponse = {
218
+ access_token: accessToken,
219
+ sandbox_url: "https://sandbox.computesdk.com",
220
+ preview_url: "https://preview.computesdk.com"
221
+ };
222
+ return await wrapWithComputeClient(sandbox, defaultAuthResponse);
187
223
  }
188
224
  }
189
225
  return sandbox;
@@ -272,28 +308,6 @@ var ComputeManager = class {
272
308
  }
273
309
  return provider;
274
310
  }
275
- /**
276
- * Wrap a provider sandbox with ComputeClient while preserving the original sandbox
277
- * This adds powerful features like WebSocket terminals, file watchers, and signals
278
- */
279
- async wrapWithComputeClient(originalSandbox, authResponse) {
280
- const client = new ComputeClient({
281
- sandboxUrl: authResponse.sandbox_url,
282
- sandboxId: originalSandbox.sandboxId,
283
- provider: originalSandbox.provider,
284
- token: authResponse.access_token,
285
- WebSocket: globalThis.WebSocket
286
- });
287
- await waitForComputeReady(client);
288
- const wrappedSandbox = Object.assign(client, {
289
- __originalSandbox: originalSandbox,
290
- // Override getInstance to return the original provider's instance
291
- getInstance: () => originalSandbox.getInstance(),
292
- // Override getProvider to return the original provider
293
- getProvider: () => originalSandbox.getProvider()
294
- });
295
- return wrappedSandbox;
296
- }
297
311
  // Future: compute.blob.*, compute.database.*, compute.git.* will be added here
298
312
  // blob = new BlobManager();
299
313
  // database = new DatabaseManager();
@@ -560,80 +574,10 @@ function createBackgroundCommand(command, args = [], options) {
560
574
  const fullCommand = args.length > 0 ? `${command} ${args.join(" ")}` : command;
561
575
  return {
562
576
  command: "sh",
563
- args: ["-c", `${fullCommand} &`],
577
+ args: ["-c", `nohup ${fullCommand} > /dev/null 2>&1 &`],
564
578
  isBackground: true
565
579
  };
566
580
  }
567
- var defaultFilesystemMethods = {
568
- readFile: async (sandbox, path, runCommand) => {
569
- const result = await runCommand(sandbox, "cat", [path]);
570
- if (result.exitCode !== 0) {
571
- throw new Error(`Failed to read file ${path}: ${result.stderr}`);
572
- }
573
- return result.stdout.replace(/\n$/, "");
574
- },
575
- writeFile: async (sandbox, path, content, runCommand) => {
576
- const result = await runCommand(sandbox, "sh", ["-c", `echo ${JSON.stringify(content)} > ${JSON.stringify(path)}`]);
577
- if (result.exitCode !== 0) {
578
- throw new Error(`Failed to write file ${path}: ${result.stderr}`);
579
- }
580
- },
581
- mkdir: async (sandbox, path, runCommand) => {
582
- const result = await runCommand(sandbox, "mkdir", ["-p", path]);
583
- if (result.exitCode !== 0) {
584
- throw new Error(`Failed to create directory ${path}: ${result.stderr}`);
585
- }
586
- },
587
- readdir: async (sandbox, path, runCommand) => {
588
- let result = await runCommand(sandbox, "ls", ["-la", path]);
589
- let hasDetailedOutput = true;
590
- if (result.exitCode !== 0) {
591
- result = await runCommand(sandbox, "ls", ["-l", path]);
592
- }
593
- if (result.exitCode !== 0) {
594
- result = await runCommand(sandbox, "ls", [path]);
595
- hasDetailedOutput = false;
596
- }
597
- if (result.exitCode !== 0) {
598
- throw new Error(`Failed to list directory ${path}: ${result.stderr}`);
599
- }
600
- const lines = (result.stdout || "").split("\n").filter((line) => line.trim() && !line.startsWith("total"));
601
- return lines.map((line) => {
602
- if (hasDetailedOutput && line.includes(" ")) {
603
- const parts = line.trim().split(/\s+/);
604
- const name = parts[parts.length - 1];
605
- const isDirectory = line.startsWith("d");
606
- return {
607
- name,
608
- path: `${path}/${name}`,
609
- isDirectory,
610
- size: parseInt(parts[4]) || 0,
611
- lastModified: /* @__PURE__ */ new Date()
612
- };
613
- } else {
614
- const name = line.trim();
615
- return {
616
- name,
617
- path: `${path}/${name}`,
618
- isDirectory: false,
619
- // Can't determine from simple ls
620
- size: 0,
621
- lastModified: /* @__PURE__ */ new Date()
622
- };
623
- }
624
- });
625
- },
626
- exists: async (sandbox, path, runCommand) => {
627
- const result = await runCommand(sandbox, "test", ["-e", path]);
628
- return result.exitCode === 0;
629
- },
630
- remove: async (sandbox, path, runCommand) => {
631
- const result = await runCommand(sandbox, "rm", ["-rf", path]);
632
- if (result.exitCode !== 0) {
633
- throw new Error(`Failed to remove ${path}: ${result.stderr}`);
634
- }
635
- }
636
- };
637
581
  var UnsupportedFileSystem = class {
638
582
  constructor(providerName) {
639
583
  this.providerName = providerName;
@@ -707,6 +651,16 @@ var GeneratedSandbox = class {
707
651
  return await this.methods.runCode(this.sandbox, code, runtime, this.config);
708
652
  }
709
653
  async runCommand(command, args, options) {
654
+ if (options?.background) {
655
+ const fullCommand = args?.length ? `${command} ${args.join(" ")}` : command;
656
+ const bgCommand = `nohup ${fullCommand} > /dev/null 2>&1 &`;
657
+ const result = await this.methods.runCommand(this.sandbox, "sh", ["-c", bgCommand], void 0);
658
+ return {
659
+ ...result,
660
+ isBackground: true,
661
+ pid: -1
662
+ };
663
+ }
710
664
  return await this.methods.runCommand(this.sandbox, command, args, options);
711
665
  }
712
666
  async getInfo() {
@@ -847,9 +801,6 @@ var GeneratedProvider = class {
847
801
  }
848
802
  };
849
803
  function createProvider(providerConfig) {
850
- if (!providerConfig.methods.sandbox.filesystem) {
851
- providerConfig.methods.sandbox.filesystem = defaultFilesystemMethods;
852
- }
853
804
  return (config) => {
854
805
  return new GeneratedProvider(config, providerConfig);
855
806
  };