@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.
@@ -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 = () => fileURLToPath(import.meta.url);
7
- var getDirname = () => path.dirname(getFilename());
8
- var __dirname = /* @__PURE__ */ getDirname();
9
-
10
- // src/bin/workbench.ts
11
- import { config } from "dotenv";
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
- // src/cli/repl.ts
78
- import * as repl from "repl";
79
- import * as cmd from "@computesdk/cmd";
80
-
81
- // src/cli/commands.ts
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 colors = {
86
- reset: "\x1B[0m",
87
- bright: "\x1B[1m",
88
- dim: "\x1B[2m",
89
- cyan: "\x1B[36m",
90
- green: "\x1B[32m",
91
- yellow: "\x1B[33m",
92
- red: "\x1B[31m",
93
- blue: "\x1B[34m",
94
- magenta: "\x1B[35m"
95
- };
96
- var c = {
97
- bold: (text) => `${colors.bright}${text}${colors.reset}`,
98
- dim: (text) => `${colors.dim}${text}${colors.reset}`,
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
- rl.question(`${question} (y/N): `, (answer) => {
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
- resolve(trimmed === "y" || trimmed === "yes");
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
- let compute2;
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 createProviderCommand(state) {
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 = createProviderCommand(state);
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();