@adhdev/daemon-core 0.8.12 → 0.8.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -632,6 +632,13 @@ function logTerminalBackendSelection(preference, ghosttyAvailable, backendKind)
632
632
  const key = `${preference}:${ghosttyAvailable}:${backendKind}`;
633
633
  if (loggedTerminalBackends.has(key)) return;
634
634
  loggedTerminalBackends.add(key);
635
+ if (backendKind === "xterm" && preference !== "xterm" && !ghosttyAvailable) {
636
+ LOG.warn(
637
+ "Terminal",
638
+ `[terminal-screen] ghostty-vt unavailable; using xterm fallback (preference=${preference})`
639
+ );
640
+ return;
641
+ }
635
642
  LOG.info(
636
643
  "Terminal",
637
644
  `[terminal-screen] backend=${backendKind} preference=${preference} ghosttyAvailable=${ghosttyAvailable}`
@@ -694,6 +701,7 @@ var init_terminal_screen = __esm({
694
701
  });
695
702
 
696
703
  // src/cli-adapters/pty-transport.ts
704
+ import * as os7 from "os";
697
705
  var pty, NodePtyRuntimeTransport, NodePtyTransportFactory;
698
706
  var init_pty_transport = __esm({
699
707
  "src/cli-adapters/pty-transport.ts"() {
@@ -734,11 +742,21 @@ var init_pty_transport = __esm({
734
742
  NodePtyTransportFactory = class {
735
743
  spawn(command, args, options) {
736
744
  if (!pty) throw new Error("node-pty is not installed");
745
+ let cwd = options.cwd;
746
+ if (cwd) {
747
+ try {
748
+ const fs15 = __require("fs");
749
+ const stat = fs15.statSync(cwd);
750
+ if (!stat.isDirectory()) cwd = os7.homedir();
751
+ } catch {
752
+ cwd = os7.homedir();
753
+ }
754
+ }
737
755
  const handle = pty.spawn(command, args, {
738
756
  name: "xterm-256color",
739
757
  cols: options.cols,
740
758
  rows: options.rows,
741
- cwd: options.cwd,
759
+ cwd,
742
760
  env: options.env
743
761
  });
744
762
  return new NodePtyRuntimeTransport(handle);
@@ -747,13 +765,25 @@ var init_pty_transport = __esm({
747
765
  }
748
766
  });
749
767
 
768
+ // src/cli-adapters/spawn-env.ts
769
+ import {
770
+ sanitizeSpawnEnv,
771
+ applyTerminalColorEnv,
772
+ ensureNodePtySpawnHelperPermissions
773
+ } from "@adhdev/session-host-core";
774
+ var init_spawn_env = __esm({
775
+ "src/cli-adapters/spawn-env.ts"() {
776
+ "use strict";
777
+ }
778
+ });
779
+
750
780
  // src/cli-adapters/provider-cli-adapter.ts
751
781
  var provider_cli_adapter_exports = {};
752
782
  __export(provider_cli_adapter_exports, {
753
783
  ProviderCliAdapter: () => ProviderCliAdapter,
754
784
  normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
755
785
  });
756
- import * as os7 from "os";
786
+ import * as os8 from "os";
757
787
  import * as path7 from "path";
758
788
  import { execSync as execSync3 } from "child_process";
759
789
  function stripAnsi(str) {
@@ -765,32 +795,6 @@ function stripTerminalNoise(str) {
765
795
  function sanitizeTerminalText(str) {
766
796
  return stripTerminalNoise(stripAnsi(str));
767
797
  }
768
- function applyPreferredTerminalColorEnv(env) {
769
- if (env.NO_COLOR) return;
770
- if (!env.TERM || env.TERM === "xterm-color") {
771
- env.TERM = "xterm-256color";
772
- }
773
- if (!env.COLORTERM) env.COLORTERM = "truecolor";
774
- if (process.platform === "win32") {
775
- if (!env.FORCE_COLOR) env.FORCE_COLOR = "1";
776
- if (!env.CLICOLOR) env.CLICOLOR = "1";
777
- }
778
- }
779
- function buildCliSpawnEnv(baseEnv, overrides) {
780
- const env = {};
781
- const source = { ...baseEnv, ...overrides || {} };
782
- for (const [key, value] of Object.entries(source)) {
783
- if (typeof value !== "string") continue;
784
- env[key] = value;
785
- }
786
- for (const key of Object.keys(env)) {
787
- if (key === "INIT_CWD" || key === "npm_command" || key === "npm_execpath" || key === "npm_node_execpath" || key.startsWith("npm_") || key.startsWith("npm_config_") || key.startsWith("npm_package_") || key.startsWith("npm_lifecycle_") || key.startsWith("PNPM_") || key.startsWith("YARN_") || key.startsWith("BUN_")) {
788
- delete env[key];
789
- }
790
- }
791
- applyPreferredTerminalColorEnv(env);
792
- return env;
793
- }
794
798
  function computeTerminalQueryTail(buffer) {
795
799
  const prefixes = ["\x1B[6n", "\x1B[?6n"];
796
800
  const maxLength = prefixes.reduce((n, value) => Math.max(n, value.length), 0) - 1;
@@ -804,7 +808,7 @@ function computeTerminalQueryTail(buffer) {
804
808
  return "";
805
809
  }
806
810
  function findBinary(name) {
807
- const isWin = os7.platform() === "win32";
811
+ const isWin = os8.platform() === "win32";
808
812
  try {
809
813
  const cmd = isWin ? `where ${name}` : `which ${name}`;
810
814
  return execSync3(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
@@ -852,7 +856,7 @@ function looksLikeMachOOrElf(filePath) {
852
856
  }
853
857
  function shSingleQuote(arg) {
854
858
  if (/^[a-zA-Z0-9@%_+=:,./-]+$/.test(arg)) return arg;
855
- if (os7.platform() === "win32") {
859
+ if (os8.platform() === "win32") {
856
860
  return `"${arg.replace(/"/g, '""')}"`;
857
861
  }
858
862
  return `'${arg.replace(/'/g, `'\\''`)}'`;
@@ -919,34 +923,21 @@ function normalizeCliProviderForRuntime(raw) {
919
923
  }
920
924
  };
921
925
  }
922
- var pty2, ProviderCliAdapter;
926
+ var pty2, buildCliSpawnEnv, ProviderCliAdapter;
923
927
  var init_provider_cli_adapter = __esm({
924
928
  "src/cli-adapters/provider-cli-adapter.ts"() {
925
929
  "use strict";
926
930
  init_logger();
927
931
  init_terminal_screen();
928
932
  init_pty_transport();
933
+ init_spawn_env();
929
934
  try {
930
935
  pty2 = __require("node-pty");
931
- if (os7.platform() !== "win32") {
932
- try {
933
- const fs15 = __require("fs");
934
- const ptyDir = path7.resolve(path7.dirname(__require.resolve("node-pty")), "..");
935
- const platformArch = `${os7.platform()}-${os7.arch()}`;
936
- const helper = path7.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
937
- if (fs15.existsSync(helper)) {
938
- const stat = fs15.statSync(helper);
939
- if (!(stat.mode & 73)) {
940
- fs15.chmodSync(helper, stat.mode | 493);
941
- LOG.info("CLI", "[node-pty] Fixed spawn-helper permissions");
942
- }
943
- }
944
- } catch {
945
- }
946
- }
936
+ ensureNodePtySpawnHelperPermissions((msg) => LOG.info("CLI", msg));
947
937
  } catch {
948
938
  LOG.error("CLI", "[ProviderCliAdapter] node-pty not found. Terminal features disabled.");
949
939
  }
940
+ buildCliSpawnEnv = sanitizeSpawnEnv;
950
941
  ProviderCliAdapter = class _ProviderCliAdapter {
951
942
  constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
952
943
  this.extraArgs = extraArgs;
@@ -954,7 +945,7 @@ var init_provider_cli_adapter = __esm({
954
945
  this.transportFactory = transportFactory;
955
946
  this.cliType = provider.type;
956
947
  this.cliName = provider.name;
957
- this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os7.homedir()) : workingDir;
948
+ this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os8.homedir()) : workingDir;
958
949
  const t = provider.timeouts || {};
959
950
  this.timeouts = {
960
951
  ptyFlush: t.ptyFlush ?? 50,
@@ -1261,7 +1252,7 @@ var init_provider_cli_adapter = __esm({
1261
1252
  if (this.ptyProcess) return;
1262
1253
  const { spawn: spawnConfig } = this.provider;
1263
1254
  const binaryPath = findBinary(spawnConfig.command);
1264
- const isWin = os7.platform() === "win32";
1255
+ const isWin = os8.platform() === "win32";
1265
1256
  const allArgs = [...spawnConfig.args, ...this.extraArgs];
1266
1257
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1267
1258
  this.resetTraceSession();
@@ -1269,13 +1260,16 @@ var init_provider_cli_adapter = __esm({
1269
1260
  let shellArgs;
1270
1261
  const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1271
1262
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1272
- const useShell = isWin ? !!spawnConfig.shell || isCmdShim : useShellUnix;
1263
+ const useShellWin = isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1264
+ const useShell = isWin ? useShellWin : useShellUnix;
1273
1265
  if (useShell) {
1274
1266
  if (!spawnConfig.shell && !isWin) {
1275
1267
  LOG.info("CLI", `[${this.cliType}] Using login shell (script shim or non-native binary)`);
1276
1268
  }
1277
1269
  if (isCmdShim) {
1278
1270
  LOG.info("CLI", `[${this.cliType}] Using cmd.exe shell for .cmd/.bat shim: ${binaryPath}`);
1271
+ } else if (isWin) {
1272
+ LOG.info("CLI", `[${this.cliType}] Using cmd.exe shell on Windows: ${binaryPath}`);
1279
1273
  }
1280
1274
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
1281
1275
  if (isWin) {
@@ -1285,6 +1279,9 @@ var init_provider_cli_adapter = __esm({
1285
1279
  shellArgs = ["-l", "-c", fullCmd];
1286
1280
  }
1287
1281
  } else {
1282
+ if (isWin && spawnConfig.shell) {
1283
+ LOG.info("CLI", `[${this.cliType}] Spawning Windows binary directly without cmd.exe: ${binaryPath}`);
1284
+ }
1288
1285
  shellCmd = binaryPath;
1289
1286
  shellArgs = allArgs;
1290
1287
  }
@@ -1313,6 +1310,12 @@ var init_provider_cli_adapter = __esm({
1313
1310
  shellArgs = ["-l", "-c", fullCmd];
1314
1311
  this.ptyProcess = this.transportFactory.spawn(shellCmd, shellArgs, ptyOpts);
1315
1312
  } else {
1313
+ if (isWin) {
1314
+ const hint = /error code 267|ERROR_DIRECTORY/i.test(msg) ? " (working directory does not exist or is not a directory)" : /error code 740|elevation/i.test(msg) ? " (requires administrator privileges)" : /error code 2|ENOENT|not found/i.test(msg) ? ` (executable not found: ${shellCmd})` : "";
1315
+ if (hint) {
1316
+ throw new Error(`Failed to spawn CLI${hint}: ${msg}`);
1317
+ }
1318
+ }
1316
1319
  throw err;
1317
1320
  }
1318
1321
  }
@@ -1487,7 +1490,7 @@ var init_provider_cli_adapter = __esm({
1487
1490
  `[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(this.summarizeTraceText(screenText, 220)).slice(0, 260)}`
1488
1491
  );
1489
1492
  }
1490
- await new Promise((resolve10) => setTimeout(resolve10, 50));
1493
+ await new Promise((resolve9) => setTimeout(resolve9, 50));
1491
1494
  }
1492
1495
  const finalScreenText = this.terminalScreen.getText() || "";
1493
1496
  LOG.warn(
@@ -1874,7 +1877,7 @@ ${data.message || ""}`.trim();
1874
1877
  if (this.startupParseGate) {
1875
1878
  const deadline = Date.now() + 1e4;
1876
1879
  while (this.startupParseGate && Date.now() < deadline) {
1877
- await new Promise((resolve10) => setTimeout(resolve10, 50));
1880
+ await new Promise((resolve9) => setTimeout(resolve9, 50));
1878
1881
  }
1879
1882
  }
1880
1883
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
@@ -2065,7 +2068,8 @@ ${data.message || ""}`.trim();
2065
2068
  const payload = stopCommand.endsWith("\r") || stopCommand.endsWith("\n") ? stopCommand : `${stopCommand}${this.sendKey}`;
2066
2069
  this.ptyProcess.write(payload);
2067
2070
  };
2068
- if (wasProcessing) setTimeout(writeCommand, 250);
2071
+ const interruptGraceMs = typeof resume.interruptGraceMs === "number" ? Math.max(100, resume.interruptGraceMs) : 500;
2072
+ if (wasProcessing) setTimeout(writeCommand, interruptGraceMs);
2069
2073
  else writeCommand();
2070
2074
  } else {
2071
2075
  this.ptyProcess.write("");
@@ -2081,17 +2085,17 @@ ${data.message || ""}`.trim();
2081
2085
  }
2082
2086
  }
2083
2087
  waitForStopped(timeoutMs) {
2084
- return new Promise((resolve10) => {
2088
+ return new Promise((resolve9) => {
2085
2089
  const startedAt = Date.now();
2086
2090
  const timer = setInterval(() => {
2087
2091
  if (!this.ptyProcess || this.currentStatus === "stopped") {
2088
2092
  clearInterval(timer);
2089
- resolve10(true);
2093
+ resolve9(true);
2090
2094
  return;
2091
2095
  }
2092
2096
  if (Date.now() - startedAt >= timeoutMs) {
2093
2097
  clearInterval(timer);
2094
- resolve10(false);
2098
+ resolve9(false);
2095
2099
  }
2096
2100
  }, 100);
2097
2101
  });
@@ -2110,6 +2114,18 @@ ${data.message || ""}`.trim();
2110
2114
  clearTimeout(this.submitRetryTimer);
2111
2115
  this.submitRetryTimer = null;
2112
2116
  }
2117
+ if (this.responseTimeout) {
2118
+ clearTimeout(this.responseTimeout);
2119
+ this.responseTimeout = null;
2120
+ }
2121
+ if (this.idleTimeout) {
2122
+ clearTimeout(this.idleTimeout);
2123
+ this.idleTimeout = null;
2124
+ }
2125
+ if (this.pendingScriptStatusTimer) {
2126
+ clearTimeout(this.pendingScriptStatusTimer);
2127
+ this.pendingScriptStatusTimer = null;
2128
+ }
2113
2129
  if (this.pendingOutputParseTimer) {
2114
2130
  clearTimeout(this.pendingOutputParseTimer);
2115
2131
  this.pendingOutputParseTimer = null;
@@ -2151,6 +2167,18 @@ ${data.message || ""}`.trim();
2151
2167
  clearTimeout(this.submitRetryTimer);
2152
2168
  this.submitRetryTimer = null;
2153
2169
  }
2170
+ if (this.responseTimeout) {
2171
+ clearTimeout(this.responseTimeout);
2172
+ this.responseTimeout = null;
2173
+ }
2174
+ if (this.idleTimeout) {
2175
+ clearTimeout(this.idleTimeout);
2176
+ this.idleTimeout = null;
2177
+ }
2178
+ if (this.pendingScriptStatusTimer) {
2179
+ clearTimeout(this.pendingScriptStatusTimer);
2180
+ this.pendingScriptStatusTimer = null;
2181
+ }
2154
2182
  if (this.pendingOutputParseTimer) {
2155
2183
  clearTimeout(this.pendingOutputParseTimer);
2156
2184
  this.pendingOutputParseTimer = null;
@@ -2665,20 +2693,20 @@ function checkPathExists(paths) {
2665
2693
  return null;
2666
2694
  }
2667
2695
  async function detectIDEs() {
2668
- const os17 = platform();
2696
+ const os18 = platform();
2669
2697
  const results = [];
2670
2698
  for (const def of getMergedDefinitions()) {
2671
2699
  const cliPath = findCliCommand(def.cli);
2672
- const appPath = checkPathExists(def.paths[os17] || []);
2700
+ const appPath = checkPathExists(def.paths[os18] || []);
2673
2701
  const installed = !!(cliPath || appPath);
2674
2702
  let resolvedCli = cliPath;
2675
- if (!resolvedCli && appPath && os17 === "darwin") {
2703
+ if (!resolvedCli && appPath && os18 === "darwin") {
2676
2704
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
2677
2705
  if (existsSync3(bundledCli)) resolvedCli = bundledCli;
2678
2706
  }
2679
- if (!resolvedCli && appPath && os17 === "win32") {
2680
- const { dirname: dirname7 } = await import("path");
2681
- const appDir = dirname7(appPath);
2707
+ if (!resolvedCli && appPath && os18 === "win32") {
2708
+ const { dirname: dirname6 } = await import("path");
2709
+ const appDir = dirname6(appPath);
2682
2710
  const candidates = [
2683
2711
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
2684
2712
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -2716,15 +2744,15 @@ function parseVersion(raw) {
2716
2744
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
2717
2745
  }
2718
2746
  function execAsync(cmd, timeoutMs = 5e3) {
2719
- return new Promise((resolve10) => {
2747
+ return new Promise((resolve9) => {
2720
2748
  const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
2721
2749
  if (err || !stdout?.trim()) {
2722
- resolve10(null);
2750
+ resolve9(null);
2723
2751
  } else {
2724
- resolve10(stdout.trim());
2752
+ resolve9(stdout.trim());
2725
2753
  }
2726
2754
  });
2727
- child.on("error", () => resolve10(null));
2755
+ child.on("error", () => resolve9(null));
2728
2756
  });
2729
2757
  }
2730
2758
  async function detectCLIs(providerLoader) {
@@ -2764,6 +2792,39 @@ async function detectCLIs(providerLoader) {
2764
2792
  }
2765
2793
  async function detectCLI(cliId, providerLoader) {
2766
2794
  const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
2795
+ if (providerLoader) {
2796
+ const cliList = providerLoader.getCliDetectionList();
2797
+ const target = cliList.find((c) => c.id === resolvedId);
2798
+ if (target) {
2799
+ const platform9 = os2.platform();
2800
+ const whichCmd = platform9 === "win32" ? "where" : "which";
2801
+ try {
2802
+ const pathResult = await execAsync(`${whichCmd} ${target.command}`);
2803
+ if (!pathResult) return null;
2804
+ const firstPath = pathResult.split("\n")[0];
2805
+ let version;
2806
+ try {
2807
+ const versionCommands = [
2808
+ target.versionCommand,
2809
+ `${target.command} --version`,
2810
+ `${target.command} -V`,
2811
+ `${target.command} -v`
2812
+ ].filter((v) => !!v);
2813
+ for (const versionCommand of versionCommands) {
2814
+ const versionResult = await execAsync(versionCommand, 3e3);
2815
+ if (versionResult) {
2816
+ version = parseVersion(versionResult);
2817
+ break;
2818
+ }
2819
+ }
2820
+ } catch {
2821
+ }
2822
+ return { ...target, installed: true, version, path: firstPath };
2823
+ } catch {
2824
+ return null;
2825
+ }
2826
+ }
2827
+ }
2767
2828
  const all = await detectCLIs(providerLoader);
2768
2829
  return all.find((c) => c.id === resolvedId && c.installed) || null;
2769
2830
  }
@@ -2891,7 +2952,7 @@ var DaemonCdpManager = class {
2891
2952
  * Returns multiple entries if multiple IDE windows are open on same port
2892
2953
  */
2893
2954
  static listAllTargets(port) {
2894
- return new Promise((resolve10) => {
2955
+ return new Promise((resolve9) => {
2895
2956
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2896
2957
  let data = "";
2897
2958
  res.on("data", (chunk) => data += chunk.toString());
@@ -2907,16 +2968,16 @@ var DaemonCdpManager = class {
2907
2968
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
2908
2969
  );
2909
2970
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
2910
- resolve10(mainPages.length > 0 ? mainPages : fallbackPages);
2971
+ resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
2911
2972
  } catch {
2912
- resolve10([]);
2973
+ resolve9([]);
2913
2974
  }
2914
2975
  });
2915
2976
  });
2916
- req.on("error", () => resolve10([]));
2977
+ req.on("error", () => resolve9([]));
2917
2978
  req.setTimeout(2e3, () => {
2918
2979
  req.destroy();
2919
- resolve10([]);
2980
+ resolve9([]);
2920
2981
  });
2921
2982
  });
2922
2983
  }
@@ -2956,7 +3017,7 @@ var DaemonCdpManager = class {
2956
3017
  }
2957
3018
  }
2958
3019
  findTargetOnPort(port) {
2959
- return new Promise((resolve10) => {
3020
+ return new Promise((resolve9) => {
2960
3021
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
2961
3022
  let data = "";
2962
3023
  res.on("data", (chunk) => data += chunk.toString());
@@ -2967,7 +3028,7 @@ var DaemonCdpManager = class {
2967
3028
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
2968
3029
  );
2969
3030
  if (pages.length === 0) {
2970
- resolve10(targets.find((t) => t.webSocketDebuggerUrl) || null);
3031
+ resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
2971
3032
  return;
2972
3033
  }
2973
3034
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -2977,24 +3038,24 @@ var DaemonCdpManager = class {
2977
3038
  const specific = list.find((t) => t.id === this._targetId);
2978
3039
  if (specific) {
2979
3040
  this._pageTitle = specific.title || "";
2980
- resolve10(specific);
3041
+ resolve9(specific);
2981
3042
  } else {
2982
3043
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
2983
- resolve10(null);
3044
+ resolve9(null);
2984
3045
  }
2985
3046
  return;
2986
3047
  }
2987
3048
  this._pageTitle = list[0]?.title || "";
2988
- resolve10(list[0]);
3049
+ resolve9(list[0]);
2989
3050
  } catch {
2990
- resolve10(null);
3051
+ resolve9(null);
2991
3052
  }
2992
3053
  });
2993
3054
  });
2994
- req.on("error", () => resolve10(null));
3055
+ req.on("error", () => resolve9(null));
2995
3056
  req.setTimeout(2e3, () => {
2996
3057
  req.destroy();
2997
- resolve10(null);
3058
+ resolve9(null);
2998
3059
  });
2999
3060
  });
3000
3061
  }
@@ -3005,7 +3066,7 @@ var DaemonCdpManager = class {
3005
3066
  this.extensionProviders = providers;
3006
3067
  }
3007
3068
  connectToTarget(wsUrl) {
3008
- return new Promise((resolve10) => {
3069
+ return new Promise((resolve9) => {
3009
3070
  this.ws = new WebSocket(wsUrl);
3010
3071
  this.ws.on("open", async () => {
3011
3072
  this._connected = true;
@@ -3015,17 +3076,17 @@ var DaemonCdpManager = class {
3015
3076
  }
3016
3077
  this.connectBrowserWs().catch(() => {
3017
3078
  });
3018
- resolve10(true);
3079
+ resolve9(true);
3019
3080
  });
3020
3081
  this.ws.on("message", (data) => {
3021
3082
  try {
3022
3083
  const msg = JSON.parse(data.toString());
3023
3084
  if (msg.id && this.pending.has(msg.id)) {
3024
- const { resolve: resolve11, reject } = this.pending.get(msg.id);
3085
+ const { resolve: resolve10, reject } = this.pending.get(msg.id);
3025
3086
  this.pending.delete(msg.id);
3026
3087
  this.failureCount = 0;
3027
3088
  if (msg.error) reject(new Error(msg.error.message));
3028
- else resolve11(msg.result);
3089
+ else resolve10(msg.result);
3029
3090
  } else if (msg.method === "Runtime.executionContextCreated") {
3030
3091
  this.contexts.add(msg.params.context.id);
3031
3092
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -3048,7 +3109,7 @@ var DaemonCdpManager = class {
3048
3109
  this.ws.on("error", (err) => {
3049
3110
  this.log(`[CDP] WebSocket error: ${err.message}`);
3050
3111
  this._connected = false;
3051
- resolve10(false);
3112
+ resolve9(false);
3052
3113
  });
3053
3114
  });
3054
3115
  }
@@ -3062,7 +3123,7 @@ var DaemonCdpManager = class {
3062
3123
  return;
3063
3124
  }
3064
3125
  this.log(`[CDP] Connecting browser WS for target discovery...`);
3065
- await new Promise((resolve10, reject) => {
3126
+ await new Promise((resolve9, reject) => {
3066
3127
  this.browserWs = new WebSocket(browserWsUrl);
3067
3128
  this.browserWs.on("open", async () => {
3068
3129
  this._browserConnected = true;
@@ -3072,16 +3133,16 @@ var DaemonCdpManager = class {
3072
3133
  } catch (e) {
3073
3134
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
3074
3135
  }
3075
- resolve10();
3136
+ resolve9();
3076
3137
  });
3077
3138
  this.browserWs.on("message", (data) => {
3078
3139
  try {
3079
3140
  const msg = JSON.parse(data.toString());
3080
3141
  if (msg.id && this.browserPending.has(msg.id)) {
3081
- const { resolve: resolve11, reject: reject2 } = this.browserPending.get(msg.id);
3142
+ const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
3082
3143
  this.browserPending.delete(msg.id);
3083
3144
  if (msg.error) reject2(new Error(msg.error.message));
3084
- else resolve11(msg.result);
3145
+ else resolve10(msg.result);
3085
3146
  }
3086
3147
  } catch {
3087
3148
  }
@@ -3101,31 +3162,31 @@ var DaemonCdpManager = class {
3101
3162
  }
3102
3163
  }
3103
3164
  getBrowserWsUrl() {
3104
- return new Promise((resolve10) => {
3165
+ return new Promise((resolve9) => {
3105
3166
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
3106
3167
  let data = "";
3107
3168
  res.on("data", (chunk) => data += chunk.toString());
3108
3169
  res.on("end", () => {
3109
3170
  try {
3110
3171
  const info = JSON.parse(data);
3111
- resolve10(info.webSocketDebuggerUrl || null);
3172
+ resolve9(info.webSocketDebuggerUrl || null);
3112
3173
  } catch {
3113
- resolve10(null);
3174
+ resolve9(null);
3114
3175
  }
3115
3176
  });
3116
3177
  });
3117
- req.on("error", () => resolve10(null));
3178
+ req.on("error", () => resolve9(null));
3118
3179
  req.setTimeout(3e3, () => {
3119
3180
  req.destroy();
3120
- resolve10(null);
3181
+ resolve9(null);
3121
3182
  });
3122
3183
  });
3123
3184
  }
3124
3185
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
3125
- return new Promise((resolve10, reject) => {
3186
+ return new Promise((resolve9, reject) => {
3126
3187
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
3127
3188
  const id = this.browserMsgId++;
3128
- this.browserPending.set(id, { resolve: resolve10, reject });
3189
+ this.browserPending.set(id, { resolve: resolve9, reject });
3129
3190
  this.browserWs.send(JSON.stringify({ id, method, params }));
3130
3191
  setTimeout(() => {
3131
3192
  if (this.browserPending.has(id)) {
@@ -3165,11 +3226,11 @@ var DaemonCdpManager = class {
3165
3226
  }
3166
3227
  // ─── CDP Protocol ────────────────────────────────────────
3167
3228
  sendInternal(method, params = {}, timeoutMs = 15e3) {
3168
- return new Promise((resolve10, reject) => {
3229
+ return new Promise((resolve9, reject) => {
3169
3230
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
3170
3231
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
3171
3232
  const id = this.msgId++;
3172
- this.pending.set(id, { resolve: resolve10, reject });
3233
+ this.pending.set(id, { resolve: resolve9, reject });
3173
3234
  this.ws.send(JSON.stringify({ id, method, params }));
3174
3235
  setTimeout(() => {
3175
3236
  if (this.pending.has(id)) {
@@ -3418,7 +3479,7 @@ var DaemonCdpManager = class {
3418
3479
  const browserWs = this.browserWs;
3419
3480
  let msgId = this.browserMsgId;
3420
3481
  const sendWs = (method, params = {}, sessionId) => {
3421
- return new Promise((resolve10, reject) => {
3482
+ return new Promise((resolve9, reject) => {
3422
3483
  const mid = msgId++;
3423
3484
  this.browserMsgId = msgId;
3424
3485
  const handler = (raw) => {
@@ -3427,7 +3488,7 @@ var DaemonCdpManager = class {
3427
3488
  if (msg.id === mid) {
3428
3489
  browserWs.removeListener("message", handler);
3429
3490
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
3430
- else resolve10(msg.result);
3491
+ else resolve9(msg.result);
3431
3492
  }
3432
3493
  } catch {
3433
3494
  }
@@ -3618,14 +3679,14 @@ var DaemonCdpManager = class {
3618
3679
  if (!ws || ws.readyState !== WebSocket.OPEN) {
3619
3680
  throw new Error("CDP not connected");
3620
3681
  }
3621
- return new Promise((resolve10, reject) => {
3682
+ return new Promise((resolve9, reject) => {
3622
3683
  const id = getNextId();
3623
3684
  pendingMap.set(id, {
3624
3685
  resolve: (result) => {
3625
3686
  if (result?.result?.subtype === "error") {
3626
3687
  reject(new Error(result.result.description));
3627
3688
  } else {
3628
- resolve10(result?.result?.value);
3689
+ resolve9(result?.result?.value);
3629
3690
  }
3630
3691
  },
3631
3692
  reject
@@ -3657,10 +3718,10 @@ var DaemonCdpManager = class {
3657
3718
  throw new Error("CDP not connected");
3658
3719
  }
3659
3720
  const sendViaSession = (method, params = {}) => {
3660
- return new Promise((resolve10, reject) => {
3721
+ return new Promise((resolve9, reject) => {
3661
3722
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
3662
3723
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
3663
- pendingMap.set(id, { resolve: resolve10, reject });
3724
+ pendingMap.set(id, { resolve: resolve9, reject });
3664
3725
  ws.send(JSON.stringify({ id, sessionId, method, params }));
3665
3726
  setTimeout(() => {
3666
3727
  if (pendingMap.has(id)) {
@@ -7192,8 +7253,24 @@ function handleSetIdeExtension(h, args) {
7192
7253
 
7193
7254
  // src/commands/workspace-commands.ts
7194
7255
  init_config();
7256
+ function loadWorkspaceConfig() {
7257
+ try {
7258
+ return loadConfig();
7259
+ } catch (e) {
7260
+ return { error: `Could not load config: ${e?.message || "unknown error"}` };
7261
+ }
7262
+ }
7263
+ function persistWorkspaceConfig(config) {
7264
+ try {
7265
+ saveConfig(config);
7266
+ return { ok: true };
7267
+ } catch (e) {
7268
+ return { error: `Could not save config: ${e?.message || "unknown error"}` };
7269
+ }
7270
+ }
7195
7271
  function handleWorkspaceList() {
7196
- const config = loadConfig();
7272
+ const config = loadWorkspaceConfig();
7273
+ if ("error" in config) return { success: false, error: config.error };
7197
7274
  const state = getWorkspaceState(config);
7198
7275
  return {
7199
7276
  success: true,
@@ -7207,31 +7284,37 @@ function handleWorkspaceAdd(args) {
7207
7284
  const label = (args?.label || "").trim() || void 0;
7208
7285
  const createIfMissing = args?.createIfMissing === true;
7209
7286
  if (!rawPath) return { success: false, error: "path required" };
7210
- const config = loadConfig();
7287
+ const config = loadWorkspaceConfig();
7288
+ if ("error" in config) return { success: false, error: config.error };
7211
7289
  const result = addWorkspaceEntry(config, rawPath, label, { createIfMissing });
7212
7290
  if ("error" in result) return { success: false, error: result.error };
7213
- saveConfig(result.config);
7291
+ const saveResult = persistWorkspaceConfig(result.config);
7292
+ if ("error" in saveResult) return { success: false, error: saveResult.error };
7214
7293
  const state = getWorkspaceState(result.config);
7215
7294
  return { success: true, entry: result.entry, ...state };
7216
7295
  }
7217
7296
  function handleWorkspaceRemove(args) {
7218
7297
  const id = (args?.id || "").trim();
7219
7298
  if (!id) return { success: false, error: "id required" };
7220
- const config = loadConfig();
7299
+ const config = loadWorkspaceConfig();
7300
+ if ("error" in config) return { success: false, error: config.error };
7221
7301
  const removed = (config.workspaces || []).find((w) => w.id === id);
7222
7302
  const result = removeWorkspaceEntry(config, id);
7223
7303
  if ("error" in result) return { success: false, error: result.error };
7224
- saveConfig(result.config);
7304
+ const saveResult = persistWorkspaceConfig(result.config);
7305
+ if ("error" in saveResult) return { success: false, error: saveResult.error };
7225
7306
  const state = getWorkspaceState(result.config);
7226
7307
  return { success: true, removedId: id, ...state };
7227
7308
  }
7228
7309
  function handleWorkspaceSetDefault(args) {
7229
7310
  const clear = args?.clear === true || args?.id === null || args?.id === "";
7230
7311
  if (clear) {
7231
- const config2 = loadConfig();
7312
+ const config2 = loadWorkspaceConfig();
7313
+ if ("error" in config2) return { success: false, error: config2.error };
7232
7314
  const result2 = setDefaultWorkspaceId(config2, null);
7233
7315
  if ("error" in result2) return { success: false, error: result2.error };
7234
- saveConfig(result2.config);
7316
+ const saveResult2 = persistWorkspaceConfig(result2.config);
7317
+ if ("error" in saveResult2) return { success: false, error: saveResult2.error };
7235
7318
  const state2 = getWorkspaceState(result2.config);
7236
7319
  return {
7237
7320
  success: true,
@@ -7243,7 +7326,9 @@ function handleWorkspaceSetDefault(args) {
7243
7326
  if (!pathArg && !idArg) {
7244
7327
  return { success: false, error: "id or path required (or clear: true)" };
7245
7328
  }
7246
- let config = loadConfig();
7329
+ const configResult = loadWorkspaceConfig();
7330
+ if ("error" in configResult) return { success: false, error: configResult.error };
7331
+ let config = configResult;
7247
7332
  let nextId;
7248
7333
  if (pathArg) {
7249
7334
  let w = findWorkspaceByPath(config, pathArg);
@@ -7259,7 +7344,8 @@ function handleWorkspaceSetDefault(args) {
7259
7344
  }
7260
7345
  const result = setDefaultWorkspaceId(config, nextId);
7261
7346
  if ("error" in result) return { success: false, error: result.error };
7262
- saveConfig(result.config);
7347
+ const saveResult = persistWorkspaceConfig(result.config);
7348
+ if ("error" in saveResult) return { success: false, error: saveResult.error };
7263
7349
  const state = getWorkspaceState(result.config);
7264
7350
  return { success: true, ...state };
7265
7351
  }
@@ -7661,7 +7747,7 @@ var DaemonCommandHandler = class {
7661
7747
  try {
7662
7748
  const http3 = await import("http");
7663
7749
  const postData = JSON.stringify(body);
7664
- const result = await new Promise((resolve10, reject) => {
7750
+ const result = await new Promise((resolve9, reject) => {
7665
7751
  const req = http3.request({
7666
7752
  hostname: "127.0.0.1",
7667
7753
  port: 19280,
@@ -7673,9 +7759,9 @@ var DaemonCommandHandler = class {
7673
7759
  res.on("data", (chunk) => data += chunk);
7674
7760
  res.on("end", () => {
7675
7761
  try {
7676
- resolve10(JSON.parse(data));
7762
+ resolve9(JSON.parse(data));
7677
7763
  } catch {
7678
- resolve10({ raw: data });
7764
+ resolve9({ raw: data });
7679
7765
  }
7680
7766
  });
7681
7767
  });
@@ -7693,15 +7779,15 @@ var DaemonCommandHandler = class {
7693
7779
  if (!providerType) return { success: false, error: "providerType required" };
7694
7780
  try {
7695
7781
  const http3 = await import("http");
7696
- const result = await new Promise((resolve10, reject) => {
7782
+ const result = await new Promise((resolve9, reject) => {
7697
7783
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
7698
7784
  let data = "";
7699
7785
  res.on("data", (chunk) => data += chunk);
7700
7786
  res.on("end", () => {
7701
7787
  try {
7702
- resolve10(JSON.parse(data));
7788
+ resolve9(JSON.parse(data));
7703
7789
  } catch {
7704
- resolve10({ raw: data });
7790
+ resolve9({ raw: data });
7705
7791
  }
7706
7792
  });
7707
7793
  }).on("error", reject);
@@ -7715,7 +7801,7 @@ var DaemonCommandHandler = class {
7715
7801
  try {
7716
7802
  const http3 = await import("http");
7717
7803
  const postData = JSON.stringify(args || {});
7718
- const result = await new Promise((resolve10, reject) => {
7804
+ const result = await new Promise((resolve9, reject) => {
7719
7805
  const req = http3.request({
7720
7806
  hostname: "127.0.0.1",
7721
7807
  port: 19280,
@@ -7727,9 +7813,9 @@ var DaemonCommandHandler = class {
7727
7813
  res.on("data", (chunk) => data += chunk);
7728
7814
  res.on("end", () => {
7729
7815
  try {
7730
- resolve10(JSON.parse(data));
7816
+ resolve9(JSON.parse(data));
7731
7817
  } catch {
7732
- resolve10({ raw: data });
7818
+ resolve9({ raw: data });
7733
7819
  }
7734
7820
  });
7735
7821
  });
@@ -7746,7 +7832,7 @@ var DaemonCommandHandler = class {
7746
7832
 
7747
7833
  // src/commands/cli-manager.ts
7748
7834
  init_provider_cli_adapter();
7749
- import * as os9 from "os";
7835
+ import * as os10 from "os";
7750
7836
  import * as path9 from "path";
7751
7837
  import * as crypto4 from "crypto";
7752
7838
  import chalk from "chalk";
@@ -7754,7 +7840,7 @@ init_config();
7754
7840
 
7755
7841
  // src/providers/cli-provider-instance.ts
7756
7842
  init_provider_cli_adapter();
7757
- import * as os8 from "os";
7843
+ import * as os9 from "os";
7758
7844
  import * as path8 from "path";
7759
7845
  import * as crypto3 from "crypto";
7760
7846
  import * as fs5 from "fs";
@@ -7842,17 +7928,60 @@ var CliProviderInstance = class {
7842
7928
  async onTick() {
7843
7929
  if (this.providerSessionId) return;
7844
7930
  let probedSessionId = null;
7845
- if (this.type === "opencode-cli") {
7846
- probedSessionId = this.probeOpenCodeSessionId();
7847
- } else if (this.type === "codex-cli") {
7848
- probedSessionId = this.probeCodexSessionId();
7849
- } else if (this.type === "goose-cli") {
7850
- probedSessionId = this.probeGooseSessionId();
7931
+ const probeConfig = this.provider.sessionProbe;
7932
+ if (probeConfig) {
7933
+ probedSessionId = this.probeSessionIdFromConfig(probeConfig);
7934
+ } else {
7935
+ if (this.type === "opencode-cli") {
7936
+ probedSessionId = this.probeSessionIdFromConfig({
7937
+ dbPath: "~/.local/share/opencode/opencode.db",
7938
+ query: "select id from session where directory in ({dirs}) and time_created >= ? and time_archived is null order by time_updated desc limit 1",
7939
+ timestampFormat: "unix_ms"
7940
+ });
7941
+ } else if (this.type === "codex-cli") {
7942
+ probedSessionId = this.probeSessionIdFromConfig({
7943
+ dbPath: "~/.codex/state_5.sqlite",
7944
+ query: "select id from threads where cwd in ({dirs}) and created_at >= ? and archived = 0 order by created_at desc limit 1",
7945
+ timestampFormat: "unix_s"
7946
+ });
7947
+ } else if (this.type === "goose-cli") {
7948
+ probedSessionId = this.probeSessionIdFromConfig({
7949
+ dbPath: "~/.local/share/goose/sessions/sessions.db",
7950
+ query: "select id from sessions where working_dir in ({dirs}) and created_at >= ? order by updated_at desc limit 1",
7951
+ timestampFormat: "iso"
7952
+ });
7953
+ }
7851
7954
  }
7852
7955
  if (probedSessionId) {
7853
7956
  this.promoteProviderSessionId(probedSessionId);
7854
7957
  }
7855
7958
  }
7959
+ /**
7960
+ * Generic session ID probe using declarative ProviderSessionProbe config.
7961
+ * Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
7962
+ */
7963
+ probeSessionIdFromConfig(probe) {
7964
+ const resolvedDbPath = probe.dbPath.replace(/^~/, os9.homedir());
7965
+ if (!fs5.existsSync(resolvedDbPath)) return null;
7966
+ const directories = this.getProbeDirectories();
7967
+ const minCreatedAt = Math.max(0, this.startedAt - 6e4);
7968
+ const tsFormat = probe.timestampFormat || "unix_ms";
7969
+ let timestampParam;
7970
+ if (tsFormat === "unix_s") {
7971
+ timestampParam = Math.floor(minCreatedAt / 1e3);
7972
+ } else if (tsFormat === "iso") {
7973
+ timestampParam = new Date(minCreatedAt).toISOString().slice(0, 19).replace("T", " ");
7974
+ } else {
7975
+ timestampParam = minCreatedAt;
7976
+ }
7977
+ const placeholders = this.buildSqlPlaceholderList(directories.length);
7978
+ const query = probe.query.replace("{dirs}", placeholders);
7979
+ try {
7980
+ return this.querySqliteText(resolvedDbPath, query, [...directories, timestampParam]);
7981
+ } catch {
7982
+ return null;
7983
+ }
7984
+ }
7856
7985
  getState() {
7857
7986
  const adapterStatus = this.adapter.getStatus();
7858
7987
  const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
@@ -8150,34 +8279,6 @@ var CliProviderInstance = class {
8150
8279
  });
8151
8280
  LOG.info("CLI", `[${this.type}] discovered provider session id: ${nextSessionId}`);
8152
8281
  }
8153
- probeOpenCodeSessionId() {
8154
- const dbPath = path8.join(os8.homedir(), ".local", "share", "opencode", "opencode.db");
8155
- if (!fs5.existsSync(dbPath)) return null;
8156
- const minCreatedAt = Math.max(0, this.startedAt - 6e4);
8157
- const directories = this.getProbeDirectories();
8158
- const query = `select id from session where directory in (${this.buildSqlPlaceholderList(directories.length)}) and time_created >= ? and time_archived is null order by time_updated desc limit 1;`;
8159
- return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
8160
- }
8161
- probeCodexSessionId() {
8162
- const dbPath = path8.join(os8.homedir(), ".codex", "state_5.sqlite");
8163
- if (!fs5.existsSync(dbPath)) return null;
8164
- const minCreatedAt = Math.max(0, Math.floor((this.startedAt - 6e4) / 1e3));
8165
- const directories = this.getProbeDirectories();
8166
- const query = `select id from threads where cwd in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? and archived = 0 order by created_at desc limit 1;`;
8167
- return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
8168
- }
8169
- probeGooseSessionId() {
8170
- const dbPath = path8.join(os8.homedir(), ".local", "share", "goose", "sessions", "sessions.db");
8171
- if (!fs5.existsSync(dbPath)) return null;
8172
- const minCreatedAtIso = new Date(Math.max(0, this.startedAt - 6e4)).toISOString().slice(0, 19).replace("T", " ");
8173
- const directories = this.getProbeDirectories();
8174
- const query = `select id from sessions where working_dir in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? order by updated_at desc limit 1;`;
8175
- try {
8176
- return this.querySqliteText(dbPath, query, [...directories, minCreatedAtIso]);
8177
- } catch {
8178
- return null;
8179
- }
8180
- }
8181
8282
  getProbeDirectories() {
8182
8283
  const dirs = /* @__PURE__ */ new Set();
8183
8284
  const addDir = (value) => {
@@ -8654,13 +8755,13 @@ var AcpProviderInstance = class {
8654
8755
  }
8655
8756
  this.currentStatus = "waiting_approval";
8656
8757
  this.detectStatusTransition();
8657
- const approved = await new Promise((resolve10) => {
8658
- this.permissionResolvers.push(resolve10);
8758
+ const approved = await new Promise((resolve9) => {
8759
+ this.permissionResolvers.push(resolve9);
8659
8760
  setTimeout(() => {
8660
- const idx = this.permissionResolvers.indexOf(resolve10);
8761
+ const idx = this.permissionResolvers.indexOf(resolve9);
8661
8762
  if (idx >= 0) {
8662
8763
  this.permissionResolvers.splice(idx, 1);
8663
- resolve10(false);
8764
+ resolve9(false);
8664
8765
  }
8665
8766
  }, 3e5);
8666
8767
  });
@@ -9367,7 +9468,7 @@ var DaemonCliManager = class {
9367
9468
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
9368
9469
  const trimmed = (workingDir || "").trim();
9369
9470
  if (!trimmed) throw new Error("working directory required");
9370
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os9.homedir()) : path9.resolve(trimmed);
9471
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path9.resolve(trimmed);
9371
9472
  const normalizedType = this.providerLoader.resolveAlias(cliType);
9372
9473
  const provider = this.providerLoader.getByAlias(cliType);
9373
9474
  const key = crypto4.randomUUID();
@@ -9451,7 +9552,19 @@ ${installInfo}`
9451
9552
  return { runtimeSessionId: sessionId };
9452
9553
  }
9453
9554
  const cliInfo = await detectCLI(cliType, this.providerLoader);
9454
- if (!cliInfo) throw new Error(`${cliType} not found`);
9555
+ if (!cliInfo) {
9556
+ const installHint = provider?.install || "";
9557
+ const displayName = provider?.displayName || provider?.name || cliType;
9558
+ const spawnCmd = provider?.spawn?.command || cliType;
9559
+ throw new Error(
9560
+ `${displayName} is not installed.
9561
+ Command '${spawnCmd}' not found on PATH.
9562
+ ` + (installHint ? `
9563
+ ${installHint}
9564
+ ` : "") + `
9565
+ Run 'adhdev doctor' for detailed diagnostics.`
9566
+ );
9567
+ }
9455
9568
  console.log(colorize("yellow", ` \u26A1 Starting CLI ${cliType} in ${resolvedDir}...`));
9456
9569
  if (provider) {
9457
9570
  console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
@@ -9767,8 +9880,9 @@ ${installInfo}`
9767
9880
  const dir = rdir.path;
9768
9881
  if (!cliType) throw new Error("cliType required");
9769
9882
  const found = this.findAdapter(cliType, { instanceKey: args?.targetSessionId, dir });
9883
+ const prevCliArgs = found ? found.adapter.extraArgs : void 0;
9770
9884
  if (found) await this.stopSession(found.key);
9771
- await this.startSession(cliType, dir);
9885
+ await this.startSession(cliType, dir, args?.cliArgs || prevCliArgs, args?.initialModel);
9772
9886
  return { success: true, restarted: true };
9773
9887
  }
9774
9888
  case "agent_command": {
@@ -9803,13 +9917,13 @@ ${installInfo}`
9803
9917
  // src/launch.ts
9804
9918
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
9805
9919
  import * as net from "net";
9806
- import * as os11 from "os";
9920
+ import * as os12 from "os";
9807
9921
  import * as path11 from "path";
9808
9922
 
9809
9923
  // src/providers/provider-loader.ts
9810
9924
  import * as fs6 from "fs";
9811
9925
  import * as path10 from "path";
9812
- import * as os10 from "os";
9926
+ import * as os11 from "os";
9813
9927
  import * as chokidar from "chokidar";
9814
9928
  init_logger();
9815
9929
  var ProviderLoader = class _ProviderLoader {
@@ -9829,7 +9943,7 @@ var ProviderLoader = class _ProviderLoader {
9829
9943
  static META_FILE = ".meta.json";
9830
9944
  constructor(options) {
9831
9945
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
9832
- const defaultProvidersDir = path10.join(os10.homedir(), ".adhdev", "providers");
9946
+ const defaultProvidersDir = path10.join(os11.homedir(), ".adhdev", "providers");
9833
9947
  if (options?.userDir) {
9834
9948
  this.userDir = options.userDir;
9835
9949
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -10386,7 +10500,7 @@ var ProviderLoader = class _ProviderLoader {
10386
10500
  return { updated: false };
10387
10501
  }
10388
10502
  try {
10389
- const etag = await new Promise((resolve10, reject) => {
10503
+ const etag = await new Promise((resolve9, reject) => {
10390
10504
  const options = {
10391
10505
  method: "HEAD",
10392
10506
  hostname: "github.com",
@@ -10404,7 +10518,7 @@ var ProviderLoader = class _ProviderLoader {
10404
10518
  headers: { "User-Agent": "adhdev-launcher" },
10405
10519
  timeout: 1e4
10406
10520
  }, (res2) => {
10407
- resolve10(res2.headers.etag || res2.headers["last-modified"] || "");
10521
+ resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
10408
10522
  });
10409
10523
  req2.on("error", reject);
10410
10524
  req2.on("timeout", () => {
@@ -10413,7 +10527,7 @@ var ProviderLoader = class _ProviderLoader {
10413
10527
  });
10414
10528
  req2.end();
10415
10529
  } else {
10416
- resolve10(res.headers.etag || res.headers["last-modified"] || "");
10530
+ resolve9(res.headers.etag || res.headers["last-modified"] || "");
10417
10531
  }
10418
10532
  });
10419
10533
  req.on("error", reject);
@@ -10429,8 +10543,8 @@ var ProviderLoader = class _ProviderLoader {
10429
10543
  return { updated: false };
10430
10544
  }
10431
10545
  this.log("Downloading latest providers from GitHub...");
10432
- const tmpTar = path10.join(os10.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
10433
- const tmpExtract = path10.join(os10.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
10546
+ const tmpTar = path10.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
10547
+ const tmpExtract = path10.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
10434
10548
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
10435
10549
  fs6.mkdirSync(tmpExtract, { recursive: true });
10436
10550
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
@@ -10477,7 +10591,7 @@ var ProviderLoader = class _ProviderLoader {
10477
10591
  downloadFile(url, destPath) {
10478
10592
  const https = __require("https");
10479
10593
  const http3 = __require("http");
10480
- return new Promise((resolve10, reject) => {
10594
+ return new Promise((resolve9, reject) => {
10481
10595
  const doRequest = (reqUrl, redirectCount = 0) => {
10482
10596
  if (redirectCount > 5) {
10483
10597
  reject(new Error("Too many redirects"));
@@ -10497,7 +10611,7 @@ var ProviderLoader = class _ProviderLoader {
10497
10611
  res.pipe(ws);
10498
10612
  ws.on("finish", () => {
10499
10613
  ws.close();
10500
- resolve10();
10614
+ resolve9();
10501
10615
  });
10502
10616
  ws.on("error", reject);
10503
10617
  });
@@ -10862,17 +10976,17 @@ async function findFreePort(ports) {
10862
10976
  throw new Error("No free port found");
10863
10977
  }
10864
10978
  function checkPortFree(port) {
10865
- return new Promise((resolve10) => {
10979
+ return new Promise((resolve9) => {
10866
10980
  const server = net.createServer();
10867
10981
  server.unref();
10868
- server.on("error", () => resolve10(false));
10982
+ server.on("error", () => resolve9(false));
10869
10983
  server.listen(port, "127.0.0.1", () => {
10870
- server.close(() => resolve10(true));
10984
+ server.close(() => resolve9(true));
10871
10985
  });
10872
10986
  });
10873
10987
  }
10874
10988
  async function isCdpActive(port) {
10875
- return new Promise((resolve10) => {
10989
+ return new Promise((resolve9) => {
10876
10990
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
10877
10991
  timeout: 2e3
10878
10992
  }, (res) => {
@@ -10881,21 +10995,21 @@ async function isCdpActive(port) {
10881
10995
  res.on("end", () => {
10882
10996
  try {
10883
10997
  const info = JSON.parse(data);
10884
- resolve10(!!info["WebKit-Version"] || !!info["Browser"]);
10998
+ resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
10885
10999
  } catch {
10886
- resolve10(false);
11000
+ resolve9(false);
10887
11001
  }
10888
11002
  });
10889
11003
  });
10890
- req.on("error", () => resolve10(false));
11004
+ req.on("error", () => resolve9(false));
10891
11005
  req.on("timeout", () => {
10892
11006
  req.destroy();
10893
- resolve10(false);
11007
+ resolve9(false);
10894
11008
  });
10895
11009
  });
10896
11010
  }
10897
11011
  async function killIdeProcess(ideId) {
10898
- const plat = os11.platform();
11012
+ const plat = os12.platform();
10899
11013
  const appName = getMacAppIdentifiers()[ideId];
10900
11014
  const winProcesses = getWinProcessNames()[ideId];
10901
11015
  try {
@@ -10954,7 +11068,7 @@ async function killIdeProcess(ideId) {
10954
11068
  }
10955
11069
  }
10956
11070
  function isIdeRunning(ideId) {
10957
- const plat = os11.platform();
11071
+ const plat = os12.platform();
10958
11072
  try {
10959
11073
  if (plat === "darwin") {
10960
11074
  const appName = getMacAppIdentifiers()[ideId];
@@ -10990,7 +11104,7 @@ function isIdeRunning(ideId) {
10990
11104
  }
10991
11105
  }
10992
11106
  function detectCurrentWorkspace(ideId) {
10993
- const plat = os11.platform();
11107
+ const plat = os12.platform();
10994
11108
  if (plat === "darwin") {
10995
11109
  try {
10996
11110
  const appName = getMacAppIdentifiers()[ideId];
@@ -11010,7 +11124,7 @@ function detectCurrentWorkspace(ideId) {
11010
11124
  const appName = appNameMap[ideId];
11011
11125
  if (appName) {
11012
11126
  const storagePath = path11.join(
11013
- process.env.APPDATA || path11.join(os11.homedir(), "AppData", "Roaming"),
11127
+ process.env.APPDATA || path11.join(os12.homedir(), "AppData", "Roaming"),
11014
11128
  appName,
11015
11129
  "storage.json"
11016
11130
  );
@@ -11032,7 +11146,7 @@ function detectCurrentWorkspace(ideId) {
11032
11146
  return void 0;
11033
11147
  }
11034
11148
  async function launchWithCdp(options = {}) {
11035
- const platform9 = os11.platform();
11149
+ const platform9 = os12.platform();
11036
11150
  let targetIde;
11037
11151
  const ides = await detectIDEs();
11038
11152
  if (options.ideId) {
@@ -11184,8 +11298,8 @@ init_logger();
11184
11298
  // src/logging/command-log.ts
11185
11299
  import * as fs7 from "fs";
11186
11300
  import * as path12 from "path";
11187
- import * as os12 from "os";
11188
- var LOG_DIR2 = process.platform === "win32" ? path12.join(process.env.LOCALAPPDATA || process.env.APPDATA || path12.join(os12.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path12.join(os12.homedir(), "Library", "Logs", "adhdev") : path12.join(os12.homedir(), ".local", "share", "adhdev", "logs");
11301
+ import * as os13 from "os";
11302
+ var LOG_DIR2 = process.platform === "win32" ? path12.join(process.env.LOCALAPPDATA || process.env.APPDATA || path12.join(os13.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path12.join(os13.homedir(), "Library", "Logs", "adhdev") : path12.join(os13.homedir(), ".local", "share", "adhdev", "logs");
11189
11303
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
11190
11304
  var MAX_DAYS = 7;
11191
11305
  try {
@@ -11321,7 +11435,7 @@ init_logger();
11321
11435
 
11322
11436
  // src/status/snapshot.ts
11323
11437
  init_config();
11324
- import * as os13 from "os";
11438
+ import * as os14 from "os";
11325
11439
  init_terminal_screen();
11326
11440
  init_logger();
11327
11441
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
@@ -11436,16 +11550,16 @@ function buildStatusSnapshot(options) {
11436
11550
  version: options.version,
11437
11551
  daemonMode: options.daemonMode,
11438
11552
  machine: {
11439
- hostname: os13.hostname(),
11440
- platform: os13.platform(),
11441
- arch: os13.arch(),
11442
- cpus: os13.cpus().length,
11553
+ hostname: os14.hostname(),
11554
+ platform: os14.platform(),
11555
+ arch: os14.arch(),
11556
+ cpus: os14.cpus().length,
11443
11557
  totalMem: memSnap.totalMem,
11444
11558
  freeMem: memSnap.freeMem,
11445
11559
  availableMem: memSnap.availableMem,
11446
- loadavg: os13.loadavg(),
11447
- uptime: os13.uptime(),
11448
- release: os13.release()
11560
+ loadavg: os14.loadavg(),
11561
+ uptime: os14.uptime(),
11562
+ release: os14.release()
11449
11563
  },
11450
11564
  machineNickname: options.machineNickname ?? cfg.machineNickname ?? null,
11451
11565
  timestamp: options.timestamp ?? Date.now(),
@@ -11465,11 +11579,11 @@ function buildStatusSnapshot(options) {
11465
11579
  import { execFileSync } from "child_process";
11466
11580
  import { spawn as spawn3 } from "child_process";
11467
11581
  import * as fs8 from "fs";
11468
- import * as os14 from "os";
11582
+ import * as os15 from "os";
11469
11583
  import * as path13 from "path";
11470
11584
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
11471
11585
  function getUpgradeLogPath() {
11472
- const home = os14.homedir();
11586
+ const home = os15.homedir();
11473
11587
  const dir = path13.join(home, ".adhdev");
11474
11588
  fs8.mkdirSync(dir, { recursive: true });
11475
11589
  return path13.join(dir, "daemon-upgrade.log");
@@ -11502,14 +11616,14 @@ async function waitForPidExit(pid, timeoutMs) {
11502
11616
  while (Date.now() - start < timeoutMs) {
11503
11617
  try {
11504
11618
  process.kill(pid, 0);
11505
- await new Promise((resolve10) => setTimeout(resolve10, 250));
11619
+ await new Promise((resolve9) => setTimeout(resolve9, 250));
11506
11620
  } catch {
11507
11621
  return;
11508
11622
  }
11509
11623
  }
11510
11624
  }
11511
11625
  function stopSessionHostProcesses(appName) {
11512
- const pidFile = path13.join(os14.homedir(), ".adhdev", `${appName}-session-host.pid`);
11626
+ const pidFile = path13.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
11513
11627
  try {
11514
11628
  if (fs8.existsSync(pidFile)) {
11515
11629
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
@@ -11538,7 +11652,7 @@ function stopSessionHostProcesses(appName) {
11538
11652
  }
11539
11653
  }
11540
11654
  function removeDaemonPidFile() {
11541
- const pidFile = path13.join(os14.homedir(), ".adhdev", "daemon.pid");
11655
+ const pidFile = path13.join(os15.homedir(), ".adhdev", "daemon.pid");
11542
11656
  try {
11543
11657
  fs8.unlinkSync(pidFile);
11544
11658
  } catch {
@@ -13048,10 +13162,10 @@ var ProviderInstanceManager = class {
13048
13162
  // src/providers/version-archive.ts
13049
13163
  import * as fs10 from "fs";
13050
13164
  import * as path14 from "path";
13051
- import * as os15 from "os";
13165
+ import * as os16 from "os";
13052
13166
  import { execSync as execSync5 } from "child_process";
13053
13167
  import { platform as platform7 } from "os";
13054
- var ARCHIVE_PATH = path14.join(os15.homedir(), ".adhdev", "version-history.json");
13168
+ var ARCHIVE_PATH = path14.join(os16.homedir(), ".adhdev", "version-history.json");
13055
13169
  var MAX_ENTRIES_PER_PROVIDER = 20;
13056
13170
  var VersionArchive = class {
13057
13171
  history = {};
@@ -13138,7 +13252,7 @@ function getVersion(binary, versionCommand) {
13138
13252
  function checkPathExists2(paths) {
13139
13253
  for (const p of paths) {
13140
13254
  if (p.includes("*")) {
13141
- const home = os15.homedir();
13255
+ const home = os16.homedir();
13142
13256
  const resolved = p.replace(/\*/g, home.split(path14.sep).pop() || "");
13143
13257
  if (fs10.existsSync(resolved)) return resolved;
13144
13258
  } else {
@@ -14735,7 +14849,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
14735
14849
  return { target, instance, adapter };
14736
14850
  }
14737
14851
  function sleep(ms) {
14738
- return new Promise((resolve10) => setTimeout(resolve10, ms));
14852
+ return new Promise((resolve9) => setTimeout(resolve9, ms));
14739
14853
  }
14740
14854
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
14741
14855
  const startedAt = Date.now();
@@ -15466,7 +15580,7 @@ async function handleCliRaw(ctx, req, res) {
15466
15580
  // src/daemon/dev-auto-implement.ts
15467
15581
  import * as fs13 from "fs";
15468
15582
  import * as path17 from "path";
15469
- import * as os16 from "os";
15583
+ import * as os17 from "os";
15470
15584
  function getAutoImplPid(ctx) {
15471
15585
  const proc = ctx.autoImplProcess;
15472
15586
  return proc && typeof proc.pid === "number" && proc.pid > 0 ? proc.pid : null;
@@ -15669,7 +15783,7 @@ async function handleAutoImplement(ctx, type, req, res) {
15669
15783
  });
15670
15784
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
15671
15785
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
15672
- const tmpDir = path17.join(os16.tmpdir(), "adhdev-autoimpl");
15786
+ const tmpDir = path17.join(os17.tmpdir(), "adhdev-autoimpl");
15673
15787
  if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
15674
15788
  const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
15675
15789
  fs13.writeFileSync(promptFile, prompt, "utf-8");
@@ -15823,7 +15937,7 @@ async function handleAutoImplement(ctx, type, req, res) {
15823
15937
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
15824
15938
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
15825
15939
  let shellCmd;
15826
- const isWin = os16.platform() === "win32";
15940
+ const isWin = os17.platform() === "win32";
15827
15941
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
15828
15942
  if (command === "claude") {
15829
15943
  const args = [...baseArgs, "--dangerously-skip-permissions"];
@@ -15867,7 +15981,7 @@ async function handleAutoImplement(ctx, type, req, res) {
15867
15981
  try {
15868
15982
  const pty3 = __require("node-pty");
15869
15983
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
15870
- const isWin2 = os16.platform() === "win32";
15984
+ const isWin2 = os17.platform() === "win32";
15871
15985
  child = pty3.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
15872
15986
  name: "xterm-256color",
15873
15987
  cols: 120,
@@ -16905,15 +17019,15 @@ var DevServer = class _DevServer {
16905
17019
  this.json(res, 500, { error: e.message });
16906
17020
  }
16907
17021
  });
16908
- return new Promise((resolve10, reject) => {
17022
+ return new Promise((resolve9, reject) => {
16909
17023
  this.server.listen(port, "127.0.0.1", () => {
16910
17024
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
16911
- resolve10();
17025
+ resolve9();
16912
17026
  });
16913
17027
  this.server.on("error", (e) => {
16914
17028
  if (e.code === "EADDRINUSE") {
16915
17029
  this.log(`Port ${port} in use, skipping dev server`);
16916
- resolve10();
17030
+ resolve9();
16917
17031
  } else {
16918
17032
  reject(e);
16919
17033
  }
@@ -16996,20 +17110,20 @@ var DevServer = class _DevServer {
16996
17110
  child.stderr?.on("data", (d) => {
16997
17111
  stderr += d.toString().slice(0, 2e3);
16998
17112
  });
16999
- await new Promise((resolve10) => {
17113
+ await new Promise((resolve9) => {
17000
17114
  const timer = setTimeout(() => {
17001
17115
  child.kill();
17002
- resolve10();
17116
+ resolve9();
17003
17117
  }, 3e3);
17004
17118
  child.on("exit", () => {
17005
17119
  clearTimeout(timer);
17006
- resolve10();
17120
+ resolve9();
17007
17121
  });
17008
17122
  child.stdout?.once("data", () => {
17009
17123
  setTimeout(() => {
17010
17124
  child.kill();
17011
17125
  clearTimeout(timer);
17012
- resolve10();
17126
+ resolve9();
17013
17127
  }, 500);
17014
17128
  });
17015
17129
  });
@@ -17518,14 +17632,14 @@ var DevServer = class _DevServer {
17518
17632
  child.stderr?.on("data", (d) => {
17519
17633
  stderr += d.toString();
17520
17634
  });
17521
- await new Promise((resolve10) => {
17635
+ await new Promise((resolve9) => {
17522
17636
  const timer = setTimeout(() => {
17523
17637
  child.kill();
17524
- resolve10();
17638
+ resolve9();
17525
17639
  }, timeout);
17526
17640
  child.on("exit", () => {
17527
17641
  clearTimeout(timer);
17528
- resolve10();
17642
+ resolve9();
17529
17643
  });
17530
17644
  });
17531
17645
  const elapsed = Date.now() - start;
@@ -18200,14 +18314,14 @@ data: ${JSON.stringify(msg.data)}
18200
18314
  res.end(JSON.stringify(data, null, 2));
18201
18315
  }
18202
18316
  async readBody(req) {
18203
- return new Promise((resolve10) => {
18317
+ return new Promise((resolve9) => {
18204
18318
  let body = "";
18205
18319
  req.on("data", (chunk) => body += chunk);
18206
18320
  req.on("end", () => {
18207
18321
  try {
18208
- resolve10(JSON.parse(body));
18322
+ resolve9(JSON.parse(body));
18209
18323
  } catch {
18210
- resolve10({});
18324
+ resolve9({});
18211
18325
  }
18212
18326
  });
18213
18327
  });
@@ -18676,7 +18790,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
18676
18790
  const deadline = Date.now() + timeoutMs;
18677
18791
  while (Date.now() < deadline) {
18678
18792
  if (await canConnect(endpoint)) return;
18679
- await new Promise((resolve10) => setTimeout(resolve10, STARTUP_POLL_MS));
18793
+ await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
18680
18794
  }
18681
18795
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
18682
18796
  }
@@ -18832,10 +18946,10 @@ async function installExtension(ide, extension) {
18832
18946
  const buffer = Buffer.from(await res.arrayBuffer());
18833
18947
  const fs15 = await import("fs");
18834
18948
  fs15.writeFileSync(vsixPath, buffer);
18835
- return new Promise((resolve10) => {
18949
+ return new Promise((resolve9) => {
18836
18950
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
18837
18951
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
18838
- resolve10({
18952
+ resolve9({
18839
18953
  extensionId: extension.id,
18840
18954
  marketplaceId: extension.marketplaceId,
18841
18955
  success: !error,
@@ -18848,11 +18962,11 @@ async function installExtension(ide, extension) {
18848
18962
  } catch (e) {
18849
18963
  }
18850
18964
  }
18851
- return new Promise((resolve10) => {
18965
+ return new Promise((resolve9) => {
18852
18966
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
18853
18967
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
18854
18968
  if (error) {
18855
- resolve10({
18969
+ resolve9({
18856
18970
  extensionId: extension.id,
18857
18971
  marketplaceId: extension.marketplaceId,
18858
18972
  success: false,
@@ -18860,7 +18974,7 @@ async function installExtension(ide, extension) {
18860
18974
  error: stderr || error.message
18861
18975
  });
18862
18976
  } else {
18863
- resolve10({
18977
+ resolve9({
18864
18978
  extensionId: extension.id,
18865
18979
  marketplaceId: extension.marketplaceId,
18866
18980
  success: true,