@computesdk/workbench 3.0.0 → 3.1.1
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/README.md +64 -0
- package/dist/bin/workbench.js +452 -135
- package/dist/bin/workbench.js.map +1 -1
- package/dist/helpers.d.ts +9 -3
- package/dist/helpers.js +3 -2
- package/dist/helpers.js.map +1 -1
- package/dist/index.js +463 -143
- package/dist/index.js.map +1 -1
- package/package.json +13 -11
package/dist/bin/workbench.js
CHANGED
|
@@ -1,16 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
2
11
|
|
|
3
12
|
// ../../node_modules/.pnpm/tsup@8.5.0_jiti@2.6.1_postcss@8.5.6_tsx@4.20.3_typescript@5.8.3_yaml@2.8.0/node_modules/tsup/assets/esm_shims.js
|
|
4
13
|
import path from "path";
|
|
5
14
|
import { fileURLToPath } from "url";
|
|
6
|
-
var getFilename
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
var getFilename, getDirname, __dirname;
|
|
16
|
+
var init_esm_shims = __esm({
|
|
17
|
+
"../../node_modules/.pnpm/tsup@8.5.0_jiti@2.6.1_postcss@8.5.6_tsx@4.20.3_typescript@5.8.3_yaml@2.8.0/node_modules/tsup/assets/esm_shims.js"() {
|
|
18
|
+
"use strict";
|
|
19
|
+
getFilename = () => fileURLToPath(import.meta.url);
|
|
20
|
+
getDirname = () => path.dirname(getFilename());
|
|
21
|
+
__dirname = /* @__PURE__ */ getDirname();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
12
24
|
|
|
13
25
|
// src/cli/state.ts
|
|
26
|
+
var state_exports = {};
|
|
27
|
+
__export(state_exports, {
|
|
28
|
+
clearSandbox: () => clearSandbox,
|
|
29
|
+
createState: () => createState,
|
|
30
|
+
formatUptime: () => formatUptime,
|
|
31
|
+
getCurrentSandbox: () => getCurrentSandbox,
|
|
32
|
+
getUptimeSeconds: () => getUptimeSeconds,
|
|
33
|
+
hasSandbox: () => hasSandbox,
|
|
34
|
+
setSandbox: () => setSandbox
|
|
35
|
+
});
|
|
14
36
|
function createState() {
|
|
15
37
|
return {
|
|
16
38
|
currentProvider: null,
|
|
@@ -19,7 +41,8 @@ function createState() {
|
|
|
19
41
|
availableProviders: [],
|
|
20
42
|
useDirectMode: false,
|
|
21
43
|
// Default to gateway mode
|
|
22
|
-
verbose: false
|
|
44
|
+
verbose: false,
|
|
45
|
+
compute: null
|
|
23
46
|
};
|
|
24
47
|
}
|
|
25
48
|
function getCurrentSandbox(state) {
|
|
@@ -73,36 +96,28 @@ function formatUptime(state) {
|
|
|
73
96
|
const remainingMinutes = minutes % 60;
|
|
74
97
|
return `${hours}h ${remainingMinutes}m`;
|
|
75
98
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
import { createCompute } from "computesdk";
|
|
99
|
+
var init_state = __esm({
|
|
100
|
+
"src/cli/state.ts"() {
|
|
101
|
+
"use strict";
|
|
102
|
+
init_esm_shims();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
83
105
|
|
|
84
106
|
// src/cli/output.ts
|
|
85
|
-
var
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
cyan: (text) => `${colors.cyan}${text}${colors.reset}`,
|
|
100
|
-
green: (text) => `${colors.green}${text}${colors.reset}`,
|
|
101
|
-
yellow: (text) => `${colors.yellow}${text}${colors.reset}`,
|
|
102
|
-
red: (text) => `${colors.red}${text}${colors.reset}`,
|
|
103
|
-
blue: (text) => `${colors.blue}${text}${colors.reset}`,
|
|
104
|
-
magenta: (text) => `${colors.magenta}${text}${colors.reset}`
|
|
105
|
-
};
|
|
107
|
+
var output_exports = {};
|
|
108
|
+
__export(output_exports, {
|
|
109
|
+
Spinner: () => Spinner,
|
|
110
|
+
c: () => c,
|
|
111
|
+
formatDuration: () => formatDuration,
|
|
112
|
+
logCommand: () => logCommand,
|
|
113
|
+
logError: () => logError,
|
|
114
|
+
logInfo: () => logInfo,
|
|
115
|
+
logSuccess: () => logSuccess,
|
|
116
|
+
logWarning: () => logWarning,
|
|
117
|
+
showHelp: () => showHelp,
|
|
118
|
+
showInfo: () => showInfo,
|
|
119
|
+
showWelcome: () => showWelcome
|
|
120
|
+
});
|
|
106
121
|
function showWelcome(availableProviders, currentProvider, useDirectMode) {
|
|
107
122
|
console.log(c.bold(c.cyan("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")));
|
|
108
123
|
console.log(c.bold(c.cyan("\u2551 ComputeSDK Workbench \u2551")));
|
|
@@ -151,39 +166,6 @@ function showInfo(state) {
|
|
|
151
166
|
console.log(` Uptime: ${formatUptime(state)}`);
|
|
152
167
|
console.log("");
|
|
153
168
|
}
|
|
154
|
-
var Spinner = class {
|
|
155
|
-
constructor(text) {
|
|
156
|
-
this.interval = null;
|
|
157
|
-
this.frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
158
|
-
this.currentFrame = 0;
|
|
159
|
-
this.text = text;
|
|
160
|
-
}
|
|
161
|
-
start() {
|
|
162
|
-
process.stdout.write("\x1B[?25l");
|
|
163
|
-
this.interval = setInterval(() => {
|
|
164
|
-
const frame = this.frames[this.currentFrame];
|
|
165
|
-
process.stdout.write(`\r${c.cyan(frame)} ${this.text}`);
|
|
166
|
-
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
167
|
-
}, 80);
|
|
168
|
-
return this;
|
|
169
|
-
}
|
|
170
|
-
succeed(text) {
|
|
171
|
-
this.stop();
|
|
172
|
-
console.log(`${c.green("\u2705")} ${text || this.text}`);
|
|
173
|
-
}
|
|
174
|
-
fail(text) {
|
|
175
|
-
this.stop();
|
|
176
|
-
console.log(`${c.red("\u274C")} ${text || this.text}`);
|
|
177
|
-
}
|
|
178
|
-
stop() {
|
|
179
|
-
if (this.interval) {
|
|
180
|
-
clearInterval(this.interval);
|
|
181
|
-
this.interval = null;
|
|
182
|
-
}
|
|
183
|
-
process.stdout.write("\r\x1B[K");
|
|
184
|
-
process.stdout.write("\x1B[?25h");
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
169
|
function formatDuration(ms) {
|
|
188
170
|
const seconds = ms / 1e3;
|
|
189
171
|
if (seconds < 1) {
|
|
@@ -222,6 +204,9 @@ ${c.bold("Provider Modes:")}
|
|
|
222
204
|
${c.bold("Sandbox Management:")}
|
|
223
205
|
${c.cyan("restart")} Restart current sandbox
|
|
224
206
|
${c.cyan("destroy")} Destroy current sandbox
|
|
207
|
+
${c.cyan("connect <url> [token]")} Connect to existing sandbox via URL
|
|
208
|
+
${c.dim("Example: connect https://sandbox-123.localhost:8080")}
|
|
209
|
+
${c.dim("Example: connect https://sandbox-123.localhost:8080 your_token")}
|
|
225
210
|
${c.cyan("info")} Show sandbox info (provider, uptime)
|
|
226
211
|
|
|
227
212
|
${c.bold("Environment:")}
|
|
@@ -257,6 +242,20 @@ ${c.bold("Running Commands:")}
|
|
|
257
242
|
${c.cyan('filesystem.exists("/path")')}
|
|
258
243
|
${c.cyan('filesystem.remove("/file")')}
|
|
259
244
|
|
|
245
|
+
${c.dim("Named Sandboxes (gateway mode only):")}
|
|
246
|
+
${c.cyan("create()")} ${c.dim("// Create & switch to new sandbox")}
|
|
247
|
+
${c.cyan('create({ namespace: "h" })')} ${c.dim("// Create with namespace & switch")}
|
|
248
|
+
${c.cyan('findOrCreate({ name: "my-app" })')} ${c.dim("// Find or create & switch")}
|
|
249
|
+
${c.cyan('find({ name: "my-app" })')} ${c.dim("// Find existing & switch")}
|
|
250
|
+
|
|
251
|
+
${c.dim("Note: Prompts before switching if you already have an active sandbox")}
|
|
252
|
+
|
|
253
|
+
${c.dim("Child Sandboxes (gateway mode only):")}
|
|
254
|
+
${c.cyan("child.create()")} ${c.dim("// Create child sandbox")}
|
|
255
|
+
${c.cyan("child.list()")} ${c.dim("// List all children")}
|
|
256
|
+
${c.cyan('child.retrieve("sandbox-id")')} ${c.dim("// Get child info")}
|
|
257
|
+
${c.cyan('child.destroy("sandbox-id")')} ${c.dim("// Delete child")}
|
|
258
|
+
|
|
260
259
|
${c.dim("Sandbox Methods:")}
|
|
261
260
|
${c.cyan("getUrl({ port: 3000 })")} ${c.dim("// Get public URL")}
|
|
262
261
|
${c.cyan(`runCode("console.log('hi')", "node")`)}
|
|
@@ -292,6 +291,71 @@ function logError(message) {
|
|
|
292
291
|
function logWarning(message) {
|
|
293
292
|
console.log(c.yellow(`\u26A0\uFE0F ${message}`));
|
|
294
293
|
}
|
|
294
|
+
function logInfo(message) {
|
|
295
|
+
console.log(c.blue(`\u2139\uFE0F ${message}`));
|
|
296
|
+
}
|
|
297
|
+
var colors, c, Spinner;
|
|
298
|
+
var init_output = __esm({
|
|
299
|
+
"src/cli/output.ts"() {
|
|
300
|
+
"use strict";
|
|
301
|
+
init_esm_shims();
|
|
302
|
+
init_state();
|
|
303
|
+
colors = {
|
|
304
|
+
reset: "\x1B[0m",
|
|
305
|
+
bright: "\x1B[1m",
|
|
306
|
+
dim: "\x1B[2m",
|
|
307
|
+
cyan: "\x1B[36m",
|
|
308
|
+
green: "\x1B[32m",
|
|
309
|
+
yellow: "\x1B[33m",
|
|
310
|
+
red: "\x1B[31m",
|
|
311
|
+
blue: "\x1B[34m",
|
|
312
|
+
magenta: "\x1B[35m"
|
|
313
|
+
};
|
|
314
|
+
c = {
|
|
315
|
+
bold: (text) => `${colors.bright}${text}${colors.reset}`,
|
|
316
|
+
dim: (text) => `${colors.dim}${text}${colors.reset}`,
|
|
317
|
+
cyan: (text) => `${colors.cyan}${text}${colors.reset}`,
|
|
318
|
+
green: (text) => `${colors.green}${text}${colors.reset}`,
|
|
319
|
+
yellow: (text) => `${colors.yellow}${text}${colors.reset}`,
|
|
320
|
+
red: (text) => `${colors.red}${text}${colors.reset}`,
|
|
321
|
+
blue: (text) => `${colors.blue}${text}${colors.reset}`,
|
|
322
|
+
magenta: (text) => `${colors.magenta}${text}${colors.reset}`
|
|
323
|
+
};
|
|
324
|
+
Spinner = class {
|
|
325
|
+
constructor(text) {
|
|
326
|
+
this.interval = null;
|
|
327
|
+
this.frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
328
|
+
this.currentFrame = 0;
|
|
329
|
+
this.text = text;
|
|
330
|
+
}
|
|
331
|
+
start() {
|
|
332
|
+
process.stdout.write("\x1B[?25l");
|
|
333
|
+
this.interval = setInterval(() => {
|
|
334
|
+
const frame = this.frames[this.currentFrame];
|
|
335
|
+
process.stdout.write(`\r${c.cyan(frame)} ${this.text}`);
|
|
336
|
+
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
337
|
+
}, 80);
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
succeed(text) {
|
|
341
|
+
this.stop();
|
|
342
|
+
console.log(`${c.green("\u2705")} ${text || this.text}`);
|
|
343
|
+
}
|
|
344
|
+
fail(text) {
|
|
345
|
+
this.stop();
|
|
346
|
+
console.log(`${c.red("\u274C")} ${text || this.text}`);
|
|
347
|
+
}
|
|
348
|
+
stop() {
|
|
349
|
+
if (this.interval) {
|
|
350
|
+
clearInterval(this.interval);
|
|
351
|
+
this.interval = null;
|
|
352
|
+
}
|
|
353
|
+
process.stdout.write("\r\x1B[K");
|
|
354
|
+
process.stdout.write("\x1B[?25h");
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
});
|
|
295
359
|
|
|
296
360
|
// src/cli/providers.ts
|
|
297
361
|
import {
|
|
@@ -299,14 +363,6 @@ import {
|
|
|
299
363
|
PROVIDER_NAMES as SHARED_PROVIDER_NAMES,
|
|
300
364
|
getProviderConfigFromEnv
|
|
301
365
|
} from "computesdk";
|
|
302
|
-
var PROVIDER_NAMES = [
|
|
303
|
-
"gateway",
|
|
304
|
-
...SHARED_PROVIDER_NAMES
|
|
305
|
-
];
|
|
306
|
-
var PROVIDER_AUTH = {
|
|
307
|
-
gateway: [["COMPUTESDK_API_KEY"]],
|
|
308
|
-
...SHARED_PROVIDER_AUTH
|
|
309
|
-
};
|
|
310
366
|
function getProviderStatus(provider) {
|
|
311
367
|
const authOptions = PROVIDER_AUTH[provider];
|
|
312
368
|
if (typeof process === "undefined") {
|
|
@@ -488,29 +544,102 @@ function getProviderConfig(providerName) {
|
|
|
488
544
|
}
|
|
489
545
|
return getProviderConfigFromEnv(providerName);
|
|
490
546
|
}
|
|
547
|
+
var PROVIDER_NAMES, PROVIDER_AUTH;
|
|
548
|
+
var init_providers = __esm({
|
|
549
|
+
"src/cli/providers.ts"() {
|
|
550
|
+
"use strict";
|
|
551
|
+
init_esm_shims();
|
|
552
|
+
init_output();
|
|
553
|
+
PROVIDER_NAMES = [
|
|
554
|
+
"gateway",
|
|
555
|
+
...SHARED_PROVIDER_NAMES
|
|
556
|
+
];
|
|
557
|
+
PROVIDER_AUTH = {
|
|
558
|
+
gateway: [["COMPUTESDK_API_KEY"]],
|
|
559
|
+
...SHARED_PROVIDER_AUTH
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
});
|
|
491
563
|
|
|
492
564
|
// src/cli/commands.ts
|
|
565
|
+
var commands_exports = {};
|
|
566
|
+
__export(commands_exports, {
|
|
567
|
+
cleanupOnExit: () => cleanupOnExit,
|
|
568
|
+
confirmSandboxSwitch: () => confirmSandboxSwitch,
|
|
569
|
+
connectToSandbox: () => connectToSandbox,
|
|
570
|
+
createSandbox: () => createSandbox,
|
|
571
|
+
defineProviderCommand: () => defineProviderCommand,
|
|
572
|
+
destroySandbox: () => destroySandbox,
|
|
573
|
+
ensureSandbox: () => ensureSandbox,
|
|
574
|
+
getComputeInstance: () => getComputeInstance,
|
|
575
|
+
restartSandbox: () => restartSandbox,
|
|
576
|
+
runCommand: () => runCommand,
|
|
577
|
+
showMode: () => showMode,
|
|
578
|
+
showVerbose: () => showVerbose,
|
|
579
|
+
switchProvider: () => switchProvider,
|
|
580
|
+
toggleMode: () => toggleMode,
|
|
581
|
+
toggleVerbose: () => toggleVerbose
|
|
582
|
+
});
|
|
583
|
+
import { createCompute } from "@computesdk/provider";
|
|
493
584
|
import * as readline from "readline";
|
|
494
|
-
async function confirm(question) {
|
|
585
|
+
async function confirm(question, defaultYes = false) {
|
|
495
586
|
return new Promise((resolve) => {
|
|
496
587
|
const rl = readline.createInterface({
|
|
497
588
|
input: process.stdin,
|
|
498
589
|
output: process.stdout
|
|
499
590
|
});
|
|
500
591
|
process.stdin.resume();
|
|
501
|
-
|
|
592
|
+
const promptSuffix = defaultYes ? "(Y/n)" : "(y/N)";
|
|
593
|
+
rl.question(`${question} ${promptSuffix}: `, (answer) => {
|
|
502
594
|
rl.close();
|
|
503
595
|
const trimmed = answer.trim().toLowerCase();
|
|
504
|
-
|
|
596
|
+
if (trimmed === "") {
|
|
597
|
+
resolve(defaultYes);
|
|
598
|
+
} else {
|
|
599
|
+
resolve(trimmed === "y" || trimmed === "yes");
|
|
600
|
+
}
|
|
505
601
|
});
|
|
506
602
|
});
|
|
507
603
|
}
|
|
604
|
+
async function confirmSandboxSwitch(state) {
|
|
605
|
+
if (!hasSandbox(state)) {
|
|
606
|
+
return true;
|
|
607
|
+
}
|
|
608
|
+
return await confirm("Switch to new sandbox?", true);
|
|
609
|
+
}
|
|
508
610
|
async function ensureSandbox(state) {
|
|
509
611
|
if (hasSandbox(state)) {
|
|
510
612
|
return;
|
|
511
613
|
}
|
|
512
614
|
await createSandbox(state);
|
|
513
615
|
}
|
|
616
|
+
async function getComputeInstance(state) {
|
|
617
|
+
if (state.compute) {
|
|
618
|
+
return state.compute;
|
|
619
|
+
}
|
|
620
|
+
const providerName = state.currentProvider || autoDetectProvider(false);
|
|
621
|
+
const useDirect = state.useDirectMode;
|
|
622
|
+
if (!providerName) {
|
|
623
|
+
throw new Error("No provider configured.");
|
|
624
|
+
}
|
|
625
|
+
let compute2;
|
|
626
|
+
if (useDirect) {
|
|
627
|
+
const providerModule = await loadProvider(providerName);
|
|
628
|
+
const providerFactory = providerModule[providerName];
|
|
629
|
+
if (!providerFactory) {
|
|
630
|
+
throw new Error(`Provider ${providerName} does not export a factory function`);
|
|
631
|
+
}
|
|
632
|
+
const config2 = getProviderConfig(providerName);
|
|
633
|
+
compute2 = createCompute({
|
|
634
|
+
defaultProvider: providerFactory(config2)
|
|
635
|
+
});
|
|
636
|
+
} else {
|
|
637
|
+
const { compute: gatewayCompute } = await import("computesdk");
|
|
638
|
+
compute2 = gatewayCompute;
|
|
639
|
+
}
|
|
640
|
+
state.compute = compute2;
|
|
641
|
+
return compute2;
|
|
642
|
+
}
|
|
514
643
|
async function createSandbox(state) {
|
|
515
644
|
const providerName = state.currentProvider || autoDetectProvider(false);
|
|
516
645
|
const useDirect = state.useDirectMode;
|
|
@@ -540,55 +669,7 @@ async function createSandbox(state) {
|
|
|
540
669
|
const spinner = new Spinner(`Creating sandbox with ${modeLabel}...`).start();
|
|
541
670
|
const startTime = Date.now();
|
|
542
671
|
try {
|
|
543
|
-
|
|
544
|
-
if (useDirect) {
|
|
545
|
-
const providerModule = await loadProvider(providerName);
|
|
546
|
-
const providerFactory = providerModule[providerName];
|
|
547
|
-
if (!providerFactory) {
|
|
548
|
-
throw new Error(`Provider ${providerName} does not export a factory function`);
|
|
549
|
-
}
|
|
550
|
-
const config2 = getProviderConfig(providerName);
|
|
551
|
-
compute2 = createCompute({
|
|
552
|
-
defaultProvider: providerFactory(config2)
|
|
553
|
-
});
|
|
554
|
-
} else {
|
|
555
|
-
const gatewayModule = await import("computesdk");
|
|
556
|
-
const gatewayFactory = gatewayModule.gateway;
|
|
557
|
-
const providerConfig = getProviderConfig(providerName);
|
|
558
|
-
const providerHeaders = {};
|
|
559
|
-
switch (providerName) {
|
|
560
|
-
case "e2b":
|
|
561
|
-
if (providerConfig.apiKey) providerHeaders["X-E2B-API-Key"] = providerConfig.apiKey;
|
|
562
|
-
break;
|
|
563
|
-
case "railway":
|
|
564
|
-
if (providerConfig.apiKey) providerHeaders["X-Railway-API-Key"] = providerConfig.apiKey;
|
|
565
|
-
if (providerConfig.projectId) providerHeaders["X-Railway-Project-ID"] = providerConfig.projectId;
|
|
566
|
-
if (providerConfig.environmentId) providerHeaders["X-Railway-Environment-ID"] = providerConfig.environmentId;
|
|
567
|
-
break;
|
|
568
|
-
case "daytona":
|
|
569
|
-
if (providerConfig.apiKey) providerHeaders["X-Daytona-API-Key"] = providerConfig.apiKey;
|
|
570
|
-
break;
|
|
571
|
-
case "modal":
|
|
572
|
-
if (providerConfig.tokenId) providerHeaders["X-Modal-Token-ID"] = providerConfig.tokenId;
|
|
573
|
-
if (providerConfig.tokenSecret) providerHeaders["X-Modal-Token-Secret"] = providerConfig.tokenSecret;
|
|
574
|
-
break;
|
|
575
|
-
case "vercel":
|
|
576
|
-
if (providerConfig.token) providerHeaders["X-Vercel-Token"] = providerConfig.token;
|
|
577
|
-
if (providerConfig.teamId) providerHeaders["X-Vercel-Team-ID"] = providerConfig.teamId;
|
|
578
|
-
if (providerConfig.projectId) providerHeaders["X-Vercel-Project-ID"] = providerConfig.projectId;
|
|
579
|
-
break;
|
|
580
|
-
}
|
|
581
|
-
const config2 = {
|
|
582
|
-
apiKey: process.env.COMPUTESDK_API_KEY,
|
|
583
|
-
provider: providerName,
|
|
584
|
-
// Tell gateway which backend to use
|
|
585
|
-
providerHeaders
|
|
586
|
-
// Pass provider credentials via headers
|
|
587
|
-
};
|
|
588
|
-
compute2 = createCompute({
|
|
589
|
-
defaultProvider: gatewayFactory(config2)
|
|
590
|
-
});
|
|
591
|
-
}
|
|
672
|
+
const compute2 = await getComputeInstance(state);
|
|
592
673
|
const result = await compute2.sandbox.create();
|
|
593
674
|
const duration = Date.now() - startTime;
|
|
594
675
|
setSandbox(state, result, providerName);
|
|
@@ -612,10 +693,6 @@ Install it with: ${c.cyan(`npm install @computesdk/${providerName}`)}
|
|
|
612
693
|
}
|
|
613
694
|
}
|
|
614
695
|
async function destroySandbox(state) {
|
|
615
|
-
if (!hasSandbox(state)) {
|
|
616
|
-
logWarning("No active sandbox");
|
|
617
|
-
return;
|
|
618
|
-
}
|
|
619
696
|
const spinner = new Spinner("Destroying sandbox...").start();
|
|
620
697
|
try {
|
|
621
698
|
const sandbox = getCurrentSandbox(state);
|
|
@@ -732,6 +809,7 @@ async function switchProvider(state, mode, providerName) {
|
|
|
732
809
|
await destroySandbox(state);
|
|
733
810
|
state.currentProvider = actualProvider;
|
|
734
811
|
state.useDirectMode = useDirect;
|
|
812
|
+
state.compute = null;
|
|
735
813
|
const modeStr = useDirect ? `${actualProvider} (direct)` : `${actualProvider} (via gateway)`;
|
|
736
814
|
logSuccess(`Switched to ${modeStr}`);
|
|
737
815
|
} else {
|
|
@@ -740,11 +818,12 @@ async function switchProvider(state, mode, providerName) {
|
|
|
740
818
|
} else {
|
|
741
819
|
state.currentProvider = actualProvider;
|
|
742
820
|
state.useDirectMode = useDirect;
|
|
821
|
+
state.compute = null;
|
|
743
822
|
const modeStr = useDirect ? `${actualProvider} (direct)` : `${actualProvider} (via gateway)`;
|
|
744
823
|
logSuccess(`Switched to ${modeStr}`);
|
|
745
824
|
}
|
|
746
825
|
}
|
|
747
|
-
function
|
|
826
|
+
function defineProviderCommand(state) {
|
|
748
827
|
return async function provider(mode, providerName) {
|
|
749
828
|
if (!mode) {
|
|
750
829
|
if (state.currentProvider) {
|
|
@@ -817,6 +896,62 @@ Verbose mode: ${status}`);
|
|
|
817
896
|
Toggle with: ${c.cyan("verbose")}
|
|
818
897
|
`);
|
|
819
898
|
}
|
|
899
|
+
async function connectToSandbox(state, sandboxUrl, token) {
|
|
900
|
+
if (!sandboxUrl) {
|
|
901
|
+
logError("Usage: connect <sandbox_url> [token]");
|
|
902
|
+
console.log("Example: connect https://sandbox-123.localhost:8080");
|
|
903
|
+
console.log("Example: connect https://sandbox-123.localhost:8080 your_access_token");
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
const cleanUrl = sandboxUrl.replace(/\/$/, "");
|
|
907
|
+
if (hasSandbox(state)) {
|
|
908
|
+
const shouldDestroy = await confirm("Disconnect from current sandbox?");
|
|
909
|
+
if (!shouldDestroy) {
|
|
910
|
+
logWarning("Keeping current sandbox. Connection cancelled.");
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
clearSandbox(state);
|
|
914
|
+
}
|
|
915
|
+
const spinner = new Spinner(`Connecting to ${cleanUrl}...`).start();
|
|
916
|
+
const startTime = Date.now();
|
|
917
|
+
try {
|
|
918
|
+
const { Sandbox } = await import("computesdk");
|
|
919
|
+
let WebSocket;
|
|
920
|
+
try {
|
|
921
|
+
const wsModule = await import("ws");
|
|
922
|
+
WebSocket = wsModule.default;
|
|
923
|
+
} catch {
|
|
924
|
+
logError('Failed to import "ws" module. Please install it: pnpm add ws');
|
|
925
|
+
throw new Error('Missing "ws" dependency');
|
|
926
|
+
}
|
|
927
|
+
const sandbox = new Sandbox({
|
|
928
|
+
sandboxUrl: cleanUrl,
|
|
929
|
+
sandboxId: "",
|
|
930
|
+
// Will be populated when we get info
|
|
931
|
+
provider: "connected",
|
|
932
|
+
// Mark as directly connected
|
|
933
|
+
token,
|
|
934
|
+
// Optional access token
|
|
935
|
+
WebSocket
|
|
936
|
+
});
|
|
937
|
+
const info = await sandbox.getInfo();
|
|
938
|
+
const duration = Date.now() - startTime;
|
|
939
|
+
setSandbox(state, sandbox, "connected");
|
|
940
|
+
spinner.succeed(`Connected to sandbox ${c.dim(`(${formatDuration(duration)})`)}`);
|
|
941
|
+
console.log(c.dim(`Provider: ${info.provider || "unknown"}`));
|
|
942
|
+
console.log(c.dim(`Sandbox ID: ${info.id || "unknown"}`));
|
|
943
|
+
} catch (error) {
|
|
944
|
+
const duration = Date.now() - startTime;
|
|
945
|
+
spinner.fail(`Failed to connect ${c.dim(`(${formatDuration(duration)})`)}`);
|
|
946
|
+
if (error instanceof Error) {
|
|
947
|
+
logError(`Error: ${error.message}`);
|
|
948
|
+
if (error.stack) {
|
|
949
|
+
console.log(c.dim(error.stack));
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
throw error;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
820
955
|
async function cleanupOnExit(state, replServer) {
|
|
821
956
|
if (!hasSandbox(state)) {
|
|
822
957
|
return;
|
|
@@ -825,6 +960,10 @@ async function cleanupOnExit(state, replServer) {
|
|
|
825
960
|
replServer.pause();
|
|
826
961
|
}
|
|
827
962
|
console.log("");
|
|
963
|
+
if (state.currentProvider === "connected") {
|
|
964
|
+
logWarning("Disconnecting from external sandbox (not destroying).");
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
828
967
|
const shouldDestroy = await confirm("Destroy active sandbox?");
|
|
829
968
|
if (shouldDestroy) {
|
|
830
969
|
await destroySandbox(state);
|
|
@@ -832,8 +971,34 @@ async function cleanupOnExit(state, replServer) {
|
|
|
832
971
|
logWarning("Sandbox left running. It may incur costs.");
|
|
833
972
|
}
|
|
834
973
|
}
|
|
974
|
+
var init_commands = __esm({
|
|
975
|
+
"src/cli/commands.ts"() {
|
|
976
|
+
"use strict";
|
|
977
|
+
init_esm_shims();
|
|
978
|
+
init_state();
|
|
979
|
+
init_output();
|
|
980
|
+
init_providers();
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
|
|
984
|
+
// src/bin/workbench.ts
|
|
985
|
+
init_esm_shims();
|
|
986
|
+
import { config } from "dotenv";
|
|
987
|
+
|
|
988
|
+
// src/cli/index.ts
|
|
989
|
+
init_esm_shims();
|
|
990
|
+
init_state();
|
|
991
|
+
|
|
992
|
+
// src/cli/repl.ts
|
|
993
|
+
init_esm_shims();
|
|
994
|
+
init_commands();
|
|
995
|
+
init_output();
|
|
996
|
+
init_providers();
|
|
997
|
+
import * as repl from "repl";
|
|
998
|
+
import * as cmd from "@computesdk/cmd";
|
|
835
999
|
|
|
836
1000
|
// src/cli/types.ts
|
|
1001
|
+
init_esm_shims();
|
|
837
1002
|
function isCommand(value) {
|
|
838
1003
|
return Array.isArray(value) && value.length > 0 && typeof value[0] === "string";
|
|
839
1004
|
}
|
|
@@ -937,7 +1102,7 @@ function injectCmdContext(replServer) {
|
|
|
937
1102
|
replServer.context.zsh = cmd.zsh;
|
|
938
1103
|
}
|
|
939
1104
|
function injectWorkbenchCommands(replServer, state) {
|
|
940
|
-
replServer.context.provider =
|
|
1105
|
+
replServer.context.provider = defineProviderCommand(state);
|
|
941
1106
|
replServer.context.providers = () => showProviders();
|
|
942
1107
|
replServer.context.mode = async (modeName) => {
|
|
943
1108
|
if (!modeName) {
|
|
@@ -952,6 +1117,9 @@ function injectWorkbenchCommands(replServer, state) {
|
|
|
952
1117
|
replServer.context.destroy = async () => {
|
|
953
1118
|
await destroySandbox(state);
|
|
954
1119
|
};
|
|
1120
|
+
replServer.context.connect = async (url, token) => {
|
|
1121
|
+
await connectToSandbox(state, url, token);
|
|
1122
|
+
};
|
|
955
1123
|
replServer.context.info = () => showInfo(state);
|
|
956
1124
|
replServer.context.verbose = () => {
|
|
957
1125
|
toggleVerbose(state);
|
|
@@ -984,6 +1152,96 @@ function injectWorkbenchCommands(replServer, state) {
|
|
|
984
1152
|
}
|
|
985
1153
|
return sandbox.runCode(code, runtime);
|
|
986
1154
|
};
|
|
1155
|
+
replServer.context.create = async (options) => {
|
|
1156
|
+
if (state.useDirectMode) {
|
|
1157
|
+
throw new Error('Named sandboxes are only available in gateway mode. Use "mode gateway" to switch.');
|
|
1158
|
+
}
|
|
1159
|
+
const { getComputeInstance: getComputeInstance2, confirmSandboxSwitch: confirmSandboxSwitch2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
|
|
1160
|
+
const { setSandbox: setSandbox2 } = await Promise.resolve().then(() => (init_state(), state_exports));
|
|
1161
|
+
const { logSuccess: logSuccess2 } = await Promise.resolve().then(() => (init_output(), output_exports));
|
|
1162
|
+
const shouldSwitch = await confirmSandboxSwitch2(state);
|
|
1163
|
+
if (!shouldSwitch) {
|
|
1164
|
+
const compute3 = await getComputeInstance2(state);
|
|
1165
|
+
const sandbox2 = await compute3.sandbox.create(options);
|
|
1166
|
+
return {
|
|
1167
|
+
sandboxId: sandbox2.sandboxId,
|
|
1168
|
+
provider: sandbox2.provider,
|
|
1169
|
+
metadata: sandbox2.getInstance().config.metadata || {}
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
const compute2 = await getComputeInstance2(state);
|
|
1173
|
+
const sandbox = await compute2.sandbox.create(options);
|
|
1174
|
+
setSandbox2(state, sandbox, sandbox.provider);
|
|
1175
|
+
logSuccess2(`Switched to sandbox ${sandbox.sandboxId}`);
|
|
1176
|
+
return {
|
|
1177
|
+
sandboxId: sandbox.sandboxId,
|
|
1178
|
+
provider: sandbox.provider,
|
|
1179
|
+
metadata: sandbox.getInstance().config.metadata || {}
|
|
1180
|
+
};
|
|
1181
|
+
};
|
|
1182
|
+
replServer.context.findOrCreate = async (options) => {
|
|
1183
|
+
if (state.useDirectMode) {
|
|
1184
|
+
throw new Error('Named sandboxes (findOrCreate) are only available in gateway mode. Use "mode gateway" to switch.');
|
|
1185
|
+
}
|
|
1186
|
+
const { getComputeInstance: getComputeInstance2, confirmSandboxSwitch: confirmSandboxSwitch2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
|
|
1187
|
+
const { setSandbox: setSandbox2 } = await Promise.resolve().then(() => (init_state(), state_exports));
|
|
1188
|
+
const { logSuccess: logSuccess2 } = await Promise.resolve().then(() => (init_output(), output_exports));
|
|
1189
|
+
const shouldSwitch = await confirmSandboxSwitch2(state);
|
|
1190
|
+
if (!shouldSwitch) {
|
|
1191
|
+
const compute3 = await getComputeInstance2(state);
|
|
1192
|
+
const sandbox2 = await compute3.sandbox.findOrCreate(options);
|
|
1193
|
+
return {
|
|
1194
|
+
sandboxId: sandbox2.sandboxId,
|
|
1195
|
+
provider: sandbox2.provider,
|
|
1196
|
+
name: options.name,
|
|
1197
|
+
namespace: options.namespace || "default",
|
|
1198
|
+
metadata: sandbox2.getInstance().config.metadata || {}
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
const compute2 = await getComputeInstance2(state);
|
|
1202
|
+
const sandbox = await compute2.sandbox.findOrCreate(options);
|
|
1203
|
+
setSandbox2(state, sandbox, sandbox.provider);
|
|
1204
|
+
logSuccess2(`Switched to sandbox ${sandbox.sandboxId}`);
|
|
1205
|
+
return {
|
|
1206
|
+
sandboxId: sandbox.sandboxId,
|
|
1207
|
+
provider: sandbox.provider,
|
|
1208
|
+
name: options.name,
|
|
1209
|
+
namespace: options.namespace || "default",
|
|
1210
|
+
metadata: sandbox.getInstance().config.metadata || {}
|
|
1211
|
+
};
|
|
1212
|
+
};
|
|
1213
|
+
replServer.context.find = async (options) => {
|
|
1214
|
+
if (state.useDirectMode) {
|
|
1215
|
+
throw new Error('Named sandboxes (find) are only available in gateway mode. Use "mode gateway" to switch.');
|
|
1216
|
+
}
|
|
1217
|
+
const { getComputeInstance: getComputeInstance2, confirmSandboxSwitch: confirmSandboxSwitch2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
|
|
1218
|
+
const { setSandbox: setSandbox2 } = await Promise.resolve().then(() => (init_state(), state_exports));
|
|
1219
|
+
const { logSuccess: logSuccess2 } = await Promise.resolve().then(() => (init_output(), output_exports));
|
|
1220
|
+
const compute2 = await getComputeInstance2(state);
|
|
1221
|
+
const sandbox = await compute2.sandbox.find(options);
|
|
1222
|
+
if (!sandbox) {
|
|
1223
|
+
return null;
|
|
1224
|
+
}
|
|
1225
|
+
const shouldSwitch = await confirmSandboxSwitch2(state);
|
|
1226
|
+
if (!shouldSwitch) {
|
|
1227
|
+
return {
|
|
1228
|
+
sandboxId: sandbox.sandboxId,
|
|
1229
|
+
provider: sandbox.provider,
|
|
1230
|
+
name: options.name,
|
|
1231
|
+
namespace: options.namespace || "default",
|
|
1232
|
+
metadata: sandbox.getInstance().config.metadata || {}
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1235
|
+
setSandbox2(state, sandbox, sandbox.provider);
|
|
1236
|
+
logSuccess2(`Switched to sandbox ${sandbox.sandboxId}`);
|
|
1237
|
+
return {
|
|
1238
|
+
sandboxId: sandbox.sandboxId,
|
|
1239
|
+
provider: sandbox.provider,
|
|
1240
|
+
name: options.name,
|
|
1241
|
+
namespace: options.namespace || "default",
|
|
1242
|
+
metadata: sandbox.getInstance().config.metadata || {}
|
|
1243
|
+
};
|
|
1244
|
+
};
|
|
987
1245
|
replServer.context.filesystem = {
|
|
988
1246
|
get readFile() {
|
|
989
1247
|
return async (path4) => {
|
|
@@ -1040,6 +1298,60 @@ function injectWorkbenchCommands(replServer, state) {
|
|
|
1040
1298
|
};
|
|
1041
1299
|
}
|
|
1042
1300
|
};
|
|
1301
|
+
replServer.context.child = {
|
|
1302
|
+
get create() {
|
|
1303
|
+
return async () => {
|
|
1304
|
+
if (state.useDirectMode) {
|
|
1305
|
+
throw new Error('Child sandboxes are only available in gateway mode. Use "mode gateway" to switch.');
|
|
1306
|
+
}
|
|
1307
|
+
const sandbox = state.currentSandbox;
|
|
1308
|
+
if (!sandbox) {
|
|
1309
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1310
|
+
}
|
|
1311
|
+
const instance = sandbox.getInstance();
|
|
1312
|
+
return instance.child.create();
|
|
1313
|
+
};
|
|
1314
|
+
},
|
|
1315
|
+
get list() {
|
|
1316
|
+
return async () => {
|
|
1317
|
+
if (state.useDirectMode) {
|
|
1318
|
+
throw new Error('Child sandboxes are only available in gateway mode. Use "mode gateway" to switch.');
|
|
1319
|
+
}
|
|
1320
|
+
const sandbox = state.currentSandbox;
|
|
1321
|
+
if (!sandbox) {
|
|
1322
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1323
|
+
}
|
|
1324
|
+
const instance = sandbox.getInstance();
|
|
1325
|
+
return instance.child.list();
|
|
1326
|
+
};
|
|
1327
|
+
},
|
|
1328
|
+
get retrieve() {
|
|
1329
|
+
return async (subdomain) => {
|
|
1330
|
+
if (state.useDirectMode) {
|
|
1331
|
+
throw new Error('Child sandboxes are only available in gateway mode. Use "mode gateway" to switch.');
|
|
1332
|
+
}
|
|
1333
|
+
const sandbox = state.currentSandbox;
|
|
1334
|
+
if (!sandbox) {
|
|
1335
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1336
|
+
}
|
|
1337
|
+
const instance = sandbox.getInstance();
|
|
1338
|
+
return instance.child.retrieve(subdomain);
|
|
1339
|
+
};
|
|
1340
|
+
},
|
|
1341
|
+
get destroy() {
|
|
1342
|
+
return async (subdomain, options) => {
|
|
1343
|
+
if (state.useDirectMode) {
|
|
1344
|
+
throw new Error('Child sandboxes are only available in gateway mode. Use "mode gateway" to switch.');
|
|
1345
|
+
}
|
|
1346
|
+
const sandbox = state.currentSandbox;
|
|
1347
|
+
if (!sandbox) {
|
|
1348
|
+
throw new Error("No active sandbox. Run a command to auto-create one.");
|
|
1349
|
+
}
|
|
1350
|
+
const instance = sandbox.getInstance();
|
|
1351
|
+
return instance.child.destroy(subdomain, options);
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1043
1355
|
replServer.context.getInstance = () => {
|
|
1044
1356
|
const sandbox = state.currentSandbox;
|
|
1045
1357
|
if (!sandbox) {
|
|
@@ -1050,7 +1362,7 @@ function injectWorkbenchCommands(replServer, state) {
|
|
|
1050
1362
|
}
|
|
1051
1363
|
function setupSmartEvaluator(replServer, state) {
|
|
1052
1364
|
const originalEval = replServer.eval;
|
|
1053
|
-
const workbenchCommands = /* @__PURE__ */ new Set(["help", "providers", "info", "env", "restart", "destroy", "mode", "verbose", "sandboxInfo"]);
|
|
1365
|
+
const workbenchCommands = /* @__PURE__ */ new Set(["help", "providers", "info", "env", "restart", "destroy", "mode", "verbose", "sandboxInfo", "connect"]);
|
|
1054
1366
|
replServer.eval = function(cmd3, context, filename, callback) {
|
|
1055
1367
|
const trimmedCmd = cmd3.trim();
|
|
1056
1368
|
const providerMatch = trimmedCmd.match(/^provider(?:\s+(direct|gateway))?\s+(\w+)$/);
|
|
@@ -1131,6 +1443,8 @@ function setupAutocomplete(replServer, state) {
|
|
|
1131
1443
|
"providers": [],
|
|
1132
1444
|
"restart": [],
|
|
1133
1445
|
"destroy": [],
|
|
1446
|
+
"connect": [],
|
|
1447
|
+
// Connect takes a URL argument
|
|
1134
1448
|
"info": [],
|
|
1135
1449
|
"env": [],
|
|
1136
1450
|
"help": [],
|
|
@@ -1224,6 +1538,9 @@ function setupHistory(replServer) {
|
|
|
1224
1538
|
}
|
|
1225
1539
|
|
|
1226
1540
|
// src/cli/index.ts
|
|
1541
|
+
init_output();
|
|
1542
|
+
init_providers();
|
|
1543
|
+
init_commands();
|
|
1227
1544
|
async function startWorkbench() {
|
|
1228
1545
|
const state = createState();
|
|
1229
1546
|
state.availableProviders = getAvailableProviders();
|