@adhdev/daemon-standalone 0.8.27 → 0.8.28

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
@@ -28029,13 +28029,13 @@ var require_dist2 = __commonJS({
28029
28029
  return LOG_DIR;
28030
28030
  }
28031
28031
  function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
28032
- return path42.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
28032
+ return path6.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
28033
28033
  }
28034
28034
  function checkDateRotation() {
28035
28035
  const today = getDateStr();
28036
28036
  if (today !== currentDate) {
28037
28037
  currentDate = today;
28038
- currentLogFile = path42.join(LOG_DIR, `daemon-${currentDate}.log`);
28038
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
28039
28039
  cleanOldLogs();
28040
28040
  }
28041
28041
  }
@@ -28049,7 +28049,7 @@ var require_dist2 = __commonJS({
28049
28049
  const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
28050
28050
  if (dateMatch && dateMatch[1] < cutoffStr) {
28051
28051
  try {
28052
- fs22.unlinkSync(path42.join(LOG_DIR, file2));
28052
+ fs22.unlinkSync(path6.join(LOG_DIR, file2));
28053
28053
  } catch {
28054
28054
  }
28055
28055
  }
@@ -28167,7 +28167,7 @@ var require_dist2 = __commonJS({
28167
28167
  writeToFile(`Log level: ${currentLevel}`);
28168
28168
  }
28169
28169
  var fs22;
28170
- var path42;
28170
+ var path6;
28171
28171
  var os42;
28172
28172
  var LEVEL_NUM;
28173
28173
  var LEVEL_LABEL;
@@ -28190,12 +28190,12 @@ var require_dist2 = __commonJS({
28190
28190
  "src/logging/logger.ts"() {
28191
28191
  "use strict";
28192
28192
  fs22 = __toESM2(require("fs"));
28193
- path42 = __toESM2(require("path"));
28193
+ path6 = __toESM2(require("path"));
28194
28194
  os42 = __toESM2(require("os"));
28195
28195
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
28196
28196
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
28197
28197
  currentLevel = "info";
28198
- LOG_DIR = process.platform === "win32" ? path42.join(process.env.LOCALAPPDATA || process.env.APPDATA || path42.join(os42.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path42.join(os42.homedir(), "Library", "Logs", "adhdev") : path42.join(os42.homedir(), ".local", "share", "adhdev", "logs");
28198
+ LOG_DIR = process.platform === "win32" ? path6.join(process.env.LOCALAPPDATA || process.env.APPDATA || path6.join(os42.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path6.join(os42.homedir(), "Library", "Logs", "adhdev") : path6.join(os42.homedir(), ".local", "share", "adhdev", "logs");
28199
28199
  MAX_LOG_SIZE = 5 * 1024 * 1024;
28200
28200
  MAX_LOG_DAYS = 7;
28201
28201
  try {
@@ -28203,16 +28203,16 @@ var require_dist2 = __commonJS({
28203
28203
  } catch {
28204
28204
  }
28205
28205
  currentDate = getDateStr();
28206
- currentLogFile = path42.join(LOG_DIR, `daemon-${currentDate}.log`);
28206
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
28207
28207
  cleanOldLogs();
28208
28208
  try {
28209
- const oldLog = path42.join(LOG_DIR, "daemon.log");
28209
+ const oldLog = path6.join(LOG_DIR, "daemon.log");
28210
28210
  if (fs22.existsSync(oldLog)) {
28211
28211
  const stat4 = fs22.statSync(oldLog);
28212
28212
  const oldDate = stat4.mtime.toISOString().slice(0, 10);
28213
- fs22.renameSync(oldLog, path42.join(LOG_DIR, `daemon-${oldDate}.log`));
28213
+ fs22.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
28214
28214
  }
28215
- const oldLogBackup = path42.join(LOG_DIR, "daemon.log.old");
28215
+ const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
28216
28216
  if (fs22.existsSync(oldLogBackup)) {
28217
28217
  fs22.unlinkSync(oldLogBackup);
28218
28218
  }
@@ -28244,7 +28244,7 @@ var require_dist2 = __commonJS({
28244
28244
  }
28245
28245
  };
28246
28246
  interceptorInstalled = false;
28247
- LOG_PATH = path42.join(LOG_DIR, `daemon-${getDateStr()}.log`);
28247
+ LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
28248
28248
  }
28249
28249
  });
28250
28250
  function isModuleNotFoundError(error48, ref) {
@@ -28666,16 +28666,22 @@ var require_dist2 = __commonJS({
28666
28666
  return "";
28667
28667
  }
28668
28668
  function findBinary(name) {
28669
+ const trimmed = String(name || "").trim();
28670
+ if (!trimmed) return trimmed;
28671
+ const expanded = trimmed.startsWith("~") ? path9.join(os8.homedir(), trimmed.slice(1)) : trimmed;
28672
+ if (path9.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
28673
+ return path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
28674
+ }
28669
28675
  const isWin = os8.platform() === "win32";
28670
28676
  try {
28671
- const cmd = isWin ? `where ${name}` : `which ${name}`;
28677
+ const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
28672
28678
  return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
28673
28679
  } catch {
28674
- return isWin ? `${name}.cmd` : name;
28680
+ return isWin ? `${trimmed}.cmd` : trimmed;
28675
28681
  }
28676
28682
  }
28677
28683
  function isScriptBinary(binaryPath) {
28678
- if (!path7.isAbsolute(binaryPath)) return false;
28684
+ if (!path9.isAbsolute(binaryPath)) return false;
28679
28685
  try {
28680
28686
  const fs15 = require("fs");
28681
28687
  const resolved = fs15.realpathSync(binaryPath);
@@ -28691,7 +28697,7 @@ var require_dist2 = __commonJS({
28691
28697
  }
28692
28698
  }
28693
28699
  function looksLikeMachOOrElf(filePath) {
28694
- if (!path7.isAbsolute(filePath)) return false;
28700
+ if (!path9.isAbsolute(filePath)) return false;
28695
28701
  try {
28696
28702
  const fs15 = require("fs");
28697
28703
  const resolved = fs15.realpathSync(filePath);
@@ -28816,7 +28822,7 @@ var require_dist2 = __commonJS({
28816
28822
  };
28817
28823
  }
28818
28824
  var os8;
28819
- var path7;
28825
+ var path9;
28820
28826
  var import_child_process4;
28821
28827
  var buildCliSpawnEnv;
28822
28828
  var ProviderCliAdapter;
@@ -28824,7 +28830,7 @@ var require_dist2 = __commonJS({
28824
28830
  "src/cli-adapters/provider-cli-adapter.ts"() {
28825
28831
  "use strict";
28826
28832
  os8 = __toESM2(require("os"));
28827
- path7 = __toESM2(require("path"));
28833
+ path9 = __toESM2(require("path"));
28828
28834
  import_child_process4 = require("child_process");
28829
28835
  init_logger();
28830
28836
  init_terminal_screen();
@@ -29179,16 +29185,17 @@ var require_dist2 = __commonJS({
29179
29185
  async spawn() {
29180
29186
  if (this.ptyProcess) return;
29181
29187
  const { spawn: spawnConfig } = this.provider;
29182
- const binaryPath = findBinary(spawnConfig.command);
29188
+ const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
29189
+ const binaryPath = findBinary(configuredCommand);
29183
29190
  const isWin = os8.platform() === "win32";
29184
29191
  const allArgs = [...spawnConfig.args, ...this.extraArgs];
29185
29192
  LOG2.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
29186
29193
  this.resetTraceSession();
29187
29194
  let shellCmd;
29188
29195
  let shellArgs;
29189
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
29196
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
29190
29197
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
29191
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
29198
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
29192
29199
  const useShell = isWin ? useShellWin : useShellUnix;
29193
29200
  if (useShell) {
29194
29201
  if (!spawnConfig.shell && !isWin) {
@@ -29562,7 +29569,7 @@ var require_dist2 = __commonJS({
29562
29569
  `[${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)}`
29563
29570
  );
29564
29571
  }
29565
- await new Promise((resolve9) => setTimeout(resolve9, 50));
29572
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
29566
29573
  }
29567
29574
  const finalScreenText = this.terminalScreen.getText() || "";
29568
29575
  LOG2.warn(
@@ -30073,7 +30080,7 @@ ${data.message || ""}`.trim();
30073
30080
  const deadline = Date.now() + 1e4;
30074
30081
  while (this.startupParseGate && Date.now() < deadline) {
30075
30082
  this.resolveStartupState("send_wait");
30076
- await new Promise((resolve9) => setTimeout(resolve9, 50));
30083
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
30077
30084
  }
30078
30085
  }
30079
30086
  await this.waitForInteractivePrompt();
@@ -30298,17 +30305,17 @@ ${data.message || ""}`.trim();
30298
30305
  }
30299
30306
  }
30300
30307
  waitForStopped(timeoutMs) {
30301
- return new Promise((resolve9) => {
30308
+ return new Promise((resolve12) => {
30302
30309
  const startedAt = Date.now();
30303
30310
  const timer = setInterval(() => {
30304
30311
  if (!this.ptyProcess || this.currentStatus === "stopped") {
30305
30312
  clearInterval(timer);
30306
- resolve9(true);
30313
+ resolve12(true);
30307
30314
  return;
30308
30315
  }
30309
30316
  if (Date.now() - startedAt >= timeoutMs) {
30310
30317
  clearInterval(timer);
30311
- resolve9(false);
30318
+ resolve12(false);
30312
30319
  }
30313
30320
  }, 100);
30314
30321
  });
@@ -30995,6 +31002,7 @@ ${data.message || ""}`.trim();
30995
31002
  var import_child_process2 = require("child_process");
30996
31003
  var import_fs3 = require("fs");
30997
31004
  var import_os22 = require("os");
31005
+ var path42 = __toESM2(require("path"));
30998
31006
  var BUILTIN_IDE_DEFINITIONS = [];
30999
31007
  var registeredIDEs = /* @__PURE__ */ new Map();
31000
31008
  function registerIDEDefinition(def) {
@@ -31011,9 +31019,16 @@ ${data.message || ""}`.trim();
31011
31019
  return [...merged.values()];
31012
31020
  }
31013
31021
  function findCliCommand(command) {
31022
+ const trimmed = String(command || "").trim();
31023
+ if (!trimmed) return null;
31024
+ if (path42.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
31025
+ const candidate = trimmed.startsWith("~") ? path42.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
31026
+ const resolved = path42.isAbsolute(candidate) ? candidate : path42.resolve(candidate);
31027
+ return (0, import_fs3.existsSync)(resolved) ? resolved : null;
31028
+ }
31014
31029
  try {
31015
31030
  const result = (0, import_child_process2.execSync)(
31016
- (0, import_os22.platform)() === "win32" ? `where ${command}` : `which ${command}`,
31031
+ (0, import_os22.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
31017
31032
  { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
31018
31033
  ).trim();
31019
31034
  return result.split("\n")[0] || null;
@@ -31036,23 +31051,23 @@ ${data.message || ""}`.trim();
31036
31051
  function checkPathExists(paths) {
31037
31052
  const home = (0, import_os22.homedir)();
31038
31053
  for (const p of paths) {
31039
- if (p.includes("*")) {
31054
+ const normalized = p.startsWith("~") ? path42.join(home, p.slice(1)) : p;
31055
+ if (normalized.includes("*")) {
31040
31056
  const username = home.split(/[\\/]/).pop() || "";
31041
- const resolved = p.replace("*", username);
31057
+ const resolved = normalized.replace("*", username);
31042
31058
  if ((0, import_fs3.existsSync)(resolved)) return resolved;
31043
31059
  } else {
31044
- if ((0, import_fs3.existsSync)(p)) return p;
31060
+ if ((0, import_fs3.existsSync)(normalized)) return normalized;
31045
31061
  }
31046
31062
  }
31047
31063
  return null;
31048
31064
  }
31049
- async function detectIDEs() {
31065
+ async function detectIDEs(providerLoader) {
31050
31066
  const os18 = (0, import_os22.platform)();
31051
31067
  const results = [];
31052
31068
  for (const def of getMergedDefinitions()) {
31053
- const cliPath = findCliCommand(def.cli);
31054
- const appPath = checkPathExists(def.paths[os18] || []);
31055
- const installed = !!(cliPath || appPath);
31069
+ const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
31070
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os18] || []) || []);
31056
31071
  let resolvedCli = cliPath;
31057
31072
  if (!resolvedCli && appPath && os18 === "darwin") {
31058
31073
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
@@ -31075,6 +31090,7 @@ ${data.message || ""}`.trim();
31075
31090
  }
31076
31091
  }
31077
31092
  }
31093
+ const installed = os18 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
31078
31094
  const version2 = resolvedCli ? getIdeVersion(resolvedCli) : null;
31079
31095
  results.push({
31080
31096
  id: def.id,
@@ -31091,48 +31107,77 @@ ${data.message || ""}`.trim();
31091
31107
  }
31092
31108
  var import_child_process22 = require("child_process");
31093
31109
  var os22 = __toESM2(require("os"));
31110
+ var path52 = __toESM2(require("path"));
31111
+ var import_fs4 = require("fs");
31094
31112
  function parseVersion(raw) {
31095
31113
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
31096
31114
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
31097
31115
  }
31116
+ function shellQuote(value) {
31117
+ if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
31118
+ return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
31119
+ }
31120
+ function expandHome(value) {
31121
+ const trimmed = value.trim();
31122
+ if (!trimmed.startsWith("~")) return trimmed;
31123
+ return path52.join(os22.homedir(), trimmed.slice(1));
31124
+ }
31125
+ function isExplicitCommandPath(command) {
31126
+ const trimmed = command.trim();
31127
+ return path52.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
31128
+ }
31129
+ function resolveCommandPath(command) {
31130
+ const trimmed = command.trim();
31131
+ if (!trimmed) return null;
31132
+ if (isExplicitCommandPath(trimmed)) {
31133
+ const expanded = expandHome(trimmed);
31134
+ const candidate = path52.isAbsolute(expanded) ? expanded : path52.resolve(expanded);
31135
+ return (0, import_fs4.existsSync)(candidate) ? candidate : null;
31136
+ }
31137
+ return null;
31138
+ }
31098
31139
  function execAsync(cmd, timeoutMs = 5e3) {
31099
- return new Promise((resolve9) => {
31140
+ return new Promise((resolve12) => {
31100
31141
  const child = (0, import_child_process22.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
31101
31142
  if (err || !stdout?.trim()) {
31102
- resolve9(null);
31143
+ resolve12(null);
31103
31144
  } else {
31104
- resolve9(stdout.trim());
31145
+ resolve12(stdout.trim());
31105
31146
  }
31106
31147
  });
31107
- child.on("error", () => resolve9(null));
31148
+ child.on("error", () => resolve12(null));
31108
31149
  });
31109
31150
  }
31110
- async function detectCLIs(providerLoader) {
31151
+ async function detectCLIs(providerLoader, options) {
31111
31152
  const platform9 = os22.platform();
31112
31153
  const whichCmd = platform9 === "win32" ? "where" : "which";
31154
+ const includeVersion = options?.includeVersion !== false;
31113
31155
  const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
31114
31156
  const results = await Promise.all(
31115
31157
  cliList.map(async (cli) => {
31116
31158
  try {
31117
- const pathResult = await execAsync(`${whichCmd} ${cli.command}`);
31159
+ const explicitPath = resolveCommandPath(cli.command);
31160
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
31118
31161
  if (!pathResult) return { ...cli, installed: false };
31119
- const firstPath = pathResult.split("\n")[0];
31162
+ const firstPath = explicitPath || pathResult.split("\n")[0];
31120
31163
  let version2;
31121
- try {
31164
+ if (includeVersion) {
31122
31165
  const versionCommands = [
31123
- cli.versionCommand,
31124
- `${cli.command} --version`,
31125
- `${cli.command} -V`,
31126
- `${cli.command} -v`
31166
+ `"${firstPath}" --version`,
31167
+ `"${firstPath}" -V`,
31168
+ `"${firstPath}" -v`,
31169
+ cli.versionCommand
31127
31170
  ].filter((v2) => !!v2);
31128
- for (const versionCommand of versionCommands) {
31129
- const versionResult = await execAsync(versionCommand, 3e3);
31130
- if (versionResult) {
31131
- version2 = parseVersion(versionResult);
31132
- break;
31171
+ try {
31172
+ for (const versionCommand of versionCommands) {
31173
+ const versionResult = await execAsync(versionCommand, 3e3);
31174
+ if (versionResult) {
31175
+ version2 = parseVersion(versionResult);
31176
+ break;
31177
+ }
31133
31178
  }
31179
+ } catch {
31134
31180
  }
31135
- } catch {
31136
31181
  }
31137
31182
  return { ...cli, installed: true, version: version2, path: firstPath };
31138
31183
  } catch {
@@ -31142,7 +31187,7 @@ ${data.message || ""}`.trim();
31142
31187
  );
31143
31188
  return results;
31144
31189
  }
31145
- async function detectCLI(cliId, providerLoader) {
31190
+ async function detectCLI(cliId, providerLoader, options) {
31146
31191
  const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
31147
31192
  if (providerLoader) {
31148
31193
  const cliList = providerLoader.getCliDetectionList();
@@ -31151,25 +31196,28 @@ ${data.message || ""}`.trim();
31151
31196
  const platform9 = os22.platform();
31152
31197
  const whichCmd = platform9 === "win32" ? "where" : "which";
31153
31198
  try {
31154
- const pathResult = await execAsync(`${whichCmd} ${target.command}`);
31199
+ const explicitPath = resolveCommandPath(target.command);
31200
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
31155
31201
  if (!pathResult) return null;
31156
- const firstPath = pathResult.split("\n")[0];
31202
+ const firstPath = explicitPath || pathResult.split("\n")[0];
31157
31203
  let version2;
31158
- try {
31204
+ if (options?.includeVersion !== false) {
31159
31205
  const versionCommands = [
31160
- target.versionCommand,
31161
- `${target.command} --version`,
31162
- `${target.command} -V`,
31163
- `${target.command} -v`
31206
+ `"${firstPath}" --version`,
31207
+ `"${firstPath}" -V`,
31208
+ `"${firstPath}" -v`,
31209
+ target.versionCommand
31164
31210
  ].filter((v2) => !!v2);
31165
- for (const versionCommand of versionCommands) {
31166
- const versionResult = await execAsync(versionCommand, 3e3);
31167
- if (versionResult) {
31168
- version2 = parseVersion(versionResult);
31169
- break;
31211
+ try {
31212
+ for (const versionCommand of versionCommands) {
31213
+ const versionResult = await execAsync(versionCommand, 3e3);
31214
+ if (versionResult) {
31215
+ version2 = parseVersion(versionResult);
31216
+ break;
31217
+ }
31170
31218
  }
31219
+ } catch {
31171
31220
  }
31172
- } catch {
31173
31221
  }
31174
31222
  return { ...target, installed: true, version: version2, path: firstPath };
31175
31223
  } catch {
@@ -31177,7 +31225,7 @@ ${data.message || ""}`.trim();
31177
31225
  }
31178
31226
  }
31179
31227
  }
31180
- const all = await detectCLIs(providerLoader);
31228
+ const all = await detectCLIs(providerLoader, options);
31181
31229
  return all.find((c) => c.id === resolvedId && c.installed) || null;
31182
31230
  }
31183
31231
  var os32 = __toESM2(require("os"));
@@ -31300,7 +31348,7 @@ ${data.message || ""}`.trim();
31300
31348
  * Returns multiple entries if multiple IDE windows are open on same port
31301
31349
  */
31302
31350
  static listAllTargets(port) {
31303
- return new Promise((resolve9) => {
31351
+ return new Promise((resolve12) => {
31304
31352
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
31305
31353
  let data = "";
31306
31354
  res.on("data", (chunk) => data += chunk.toString());
@@ -31316,16 +31364,16 @@ ${data.message || ""}`.trim();
31316
31364
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
31317
31365
  );
31318
31366
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
31319
- resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
31367
+ resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
31320
31368
  } catch {
31321
- resolve9([]);
31369
+ resolve12([]);
31322
31370
  }
31323
31371
  });
31324
31372
  });
31325
- req.on("error", () => resolve9([]));
31373
+ req.on("error", () => resolve12([]));
31326
31374
  req.setTimeout(2e3, () => {
31327
31375
  req.destroy();
31328
- resolve9([]);
31376
+ resolve12([]);
31329
31377
  });
31330
31378
  });
31331
31379
  }
@@ -31365,7 +31413,7 @@ ${data.message || ""}`.trim();
31365
31413
  }
31366
31414
  }
31367
31415
  findTargetOnPort(port) {
31368
- return new Promise((resolve9) => {
31416
+ return new Promise((resolve12) => {
31369
31417
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
31370
31418
  let data = "";
31371
31419
  res.on("data", (chunk) => data += chunk.toString());
@@ -31376,7 +31424,7 @@ ${data.message || ""}`.trim();
31376
31424
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
31377
31425
  );
31378
31426
  if (pages.length === 0) {
31379
- resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
31427
+ resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
31380
31428
  return;
31381
31429
  }
31382
31430
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -31386,24 +31434,24 @@ ${data.message || ""}`.trim();
31386
31434
  const specific = list.find((t) => t.id === this._targetId);
31387
31435
  if (specific) {
31388
31436
  this._pageTitle = specific.title || "";
31389
- resolve9(specific);
31437
+ resolve12(specific);
31390
31438
  } else {
31391
31439
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
31392
- resolve9(null);
31440
+ resolve12(null);
31393
31441
  }
31394
31442
  return;
31395
31443
  }
31396
31444
  this._pageTitle = list[0]?.title || "";
31397
- resolve9(list[0]);
31445
+ resolve12(list[0]);
31398
31446
  } catch {
31399
- resolve9(null);
31447
+ resolve12(null);
31400
31448
  }
31401
31449
  });
31402
31450
  });
31403
- req.on("error", () => resolve9(null));
31451
+ req.on("error", () => resolve12(null));
31404
31452
  req.setTimeout(2e3, () => {
31405
31453
  req.destroy();
31406
- resolve9(null);
31454
+ resolve12(null);
31407
31455
  });
31408
31456
  });
31409
31457
  }
@@ -31414,7 +31462,7 @@ ${data.message || ""}`.trim();
31414
31462
  this.extensionProviders = providers;
31415
31463
  }
31416
31464
  connectToTarget(wsUrl) {
31417
- return new Promise((resolve9) => {
31465
+ return new Promise((resolve12) => {
31418
31466
  this.ws = new import_ws2.default(wsUrl);
31419
31467
  this.ws.on("open", async () => {
31420
31468
  this._connected = true;
@@ -31424,17 +31472,17 @@ ${data.message || ""}`.trim();
31424
31472
  }
31425
31473
  this.connectBrowserWs().catch(() => {
31426
31474
  });
31427
- resolve9(true);
31475
+ resolve12(true);
31428
31476
  });
31429
31477
  this.ws.on("message", (data) => {
31430
31478
  try {
31431
31479
  const msg = JSON.parse(data.toString());
31432
31480
  if (msg.id && this.pending.has(msg.id)) {
31433
- const { resolve: resolve10, reject } = this.pending.get(msg.id);
31481
+ const { resolve: resolve13, reject } = this.pending.get(msg.id);
31434
31482
  this.pending.delete(msg.id);
31435
31483
  this.failureCount = 0;
31436
31484
  if (msg.error) reject(new Error(msg.error.message));
31437
- else resolve10(msg.result);
31485
+ else resolve13(msg.result);
31438
31486
  } else if (msg.method === "Runtime.executionContextCreated") {
31439
31487
  this.contexts.add(msg.params.context.id);
31440
31488
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -31457,7 +31505,7 @@ ${data.message || ""}`.trim();
31457
31505
  this.ws.on("error", (err) => {
31458
31506
  this.log(`[CDP] WebSocket error: ${err.message}`);
31459
31507
  this._connected = false;
31460
- resolve9(false);
31508
+ resolve12(false);
31461
31509
  });
31462
31510
  });
31463
31511
  }
@@ -31471,7 +31519,7 @@ ${data.message || ""}`.trim();
31471
31519
  return;
31472
31520
  }
31473
31521
  this.log(`[CDP] Connecting browser WS for target discovery...`);
31474
- await new Promise((resolve9, reject) => {
31522
+ await new Promise((resolve12, reject) => {
31475
31523
  this.browserWs = new import_ws2.default(browserWsUrl);
31476
31524
  this.browserWs.on("open", async () => {
31477
31525
  this._browserConnected = true;
@@ -31481,16 +31529,16 @@ ${data.message || ""}`.trim();
31481
31529
  } catch (e) {
31482
31530
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
31483
31531
  }
31484
- resolve9();
31532
+ resolve12();
31485
31533
  });
31486
31534
  this.browserWs.on("message", (data) => {
31487
31535
  try {
31488
31536
  const msg = JSON.parse(data.toString());
31489
31537
  if (msg.id && this.browserPending.has(msg.id)) {
31490
- const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
31538
+ const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
31491
31539
  this.browserPending.delete(msg.id);
31492
31540
  if (msg.error) reject2(new Error(msg.error.message));
31493
- else resolve10(msg.result);
31541
+ else resolve13(msg.result);
31494
31542
  }
31495
31543
  } catch {
31496
31544
  }
@@ -31510,31 +31558,31 @@ ${data.message || ""}`.trim();
31510
31558
  }
31511
31559
  }
31512
31560
  getBrowserWsUrl() {
31513
- return new Promise((resolve9) => {
31561
+ return new Promise((resolve12) => {
31514
31562
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
31515
31563
  let data = "";
31516
31564
  res.on("data", (chunk) => data += chunk.toString());
31517
31565
  res.on("end", () => {
31518
31566
  try {
31519
31567
  const info = JSON.parse(data);
31520
- resolve9(info.webSocketDebuggerUrl || null);
31568
+ resolve12(info.webSocketDebuggerUrl || null);
31521
31569
  } catch {
31522
- resolve9(null);
31570
+ resolve12(null);
31523
31571
  }
31524
31572
  });
31525
31573
  });
31526
- req.on("error", () => resolve9(null));
31574
+ req.on("error", () => resolve12(null));
31527
31575
  req.setTimeout(3e3, () => {
31528
31576
  req.destroy();
31529
- resolve9(null);
31577
+ resolve12(null);
31530
31578
  });
31531
31579
  });
31532
31580
  }
31533
31581
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
31534
- return new Promise((resolve9, reject) => {
31582
+ return new Promise((resolve12, reject) => {
31535
31583
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
31536
31584
  const id = this.browserMsgId++;
31537
- this.browserPending.set(id, { resolve: resolve9, reject });
31585
+ this.browserPending.set(id, { resolve: resolve12, reject });
31538
31586
  this.browserWs.send(JSON.stringify({ id, method, params }));
31539
31587
  setTimeout(() => {
31540
31588
  if (this.browserPending.has(id)) {
@@ -31574,11 +31622,11 @@ ${data.message || ""}`.trim();
31574
31622
  }
31575
31623
  // ─── CDP Protocol ────────────────────────────────────────
31576
31624
  sendInternal(method, params = {}, timeoutMs = 15e3) {
31577
- return new Promise((resolve9, reject) => {
31625
+ return new Promise((resolve12, reject) => {
31578
31626
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
31579
31627
  if (this.ws.readyState !== import_ws2.default.OPEN) return reject(new Error("WebSocket not open"));
31580
31628
  const id = this.msgId++;
31581
- this.pending.set(id, { resolve: resolve9, reject });
31629
+ this.pending.set(id, { resolve: resolve12, reject });
31582
31630
  this.ws.send(JSON.stringify({ id, method, params }));
31583
31631
  setTimeout(() => {
31584
31632
  if (this.pending.has(id)) {
@@ -31827,7 +31875,7 @@ ${data.message || ""}`.trim();
31827
31875
  const browserWs = this.browserWs;
31828
31876
  let msgId = this.browserMsgId;
31829
31877
  const sendWs = (method, params = {}, sessionId) => {
31830
- return new Promise((resolve9, reject) => {
31878
+ return new Promise((resolve12, reject) => {
31831
31879
  const mid = msgId++;
31832
31880
  this.browserMsgId = msgId;
31833
31881
  const handler = (raw) => {
@@ -31836,7 +31884,7 @@ ${data.message || ""}`.trim();
31836
31884
  if (msg.id === mid) {
31837
31885
  browserWs.removeListener("message", handler);
31838
31886
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
31839
- else resolve9(msg.result);
31887
+ else resolve12(msg.result);
31840
31888
  }
31841
31889
  } catch {
31842
31890
  }
@@ -32027,14 +32075,14 @@ ${data.message || ""}`.trim();
32027
32075
  if (!ws2 || ws2.readyState !== import_ws2.default.OPEN) {
32028
32076
  throw new Error("CDP not connected");
32029
32077
  }
32030
- return new Promise((resolve9, reject) => {
32078
+ return new Promise((resolve12, reject) => {
32031
32079
  const id = getNextId();
32032
32080
  pendingMap.set(id, {
32033
32081
  resolve: (result) => {
32034
32082
  if (result?.result?.subtype === "error") {
32035
32083
  reject(new Error(result.result.description));
32036
32084
  } else {
32037
- resolve9(result?.result?.value);
32085
+ resolve12(result?.result?.value);
32038
32086
  }
32039
32087
  },
32040
32088
  reject
@@ -32066,10 +32114,10 @@ ${data.message || ""}`.trim();
32066
32114
  throw new Error("CDP not connected");
32067
32115
  }
32068
32116
  const sendViaSession = (method, params = {}) => {
32069
- return new Promise((resolve9, reject) => {
32117
+ return new Promise((resolve12, reject) => {
32070
32118
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
32071
32119
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
32072
- pendingMap.set(id, { resolve: resolve9, reject });
32120
+ pendingMap.set(id, { resolve: resolve12, reject });
32073
32121
  ws2.send(JSON.stringify({ id, sessionId, method, params }));
32074
32122
  setTimeout(() => {
32075
32123
  if (pendingMap.has(id)) {
@@ -32687,9 +32735,9 @@ ${data.message || ""}`.trim();
32687
32735
  return String(value);
32688
32736
  }
32689
32737
  var fs32 = __toESM2(require("fs"));
32690
- var path52 = __toESM2(require("path"));
32738
+ var path7 = __toESM2(require("path"));
32691
32739
  var os52 = __toESM2(require("os"));
32692
- var HISTORY_DIR = path52.join(os52.homedir(), ".adhdev", "history");
32740
+ var HISTORY_DIR = path7.join(os52.homedir(), ".adhdev", "history");
32693
32741
  var RETAIN_DAYS = 30;
32694
32742
  var ChatHistoryWriter = class {
32695
32743
  /** Last seen message count per agent (deduplication) */
@@ -32734,11 +32782,11 @@ ${data.message || ""}`.trim();
32734
32782
  });
32735
32783
  }
32736
32784
  if (newMessages.length === 0) return;
32737
- const dir = path52.join(HISTORY_DIR, this.sanitize(agentType));
32785
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
32738
32786
  fs32.mkdirSync(dir, { recursive: true });
32739
32787
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
32740
32788
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
32741
- const filePath = path52.join(dir, `${filePrefix}${date5}.jsonl`);
32789
+ const filePath = path7.join(dir, `${filePrefix}${date5}.jsonl`);
32742
32790
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
32743
32791
  fs32.appendFileSync(filePath, lines, "utf-8");
32744
32792
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
@@ -32792,14 +32840,14 @@ ${data.message || ""}`.trim();
32792
32840
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
32793
32841
  this.lastSeenCounts.delete(fromDedupKey);
32794
32842
  }
32795
- const dir = path52.join(HISTORY_DIR, this.sanitize(agentType));
32843
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
32796
32844
  if (!fs32.existsSync(dir)) return;
32797
32845
  const fromPrefix = `${this.sanitize(fromId)}_`;
32798
32846
  const toPrefix = `${this.sanitize(toId)}_`;
32799
32847
  const files = fs32.readdirSync(dir).filter((file2) => file2.startsWith(fromPrefix) && file2.endsWith(".jsonl"));
32800
32848
  for (const file2 of files) {
32801
- const sourcePath = path52.join(dir, file2);
32802
- const targetPath = path52.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
32849
+ const sourcePath = path7.join(dir, file2);
32850
+ const targetPath = path7.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
32803
32851
  const sourceLines = fs32.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
32804
32852
  const rewritten = sourceLines.map((line) => {
32805
32853
  try {
@@ -32840,10 +32888,10 @@ ${data.message || ""}`.trim();
32840
32888
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
32841
32889
  const agentDirs = fs32.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
32842
32890
  for (const dir of agentDirs) {
32843
- const dirPath = path52.join(HISTORY_DIR, dir.name);
32891
+ const dirPath = path7.join(HISTORY_DIR, dir.name);
32844
32892
  const files = fs32.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
32845
32893
  for (const file2 of files) {
32846
- const filePath = path52.join(dirPath, file2);
32894
+ const filePath = path7.join(dirPath, file2);
32847
32895
  const stat4 = fs32.statSync(filePath);
32848
32896
  if (stat4.mtimeMs < cutoff) {
32849
32897
  fs32.unlinkSync(filePath);
@@ -32861,7 +32909,7 @@ ${data.message || ""}`.trim();
32861
32909
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
32862
32910
  try {
32863
32911
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
32864
- const dir = path52.join(HISTORY_DIR, sanitized);
32912
+ const dir = path7.join(HISTORY_DIR, sanitized);
32865
32913
  if (!fs32.existsSync(dir)) return { messages: [], hasMore: false };
32866
32914
  const sanitizedInstance = historySessionId?.replace(/[^a-zA-Z0-9_-]/g, "_");
32867
32915
  const files = fs32.readdirSync(dir).filter((f) => {
@@ -32875,7 +32923,7 @@ ${data.message || ""}`.trim();
32875
32923
  const needed = offset + limit + 1;
32876
32924
  for (const file2 of files) {
32877
32925
  if (allMessages.length >= needed) break;
32878
- const filePath = path52.join(dir, file2);
32926
+ const filePath = path7.join(dir, file2);
32879
32927
  const content = fs32.readFileSync(filePath, "utf-8");
32880
32928
  const lines = content.trim().split("\n").filter(Boolean);
32881
32929
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -32897,7 +32945,7 @@ ${data.message || ""}`.trim();
32897
32945
  function listSavedHistorySessions(agentType, options = {}) {
32898
32946
  try {
32899
32947
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
32900
- const dir = path52.join(HISTORY_DIR, sanitized);
32948
+ const dir = path7.join(HISTORY_DIR, sanitized);
32901
32949
  if (!fs32.existsSync(dir)) return { sessions: [], hasMore: false };
32902
32950
  const groupedFiles = /* @__PURE__ */ new Map();
32903
32951
  const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
@@ -32918,7 +32966,7 @@ ${data.message || ""}`.trim();
32918
32966
  let sessionTitle = "";
32919
32967
  let preview = "";
32920
32968
  for (const file2 of files.sort()) {
32921
- const filePath = path52.join(dir, file2);
32969
+ const filePath = path7.join(dir, file2);
32922
32970
  const content = fs32.readFileSync(filePath, "utf-8");
32923
32971
  const lines = content.split("\n").filter(Boolean);
32924
32972
  for (const line of lines) {
@@ -35073,6 +35121,14 @@ ${effect.notification.body || ""}`.trim();
35073
35121
  } catch {
35074
35122
  }
35075
35123
  }
35124
+ if (parsed?.sessions && Array.isArray(parsed.sessions)) {
35125
+ LOG2.info("Command", `[list_chats] OK: ${parsed.sessions.length} chats`);
35126
+ return { success: true, chats: parsed.sessions };
35127
+ }
35128
+ if (parsed?.chats && Array.isArray(parsed.chats)) {
35129
+ LOG2.info("Command", `[list_chats] OK: ${parsed.chats.length} chats`);
35130
+ return { success: true, chats: parsed.chats };
35131
+ }
35076
35132
  if (Array.isArray(parsed)) {
35077
35133
  LOG2.info("Command", `[list_chats] OK: ${parsed.length} chats`);
35078
35134
  return { success: true, chats: parsed };
@@ -35142,7 +35198,13 @@ ${effect.notification.body || ""}`.trim();
35142
35198
  } catch (e) {
35143
35199
  return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
35144
35200
  }
35145
- const script = h.getProviderScript("switchSession", { SESSION_ID: JSON.stringify(sessionId) }) || h.getProviderScript("switch_session", { SESSION_ID: JSON.stringify(sessionId) });
35201
+ const switchParams = {
35202
+ sessionId,
35203
+ title: sessionId,
35204
+ id: sessionId,
35205
+ SESSION_ID: JSON.stringify(sessionId)
35206
+ };
35207
+ const script = h.getProviderScript("switchSession", switchParams) || h.getProviderScript("switch_session", switchParams);
35146
35208
  if (!script) return { success: false, error: "switch_session script not available" };
35147
35209
  try {
35148
35210
  const raw = await cdp.evaluate(script, 15e3);
@@ -35221,8 +35283,8 @@ ${effect.notification.body || ""}`.trim();
35221
35283
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
35222
35284
  if (adapter) {
35223
35285
  const acpInstance = adapter._acpInstance;
35224
- if (acpInstance && typeof acpInstance.onEvent === "function") {
35225
- acpInstance.onEvent("set_mode", { mode });
35286
+ if (acpInstance && typeof acpInstance.setMode === "function") {
35287
+ await acpInstance.setMode(mode);
35226
35288
  return { success: true, mode };
35227
35289
  }
35228
35290
  }
@@ -35279,9 +35341,9 @@ ${effect.notification.body || ""}`.trim();
35279
35341
  LOG2.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
35280
35342
  if (adapter) {
35281
35343
  const acpInstance = adapter._acpInstance;
35282
- if (acpInstance && typeof acpInstance.onEvent === "function") {
35283
- acpInstance.onEvent("change_model", { model });
35284
- LOG2.info("Command", `[change_model] Dispatched change_model event to ACP instance`);
35344
+ if (acpInstance && typeof acpInstance.setConfigOption === "function") {
35345
+ await acpInstance.setConfigOption("model", model);
35346
+ LOG2.info("Command", `[change_model] Updated ACP model to ${model}`);
35285
35347
  return { success: true, model };
35286
35348
  }
35287
35349
  }
@@ -35401,6 +35463,18 @@ ${effect.notification.body || ""}`.trim();
35401
35463
  const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
35402
35464
  return { success: ok };
35403
35465
  }
35466
+ if (transport === "acp") {
35467
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
35468
+ const acpInstance = adapter?._acpInstance;
35469
+ if (!acpInstance) return { success: false, error: "ACP instance not found" };
35470
+ try {
35471
+ await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
35472
+ LOG2.info("Command", `[resolveAction] ACP \u2192 ${action}`);
35473
+ return { success: true, action };
35474
+ } catch (e) {
35475
+ return { success: false, error: e?.message || "ACP resolve action failed" };
35476
+ }
35477
+ }
35404
35478
  if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
35405
35479
  const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
35406
35480
  if (script) {
@@ -35477,7 +35551,7 @@ ${effect.notification.body || ""}`.trim();
35477
35551
  return { success: false, error: "resolveAction script not available for this provider" };
35478
35552
  }
35479
35553
  var fs42 = __toESM2(require("fs"));
35480
- var path6 = __toESM2(require("path"));
35554
+ var path8 = __toESM2(require("path"));
35481
35555
  var os62 = __toESM2(require("os"));
35482
35556
  var KEY_TO_VK = {
35483
35557
  Backspace: 8,
@@ -35729,25 +35803,25 @@ ${effect.notification.body || ""}`.trim();
35729
35803
  const inputPath = rawPath || ".";
35730
35804
  const home = os62.homedir();
35731
35805
  if (inputPath.startsWith("~")) {
35732
- return path6.resolve(path6.join(home, inputPath.slice(1)));
35806
+ return path8.resolve(path8.join(home, inputPath.slice(1)));
35733
35807
  }
35734
35808
  if (process.platform === "win32") {
35735
35809
  const normalized = normalizeWindowsRequestedPath(inputPath);
35736
- if (path6.win32.isAbsolute(normalized)) {
35737
- return path6.win32.normalize(normalized);
35810
+ if (path8.win32.isAbsolute(normalized)) {
35811
+ return path8.win32.normalize(normalized);
35738
35812
  }
35739
- return path6.win32.resolve(normalized);
35813
+ return path8.win32.resolve(normalized);
35740
35814
  }
35741
- if (path6.isAbsolute(inputPath)) {
35742
- return path6.normalize(inputPath);
35815
+ if (path8.isAbsolute(inputPath)) {
35816
+ return path8.normalize(inputPath);
35743
35817
  }
35744
- return path6.resolve(inputPath);
35818
+ return path8.resolve(inputPath);
35745
35819
  }
35746
35820
  function listDirectoryEntriesSafe(dirPath) {
35747
35821
  const entries = fs42.readdirSync(dirPath, { withFileTypes: true });
35748
35822
  const files = [];
35749
35823
  for (const entry of entries) {
35750
- const entryPath = path6.join(dirPath, entry.name);
35824
+ const entryPath = path8.join(dirPath, entry.name);
35751
35825
  try {
35752
35826
  if (entry.isDirectory()) {
35753
35827
  files.push({ name: entry.name, type: "directory" });
@@ -35786,7 +35860,7 @@ ${effect.notification.body || ""}`.trim();
35786
35860
  async function handleFileWrite(h, args) {
35787
35861
  try {
35788
35862
  const filePath = resolveSafePath(args?.path);
35789
- fs42.mkdirSync(path6.dirname(filePath), { recursive: true });
35863
+ fs42.mkdirSync(path8.dirname(filePath), { recursive: true });
35790
35864
  fs42.writeFileSync(filePath, args?.content || "", "utf-8");
35791
35865
  return { success: true, path: filePath };
35792
35866
  } catch (e) {
@@ -35872,7 +35946,7 @@ ${effect.notification.body || ""}`.trim();
35872
35946
  }
35873
35947
  return { success: true, settings: allSettings, values: allValues };
35874
35948
  }
35875
- function handleSetProviderSetting(h, args) {
35949
+ async function handleSetProviderSetting(h, args) {
35876
35950
  const loader = h.ctx.providerLoader;
35877
35951
  const { providerType, key, value } = args || {};
35878
35952
  if (!providerType || !key || value === void 0) {
@@ -35885,6 +35959,7 @@ ${effect.notification.body || ""}`.trim();
35885
35959
  const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
35886
35960
  LOG2.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
35887
35961
  }
35962
+ await h.ctx.onProviderSettingChanged?.(providerType, key, value);
35888
35963
  return { success: true, providerType, key, value };
35889
35964
  }
35890
35965
  return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
@@ -35922,10 +35997,10 @@ ${effect.notification.body || ""}`.trim();
35922
35997
  }
35923
35998
  const command = payload.command;
35924
35999
  if (!command || typeof command !== "object") return null;
35925
- if (command.type !== "send_message") return null;
36000
+ if (command.type !== "send_message" && command.type !== "pty_write") return null;
35926
36001
  const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
35927
36002
  if (!text) return null;
35928
- return { type: "send_message", text };
36003
+ return { type: command.type, text };
35929
36004
  }
35930
36005
  function applyProviderPatch(h, args, payload) {
35931
36006
  if (!payload || typeof payload !== "object") return;
@@ -35966,6 +36041,8 @@ ${effect.notification.body || ""}`.trim();
35966
36041
  const cliCommand = getCliScriptCommand(parsed.payload);
35967
36042
  if (cliCommand?.type === "send_message" && cliCommand.text) {
35968
36043
  await adapter.sendMessage(cliCommand.text);
36044
+ } else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
36045
+ adapter.writeRaw(cliCommand.text + "\r");
35969
36046
  }
35970
36047
  applyProviderPatch(h, args, parsed.payload);
35971
36048
  return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
@@ -36640,7 +36717,7 @@ ${effect.notification.body || ""}`.trim();
36640
36717
  try {
36641
36718
  const http3 = await import("http");
36642
36719
  const postData = JSON.stringify(body);
36643
- const result = await new Promise((resolve9, reject) => {
36720
+ const result = await new Promise((resolve12, reject) => {
36644
36721
  const req = http3.request({
36645
36722
  hostname: "127.0.0.1",
36646
36723
  port: 19280,
@@ -36652,9 +36729,9 @@ ${effect.notification.body || ""}`.trim();
36652
36729
  res.on("data", (chunk) => data += chunk);
36653
36730
  res.on("end", () => {
36654
36731
  try {
36655
- resolve9(JSON.parse(data));
36732
+ resolve12(JSON.parse(data));
36656
36733
  } catch {
36657
- resolve9({ raw: data });
36734
+ resolve12({ raw: data });
36658
36735
  }
36659
36736
  });
36660
36737
  });
@@ -36672,15 +36749,15 @@ ${effect.notification.body || ""}`.trim();
36672
36749
  if (!providerType) return { success: false, error: "providerType required" };
36673
36750
  try {
36674
36751
  const http3 = await import("http");
36675
- const result = await new Promise((resolve9, reject) => {
36752
+ const result = await new Promise((resolve12, reject) => {
36676
36753
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
36677
36754
  let data = "";
36678
36755
  res.on("data", (chunk) => data += chunk);
36679
36756
  res.on("end", () => {
36680
36757
  try {
36681
- resolve9(JSON.parse(data));
36758
+ resolve12(JSON.parse(data));
36682
36759
  } catch {
36683
- resolve9({ raw: data });
36760
+ resolve12({ raw: data });
36684
36761
  }
36685
36762
  });
36686
36763
  }).on("error", reject);
@@ -36694,7 +36771,7 @@ ${effect.notification.body || ""}`.trim();
36694
36771
  try {
36695
36772
  const http3 = await import("http");
36696
36773
  const postData = JSON.stringify(args || {});
36697
- const result = await new Promise((resolve9, reject) => {
36774
+ const result = await new Promise((resolve12, reject) => {
36698
36775
  const req = http3.request({
36699
36776
  hostname: "127.0.0.1",
36700
36777
  port: 19280,
@@ -36706,9 +36783,9 @@ ${effect.notification.body || ""}`.trim();
36706
36783
  res.on("data", (chunk) => data += chunk);
36707
36784
  res.on("end", () => {
36708
36785
  try {
36709
- resolve9(JSON.parse(data));
36786
+ resolve12(JSON.parse(data));
36710
36787
  } catch {
36711
- resolve9({ raw: data });
36788
+ resolve12({ raw: data });
36712
36789
  }
36713
36790
  });
36714
36791
  });
@@ -36723,13 +36800,13 @@ ${effect.notification.body || ""}`.trim();
36723
36800
  }
36724
36801
  };
36725
36802
  var os10 = __toESM2(require("os"));
36726
- var path9 = __toESM2(require("path"));
36803
+ var path11 = __toESM2(require("path"));
36727
36804
  var crypto4 = __toESM2(require("crypto"));
36728
36805
  var import_chalk = __toESM2(require("chalk"));
36729
36806
  init_provider_cli_adapter();
36730
36807
  init_config();
36731
36808
  var os9 = __toESM2(require("os"));
36732
- var path8 = __toESM2(require("path"));
36809
+ var path10 = __toESM2(require("path"));
36733
36810
  var crypto3 = __toESM2(require("crypto"));
36734
36811
  var fs5 = __toESM2(require("fs"));
36735
36812
  var import_node_module = require("module");
@@ -36738,7 +36815,7 @@ ${effect.notification.body || ""}`.trim();
36738
36815
  var CachedDatabaseSync = null;
36739
36816
  function getDatabaseSync() {
36740
36817
  if (CachedDatabaseSync) return CachedDatabaseSync;
36741
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path8.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
36818
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
36742
36819
  const sqliteModule = requireFn(`node:${"sqlite"}`);
36743
36820
  CachedDatabaseSync = sqliteModule.DatabaseSync;
36744
36821
  if (!CachedDatabaseSync) {
@@ -37561,8 +37638,9 @@ ${effect.notification.body || ""}`.trim();
37561
37638
  async setConfigOption(category, value) {
37562
37639
  const opt = this.configOptions.find((c) => c.category === category);
37563
37640
  if (!opt) {
37564
- this.log.warn(`[${this.type}] No config option for category: ${category}`);
37565
- return;
37641
+ const message = `[${this.type}] No config option for category: ${category}`;
37642
+ this.log.warn(message);
37643
+ throw new Error(message);
37566
37644
  }
37567
37645
  if (this.useStaticConfig) {
37568
37646
  opt.currentValue = value;
@@ -37574,8 +37652,9 @@ ${effect.notification.body || ""}`.trim();
37574
37652
  return;
37575
37653
  }
37576
37654
  if (!this.connection || !this.sessionId) {
37577
- this.log.warn(`[${this.type}] Cannot set config: no active connection/session`);
37578
- return;
37655
+ const message = `[${this.type}] Cannot set config: no active connection/session`;
37656
+ this.log.warn(message);
37657
+ throw new Error(message);
37579
37658
  }
37580
37659
  try {
37581
37660
  this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
@@ -37589,7 +37668,9 @@ ${effect.notification.body || ""}`.trim();
37589
37668
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
37590
37669
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
37591
37670
  } catch (e) {
37592
- this.log.warn(`[${this.type}] set_config_option failed: ${e?.message}`);
37671
+ const message = e?.message || "Unknown ACP config error";
37672
+ this.log.warn(`[${this.type}] set_config_option failed: ${message}`);
37673
+ throw new Error(message);
37593
37674
  }
37594
37675
  }
37595
37676
  async setMode(modeId) {
@@ -37605,8 +37686,9 @@ ${effect.notification.body || ""}`.trim();
37605
37686
  return;
37606
37687
  }
37607
37688
  if (!this.connection || !this.sessionId) {
37608
- this.log.warn(`[${this.type}] Cannot set mode: no active connection/session`);
37609
- return;
37689
+ const message = `[${this.type}] Cannot set mode: no active connection/session`;
37690
+ this.log.warn(message);
37691
+ throw new Error(message);
37610
37692
  }
37611
37693
  try {
37612
37694
  await this.connection.setSessionMode({
@@ -37616,7 +37698,9 @@ ${effect.notification.body || ""}`.trim();
37616
37698
  this.currentMode = modeId;
37617
37699
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
37618
37700
  } catch (e) {
37619
- this.log.warn(`[${this.type}] set_mode failed: ${e?.message}`);
37701
+ const message = e?.message || "Unknown ACP mode error";
37702
+ this.log.warn(`[${this.type}] set_mode failed: ${message}`);
37703
+ throw new Error(message);
37620
37704
  }
37621
37705
  }
37622
37706
  /** Static config: kill process and restart with new args */
@@ -37664,7 +37748,7 @@ ${effect.notification.body || ""}`.trim();
37664
37748
  if (!spawnConfig) {
37665
37749
  throw new Error(`[ACP:${this.type}] No spawn config defined`);
37666
37750
  }
37667
- const command = spawnConfig.command;
37751
+ const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
37668
37752
  let baseArgs = spawnConfig.args || [];
37669
37753
  if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
37670
37754
  baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
@@ -37780,13 +37864,13 @@ ${effect.notification.body || ""}`.trim();
37780
37864
  }
37781
37865
  this.currentStatus = "waiting_approval";
37782
37866
  this.detectStatusTransition();
37783
- const approved = await new Promise((resolve9) => {
37784
- this.permissionResolvers.push(resolve9);
37867
+ const approved = await new Promise((resolve12) => {
37868
+ this.permissionResolvers.push(resolve12);
37785
37869
  setTimeout(() => {
37786
- const idx = this.permissionResolvers.indexOf(resolve9);
37870
+ const idx = this.permissionResolvers.indexOf(resolve12);
37787
37871
  if (idx >= 0) {
37788
37872
  this.permissionResolvers.splice(idx, 1);
37789
- resolve9(false);
37873
+ resolve12(false);
37790
37874
  }
37791
37875
  }, 3e5);
37792
37876
  });
@@ -38491,7 +38575,7 @@ ${effect.notification.body || ""}`.trim();
38491
38575
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
38492
38576
  const trimmed = (workingDir || "").trim();
38493
38577
  if (!trimmed) throw new Error("working directory required");
38494
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path9.resolve(trimmed);
38578
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path11.resolve(trimmed);
38495
38579
  const normalizedType = this.providerLoader.resolveAlias(cliType);
38496
38580
  const provider = this.providerLoader.getByAlias(cliType);
38497
38581
  const key = crypto4.randomUUID();
@@ -38578,10 +38662,10 @@ ${installInfo}`
38578
38662
  if (!cliInfo) {
38579
38663
  const installHint = provider?.install || "";
38580
38664
  const displayName = provider?.displayName || provider?.name || cliType;
38581
- const spawnCmd = provider?.spawn?.command || cliType;
38665
+ const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
38582
38666
  throw new Error(
38583
38667
  `${displayName} is not installed.
38584
- Command '${spawnCmd}' not found on PATH.
38668
+ Command '${spawnCmd}' is not available.
38585
38669
  ` + (installHint ? `
38586
38670
  ${installHint}
38587
38671
  ` : "") + `
@@ -38939,14 +39023,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
38939
39023
  var import_child_process6 = require("child_process");
38940
39024
  var net3 = __toESM2(require("net"));
38941
39025
  var os12 = __toESM2(require("os"));
38942
- var path11 = __toESM2(require("path"));
39026
+ var path13 = __toESM2(require("path"));
38943
39027
  var fs6 = __toESM2(require("fs"));
38944
- var path10 = __toESM2(require("path"));
39028
+ var path12 = __toESM2(require("path"));
38945
39029
  var os11 = __toESM2(require("os"));
38946
39030
  var chokidar = __toESM2((init_chokidar(), __toCommonJS(chokidar_exports)));
38947
39031
  init_logger();
38948
39032
  var ProviderLoader = class _ProviderLoader {
38949
39033
  providers = /* @__PURE__ */ new Map();
39034
+ providerAvailability = /* @__PURE__ */ new Map();
38950
39035
  userDir;
38951
39036
  upstreamDir;
38952
39037
  disableUpstream;
@@ -38962,12 +39047,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
38962
39047
  static META_FILE = ".meta.json";
38963
39048
  constructor(options) {
38964
39049
  this.logFn = options?.logFn || LOG2.forComponent("Provider").asLogFn();
38965
- const defaultProvidersDir = path10.join(os11.homedir(), ".adhdev", "providers");
39050
+ const defaultProvidersDir = path12.join(os11.homedir(), ".adhdev", "providers");
38966
39051
  if (options?.userDir) {
38967
39052
  this.userDir = options.userDir;
38968
39053
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
38969
39054
  } else {
38970
- const localRepoPath = path10.resolve(__dirname, "../../../../../adhdev-providers");
39055
+ const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
38971
39056
  if (fs6.existsSync(localRepoPath)) {
38972
39057
  this.userDir = localRepoPath;
38973
39058
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -38976,7 +39061,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
38976
39061
  this.log(`Using default user providers directory: ${this.userDir}`);
38977
39062
  }
38978
39063
  }
38979
- this.upstreamDir = path10.join(defaultProvidersDir, ".upstream");
39064
+ this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
38980
39065
  this.disableUpstream = options?.disableUpstream ?? false;
38981
39066
  }
38982
39067
  log(msg) {
@@ -39006,7 +39091,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39006
39091
  * Canonical provider directory shape for a given root.
39007
39092
  */
39008
39093
  getProviderDir(root, category, type) {
39009
- return path10.join(root, category, type);
39094
+ return path12.join(root, category, type);
39010
39095
  }
39011
39096
  /**
39012
39097
  * Canonical user override directory for a provider.
@@ -39033,7 +39118,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39033
39118
  resolveProviderFile(type, ...segments) {
39034
39119
  const dir = this.findProviderDirInternal(type);
39035
39120
  if (!dir) return null;
39036
- return path10.join(dir, ...segments);
39121
+ return path12.join(dir, ...segments);
39037
39122
  }
39038
39123
  /**
39039
39124
  * Load all providers (3-tier priority)
@@ -39044,6 +39129,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39044
39129
  */
39045
39130
  loadAll() {
39046
39131
  this.providers.clear();
39132
+ this.providerAvailability.clear();
39047
39133
  let upstreamCount = 0;
39048
39134
  if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
39049
39135
  upstreamCount = this.loadDir(this.upstreamDir);
@@ -39071,7 +39157,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39071
39157
  if (!fs6.existsSync(this.upstreamDir)) return false;
39072
39158
  try {
39073
39159
  return fs6.readdirSync(this.upstreamDir).some(
39074
- (d) => fs6.statSync(path10.join(this.upstreamDir, d)).isDirectory()
39160
+ (d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
39075
39161
  );
39076
39162
  } catch {
39077
39163
  return false;
@@ -39114,11 +39200,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
39114
39200
  if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
39115
39201
  const verCmdConfig = p.versionCommand;
39116
39202
  const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
39203
+ const command = this.getSpawnCommand(p.type, p.spawn.command);
39117
39204
  result.push({
39118
39205
  id: p.type,
39119
39206
  displayName: p.displayName || p.name,
39120
39207
  icon: p.icon || "\u{1F527}",
39121
- command: p.spawn.command,
39208
+ command,
39122
39209
  category: p.category,
39123
39210
  ...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
39124
39211
  });
@@ -39247,6 +39334,71 @@ Run 'adhdev doctor' for detailed diagnostics.`
39247
39334
  getAvailableIdeTypes() {
39248
39335
  return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
39249
39336
  }
39337
+ getSpawnCommand(type, fallback) {
39338
+ const override = this.getOptionalStringSetting(type, "executablePath");
39339
+ if (override) return override;
39340
+ return fallback || this.providers.get(type)?.spawn?.command || type;
39341
+ }
39342
+ getIdeCliCommand(type, fallback) {
39343
+ const override = this.getOptionalStringSetting(type, "cliPathOverride");
39344
+ if (override) return override;
39345
+ return fallback || this.providers.get(type)?.cli || null;
39346
+ }
39347
+ getIdePathCandidates(type, fallback) {
39348
+ const override = this.getOptionalStringSetting(type, "appPathOverride");
39349
+ if (override) return [override];
39350
+ if (fallback && fallback.length > 0) return fallback;
39351
+ const osPaths = this.providers.get(type)?.paths?.[process.platform];
39352
+ return Array.isArray(osPaths) ? [...osPaths] : [];
39353
+ }
39354
+ setProviderAvailability(type, state) {
39355
+ this.providerAvailability.set(type, {
39356
+ installed: !!state.installed,
39357
+ detectedPath: state.detectedPath ?? null
39358
+ });
39359
+ }
39360
+ setCliDetectionResults(results, replace = true) {
39361
+ if (replace) {
39362
+ for (const provider of this.providers.values()) {
39363
+ if (provider.category === "cli" || provider.category === "acp") {
39364
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
39365
+ }
39366
+ }
39367
+ }
39368
+ for (const result of results) {
39369
+ this.setProviderAvailability(result.id, {
39370
+ installed: !!result.installed,
39371
+ detectedPath: result.path || null
39372
+ });
39373
+ }
39374
+ }
39375
+ setIdeDetectionResults(results, replace = true) {
39376
+ if (replace) {
39377
+ for (const provider of this.providers.values()) {
39378
+ if (provider.category === "ide") {
39379
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
39380
+ }
39381
+ }
39382
+ }
39383
+ for (const result of results) {
39384
+ this.setProviderAvailability(result.id, {
39385
+ installed: !!result.installed,
39386
+ detectedPath: result.cliCommand || result.path || null
39387
+ });
39388
+ }
39389
+ }
39390
+ getAvailableProviderInfos() {
39391
+ return this.getAll().map((provider) => {
39392
+ const availability = this.providerAvailability.get(provider.type);
39393
+ return {
39394
+ ...provider,
39395
+ ...availability ? {
39396
+ installed: availability.installed,
39397
+ detectedPath: availability.detectedPath
39398
+ } : {}
39399
+ };
39400
+ });
39401
+ }
39250
39402
  /**
39251
39403
  * Register IDE providers to core/detector registry
39252
39404
  * → Enables detectIDEs() to detect provider.js-based IDEs
@@ -39321,8 +39473,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
39321
39473
  resolved._resolvedScriptDir = entry.scriptDir;
39322
39474
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
39323
39475
  if (providerDir) {
39324
- const fullDir = path10.join(providerDir, entry.scriptDir);
39325
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
39476
+ const fullDir = path12.join(providerDir, entry.scriptDir);
39477
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
39326
39478
  }
39327
39479
  matched = true;
39328
39480
  }
@@ -39337,8 +39489,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
39337
39489
  resolved._resolvedScriptDir = base.defaultScriptDir;
39338
39490
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
39339
39491
  if (providerDir) {
39340
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
39341
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
39492
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
39493
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
39342
39494
  }
39343
39495
  }
39344
39496
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -39355,8 +39507,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
39355
39507
  resolved._resolvedScriptDir = dirOverride;
39356
39508
  resolved._resolvedScriptsSource = `versions:${range}`;
39357
39509
  if (providerDir) {
39358
- const fullDir = path10.join(providerDir, dirOverride);
39359
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
39510
+ const fullDir = path12.join(providerDir, dirOverride);
39511
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
39360
39512
  }
39361
39513
  }
39362
39514
  } else if (override.scripts) {
@@ -39372,8 +39524,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
39372
39524
  resolved._resolvedScriptDir = base.defaultScriptDir;
39373
39525
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
39374
39526
  if (providerDir) {
39375
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
39376
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
39527
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
39528
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
39377
39529
  }
39378
39530
  }
39379
39531
  }
@@ -39398,14 +39550,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
39398
39550
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
39399
39551
  return null;
39400
39552
  }
39401
- const dir = path10.join(providerDir, scriptDir);
39553
+ const dir = path12.join(providerDir, scriptDir);
39402
39554
  if (!fs6.existsSync(dir)) {
39403
39555
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
39404
39556
  return null;
39405
39557
  }
39406
39558
  const cached2 = this.scriptsCache.get(dir);
39407
39559
  if (cached2) return cached2;
39408
- const scriptsJs = path10.join(dir, "scripts.js");
39560
+ const scriptsJs = path12.join(dir, "scripts.js");
39409
39561
  if (fs6.existsSync(scriptsJs)) {
39410
39562
  try {
39411
39563
  delete require.cache[require.resolve(scriptsJs)];
@@ -39447,7 +39599,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39447
39599
  return;
39448
39600
  }
39449
39601
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
39450
- this.log(`File changed: ${path10.basename(filePath)}, reloading...`);
39602
+ this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
39451
39603
  this.reload();
39452
39604
  }
39453
39605
  };
@@ -39502,7 +39654,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39502
39654
  }
39503
39655
  const https = require("https");
39504
39656
  const { execSync: execSync7 } = require("child_process");
39505
- const metaPath = path10.join(this.upstreamDir, _ProviderLoader.META_FILE);
39657
+ const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
39506
39658
  let prevEtag = "";
39507
39659
  let prevTimestamp = 0;
39508
39660
  try {
@@ -39519,7 +39671,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39519
39671
  return { updated: false };
39520
39672
  }
39521
39673
  try {
39522
- const etag = await new Promise((resolve9, reject) => {
39674
+ const etag = await new Promise((resolve12, reject) => {
39523
39675
  const options = {
39524
39676
  method: "HEAD",
39525
39677
  hostname: "github.com",
@@ -39537,7 +39689,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39537
39689
  headers: { "User-Agent": "adhdev-launcher" },
39538
39690
  timeout: 1e4
39539
39691
  }, (res2) => {
39540
- resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
39692
+ resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
39541
39693
  });
39542
39694
  req2.on("error", reject);
39543
39695
  req2.on("timeout", () => {
@@ -39546,7 +39698,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39546
39698
  });
39547
39699
  req2.end();
39548
39700
  } else {
39549
- resolve9(res.headers.etag || res.headers["last-modified"] || "");
39701
+ resolve12(res.headers.etag || res.headers["last-modified"] || "");
39550
39702
  }
39551
39703
  });
39552
39704
  req.on("error", reject);
@@ -39562,17 +39714,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
39562
39714
  return { updated: false };
39563
39715
  }
39564
39716
  this.log("Downloading latest providers from GitHub...");
39565
- const tmpTar = path10.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
39566
- const tmpExtract = path10.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
39717
+ const tmpTar = path12.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
39718
+ const tmpExtract = path12.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
39567
39719
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
39568
39720
  fs6.mkdirSync(tmpExtract, { recursive: true });
39569
39721
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
39570
39722
  const extracted = fs6.readdirSync(tmpExtract);
39571
39723
  const rootDir = extracted.find(
39572
- (d) => fs6.statSync(path10.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
39724
+ (d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
39573
39725
  );
39574
39726
  if (!rootDir) throw new Error("Unexpected tarball structure");
39575
- const sourceDir = path10.join(tmpExtract, rootDir);
39727
+ const sourceDir = path12.join(tmpExtract, rootDir);
39576
39728
  const backupDir = this.upstreamDir + ".bak";
39577
39729
  if (fs6.existsSync(this.upstreamDir)) {
39578
39730
  if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
@@ -39610,7 +39762,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39610
39762
  downloadFile(url2, destPath) {
39611
39763
  const https = require("https");
39612
39764
  const http3 = require("http");
39613
- return new Promise((resolve9, reject) => {
39765
+ return new Promise((resolve12, reject) => {
39614
39766
  const doRequest = (reqUrl, redirectCount = 0) => {
39615
39767
  if (redirectCount > 5) {
39616
39768
  reject(new Error("Too many redirects"));
@@ -39630,7 +39782,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39630
39782
  res.pipe(ws2);
39631
39783
  ws2.on("finish", () => {
39632
39784
  ws2.close();
39633
- resolve9();
39785
+ resolve12();
39634
39786
  });
39635
39787
  ws2.on("error", reject);
39636
39788
  });
@@ -39647,8 +39799,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
39647
39799
  copyDirRecursive(src, dest) {
39648
39800
  fs6.mkdirSync(dest, { recursive: true });
39649
39801
  for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
39650
- const srcPath = path10.join(src, entry.name);
39651
- const destPath = path10.join(dest, entry.name);
39802
+ const srcPath = path12.join(src, entry.name);
39803
+ const destPath = path12.join(dest, entry.name);
39652
39804
  if (entry.isDirectory()) {
39653
39805
  this.copyDirRecursive(srcPath, destPath);
39654
39806
  } else {
@@ -39659,7 +39811,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39659
39811
  /** .meta.json save */
39660
39812
  writeMeta(metaPath, etag, timestamp) {
39661
39813
  try {
39662
- fs6.mkdirSync(path10.dirname(metaPath), { recursive: true });
39814
+ fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
39663
39815
  fs6.writeFileSync(metaPath, JSON.stringify({
39664
39816
  etag,
39665
39817
  timestamp,
@@ -39676,7 +39828,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39676
39828
  const scan = (d) => {
39677
39829
  try {
39678
39830
  for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
39679
- if (entry.isDirectory()) scan(path10.join(d, entry.name));
39831
+ if (entry.isDirectory()) scan(path12.join(d, entry.name));
39680
39832
  else if (entry.name === "provider.json") count++;
39681
39833
  }
39682
39834
  } catch {
@@ -39690,9 +39842,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
39690
39842
  * Get public settings schema for a provider (for dashboard UI rendering)
39691
39843
  */
39692
39844
  getPublicSettings(type) {
39693
- const provider = this.providers.get(type);
39694
- if (!provider?.settings) return [];
39695
- return Object.entries(provider.settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
39845
+ const settings = this.getSettingsSchema(type);
39846
+ return Object.entries(settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
39696
39847
  }
39697
39848
  /**
39698
39849
  * Get public settings schema for all providers
@@ -39709,8 +39860,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39709
39860
  * Resolved setting value for a provider (default + user override)
39710
39861
  */
39711
39862
  getSettingValue(type, key) {
39712
- const provider = this.providers.get(type);
39713
- const schemaDef = provider?.settings?.[key];
39863
+ const schemaDef = this.getSettingsSchema(type)[key];
39714
39864
  const defaultVal = schemaDef ? schemaDef.default : void 0;
39715
39865
  try {
39716
39866
  const { loadConfig: loadConfig22 } = (init_config(), __toCommonJS2(config_exports));
@@ -39725,10 +39875,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
39725
39875
  * All resolved settings for a provider (default + user override)
39726
39876
  */
39727
39877
  getSettings(type) {
39728
- const provider = this.providers.get(type);
39729
- if (!provider?.settings) return {};
39878
+ const settings = this.getSettingsSchema(type);
39730
39879
  const result = {};
39731
- for (const [key, def] of Object.entries(provider.settings)) {
39880
+ for (const [key] of Object.entries(settings)) {
39732
39881
  result[key] = this.getSettingValue(type, key);
39733
39882
  }
39734
39883
  return result;
@@ -39737,11 +39886,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
39737
39886
  * Save provider setting value (writes to config.json)
39738
39887
  */
39739
39888
  setSetting(type, key, value) {
39740
- const provider = this.providers.get(type);
39741
- const schemaDef = provider?.settings?.[key];
39889
+ const schemaDef = this.getSettingsSchema(type)[key];
39742
39890
  if (!schemaDef) return false;
39743
39891
  if (!schemaDef.public) return false;
39744
39892
  if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
39893
+ if (schemaDef.type === "string" && typeof value !== "string") return false;
39745
39894
  if (schemaDef.type === "number") {
39746
39895
  if (typeof value !== "number") return false;
39747
39896
  if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
@@ -39762,6 +39911,53 @@ Run 'adhdev doctor' for detailed diagnostics.`
39762
39911
  return false;
39763
39912
  }
39764
39913
  }
39914
+ getOptionalStringSetting(type, key) {
39915
+ const value = this.getSettingValue(type, key);
39916
+ if (typeof value !== "string") return null;
39917
+ const trimmed = value.trim();
39918
+ return trimmed ? trimmed : null;
39919
+ }
39920
+ getSettingsSchema(type) {
39921
+ const provider = this.providers.get(type);
39922
+ if (!provider) return {};
39923
+ return {
39924
+ ...this.getSyntheticSettings(type, provider),
39925
+ ...provider.settings || {}
39926
+ };
39927
+ }
39928
+ getSyntheticSettings(type, provider) {
39929
+ const result = {};
39930
+ if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
39931
+ result.executablePath = {
39932
+ type: "string",
39933
+ default: "",
39934
+ public: true,
39935
+ label: "Executable path",
39936
+ description: "Optional absolute path for this provider binary. Leave blank to use the default PATH lookup."
39937
+ };
39938
+ }
39939
+ if (provider.category === "ide") {
39940
+ if (provider.cli && !provider.settings?.cliPathOverride) {
39941
+ result.cliPathOverride = {
39942
+ type: "string",
39943
+ default: "",
39944
+ public: true,
39945
+ label: "CLI path override",
39946
+ description: "Optional absolute path for the IDE CLI launcher. Leave blank to use the detected default."
39947
+ };
39948
+ }
39949
+ if (provider.paths && !provider.settings?.appPathOverride) {
39950
+ result.appPathOverride = {
39951
+ type: "string",
39952
+ default: "",
39953
+ public: true,
39954
+ label: "App path override",
39955
+ description: "Optional absolute path for the IDE app bundle or executable. Leave blank to use the default install locations."
39956
+ };
39957
+ }
39958
+ }
39959
+ return result;
39960
+ }
39765
39961
  // ─── Private ───────────────────────────────────
39766
39962
  /**
39767
39963
  * Find the on-disk directory for a provider by type.
@@ -39775,17 +39971,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
39775
39971
  for (const root of searchRoots) {
39776
39972
  if (!fs6.existsSync(root)) continue;
39777
39973
  const candidate = this.getProviderDir(root, cat, type);
39778
- if (fs6.existsSync(path10.join(candidate, "provider.json"))) return candidate;
39779
- const catDir = path10.join(root, cat);
39974
+ if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
39975
+ const catDir = path12.join(root, cat);
39780
39976
  if (fs6.existsSync(catDir)) {
39781
39977
  try {
39782
39978
  for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
39783
39979
  if (!entry.isDirectory()) continue;
39784
- const jsonPath = path10.join(catDir, entry.name, "provider.json");
39980
+ const jsonPath = path12.join(catDir, entry.name, "provider.json");
39785
39981
  if (fs6.existsSync(jsonPath)) {
39786
39982
  try {
39787
39983
  const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
39788
- if (data.type === type) return path10.join(catDir, entry.name);
39984
+ if (data.type === type) return path12.join(catDir, entry.name);
39789
39985
  } catch {
39790
39986
  }
39791
39987
  }
@@ -39802,7 +39998,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39802
39998
  * (template substitution is NOT applied here — scripts.js handles that)
39803
39999
  */
39804
40000
  buildScriptWrappersFromDir(dir) {
39805
- const scriptsJs = path10.join(dir, "scripts.js");
40001
+ const scriptsJs = path12.join(dir, "scripts.js");
39806
40002
  if (fs6.existsSync(scriptsJs)) {
39807
40003
  try {
39808
40004
  delete require.cache[require.resolve(scriptsJs)];
@@ -39816,7 +40012,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39816
40012
  for (const file2 of fs6.readdirSync(dir)) {
39817
40013
  if (!file2.endsWith(".js")) continue;
39818
40014
  const scriptName = toCamel(file2.replace(".js", ""));
39819
- const filePath = path10.join(dir, file2);
40015
+ const filePath = path12.join(dir, file2);
39820
40016
  result[scriptName] = (...args) => {
39821
40017
  try {
39822
40018
  let content = fs6.readFileSync(filePath, "utf-8");
@@ -39876,7 +40072,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39876
40072
  }
39877
40073
  const hasJson = entries.some((e) => e.name === "provider.json");
39878
40074
  if (hasJson) {
39879
- const jsonPath = path10.join(d, "provider.json");
40075
+ const jsonPath = path12.join(d, "provider.json");
39880
40076
  try {
39881
40077
  const raw = fs6.readFileSync(jsonPath, "utf-8");
39882
40078
  const mod = JSON.parse(raw);
@@ -39889,7 +40085,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39889
40085
  delete mod.extensionIdPattern_flags;
39890
40086
  }
39891
40087
  const hasCompatibility = Array.isArray(mod.compatibility);
39892
- const scriptsPath = path10.join(d, "scripts.js");
40088
+ const scriptsPath = path12.join(d, "scripts.js");
39893
40089
  if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
39894
40090
  try {
39895
40091
  delete require.cache[require.resolve(scriptsPath)];
@@ -39915,7 +40111,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
39915
40111
  if (!entry.isDirectory()) continue;
39916
40112
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
39917
40113
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
39918
- scan(path10.join(d, entry.name));
40114
+ scan(path12.join(d, entry.name));
39919
40115
  }
39920
40116
  }
39921
40117
  };
@@ -40009,17 +40205,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
40009
40205
  throw new Error("No free port found");
40010
40206
  }
40011
40207
  function checkPortFree(port) {
40012
- return new Promise((resolve9) => {
40208
+ return new Promise((resolve12) => {
40013
40209
  const server = net3.createServer();
40014
40210
  server.unref();
40015
- server.on("error", () => resolve9(false));
40211
+ server.on("error", () => resolve12(false));
40016
40212
  server.listen(port, "127.0.0.1", () => {
40017
- server.close(() => resolve9(true));
40213
+ server.close(() => resolve12(true));
40018
40214
  });
40019
40215
  });
40020
40216
  }
40021
40217
  async function isCdpActive(port) {
40022
- return new Promise((resolve9) => {
40218
+ return new Promise((resolve12) => {
40023
40219
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
40024
40220
  timeout: 2e3
40025
40221
  }, (res) => {
@@ -40028,16 +40224,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
40028
40224
  res.on("end", () => {
40029
40225
  try {
40030
40226
  const info = JSON.parse(data);
40031
- resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
40227
+ resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
40032
40228
  } catch {
40033
- resolve9(false);
40229
+ resolve12(false);
40034
40230
  }
40035
40231
  });
40036
40232
  });
40037
- req.on("error", () => resolve9(false));
40233
+ req.on("error", () => resolve12(false));
40038
40234
  req.on("timeout", () => {
40039
40235
  req.destroy();
40040
- resolve9(false);
40236
+ resolve12(false);
40041
40237
  });
40042
40238
  });
40043
40239
  }
@@ -40171,8 +40367,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
40171
40367
  const appNameMap = getMacAppIdentifiers();
40172
40368
  const appName = appNameMap[ideId];
40173
40369
  if (appName) {
40174
- const storagePath = path11.join(
40175
- process.env.APPDATA || path11.join(os12.homedir(), "AppData", "Roaming"),
40370
+ const storagePath = path13.join(
40371
+ process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
40176
40372
  appName,
40177
40373
  "storage.json"
40178
40374
  );
@@ -40196,7 +40392,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
40196
40392
  async function launchWithCdp(options = {}) {
40197
40393
  const platform9 = os12.platform();
40198
40394
  let targetIde;
40199
- const ides = await detectIDEs();
40395
+ const ides = await detectIDEs(getProviderLoader());
40200
40396
  if (options.ideId) {
40201
40397
  targetIde = ides.find((i) => i.id === options.ideId && i.installed);
40202
40398
  if (!targetIde) {
@@ -40346,9 +40542,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
40346
40542
  init_config();
40347
40543
  init_logger();
40348
40544
  var fs7 = __toESM2(require("fs"));
40349
- var path12 = __toESM2(require("path"));
40545
+ var path14 = __toESM2(require("path"));
40350
40546
  var os13 = __toESM2(require("os"));
40351
- 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");
40547
+ var LOG_DIR2 = process.platform === "win32" ? path14.join(process.env.LOCALAPPDATA || process.env.APPDATA || path14.join(os13.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path14.join(os13.homedir(), "Library", "Logs", "adhdev") : path14.join(os13.homedir(), ".local", "share", "adhdev", "logs");
40352
40548
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
40353
40549
  var MAX_DAYS = 7;
40354
40550
  try {
@@ -40386,13 +40582,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
40386
40582
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
40387
40583
  }
40388
40584
  var currentDate2 = getDateStr2();
40389
- var currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
40585
+ var currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
40390
40586
  var writeCount2 = 0;
40391
40587
  function checkRotation() {
40392
40588
  const today = getDateStr2();
40393
40589
  if (today !== currentDate2) {
40394
40590
  currentDate2 = today;
40395
- currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
40591
+ currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
40396
40592
  cleanOldFiles();
40397
40593
  }
40398
40594
  }
@@ -40406,7 +40602,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
40406
40602
  const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
40407
40603
  if (dateMatch && dateMatch[1] < cutoffStr) {
40408
40604
  try {
40409
- fs7.unlinkSync(path12.join(LOG_DIR2, file2));
40605
+ fs7.unlinkSync(path14.join(LOG_DIR2, file2));
40410
40606
  } catch {
40411
40607
  }
40412
40608
  }
@@ -40494,12 +40690,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
40494
40690
  }));
40495
40691
  }
40496
40692
  function buildAvailableProviders(providerLoader) {
40497
- return providerLoader.getAll().map((provider) => ({
40693
+ const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
40694
+ return providers.map((provider) => ({
40498
40695
  type: provider.type,
40499
40696
  name: provider.displayName || provider.type,
40500
40697
  displayName: provider.displayName || provider.type,
40501
40698
  icon: provider.icon || "\u{1F4BB}",
40502
- category: provider.category
40699
+ category: provider.category,
40700
+ ...provider.installed !== void 0 ? { installed: provider.installed } : {},
40701
+ ...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
40503
40702
  }));
40504
40703
  }
40505
40704
  function parseMessageTime(value) {
@@ -40625,13 +40824,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
40625
40824
  var import_child_process8 = require("child_process");
40626
40825
  var fs8 = __toESM2(require("fs"));
40627
40826
  var os15 = __toESM2(require("os"));
40628
- var path13 = __toESM2(require("path"));
40827
+ var path15 = __toESM2(require("path"));
40629
40828
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
40630
40829
  function getUpgradeLogPath() {
40631
40830
  const home = os15.homedir();
40632
- const dir = path13.join(home, ".adhdev");
40831
+ const dir = path15.join(home, ".adhdev");
40633
40832
  fs8.mkdirSync(dir, { recursive: true });
40634
- return path13.join(dir, "daemon-upgrade.log");
40833
+ return path15.join(dir, "daemon-upgrade.log");
40635
40834
  }
40636
40835
  function appendUpgradeLog(message) {
40637
40836
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -40664,14 +40863,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
40664
40863
  while (Date.now() - start < timeoutMs) {
40665
40864
  try {
40666
40865
  process.kill(pid, 0);
40667
- await new Promise((resolve9) => setTimeout(resolve9, 250));
40866
+ await new Promise((resolve12) => setTimeout(resolve12, 250));
40668
40867
  } catch {
40669
40868
  return;
40670
40869
  }
40671
40870
  }
40672
40871
  }
40673
40872
  function stopSessionHostProcesses(appName) {
40674
- const pidFile = path13.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
40873
+ const pidFile = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
40675
40874
  try {
40676
40875
  if (fs8.existsSync(pidFile)) {
40677
40876
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
@@ -40700,7 +40899,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
40700
40899
  }
40701
40900
  }
40702
40901
  function removeDaemonPidFile() {
40703
- const pidFile = path13.join(os15.homedir(), ".adhdev", "daemon.pid");
40902
+ const pidFile = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
40704
40903
  try {
40705
40904
  fs8.unlinkSync(pidFile);
40706
40905
  } catch {
@@ -40711,7 +40910,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
40711
40910
  const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
40712
40911
  if (!npmRoot) return;
40713
40912
  const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
40714
- const binDir = process.platform === "win32" ? npmPrefix : path13.join(npmPrefix, "bin");
40913
+ const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
40715
40914
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
40716
40915
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
40717
40916
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -40719,25 +40918,25 @@ Run 'adhdev doctor' for detailed diagnostics.`
40719
40918
  }
40720
40919
  if (pkgName.startsWith("@")) {
40721
40920
  const [scope, name] = pkgName.split("/");
40722
- const scopeDir = path13.join(npmRoot, scope);
40921
+ const scopeDir = path15.join(npmRoot, scope);
40723
40922
  if (!fs8.existsSync(scopeDir)) return;
40724
40923
  for (const entry of fs8.readdirSync(scopeDir)) {
40725
40924
  if (!entry.startsWith(`.${name}-`)) continue;
40726
- fs8.rmSync(path13.join(scopeDir, entry), { recursive: true, force: true });
40727
- appendUpgradeLog(`Removed stale scoped staging dir: ${path13.join(scopeDir, entry)}`);
40925
+ fs8.rmSync(path15.join(scopeDir, entry), { recursive: true, force: true });
40926
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
40728
40927
  }
40729
40928
  } else {
40730
40929
  for (const entry of fs8.readdirSync(npmRoot)) {
40731
40930
  if (!entry.startsWith(`.${pkgName}-`)) continue;
40732
- fs8.rmSync(path13.join(npmRoot, entry), { recursive: true, force: true });
40733
- appendUpgradeLog(`Removed stale staging dir: ${path13.join(npmRoot, entry)}`);
40931
+ fs8.rmSync(path15.join(npmRoot, entry), { recursive: true, force: true });
40932
+ appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
40734
40933
  }
40735
40934
  }
40736
40935
  if (fs8.existsSync(binDir)) {
40737
40936
  for (const entry of fs8.readdirSync(binDir)) {
40738
40937
  if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
40739
- fs8.rmSync(path13.join(binDir, entry), { recursive: true, force: true });
40740
- appendUpgradeLog(`Removed stale bin staging entry: ${path13.join(binDir, entry)}`);
40938
+ fs8.rmSync(path15.join(binDir, entry), { recursive: true, force: true });
40939
+ appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, entry)}`);
40741
40940
  }
40742
40941
  }
40743
40942
  }
@@ -40779,7 +40978,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
40779
40978
  appendUpgradeLog(installOutput.trim());
40780
40979
  }
40781
40980
  if (process.platform === "win32") {
40782
- await new Promise((resolve9) => setTimeout(resolve9, 500));
40981
+ await new Promise((resolve12) => setTimeout(resolve12, 500));
40783
40982
  cleanupStaleGlobalInstallDirs(payload.packageName);
40784
40983
  appendUpgradeLog("Post-install staging cleanup complete");
40785
40984
  }
@@ -41055,6 +41254,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
41055
41254
  if (!ideType) throw new Error("ideType required");
41056
41255
  const killProcess = args?.killProcess !== false;
41057
41256
  await this.stopIde(ideType, killProcess);
41257
+ try {
41258
+ const results = await detectIDEs(this.deps.providerLoader);
41259
+ this.deps.detectedIdes.value = results;
41260
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
41261
+ } catch {
41262
+ }
41058
41263
  return { success: true, ideType, stopped: true, processKilled: killProcess };
41059
41264
  }
41060
41265
  // ─── IDE restart ───
@@ -41097,6 +41302,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
41097
41302
  }
41098
41303
  }
41099
41304
  this.deps.onIdeConnected?.();
41305
+ try {
41306
+ const results = await detectIDEs(this.deps.providerLoader);
41307
+ this.deps.detectedIdes.value = results;
41308
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
41309
+ } catch {
41310
+ }
41100
41311
  if (result.success && resolvedWorkspace) {
41101
41312
  try {
41102
41313
  const next = appendRecentActivity(loadState(), {
@@ -41124,8 +41335,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
41124
41335
  }
41125
41336
  // ─── Detect IDEs ───
41126
41337
  case "detect_ides": {
41127
- const results = await detectIDEs();
41338
+ const results = await detectIDEs(this.deps.providerLoader);
41128
41339
  this.deps.detectedIdes.value = results;
41340
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
41129
41341
  return { success: true, detectedInfo: results };
41130
41342
  }
41131
41343
  // ─── Set User Name ───
@@ -41631,7 +41843,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
41631
41843
  const raw = await evaluate(script, 1e4);
41632
41844
  const data = typeof raw === "string" ? JSON.parse(raw) : raw;
41633
41845
  if (data?.error) return [];
41634
- return Array.isArray(data) ? data : [];
41846
+ if (Array.isArray(data)) return data;
41847
+ if (Array.isArray(data?.sessions)) return data.sessions;
41848
+ if (Array.isArray(data?.chats)) return data.chats;
41849
+ return [];
41635
41850
  } catch {
41636
41851
  return [];
41637
41852
  }
@@ -41639,7 +41854,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
41639
41854
  async switchSession(evaluate, sessionId) {
41640
41855
  const script = this.callScript("switchSession", sessionId);
41641
41856
  if (!script) return false;
41642
- return await evaluate(script, 1e4) === true;
41857
+ const raw = await evaluate(script, 1e4);
41858
+ const data = this.parseMaybeJson(raw);
41859
+ if (data === true) return true;
41860
+ if (typeof data === "string") {
41861
+ const normalized = data.trim().toLowerCase();
41862
+ return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
41863
+ }
41864
+ if (data && typeof data === "object") {
41865
+ return data.switched === true || data.success === true || data.ok === true;
41866
+ }
41867
+ return false;
41643
41868
  }
41644
41869
  async focusEditor(evaluate) {
41645
41870
  const script = this.callScript("focusEditor");
@@ -42319,11 +42544,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
42319
42544
  }
42320
42545
  };
42321
42546
  var fs10 = __toESM2(require("fs"));
42322
- var path14 = __toESM2(require("path"));
42547
+ var path16 = __toESM2(require("path"));
42323
42548
  var os16 = __toESM2(require("os"));
42324
42549
  var import_child_process9 = require("child_process");
42325
42550
  var import_os3 = require("os");
42326
- var ARCHIVE_PATH = path14.join(os16.homedir(), ".adhdev", "version-history.json");
42551
+ var ARCHIVE_PATH = path16.join(os16.homedir(), ".adhdev", "version-history.json");
42327
42552
  var MAX_ENTRIES_PER_PROVIDER = 20;
42328
42553
  var VersionArchive = class {
42329
42554
  history = {};
@@ -42370,7 +42595,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
42370
42595
  }
42371
42596
  save() {
42372
42597
  try {
42373
- fs10.mkdirSync(path14.dirname(ARCHIVE_PATH), { recursive: true });
42598
+ fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
42374
42599
  fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
42375
42600
  } catch {
42376
42601
  }
@@ -42411,7 +42636,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
42411
42636
  for (const p of paths) {
42412
42637
  if (p.includes("*")) {
42413
42638
  const home = os16.homedir();
42414
- const resolved = p.replace(/\*/g, home.split(path14.sep).pop() || "");
42639
+ const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
42415
42640
  if (fs10.existsSync(resolved)) return resolved;
42416
42641
  } else {
42417
42642
  if (fs10.existsSync(p)) return p;
@@ -42421,7 +42646,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
42421
42646
  }
42422
42647
  function getMacAppVersion(appPath) {
42423
42648
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
42424
- const plistPath = path14.join(appPath, "Contents", "Info.plist");
42649
+ const plistPath = path16.join(appPath, "Contents", "Info.plist");
42425
42650
  if (!fs10.existsSync(plistPath)) return null;
42426
42651
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
42427
42652
  return raw || null;
@@ -42448,7 +42673,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
42448
42673
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
42449
42674
  let resolvedBin = cliBin;
42450
42675
  if (!resolvedBin && appPath && currentOs === "darwin") {
42451
- const bundled = path14.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
42676
+ const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
42452
42677
  if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
42453
42678
  }
42454
42679
  info.installed = !!(appPath || resolvedBin);
@@ -42487,7 +42712,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
42487
42712
  }
42488
42713
  var http2 = __toESM2(require("http"));
42489
42714
  var fs14 = __toESM2(require("fs"));
42490
- var path18 = __toESM2(require("path"));
42715
+ var path20 = __toESM2(require("path"));
42491
42716
  function generateFiles(type, name, category, opts = {}) {
42492
42717
  const { cdpPorts, cli, processName, installPath, binary, extensionId, version: version2 = "0.1" } = opts;
42493
42718
  if (category === "cli" || category === "acp") {
@@ -42817,7 +43042,7 @@ async (params) => {
42817
43042
  }
42818
43043
  init_logger();
42819
43044
  var fs11 = __toESM2(require("fs"));
42820
- var path15 = __toESM2(require("path"));
43045
+ var path17 = __toESM2(require("path"));
42821
43046
  init_logger();
42822
43047
  async function handleCdpEvaluate(ctx, req, res) {
42823
43048
  const body = await ctx.readBody(req);
@@ -42996,17 +43221,17 @@ async (params) => {
42996
43221
  return;
42997
43222
  }
42998
43223
  let scriptsPath = "";
42999
- const directScripts = path15.join(dir, "scripts.js");
43224
+ const directScripts = path17.join(dir, "scripts.js");
43000
43225
  if (fs11.existsSync(directScripts)) {
43001
43226
  scriptsPath = directScripts;
43002
43227
  } else {
43003
- const scriptsDir = path15.join(dir, "scripts");
43228
+ const scriptsDir = path17.join(dir, "scripts");
43004
43229
  if (fs11.existsSync(scriptsDir)) {
43005
43230
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
43006
- return fs11.statSync(path15.join(scriptsDir, d)).isDirectory();
43231
+ return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
43007
43232
  }).sort().reverse();
43008
43233
  for (const ver of versions) {
43009
- const p = path15.join(scriptsDir, ver, "scripts.js");
43234
+ const p = path17.join(scriptsDir, ver, "scripts.js");
43010
43235
  if (fs11.existsSync(p)) {
43011
43236
  scriptsPath = p;
43012
43237
  break;
@@ -43823,7 +44048,7 @@ async (params) => {
43823
44048
  }
43824
44049
  }
43825
44050
  var fs12 = __toESM2(require("fs"));
43826
- var path16 = __toESM2(require("path"));
44051
+ var path18 = __toESM2(require("path"));
43827
44052
  function slugifyFixtureName(value) {
43828
44053
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
43829
44054
  return normalized || `fixture-${Date.now()}`;
@@ -43833,11 +44058,11 @@ async (params) => {
43833
44058
  if (!providerDir) {
43834
44059
  throw new Error(`Provider directory not found for '${type}'`);
43835
44060
  }
43836
- return path16.join(providerDir, "fixtures");
44061
+ return path18.join(providerDir, "fixtures");
43837
44062
  }
43838
44063
  function readCliFixture(ctx, type, name) {
43839
44064
  const fixtureDir = getCliFixtureDir(ctx, type);
43840
- const filePath = path16.join(fixtureDir, `${name}.json`);
44065
+ const filePath = path18.join(fixtureDir, `${name}.json`);
43841
44066
  if (!fs12.existsSync(filePath)) {
43842
44067
  throw new Error(`Fixture not found: ${filePath}`);
43843
44068
  }
@@ -43997,7 +44222,7 @@ async (params) => {
43997
44222
  return { target, instance, adapter };
43998
44223
  }
43999
44224
  function sleep(ms2) {
44000
- return new Promise((resolve9) => setTimeout(resolve9, ms2));
44225
+ return new Promise((resolve12) => setTimeout(resolve12, ms2));
44001
44226
  }
44002
44227
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
44003
44228
  const startedAt = Date.now();
@@ -44596,7 +44821,7 @@ async (params) => {
44596
44821
  },
44597
44822
  notes: typeof body?.notes === "string" ? body.notes : void 0
44598
44823
  };
44599
- const filePath = path16.join(fixtureDir, `${name}.json`);
44824
+ const filePath = path18.join(fixtureDir, `${name}.json`);
44600
44825
  fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
44601
44826
  ctx.json(res, 200, {
44602
44827
  saved: true,
@@ -44620,7 +44845,7 @@ async (params) => {
44620
44845
  return;
44621
44846
  }
44622
44847
  const fixtures = fs12.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
44623
- const fullPath = path16.join(fixtureDir, file2);
44848
+ const fullPath = path18.join(fixtureDir, file2);
44624
44849
  try {
44625
44850
  const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
44626
44851
  return {
@@ -44754,7 +44979,7 @@ async (params) => {
44754
44979
  }
44755
44980
  }
44756
44981
  var fs13 = __toESM2(require("fs"));
44757
- var path17 = __toESM2(require("path"));
44982
+ var path19 = __toESM2(require("path"));
44758
44983
  var os17 = __toESM2(require("os"));
44759
44984
  function getAutoImplPid(ctx) {
44760
44985
  const proc = ctx.autoImplProcess;
@@ -44794,22 +45019,22 @@ async (params) => {
44794
45019
  if (!fs13.existsSync(scriptsDir)) return null;
44795
45020
  const versions = fs13.readdirSync(scriptsDir).filter((d) => {
44796
45021
  try {
44797
- return fs13.statSync(path17.join(scriptsDir, d)).isDirectory();
45022
+ return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
44798
45023
  } catch {
44799
45024
  return false;
44800
45025
  }
44801
45026
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
44802
45027
  if (versions.length === 0) return null;
44803
- return path17.join(scriptsDir, versions[0]);
45028
+ return path19.join(scriptsDir, versions[0]);
44804
45029
  }
44805
45030
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
44806
- const canonicalUserDir = path17.resolve(ctx.providerLoader.getUserProviderDir(category, type));
44807
- const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
44808
- const upstreamRoot = path17.resolve(ctx.providerLoader.getUpstreamDir());
44809
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
45031
+ const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
45032
+ const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
45033
+ const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
45034
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
44810
45035
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
44811
45036
  }
44812
- if (path17.basename(desiredDir) !== type) {
45037
+ if (path19.basename(desiredDir) !== type) {
44813
45038
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
44814
45039
  }
44815
45040
  const sourceDir = ctx.findProviderDir(type);
@@ -44817,11 +45042,11 @@ async (params) => {
44817
45042
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
44818
45043
  }
44819
45044
  if (!fs13.existsSync(desiredDir)) {
44820
- fs13.mkdirSync(path17.dirname(desiredDir), { recursive: true });
45045
+ fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
44821
45046
  fs13.cpSync(sourceDir, desiredDir, { recursive: true });
44822
45047
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
44823
45048
  }
44824
- const providerJson = path17.join(desiredDir, "provider.json");
45049
+ const providerJson = path19.join(desiredDir, "provider.json");
44825
45050
  if (!fs13.existsSync(providerJson)) {
44826
45051
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
44827
45052
  }
@@ -44844,13 +45069,13 @@ async (params) => {
44844
45069
  const refDir = ctx.findProviderDir(referenceType);
44845
45070
  if (!refDir || !fs13.existsSync(refDir)) return {};
44846
45071
  const referenceScripts = {};
44847
- const scriptsDir = path17.join(refDir, "scripts");
45072
+ const scriptsDir = path19.join(refDir, "scripts");
44848
45073
  const latestDir = getLatestScriptVersionDir(scriptsDir);
44849
45074
  if (!latestDir) return referenceScripts;
44850
45075
  for (const file2 of fs13.readdirSync(latestDir)) {
44851
45076
  if (!file2.endsWith(".js")) continue;
44852
45077
  try {
44853
- referenceScripts[file2] = fs13.readFileSync(path17.join(latestDir, file2), "utf-8");
45078
+ referenceScripts[file2] = fs13.readFileSync(path19.join(latestDir, file2), "utf-8");
44854
45079
  } catch {
44855
45080
  }
44856
45081
  }
@@ -44958,9 +45183,9 @@ async (params) => {
44958
45183
  });
44959
45184
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
44960
45185
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
44961
- const tmpDir = path17.join(os17.tmpdir(), "adhdev-autoimpl");
45186
+ const tmpDir = path19.join(os17.tmpdir(), "adhdev-autoimpl");
44962
45187
  if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
44963
- const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
45188
+ const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
44964
45189
  fs13.writeFileSync(promptFile, prompt, "utf-8");
44965
45190
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
44966
45191
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -45387,7 +45612,7 @@ async (params) => {
45387
45612
  setMode: "set_mode.js"
45388
45613
  };
45389
45614
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
45390
- const scriptsDir = path17.join(providerDir, "scripts");
45615
+ const scriptsDir = path19.join(providerDir, "scripts");
45391
45616
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
45392
45617
  if (latestScriptsDir) {
45393
45618
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -45398,7 +45623,7 @@ async (params) => {
45398
45623
  for (const file2 of fs13.readdirSync(latestScriptsDir)) {
45399
45624
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
45400
45625
  try {
45401
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
45626
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
45402
45627
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
45403
45628
  lines.push("```javascript");
45404
45629
  lines.push(content);
@@ -45415,7 +45640,7 @@ async (params) => {
45415
45640
  lines.push("");
45416
45641
  for (const file2 of refFiles) {
45417
45642
  try {
45418
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
45643
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
45419
45644
  lines.push(`### \`${file2}\` \u{1F512}`);
45420
45645
  lines.push("```javascript");
45421
45646
  lines.push(content);
@@ -45456,10 +45681,10 @@ async (params) => {
45456
45681
  lines.push("");
45457
45682
  }
45458
45683
  }
45459
- const docsDir = path17.join(providerDir, "../../docs");
45684
+ const docsDir = path19.join(providerDir, "../../docs");
45460
45685
  const loadGuide = (name) => {
45461
45686
  try {
45462
- const p = path17.join(docsDir, name);
45687
+ const p = path19.join(docsDir, name);
45463
45688
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
45464
45689
  } catch {
45465
45690
  }
@@ -45694,7 +45919,7 @@ async (params) => {
45694
45919
  parseApproval: "parse_approval.js"
45695
45920
  };
45696
45921
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
45697
- const scriptsDir = path17.join(providerDir, "scripts");
45922
+ const scriptsDir = path19.join(providerDir, "scripts");
45698
45923
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
45699
45924
  if (latestScriptsDir) {
45700
45925
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -45706,7 +45931,7 @@ async (params) => {
45706
45931
  if (!file2.endsWith(".js")) continue;
45707
45932
  if (!targetFileNames.has(file2)) continue;
45708
45933
  try {
45709
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
45934
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
45710
45935
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
45711
45936
  lines.push("```javascript");
45712
45937
  lines.push(content);
@@ -45722,7 +45947,7 @@ async (params) => {
45722
45947
  lines.push("");
45723
45948
  for (const file2 of refFiles) {
45724
45949
  try {
45725
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
45950
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
45726
45951
  lines.push(`### \`${file2}\` \u{1F512}`);
45727
45952
  lines.push("```javascript");
45728
45953
  lines.push(content);
@@ -45755,10 +45980,10 @@ async (params) => {
45755
45980
  lines.push("");
45756
45981
  }
45757
45982
  }
45758
- const docsDir = path17.join(providerDir, "../../docs");
45983
+ const docsDir = path19.join(providerDir, "../../docs");
45759
45984
  const loadGuide = (name) => {
45760
45985
  try {
45761
- const p = path17.join(docsDir, name);
45986
+ const p = path19.join(docsDir, name);
45762
45987
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
45763
45988
  } catch {
45764
45989
  }
@@ -46167,8 +46392,8 @@ data: ${JSON.stringify(msg.data)}
46167
46392
  }
46168
46393
  getEndpointList() {
46169
46394
  return this.routes.map((r) => {
46170
- const path19 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
46171
- return `${r.method.padEnd(5)} ${path19}`;
46395
+ const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
46396
+ return `${r.method.padEnd(5)} ${path21}`;
46172
46397
  });
46173
46398
  }
46174
46399
  async start(port = DEV_SERVER_PORT) {
@@ -46199,15 +46424,15 @@ data: ${JSON.stringify(msg.data)}
46199
46424
  this.json(res, 500, { error: e.message });
46200
46425
  }
46201
46426
  });
46202
- return new Promise((resolve9, reject) => {
46427
+ return new Promise((resolve12, reject) => {
46203
46428
  this.server.listen(port, "127.0.0.1", () => {
46204
46429
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
46205
- resolve9();
46430
+ resolve12();
46206
46431
  });
46207
46432
  this.server.on("error", (e) => {
46208
46433
  if (e.code === "EADDRINUSE") {
46209
46434
  this.log(`Port ${port} in use, skipping dev server`);
46210
- resolve9();
46435
+ resolve12();
46211
46436
  } else {
46212
46437
  reject(e);
46213
46438
  }
@@ -46290,20 +46515,20 @@ data: ${JSON.stringify(msg.data)}
46290
46515
  child.stderr?.on("data", (d) => {
46291
46516
  stderr += d.toString().slice(0, 2e3);
46292
46517
  });
46293
- await new Promise((resolve9) => {
46518
+ await new Promise((resolve12) => {
46294
46519
  const timer = setTimeout(() => {
46295
46520
  child.kill();
46296
- resolve9();
46521
+ resolve12();
46297
46522
  }, 3e3);
46298
46523
  child.on("exit", () => {
46299
46524
  clearTimeout(timer);
46300
- resolve9();
46525
+ resolve12();
46301
46526
  });
46302
46527
  child.stdout?.once("data", () => {
46303
46528
  setTimeout(() => {
46304
46529
  child.kill();
46305
46530
  clearTimeout(timer);
46306
- resolve9();
46531
+ resolve12();
46307
46532
  }, 500);
46308
46533
  });
46309
46534
  });
@@ -46450,12 +46675,12 @@ data: ${JSON.stringify(msg.data)}
46450
46675
  // ─── DevConsole SPA ───
46451
46676
  getConsoleDistDir() {
46452
46677
  const candidates = [
46453
- path18.resolve(__dirname, "../../web-devconsole/dist"),
46454
- path18.resolve(__dirname, "../../../web-devconsole/dist"),
46455
- path18.join(process.cwd(), "packages/web-devconsole/dist")
46678
+ path20.resolve(__dirname, "../../web-devconsole/dist"),
46679
+ path20.resolve(__dirname, "../../../web-devconsole/dist"),
46680
+ path20.join(process.cwd(), "packages/web-devconsole/dist")
46456
46681
  ];
46457
46682
  for (const dir of candidates) {
46458
- if (fs14.existsSync(path18.join(dir, "index.html"))) return dir;
46683
+ if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
46459
46684
  }
46460
46685
  return null;
46461
46686
  }
@@ -46465,7 +46690,7 @@ data: ${JSON.stringify(msg.data)}
46465
46690
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
46466
46691
  return;
46467
46692
  }
46468
- const htmlPath = path18.join(distDir, "index.html");
46693
+ const htmlPath = path20.join(distDir, "index.html");
46469
46694
  try {
46470
46695
  const html = fs14.readFileSync(htmlPath, "utf-8");
46471
46696
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -46490,15 +46715,15 @@ data: ${JSON.stringify(msg.data)}
46490
46715
  this.json(res, 404, { error: "Not found" });
46491
46716
  return;
46492
46717
  }
46493
- const safePath = path18.normalize(pathname).replace(/^\.\.\//, "");
46494
- const filePath = path18.join(distDir, safePath);
46718
+ const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
46719
+ const filePath = path20.join(distDir, safePath);
46495
46720
  if (!filePath.startsWith(distDir)) {
46496
46721
  this.json(res, 403, { error: "Forbidden" });
46497
46722
  return;
46498
46723
  }
46499
46724
  try {
46500
46725
  const content = fs14.readFileSync(filePath);
46501
- const ext = path18.extname(filePath);
46726
+ const ext = path20.extname(filePath);
46502
46727
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
46503
46728
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
46504
46729
  res.end(content);
@@ -46611,9 +46836,9 @@ data: ${JSON.stringify(msg.data)}
46611
46836
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
46612
46837
  if (entry.isDirectory()) {
46613
46838
  files.push({ path: rel, size: 0, type: "dir" });
46614
- scan(path18.join(d, entry.name), rel);
46839
+ scan(path20.join(d, entry.name), rel);
46615
46840
  } else {
46616
- const stat4 = fs14.statSync(path18.join(d, entry.name));
46841
+ const stat4 = fs14.statSync(path20.join(d, entry.name));
46617
46842
  files.push({ path: rel, size: stat4.size, type: "file" });
46618
46843
  }
46619
46844
  }
@@ -46636,7 +46861,7 @@ data: ${JSON.stringify(msg.data)}
46636
46861
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
46637
46862
  return;
46638
46863
  }
46639
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
46864
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
46640
46865
  if (!fullPath.startsWith(dir)) {
46641
46866
  this.json(res, 403, { error: "Forbidden" });
46642
46867
  return;
@@ -46661,14 +46886,14 @@ data: ${JSON.stringify(msg.data)}
46661
46886
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
46662
46887
  return;
46663
46888
  }
46664
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
46889
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
46665
46890
  if (!fullPath.startsWith(dir)) {
46666
46891
  this.json(res, 403, { error: "Forbidden" });
46667
46892
  return;
46668
46893
  }
46669
46894
  try {
46670
46895
  if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
46671
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
46896
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
46672
46897
  fs14.writeFileSync(fullPath, content, "utf-8");
46673
46898
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
46674
46899
  this.providerLoader.reload();
@@ -46685,7 +46910,7 @@ data: ${JSON.stringify(msg.data)}
46685
46910
  return;
46686
46911
  }
46687
46912
  for (const name of ["scripts.js", "provider.json"]) {
46688
- const p = path18.join(dir, name);
46913
+ const p = path20.join(dir, name);
46689
46914
  if (fs14.existsSync(p)) {
46690
46915
  const source = fs14.readFileSync(p, "utf-8");
46691
46916
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -46706,8 +46931,8 @@ data: ${JSON.stringify(msg.data)}
46706
46931
  this.json(res, 404, { error: `Provider not found: ${type}` });
46707
46932
  return;
46708
46933
  }
46709
- const target = fs14.existsSync(path18.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
46710
- const targetPath = path18.join(dir, target);
46934
+ const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
46935
+ const targetPath = path20.join(dir, target);
46711
46936
  try {
46712
46937
  if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
46713
46938
  fs14.writeFileSync(targetPath, source, "utf-8");
@@ -46812,14 +47037,14 @@ data: ${JSON.stringify(msg.data)}
46812
47037
  child.stderr?.on("data", (d) => {
46813
47038
  stderr += d.toString();
46814
47039
  });
46815
- await new Promise((resolve9) => {
47040
+ await new Promise((resolve12) => {
46816
47041
  const timer = setTimeout(() => {
46817
47042
  child.kill();
46818
- resolve9();
47043
+ resolve12();
46819
47044
  }, timeout);
46820
47045
  child.on("exit", () => {
46821
47046
  clearTimeout(timer);
46822
- resolve9();
47047
+ resolve12();
46823
47048
  });
46824
47049
  });
46825
47050
  const elapsed = Date.now() - start;
@@ -46867,7 +47092,7 @@ data: ${JSON.stringify(msg.data)}
46867
47092
  }
46868
47093
  let targetDir;
46869
47094
  targetDir = this.providerLoader.getUserProviderDir(category, type);
46870
- const jsonPath = path18.join(targetDir, "provider.json");
47095
+ const jsonPath = path20.join(targetDir, "provider.json");
46871
47096
  if (fs14.existsSync(jsonPath)) {
46872
47097
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
46873
47098
  return;
@@ -46879,8 +47104,8 @@ data: ${JSON.stringify(msg.data)}
46879
47104
  const createdFiles = ["provider.json"];
46880
47105
  if (result.files) {
46881
47106
  for (const [relPath, content] of Object.entries(result.files)) {
46882
- const fullPath = path18.join(targetDir, relPath);
46883
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
47107
+ const fullPath = path20.join(targetDir, relPath);
47108
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
46884
47109
  fs14.writeFileSync(fullPath, content, "utf-8");
46885
47110
  createdFiles.push(relPath);
46886
47111
  }
@@ -46933,22 +47158,22 @@ data: ${JSON.stringify(msg.data)}
46933
47158
  if (!fs14.existsSync(scriptsDir)) return null;
46934
47159
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
46935
47160
  try {
46936
- return fs14.statSync(path18.join(scriptsDir, d)).isDirectory();
47161
+ return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
46937
47162
  } catch {
46938
47163
  return false;
46939
47164
  }
46940
47165
  }).sort((a, b2) => b2.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
46941
47166
  if (versions.length === 0) return null;
46942
- return path18.join(scriptsDir, versions[0]);
47167
+ return path20.join(scriptsDir, versions[0]);
46943
47168
  }
46944
47169
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
46945
- const canonicalUserDir = path18.resolve(this.providerLoader.getUserProviderDir(category, type));
46946
- const desiredDir = requestedDir ? path18.resolve(requestedDir) : canonicalUserDir;
46947
- const upstreamRoot = path18.resolve(this.providerLoader.getUpstreamDir());
46948
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path18.sep}`)) {
47170
+ const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
47171
+ const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
47172
+ const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
47173
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
46949
47174
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
46950
47175
  }
46951
- if (path18.basename(desiredDir) !== type) {
47176
+ if (path20.basename(desiredDir) !== type) {
46952
47177
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
46953
47178
  }
46954
47179
  const sourceDir = this.findProviderDir(type);
@@ -46956,11 +47181,11 @@ data: ${JSON.stringify(msg.data)}
46956
47181
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
46957
47182
  }
46958
47183
  if (!fs14.existsSync(desiredDir)) {
46959
- fs14.mkdirSync(path18.dirname(desiredDir), { recursive: true });
47184
+ fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
46960
47185
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
46961
47186
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
46962
47187
  }
46963
- const providerJson = path18.join(desiredDir, "provider.json");
47188
+ const providerJson = path20.join(desiredDir, "provider.json");
46964
47189
  if (!fs14.existsSync(providerJson)) {
46965
47190
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
46966
47191
  }
@@ -47008,7 +47233,7 @@ data: ${JSON.stringify(msg.data)}
47008
47233
  setMode: "set_mode.js"
47009
47234
  };
47010
47235
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
47011
- const scriptsDir = path18.join(providerDir, "scripts");
47236
+ const scriptsDir = path20.join(providerDir, "scripts");
47012
47237
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
47013
47238
  if (latestScriptsDir) {
47014
47239
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -47019,7 +47244,7 @@ data: ${JSON.stringify(msg.data)}
47019
47244
  for (const file2 of fs14.readdirSync(latestScriptsDir)) {
47020
47245
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
47021
47246
  try {
47022
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
47247
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
47023
47248
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
47024
47249
  lines.push("```javascript");
47025
47250
  lines.push(content);
@@ -47036,7 +47261,7 @@ data: ${JSON.stringify(msg.data)}
47036
47261
  lines.push("");
47037
47262
  for (const file2 of refFiles) {
47038
47263
  try {
47039
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
47264
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
47040
47265
  lines.push(`### \`${file2}\` \u{1F512}`);
47041
47266
  lines.push("```javascript");
47042
47267
  lines.push(content);
@@ -47077,10 +47302,10 @@ data: ${JSON.stringify(msg.data)}
47077
47302
  lines.push("");
47078
47303
  }
47079
47304
  }
47080
- const docsDir = path18.join(providerDir, "../../docs");
47305
+ const docsDir = path20.join(providerDir, "../../docs");
47081
47306
  const loadGuide = (name) => {
47082
47307
  try {
47083
- const p = path18.join(docsDir, name);
47308
+ const p = path20.join(docsDir, name);
47084
47309
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
47085
47310
  } catch {
47086
47311
  }
@@ -47254,7 +47479,7 @@ data: ${JSON.stringify(msg.data)}
47254
47479
  parseApproval: "parse_approval.js"
47255
47480
  };
47256
47481
  const targetFileNames = new Set(functions.map((fn2) => funcToFile[fn2]).filter(Boolean));
47257
- const scriptsDir = path18.join(providerDir, "scripts");
47482
+ const scriptsDir = path20.join(providerDir, "scripts");
47258
47483
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
47259
47484
  if (latestScriptsDir) {
47260
47485
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -47266,7 +47491,7 @@ data: ${JSON.stringify(msg.data)}
47266
47491
  if (!file2.endsWith(".js")) continue;
47267
47492
  if (!targetFileNames.has(file2)) continue;
47268
47493
  try {
47269
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
47494
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
47270
47495
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
47271
47496
  lines.push("```javascript");
47272
47497
  lines.push(content);
@@ -47282,7 +47507,7 @@ data: ${JSON.stringify(msg.data)}
47282
47507
  lines.push("");
47283
47508
  for (const file2 of refFiles) {
47284
47509
  try {
47285
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
47510
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
47286
47511
  lines.push(`### \`${file2}\` \u{1F512}`);
47287
47512
  lines.push("```javascript");
47288
47513
  lines.push(content);
@@ -47315,10 +47540,10 @@ data: ${JSON.stringify(msg.data)}
47315
47540
  lines.push("");
47316
47541
  }
47317
47542
  }
47318
- const docsDir = path18.join(providerDir, "../../docs");
47543
+ const docsDir = path20.join(providerDir, "../../docs");
47319
47544
  const loadGuide = (name) => {
47320
47545
  try {
47321
- const p = path18.join(docsDir, name);
47546
+ const p = path20.join(docsDir, name);
47322
47547
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
47323
47548
  } catch {
47324
47549
  }
@@ -47494,14 +47719,14 @@ data: ${JSON.stringify(msg.data)}
47494
47719
  res.end(JSON.stringify(data, null, 2));
47495
47720
  }
47496
47721
  async readBody(req) {
47497
- return new Promise((resolve9) => {
47722
+ return new Promise((resolve12) => {
47498
47723
  let body = "";
47499
47724
  req.on("data", (chunk) => body += chunk);
47500
47725
  req.on("end", () => {
47501
47726
  try {
47502
- resolve9(JSON.parse(body));
47727
+ resolve12(JSON.parse(body));
47503
47728
  } catch {
47504
- resolve9({});
47729
+ resolve12({});
47505
47730
  }
47506
47731
  });
47507
47732
  });
@@ -47963,7 +48188,7 @@ data: ${JSON.stringify(msg.data)}
47963
48188
  const deadline = Date.now() + timeoutMs;
47964
48189
  while (Date.now() < deadline) {
47965
48190
  if (await canConnect(endpoint)) return;
47966
- await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
48191
+ await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
47967
48192
  }
47968
48193
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
47969
48194
  }
@@ -48117,10 +48342,10 @@ data: ${JSON.stringify(msg.data)}
48117
48342
  const buffer = Buffer.from(await res.arrayBuffer());
48118
48343
  const fs15 = await import("fs");
48119
48344
  fs15.writeFileSync(vsixPath, buffer);
48120
- return new Promise((resolve9) => {
48345
+ return new Promise((resolve12) => {
48121
48346
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
48122
48347
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
48123
- resolve9({
48348
+ resolve12({
48124
48349
  extensionId: extension.id,
48125
48350
  marketplaceId: extension.marketplaceId,
48126
48351
  success: !error48,
@@ -48133,11 +48358,11 @@ data: ${JSON.stringify(msg.data)}
48133
48358
  } catch (e) {
48134
48359
  }
48135
48360
  }
48136
- return new Promise((resolve9) => {
48361
+ return new Promise((resolve12) => {
48137
48362
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
48138
48363
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
48139
48364
  if (error48) {
48140
- resolve9({
48365
+ resolve12({
48141
48366
  extensionId: extension.id,
48142
48367
  marketplaceId: extension.marketplaceId,
48143
48368
  success: false,
@@ -48145,7 +48370,7 @@ data: ${JSON.stringify(msg.data)}
48145
48370
  error: stderr || error48.message
48146
48371
  });
48147
48372
  } else {
48148
- resolve9({
48373
+ resolve12({
48149
48374
  extensionId: extension.id,
48150
48375
  marketplaceId: extension.marketplaceId,
48151
48376
  success: true,
@@ -48277,13 +48502,32 @@ data: ${JSON.stringify(msg.data)}
48277
48502
  const detectedIdesRef = { value: [] };
48278
48503
  let agentStreamManager = null;
48279
48504
  let poller = null;
48505
+ const refreshProviderAvailability = async (providerType) => {
48506
+ const targetProvider = providerType ? providerLoader.getMeta(providerLoader.resolveAlias(providerType)) : null;
48507
+ const targetCategory = targetProvider?.category;
48508
+ if (!providerType || targetCategory === "cli" || targetCategory === "acp") {
48509
+ if (providerType && targetProvider) {
48510
+ const detected = await detectCLI(targetProvider.type, providerLoader, { includeVersion: false });
48511
+ providerLoader.setProviderAvailability(targetProvider.type, {
48512
+ installed: !!detected,
48513
+ detectedPath: detected?.path || null
48514
+ });
48515
+ } else {
48516
+ providerLoader.setCliDetectionResults(await detectCLIs(providerLoader, { includeVersion: false }), true);
48517
+ }
48518
+ }
48519
+ if (!providerType || targetCategory === "ide") {
48520
+ detectedIdesRef.value = await detectIDEs(providerLoader);
48521
+ providerLoader.setIdeDetectionResults(detectedIdesRef.value, true);
48522
+ }
48523
+ };
48280
48524
  const cliManager = new DaemonCliManager({
48281
48525
  ...config2.cliManagerDeps,
48282
48526
  getInstanceManager: () => instanceManager,
48283
48527
  getSessionRegistry: () => sessionRegistry
48284
48528
  }, providerLoader);
48285
48529
  LOG2.info("Init", "Detecting IDEs...");
48286
- detectedIdesRef.value = await detectIDEs();
48530
+ await refreshProviderAvailability();
48287
48531
  const installed = detectedIdesRef.value.filter((i) => i.installed);
48288
48532
  LOG2.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
48289
48533
  const cdpSetupContext = {
@@ -48323,7 +48567,11 @@ data: ${JSON.stringify(msg.data)}
48323
48567
  adapters: cliManager.adapters,
48324
48568
  providerLoader,
48325
48569
  instanceManager,
48326
- sessionRegistry
48570
+ sessionRegistry,
48571
+ onProviderSettingChanged: async (providerType) => {
48572
+ await refreshProviderAvailability(providerType);
48573
+ config2.onStatusChange?.();
48574
+ }
48327
48575
  });
48328
48576
  agentStreamManager = new DaemonAgentStreamManager(
48329
48577
  LOG2.forComponent("AgentStream").asLogFn(),