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.js +63 -112
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +63 -112
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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/
|
|
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://
|
|
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
|
|
115
|
+
throw new Error(`Failed to install compute daemon: ${errorOutput}`);
|
|
113
116
|
}
|
|
114
117
|
}
|
|
115
|
-
async function
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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",
|
|
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
|
};
|