@computesdk/workbench 3.1.4 → 3.1.6

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 CHANGED
@@ -37,6 +37,7 @@ function createState() {
37
37
  useDirectMode: false,
38
38
  // Default to gateway mode
39
39
  verbose: false,
40
+ // Enabled automatically for local provider
40
41
  compute: null
41
42
  };
42
43
  }
@@ -113,21 +114,27 @@ __export(output_exports, {
113
114
  showInfo: () => showInfo,
114
115
  showWelcome: () => showWelcome
115
116
  });
116
- function showWelcome(availableProviders, currentProvider, useDirectMode) {
117
+ function showWelcome(availableProviders, currentProvider, useDirectMode, localDaemonRunning = false) {
117
118
  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")));
118
119
  console.log(c.bold(c.cyan("\u2551 ComputeSDK Workbench \u2551")));
119
120
  console.log(c.bold(c.cyan("\u255A\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\u255D\n")));
120
121
  console.log(c.dim("Prompt shows connection status: > (disconnected) or provider:sandbox> (connected)\n"));
122
+ if (localDaemonRunning) {
123
+ console.log(c.green("Local daemon detected - auto-connecting...\n"));
124
+ }
121
125
  if (availableProviders.length > 0) {
122
126
  const backendProviders = availableProviders.filter((p) => p !== "gateway");
123
127
  console.log(`Providers available: ${backendProviders.join(", ")}`);
124
128
  if (currentProvider) {
125
- if (useDirectMode) {
126
- console.log(`Current provider: ${c.green(currentProvider)} (\u{1F517} direct mode)
129
+ if (currentProvider === "local") {
130
+ console.log(`Current provider: ${c.green("local")} (local daemon)
131
+ `);
132
+ } else if (useDirectMode) {
133
+ console.log(`Current provider: ${c.green(currentProvider)} (direct mode)
127
134
  `);
128
135
  } else {
129
136
  const backendProvider = currentProvider === "gateway" ? backendProviders[0] || "auto" : currentProvider;
130
- console.log(`Current provider: ${c.green(backendProvider)} (\u{1F310} via gateway)
137
+ console.log(`Current provider: ${c.green(backendProvider)} (via gateway)
131
138
  `);
132
139
  }
133
140
  } else {
@@ -136,7 +143,7 @@ ${c.dim('Tip: Use "provider <name>" to select a provider')}
136
143
  `);
137
144
  }
138
145
  } else {
139
- console.log(c.yellow("\u26A0\uFE0F No providers detected.\n"));
146
+ console.log(c.yellow("No providers detected.\n"));
140
147
  console.log("To get started:");
141
148
  console.log(" 1. Copy .env.example to .env");
142
149
  console.log(" 2. Add your provider credentials");
@@ -199,10 +206,14 @@ ${c.bold("Provider Modes:")}
199
206
  ${c.bold("Sandbox Management:")}
200
207
  ${c.cyan("restart")} Restart current sandbox
201
208
  ${c.cyan("destroy")} Destroy current sandbox
202
- ${c.cyan("connect <url> [token]")} Connect to existing sandbox via URL
203
- ${c.dim("Example: connect https://sandbox-123.localhost:8080")}
204
- ${c.dim("Example: connect https://sandbox-123.localhost:8080 your_token")}
205
209
  ${c.cyan("info")} Show sandbox info (provider, uptime)
210
+ ${c.cyan("connect <url> [token]")} Connect to sandbox via URL
211
+
212
+ ${c.bold("Local Daemon:")}
213
+ ${c.cyan("provider local")} Connect to local daemon's main sandbox
214
+ ${c.cyan("provider local list")} List local sandboxes
215
+ ${c.cyan("provider local <subdomain>")} Connect to specific local sandbox
216
+ ${c.dim("Example: provider local separate-snail-qkktux")}
206
217
 
207
218
  ${c.bold("Environment:")}
208
219
  ${c.cyan("env")} Show environment/credentials status
@@ -257,6 +268,24 @@ ${c.bold("Running Commands:")}
257
268
  ${c.cyan("sandboxInfo()")} ${c.dim("// Get sandbox details")}
258
269
  ${c.cyan("getInstance()")} ${c.dim("// Get native instance")}
259
270
 
271
+ ${c.dim("Terminal (PTY & Exec):")}
272
+ ${c.cyan("terminal.create({ pty: true })")} ${c.dim("// Create PTY terminal")}
273
+ ${c.cyan("terminal.create({ pty: false })")} ${c.dim("// Create exec terminal")}
274
+ ${c.cyan("terminal.list()")} ${c.dim("// List all terminals")}
275
+ ${c.cyan("terminal.retrieve(id)")} ${c.dim("// Get terminal by ID")}
276
+ ${c.cyan("terminal.destroy(id)")} ${c.dim("// Close terminal by ID")}
277
+
278
+ ${c.dim("PTY Terminal:")}
279
+ ${c.cyan("term = terminal.create({ pty: true })")}
280
+ ${c.cyan('term.on("output", (data) => console.log(data))')}
281
+ ${c.cyan('term.write("echo hello\\n")')}
282
+ ${c.cyan("term.destroy()")}
283
+
284
+ ${c.dim("Exec Terminal:")}
285
+ ${c.cyan("exec = terminal.create({ pty: false })")}
286
+ ${c.cyan('cmd = exec.command.run("ls -la")')}
287
+ ${c.cyan("cmd.stdout")} ${c.dim("// view output")}
288
+
260
289
  ${c.dim('Note: No need to use "await" - promises are auto-awaited!')}
261
290
 
262
291
  ${c.dim("Compute CLI:")}
@@ -561,12 +590,15 @@ var commands_exports = {};
561
590
  __export(commands_exports, {
562
591
  cleanupOnExit: () => cleanupOnExit,
563
592
  confirmSandboxSwitch: () => confirmSandboxSwitch,
593
+ connectToLocal: () => connectToLocal,
564
594
  connectToSandbox: () => connectToSandbox,
565
595
  createSandbox: () => createSandbox,
566
596
  defineProviderCommand: () => defineProviderCommand,
567
597
  destroySandbox: () => destroySandbox,
568
598
  ensureSandbox: () => ensureSandbox,
569
599
  getComputeInstance: () => getComputeInstance,
600
+ isLocalDaemonRunning: () => isLocalDaemonRunning,
601
+ listLocalSandboxes: () => listLocalSandboxes,
570
602
  restartSandbox: () => restartSandbox,
571
603
  runCommand: () => runCommand,
572
604
  showMode: () => showMode,
@@ -577,31 +609,58 @@ __export(commands_exports, {
577
609
  });
578
610
  import { createCompute } from "@computesdk/provider";
579
611
  import { escapeArgs } from "@computesdk/cmd";
580
- import * as readline from "readline";
581
- async function confirm(question, defaultYes = false) {
582
- return new Promise((resolve) => {
583
- const rl = readline.createInterface({
584
- input: process.stdin,
585
- output: process.stdout
586
- });
612
+ async function confirm(question, defaultYes = false, _state) {
613
+ const promptSuffix = defaultYes ? "(Y/n)" : "(y/N)";
614
+ process.stdout.write(`${question} ${promptSuffix}: `);
615
+ if (process.stdin.isPaused()) {
587
616
  process.stdin.resume();
588
- const promptSuffix = defaultYes ? "(Y/n)" : "(y/N)";
589
- rl.question(`${question} ${promptSuffix}: `, (answer) => {
590
- rl.close();
591
- const trimmed = answer.trim().toLowerCase();
592
- if (trimmed === "") {
617
+ }
618
+ return new Promise((resolve) => {
619
+ const wasRaw = process.stdin.isRaw;
620
+ if (process.stdin.isTTY) {
621
+ process.stdin.setRawMode(true);
622
+ }
623
+ const cleanup = (restoreRaw) => {
624
+ process.stdin.removeListener("data", onData);
625
+ if (process.stdin.isTTY && restoreRaw) {
626
+ process.stdin.setRawMode(wasRaw || false);
627
+ }
628
+ };
629
+ const onData = (key) => {
630
+ const char = key.toString();
631
+ if (char === "") {
632
+ process.stdout.write("^C\n");
633
+ cleanup(true);
634
+ resolve(false);
635
+ return;
636
+ }
637
+ if (char === "\r" || char === "\n") {
638
+ process.stdout.write(defaultYes ? "Y\n" : "N\n");
639
+ cleanup(true);
593
640
  resolve(defaultYes);
594
- } else {
595
- resolve(trimmed === "y" || trimmed === "yes");
641
+ return;
596
642
  }
597
- });
643
+ if (char === "y" || char === "Y") {
644
+ process.stdout.write("y\n");
645
+ cleanup(true);
646
+ resolve(true);
647
+ return;
648
+ }
649
+ if (char === "n" || char === "N") {
650
+ process.stdout.write("n\n");
651
+ cleanup(true);
652
+ resolve(false);
653
+ return;
654
+ }
655
+ };
656
+ process.stdin.on("data", onData);
598
657
  });
599
658
  }
600
659
  async function confirmSandboxSwitch(state) {
601
660
  if (!hasSandbox(state)) {
602
661
  return true;
603
662
  }
604
- return await confirm("Switch to new sandbox?", true);
663
+ return await confirm("Switch to new sandbox?", true, state);
605
664
  }
606
665
  async function ensureSandbox(state) {
607
666
  if (hasSandbox(state)) {
@@ -763,6 +822,14 @@ function isStaleConnectionError(error) {
763
822
  return stalePhrases.some((phrase) => message.includes(phrase));
764
823
  }
765
824
  async function switchProvider(state, mode, providerName) {
825
+ if (mode === "local") {
826
+ if (providerName === "list") {
827
+ await listLocalSandboxes();
828
+ return;
829
+ }
830
+ await connectToLocal(state, providerName);
831
+ return;
832
+ }
766
833
  let useDirect = false;
767
834
  let actualProvider = mode;
768
835
  if (mode === "direct") {
@@ -787,7 +854,7 @@ async function switchProvider(state, mode, providerName) {
787
854
  }
788
855
  if (!isValidProvider(actualProvider)) {
789
856
  logError(`Unknown provider: ${actualProvider}`);
790
- console.log(`Available providers: e2b, railway, daytona, modal, runloop, vercel, cloudflare, codesandbox, blaxel`);
857
+ console.log(`Available providers: e2b, railway, daytona, modal, runloop, vercel, cloudflare, codesandbox, blaxel, local`);
791
858
  return;
792
859
  }
793
860
  if (!useDirect && !isProviderReady("gateway")) {
@@ -801,7 +868,7 @@ async function switchProvider(state, mode, providerName) {
801
868
  return;
802
869
  }
803
870
  if (hasSandbox(state)) {
804
- const shouldDestroy = await confirm("Destroy current sandbox?");
871
+ const shouldDestroy = await confirm("Destroy current sandbox?", false, state);
805
872
  if (shouldDestroy) {
806
873
  await destroySandbox(state);
807
874
  state.currentProvider = actualProvider;
@@ -824,7 +891,7 @@ function defineProviderCommand(state) {
824
891
  return async function provider(mode, providerName) {
825
892
  if (!mode) {
826
893
  if (state.currentProvider) {
827
- const modeStr = state.useDirectMode ? "direct" : "via gateway";
894
+ const modeStr = state.useDirectMode ? "direct" : state.currentProvider === "local" ? "local daemon" : "via gateway";
828
895
  console.log(`
829
896
  Current provider: ${c.green(state.currentProvider)} (${modeStr})
830
897
  `);
@@ -902,8 +969,8 @@ async function connectToSandbox(state, sandboxUrl, token) {
902
969
  }
903
970
  const cleanUrl = sandboxUrl.replace(/\/$/, "");
904
971
  if (hasSandbox(state)) {
905
- const shouldDestroy = await confirm("Disconnect from current sandbox?");
906
- if (!shouldDestroy) {
972
+ const shouldDisconnect = await confirm("Disconnect from current sandbox?", false, state);
973
+ if (!shouldDisconnect) {
907
974
  logWarning("Keeping current sandbox. Connection cancelled.");
908
975
  return;
909
976
  }
@@ -949,6 +1016,125 @@ async function connectToSandbox(state, sandboxUrl, token) {
949
1016
  throw error;
950
1017
  }
951
1018
  }
1019
+ async function readLocalConfig() {
1020
+ const os2 = await import("os");
1021
+ const fs = await import("fs/promises");
1022
+ const path3 = await import("path");
1023
+ const configPath = path3.join(os2.homedir(), ".compute", "config.json");
1024
+ try {
1025
+ const content = await fs.readFile(configPath, "utf-8");
1026
+ return JSON.parse(content);
1027
+ } catch {
1028
+ return null;
1029
+ }
1030
+ }
1031
+ async function isLocalDaemonRunning() {
1032
+ const os2 = await import("os");
1033
+ const fs = await import("fs/promises");
1034
+ const path3 = await import("path");
1035
+ const pidPath = path3.join(os2.homedir(), ".compute", "compute.pid");
1036
+ try {
1037
+ const pidContent = await fs.readFile(pidPath, "utf-8");
1038
+ const pid = parseInt(pidContent.trim(), 10);
1039
+ process.kill(pid, 0);
1040
+ return true;
1041
+ } catch {
1042
+ return false;
1043
+ }
1044
+ }
1045
+ async function listLocalSandboxes() {
1046
+ const config = await readLocalConfig();
1047
+ if (!config) {
1048
+ logError("No local daemon config found at ~/.compute/config.json");
1049
+ console.log(c.dim('Run "compute start" to start the local daemon'));
1050
+ return;
1051
+ }
1052
+ const isRunning = await isLocalDaemonRunning();
1053
+ console.log("");
1054
+ console.log(c.bold("Local Daemon Status:"), isRunning ? c.green("Running") : c.red("Stopped"));
1055
+ console.log("");
1056
+ if (!config.sandboxes || config.sandboxes.length === 0) {
1057
+ console.log(c.dim("No sandboxes found"));
1058
+ return;
1059
+ }
1060
+ console.log(c.bold("Sandboxes:"));
1061
+ for (const sandbox of config.sandboxes) {
1062
+ const isMain = sandbox.subdomain === config.main_subdomain;
1063
+ const mainLabel = isMain ? c.green(" (main)") : "";
1064
+ console.log(` ${c.cyan(sandbox.subdomain)}${mainLabel}`);
1065
+ console.log(c.dim(` https://${sandbox.subdomain}.sandbox.computesdk.com`));
1066
+ }
1067
+ console.log("");
1068
+ console.log(c.dim(`Connect with: local ${config.main_subdomain}`));
1069
+ console.log("");
1070
+ }
1071
+ async function connectToLocal(state, subdomain) {
1072
+ const config = await readLocalConfig();
1073
+ if (!config) {
1074
+ logError("No local daemon config found at ~/.compute/config.json");
1075
+ console.log(c.dim('Run "compute start" to start the local daemon'));
1076
+ return;
1077
+ }
1078
+ const isRunning = await isLocalDaemonRunning();
1079
+ if (!isRunning) {
1080
+ logError("Local daemon is not running");
1081
+ console.log(c.dim('Run "compute start" to start the local daemon'));
1082
+ return;
1083
+ }
1084
+ const targetSubdomain = subdomain || config.main_subdomain;
1085
+ const sandbox = config.sandboxes.find((s) => s.subdomain === targetSubdomain);
1086
+ if (!sandbox) {
1087
+ logError(`Sandbox "${targetSubdomain}" not found`);
1088
+ console.log(c.dim('Run "local list" to see available sandboxes'));
1089
+ return;
1090
+ }
1091
+ const sandboxUrl = `https://${targetSubdomain}.sandbox.computesdk.com`;
1092
+ const token = config.access_token;
1093
+ if (hasSandbox(state)) {
1094
+ const shouldDisconnect = await confirm("Disconnect from current sandbox?", false, state);
1095
+ if (!shouldDisconnect) {
1096
+ logWarning("Keeping current sandbox. Connection cancelled.");
1097
+ return;
1098
+ }
1099
+ clearSandbox(state);
1100
+ }
1101
+ const spinner = new Spinner(`Connecting to local sandbox ${targetSubdomain}...`).start();
1102
+ const startTime = Date.now();
1103
+ try {
1104
+ const { Sandbox } = await import("computesdk");
1105
+ let WebSocket;
1106
+ try {
1107
+ const wsModule = await import("ws");
1108
+ WebSocket = wsModule.default;
1109
+ } catch {
1110
+ spinner.fail('Failed to import "ws" module');
1111
+ logError("Please install ws: pnpm add ws");
1112
+ throw new Error('Missing "ws" dependency');
1113
+ }
1114
+ const sandboxInstance = new Sandbox({
1115
+ sandboxUrl,
1116
+ sandboxId: targetSubdomain,
1117
+ provider: "local",
1118
+ token,
1119
+ WebSocket
1120
+ });
1121
+ const info = await sandboxInstance.getInfo();
1122
+ const duration = Date.now() - startTime;
1123
+ setSandbox(state, sandboxInstance, "local");
1124
+ state.verbose = true;
1125
+ spinner.succeed(`Connected to local sandbox ${c.dim(`(${formatDuration(duration)})`)}`);
1126
+ console.log(c.dim(`Sandbox: ${targetSubdomain}`));
1127
+ console.log(c.dim(`URL: ${sandboxUrl}`));
1128
+ console.log(c.dim(`Verbose mode: enabled (for debugging)`));
1129
+ } catch (error) {
1130
+ const duration = Date.now() - startTime;
1131
+ spinner.fail(`Failed to connect ${c.dim(`(${formatDuration(duration)})`)}`);
1132
+ if (error instanceof Error) {
1133
+ logError(`Error: ${error.message}`);
1134
+ }
1135
+ throw error;
1136
+ }
1137
+ }
952
1138
  async function cleanupOnExit(state, replServer) {
953
1139
  if (!hasSandbox(state)) {
954
1140
  return;
@@ -961,7 +1147,7 @@ async function cleanupOnExit(state, replServer) {
961
1147
  logWarning("Disconnecting from external sandbox (not destroying).");
962
1148
  return;
963
1149
  }
964
- const shouldDestroy = await confirm("Destroy active sandbox?");
1150
+ const shouldDestroy = await confirm("Destroy active sandbox?", false, state);
965
1151
  if (shouldDestroy) {
966
1152
  await destroySandbox(state);
967
1153
  } else {
@@ -1351,6 +1537,59 @@ function injectWorkbenchCommands(replServer, state) {
1351
1537
  };
1352
1538
  }
1353
1539
  };
1540
+ replServer.context.terminal = {
1541
+ get create() {
1542
+ return async (options) => {
1543
+ const sandbox = state.currentSandbox;
1544
+ if (!sandbox) {
1545
+ throw new Error("No active sandbox. Run a command to auto-create one.");
1546
+ }
1547
+ const term = await sandbox.terminal.create(options);
1548
+ if (state.verbose) {
1549
+ if (term._ws) {
1550
+ term._ws.config.debug = true;
1551
+ }
1552
+ term.on("output", (data) => {
1553
+ console.log("[terminal:output]", JSON.stringify(data));
1554
+ });
1555
+ term.on("error", (error) => {
1556
+ console.log("[terminal:error]", error);
1557
+ });
1558
+ term.on("destroyed", () => {
1559
+ console.log("[terminal:destroyed]");
1560
+ });
1561
+ }
1562
+ return term;
1563
+ };
1564
+ },
1565
+ get list() {
1566
+ return async () => {
1567
+ const sandbox = state.currentSandbox;
1568
+ if (!sandbox) {
1569
+ throw new Error("No active sandbox. Run a command to auto-create one.");
1570
+ }
1571
+ return sandbox.terminal.list();
1572
+ };
1573
+ },
1574
+ get retrieve() {
1575
+ return async (id) => {
1576
+ const sandbox = state.currentSandbox;
1577
+ if (!sandbox) {
1578
+ throw new Error("No active sandbox. Run a command to auto-create one.");
1579
+ }
1580
+ return sandbox.terminal.retrieve(id);
1581
+ };
1582
+ },
1583
+ get destroy() {
1584
+ return async (id) => {
1585
+ const sandbox = state.currentSandbox;
1586
+ if (!sandbox) {
1587
+ throw new Error("No active sandbox. Run a command to auto-create one.");
1588
+ }
1589
+ return sandbox.terminal.destroy(id);
1590
+ };
1591
+ }
1592
+ };
1354
1593
  replServer.context.getInstance = () => {
1355
1594
  const sandbox = state.currentSandbox;
1356
1595
  if (!sandbox) {
@@ -1364,6 +1603,13 @@ function setupSmartEvaluator(replServer, state) {
1364
1603
  const workbenchCommands = /* @__PURE__ */ new Set(["help", "providers", "info", "env", "restart", "destroy", "mode", "verbose", "sandboxInfo", "connect"]);
1365
1604
  replServer.eval = function(cmd2, context, filename, callback) {
1366
1605
  const trimmedCmd = cmd2.trim();
1606
+ const providerLocalMatch = trimmedCmd.match(/^provider\s+local(?:\s+(\S+))?$/);
1607
+ if (providerLocalMatch) {
1608
+ const arg = providerLocalMatch[1];
1609
+ const providerCmd = arg ? `await provider('local', '${arg}')` : `await provider('local')`;
1610
+ originalEval.call(this, providerCmd, context, filename, callback);
1611
+ return;
1612
+ }
1367
1613
  const providerMatch = trimmedCmd.match(/^provider(?:\s+(direct|gateway))?\s+(\w+)$/);
1368
1614
  if (providerMatch) {
1369
1615
  const mode = providerMatch[1] || null;
@@ -1436,8 +1682,8 @@ function setupSmartEvaluator(replServer, state) {
1436
1682
  function setupAutocomplete(replServer, state) {
1437
1683
  const originalCompleter = replServer.completer;
1438
1684
  const workbenchCommands = {
1439
- "provider": [...PROVIDER_NAMES],
1440
- // Use actual provider names from config
1685
+ "provider": [...PROVIDER_NAMES, "local"],
1686
+ // Include 'local' as a provider option
1441
1687
  "mode": ["gateway", "direct"],
1442
1688
  "providers": [],
1443
1689
  "restart": [],
@@ -1542,22 +1788,38 @@ init_providers();
1542
1788
  init_commands();
1543
1789
  async function startWorkbench() {
1544
1790
  const state = createState();
1791
+ const localDaemonRunning = await isLocalDaemonRunning();
1545
1792
  state.availableProviders = getAvailableProviders();
1793
+ if (localDaemonRunning) {
1794
+ state.availableProviders.push("local");
1795
+ }
1546
1796
  const detectedProvider = autoDetectProvider();
1547
- const hasGateway = state.availableProviders.includes("gateway");
1548
- const backendProviders = state.availableProviders.filter((p) => p !== "gateway");
1549
- if (hasGateway && backendProviders.length > 0) {
1550
- state.currentProvider = backendProviders[0] || "e2b";
1797
+ if (localDaemonRunning) {
1798
+ state.currentProvider = "local";
1551
1799
  state.useDirectMode = false;
1552
- } else if (backendProviders.length > 0) {
1553
- state.currentProvider = backendProviders[0];
1554
- state.useDirectMode = true;
1800
+ state.verbose = true;
1555
1801
  } else {
1556
- state.currentProvider = detectedProvider;
1557
- state.useDirectMode = false;
1802
+ const hasGateway = state.availableProviders.includes("gateway");
1803
+ const backendProviders = state.availableProviders.filter((p) => p !== "gateway" && p !== "local");
1804
+ if (hasGateway && backendProviders.length > 0) {
1805
+ state.currentProvider = backendProviders[0] || "e2b";
1806
+ state.useDirectMode = false;
1807
+ } else if (backendProviders.length > 0) {
1808
+ state.currentProvider = backendProviders[0];
1809
+ state.useDirectMode = true;
1810
+ } else {
1811
+ state.currentProvider = detectedProvider;
1812
+ state.useDirectMode = false;
1813
+ }
1558
1814
  }
1559
- showWelcome(state.availableProviders, state.currentProvider, state.useDirectMode);
1815
+ showWelcome(state.availableProviders, state.currentProvider, state.useDirectMode, localDaemonRunning);
1560
1816
  const replServer = createREPL(state);
1817
+ if (localDaemonRunning) {
1818
+ try {
1819
+ await connectToLocal(state);
1820
+ } catch {
1821
+ }
1822
+ }
1561
1823
  replServer.on("exit", async () => {
1562
1824
  await cleanupOnExit(state, replServer);
1563
1825
  process.exit(0);