@adhdev/daemon-core 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
@@ -251,13 +251,13 @@ function getDaemonLogDir() {
251
251
  return LOG_DIR;
252
252
  }
253
253
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
254
- return path4.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
254
+ return path6.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
255
255
  }
256
256
  function checkDateRotation() {
257
257
  const today = getDateStr();
258
258
  if (today !== currentDate) {
259
259
  currentDate = today;
260
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
260
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
261
261
  cleanOldLogs();
262
262
  }
263
263
  }
@@ -271,7 +271,7 @@ function cleanOldLogs() {
271
271
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
272
272
  if (dateMatch && dateMatch[1] < cutoffStr) {
273
273
  try {
274
- fs2.unlinkSync(path4.join(LOG_DIR, file));
274
+ fs2.unlinkSync(path6.join(LOG_DIR, file));
275
275
  } catch {
276
276
  }
277
277
  }
@@ -388,17 +388,17 @@ function installGlobalInterceptor() {
388
388
  writeToFile(`Log file: ${currentLogFile}`);
389
389
  writeToFile(`Log level: ${currentLevel}`);
390
390
  }
391
- var fs2, path4, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
391
+ var fs2, path6, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
392
392
  var init_logger = __esm({
393
393
  "src/logging/logger.ts"() {
394
394
  "use strict";
395
395
  fs2 = __toESM(require("fs"));
396
- path4 = __toESM(require("path"));
396
+ path6 = __toESM(require("path"));
397
397
  os4 = __toESM(require("os"));
398
398
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
399
399
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
400
400
  currentLevel = "info";
401
- LOG_DIR = process.platform === "win32" ? path4.join(process.env.LOCALAPPDATA || process.env.APPDATA || path4.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path4.join(os4.homedir(), "Library", "Logs", "adhdev") : path4.join(os4.homedir(), ".local", "share", "adhdev", "logs");
401
+ LOG_DIR = process.platform === "win32" ? path6.join(process.env.LOCALAPPDATA || process.env.APPDATA || path6.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path6.join(os4.homedir(), "Library", "Logs", "adhdev") : path6.join(os4.homedir(), ".local", "share", "adhdev", "logs");
402
402
  MAX_LOG_SIZE = 5 * 1024 * 1024;
403
403
  MAX_LOG_DAYS = 7;
404
404
  try {
@@ -406,16 +406,16 @@ var init_logger = __esm({
406
406
  } catch {
407
407
  }
408
408
  currentDate = getDateStr();
409
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
409
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
410
410
  cleanOldLogs();
411
411
  try {
412
- const oldLog = path4.join(LOG_DIR, "daemon.log");
412
+ const oldLog = path6.join(LOG_DIR, "daemon.log");
413
413
  if (fs2.existsSync(oldLog)) {
414
414
  const stat = fs2.statSync(oldLog);
415
415
  const oldDate = stat.mtime.toISOString().slice(0, 10);
416
- fs2.renameSync(oldLog, path4.join(LOG_DIR, `daemon-${oldDate}.log`));
416
+ fs2.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
417
417
  }
418
- const oldLogBackup = path4.join(LOG_DIR, "daemon.log.old");
418
+ const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
419
419
  if (fs2.existsSync(oldLogBackup)) {
420
420
  fs2.unlinkSync(oldLogBackup);
421
421
  }
@@ -447,7 +447,7 @@ var init_logger = __esm({
447
447
  }
448
448
  };
449
449
  interceptorInstalled = false;
450
- LOG_PATH = path4.join(LOG_DIR, `daemon-${getDateStr()}.log`);
450
+ LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
451
451
  }
452
452
  });
453
453
 
@@ -872,16 +872,22 @@ function computeTerminalQueryTail(buffer) {
872
872
  return "";
873
873
  }
874
874
  function findBinary(name) {
875
+ const trimmed = String(name || "").trim();
876
+ if (!trimmed) return trimmed;
877
+ const expanded = trimmed.startsWith("~") ? path9.join(os8.homedir(), trimmed.slice(1)) : trimmed;
878
+ if (path9.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
879
+ return path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
880
+ }
875
881
  const isWin = os8.platform() === "win32";
876
882
  try {
877
- const cmd = isWin ? `where ${name}` : `which ${name}`;
883
+ const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
878
884
  return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
879
885
  } catch {
880
- return isWin ? `${name}.cmd` : name;
886
+ return isWin ? `${trimmed}.cmd` : trimmed;
881
887
  }
882
888
  }
883
889
  function isScriptBinary(binaryPath) {
884
- if (!path7.isAbsolute(binaryPath)) return false;
890
+ if (!path9.isAbsolute(binaryPath)) return false;
885
891
  try {
886
892
  const fs15 = require("fs");
887
893
  const resolved = fs15.realpathSync(binaryPath);
@@ -897,7 +903,7 @@ function isScriptBinary(binaryPath) {
897
903
  }
898
904
  }
899
905
  function looksLikeMachOOrElf(filePath) {
900
- if (!path7.isAbsolute(filePath)) return false;
906
+ if (!path9.isAbsolute(filePath)) return false;
901
907
  try {
902
908
  const fs15 = require("fs");
903
909
  const resolved = fs15.realpathSync(filePath);
@@ -1021,12 +1027,12 @@ function normalizeCliProviderForRuntime(raw) {
1021
1027
  }
1022
1028
  };
1023
1029
  }
1024
- var os8, path7, import_child_process4, buildCliSpawnEnv, ProviderCliAdapter;
1030
+ var os8, path9, import_child_process4, buildCliSpawnEnv, ProviderCliAdapter;
1025
1031
  var init_provider_cli_adapter = __esm({
1026
1032
  "src/cli-adapters/provider-cli-adapter.ts"() {
1027
1033
  "use strict";
1028
1034
  os8 = __toESM(require("os"));
1029
- path7 = __toESM(require("path"));
1035
+ path9 = __toESM(require("path"));
1030
1036
  import_child_process4 = require("child_process");
1031
1037
  init_logger();
1032
1038
  init_terminal_screen();
@@ -1381,16 +1387,17 @@ var init_provider_cli_adapter = __esm({
1381
1387
  async spawn() {
1382
1388
  if (this.ptyProcess) return;
1383
1389
  const { spawn: spawnConfig } = this.provider;
1384
- const binaryPath = findBinary(spawnConfig.command);
1390
+ const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
1391
+ const binaryPath = findBinary(configuredCommand);
1385
1392
  const isWin = os8.platform() === "win32";
1386
1393
  const allArgs = [...spawnConfig.args, ...this.extraArgs];
1387
1394
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1388
1395
  this.resetTraceSession();
1389
1396
  let shellCmd;
1390
1397
  let shellArgs;
1391
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1398
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1392
1399
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1393
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1400
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1394
1401
  const useShell = isWin ? useShellWin : useShellUnix;
1395
1402
  if (useShell) {
1396
1403
  if (!spawnConfig.shell && !isWin) {
@@ -1764,7 +1771,7 @@ var init_provider_cli_adapter = __esm({
1764
1771
  `[${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)}`
1765
1772
  );
1766
1773
  }
1767
- await new Promise((resolve9) => setTimeout(resolve9, 50));
1774
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
1768
1775
  }
1769
1776
  const finalScreenText = this.terminalScreen.getText() || "";
1770
1777
  LOG.warn(
@@ -2275,7 +2282,7 @@ ${data.message || ""}`.trim();
2275
2282
  const deadline = Date.now() + 1e4;
2276
2283
  while (this.startupParseGate && Date.now() < deadline) {
2277
2284
  this.resolveStartupState("send_wait");
2278
- await new Promise((resolve9) => setTimeout(resolve9, 50));
2285
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
2279
2286
  }
2280
2287
  }
2281
2288
  await this.waitForInteractivePrompt();
@@ -2500,17 +2507,17 @@ ${data.message || ""}`.trim();
2500
2507
  }
2501
2508
  }
2502
2509
  waitForStopped(timeoutMs) {
2503
- return new Promise((resolve9) => {
2510
+ return new Promise((resolve12) => {
2504
2511
  const startedAt = Date.now();
2505
2512
  const timer = setInterval(() => {
2506
2513
  if (!this.ptyProcess || this.currentStatus === "stopped") {
2507
2514
  clearInterval(timer);
2508
- resolve9(true);
2515
+ resolve12(true);
2509
2516
  return;
2510
2517
  }
2511
2518
  if (Date.now() - startedAt >= timeoutMs) {
2512
2519
  clearInterval(timer);
2513
- resolve9(false);
2520
+ resolve12(false);
2514
2521
  }
2515
2522
  }, 100);
2516
2523
  });
@@ -3209,6 +3216,7 @@ function resetState() {
3209
3216
  var import_child_process = require("child_process");
3210
3217
  var import_fs3 = require("fs");
3211
3218
  var import_os2 = require("os");
3219
+ var path4 = __toESM(require("path"));
3212
3220
  var BUILTIN_IDE_DEFINITIONS = [];
3213
3221
  var registeredIDEs = /* @__PURE__ */ new Map();
3214
3222
  function registerIDEDefinition(def) {
@@ -3225,9 +3233,16 @@ function getMergedDefinitions() {
3225
3233
  return [...merged.values()];
3226
3234
  }
3227
3235
  function findCliCommand(command) {
3236
+ const trimmed = String(command || "").trim();
3237
+ if (!trimmed) return null;
3238
+ if (path4.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
3239
+ const candidate = trimmed.startsWith("~") ? path4.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
3240
+ const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(candidate);
3241
+ return (0, import_fs3.existsSync)(resolved) ? resolved : null;
3242
+ }
3228
3243
  try {
3229
3244
  const result = (0, import_child_process.execSync)(
3230
- (0, import_os2.platform)() === "win32" ? `where ${command}` : `which ${command}`,
3245
+ (0, import_os2.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
3231
3246
  { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
3232
3247
  ).trim();
3233
3248
  return result.split("\n")[0] || null;
@@ -3250,23 +3265,23 @@ function getIdeVersion(cliCommand) {
3250
3265
  function checkPathExists(paths) {
3251
3266
  const home = (0, import_os2.homedir)();
3252
3267
  for (const p of paths) {
3253
- if (p.includes("*")) {
3268
+ const normalized = p.startsWith("~") ? path4.join(home, p.slice(1)) : p;
3269
+ if (normalized.includes("*")) {
3254
3270
  const username = home.split(/[\\/]/).pop() || "";
3255
- const resolved = p.replace("*", username);
3271
+ const resolved = normalized.replace("*", username);
3256
3272
  if ((0, import_fs3.existsSync)(resolved)) return resolved;
3257
3273
  } else {
3258
- if ((0, import_fs3.existsSync)(p)) return p;
3274
+ if ((0, import_fs3.existsSync)(normalized)) return normalized;
3259
3275
  }
3260
3276
  }
3261
3277
  return null;
3262
3278
  }
3263
- async function detectIDEs() {
3279
+ async function detectIDEs(providerLoader) {
3264
3280
  const os18 = (0, import_os2.platform)();
3265
3281
  const results = [];
3266
3282
  for (const def of getMergedDefinitions()) {
3267
- const cliPath = findCliCommand(def.cli);
3268
- const appPath = checkPathExists(def.paths[os18] || []);
3269
- const installed = !!(cliPath || appPath);
3283
+ const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
3284
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os18] || []) || []);
3270
3285
  let resolvedCli = cliPath;
3271
3286
  if (!resolvedCli && appPath && os18 === "darwin") {
3272
3287
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
@@ -3289,6 +3304,7 @@ async function detectIDEs() {
3289
3304
  }
3290
3305
  }
3291
3306
  }
3307
+ const installed = os18 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
3292
3308
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
3293
3309
  results.push({
3294
3310
  id: def.id,
@@ -3307,48 +3323,77 @@ async function detectIDEs() {
3307
3323
  // src/detection/cli-detector.ts
3308
3324
  var import_child_process2 = require("child_process");
3309
3325
  var os2 = __toESM(require("os"));
3326
+ var path5 = __toESM(require("path"));
3327
+ var import_fs4 = require("fs");
3310
3328
  function parseVersion(raw) {
3311
3329
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
3312
3330
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
3313
3331
  }
3332
+ function shellQuote(value) {
3333
+ if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
3334
+ return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
3335
+ }
3336
+ function expandHome(value) {
3337
+ const trimmed = value.trim();
3338
+ if (!trimmed.startsWith("~")) return trimmed;
3339
+ return path5.join(os2.homedir(), trimmed.slice(1));
3340
+ }
3341
+ function isExplicitCommandPath(command) {
3342
+ const trimmed = command.trim();
3343
+ return path5.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
3344
+ }
3345
+ function resolveCommandPath(command) {
3346
+ const trimmed = command.trim();
3347
+ if (!trimmed) return null;
3348
+ if (isExplicitCommandPath(trimmed)) {
3349
+ const expanded = expandHome(trimmed);
3350
+ const candidate = path5.isAbsolute(expanded) ? expanded : path5.resolve(expanded);
3351
+ return (0, import_fs4.existsSync)(candidate) ? candidate : null;
3352
+ }
3353
+ return null;
3354
+ }
3314
3355
  function execAsync(cmd, timeoutMs = 5e3) {
3315
- return new Promise((resolve9) => {
3356
+ return new Promise((resolve12) => {
3316
3357
  const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
3317
3358
  if (err || !stdout?.trim()) {
3318
- resolve9(null);
3359
+ resolve12(null);
3319
3360
  } else {
3320
- resolve9(stdout.trim());
3361
+ resolve12(stdout.trim());
3321
3362
  }
3322
3363
  });
3323
- child.on("error", () => resolve9(null));
3364
+ child.on("error", () => resolve12(null));
3324
3365
  });
3325
3366
  }
3326
- async function detectCLIs(providerLoader) {
3367
+ async function detectCLIs(providerLoader, options) {
3327
3368
  const platform9 = os2.platform();
3328
3369
  const whichCmd = platform9 === "win32" ? "where" : "which";
3370
+ const includeVersion = options?.includeVersion !== false;
3329
3371
  const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
3330
3372
  const results = await Promise.all(
3331
3373
  cliList.map(async (cli) => {
3332
3374
  try {
3333
- const pathResult = await execAsync(`${whichCmd} ${cli.command}`);
3375
+ const explicitPath = resolveCommandPath(cli.command);
3376
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
3334
3377
  if (!pathResult) return { ...cli, installed: false };
3335
- const firstPath = pathResult.split("\n")[0];
3378
+ const firstPath = explicitPath || pathResult.split("\n")[0];
3336
3379
  let version;
3337
- try {
3380
+ if (includeVersion) {
3338
3381
  const versionCommands = [
3339
- cli.versionCommand,
3340
- `${cli.command} --version`,
3341
- `${cli.command} -V`,
3342
- `${cli.command} -v`
3382
+ `"${firstPath}" --version`,
3383
+ `"${firstPath}" -V`,
3384
+ `"${firstPath}" -v`,
3385
+ cli.versionCommand
3343
3386
  ].filter((v) => !!v);
3344
- for (const versionCommand of versionCommands) {
3345
- const versionResult = await execAsync(versionCommand, 3e3);
3346
- if (versionResult) {
3347
- version = parseVersion(versionResult);
3348
- break;
3387
+ try {
3388
+ for (const versionCommand of versionCommands) {
3389
+ const versionResult = await execAsync(versionCommand, 3e3);
3390
+ if (versionResult) {
3391
+ version = parseVersion(versionResult);
3392
+ break;
3393
+ }
3349
3394
  }
3395
+ } catch {
3350
3396
  }
3351
- } catch {
3352
3397
  }
3353
3398
  return { ...cli, installed: true, version, path: firstPath };
3354
3399
  } catch {
@@ -3358,7 +3403,7 @@ async function detectCLIs(providerLoader) {
3358
3403
  );
3359
3404
  return results;
3360
3405
  }
3361
- async function detectCLI(cliId, providerLoader) {
3406
+ async function detectCLI(cliId, providerLoader, options) {
3362
3407
  const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
3363
3408
  if (providerLoader) {
3364
3409
  const cliList = providerLoader.getCliDetectionList();
@@ -3367,25 +3412,28 @@ async function detectCLI(cliId, providerLoader) {
3367
3412
  const platform9 = os2.platform();
3368
3413
  const whichCmd = platform9 === "win32" ? "where" : "which";
3369
3414
  try {
3370
- const pathResult = await execAsync(`${whichCmd} ${target.command}`);
3415
+ const explicitPath = resolveCommandPath(target.command);
3416
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
3371
3417
  if (!pathResult) return null;
3372
- const firstPath = pathResult.split("\n")[0];
3418
+ const firstPath = explicitPath || pathResult.split("\n")[0];
3373
3419
  let version;
3374
- try {
3420
+ if (options?.includeVersion !== false) {
3375
3421
  const versionCommands = [
3376
- target.versionCommand,
3377
- `${target.command} --version`,
3378
- `${target.command} -V`,
3379
- `${target.command} -v`
3422
+ `"${firstPath}" --version`,
3423
+ `"${firstPath}" -V`,
3424
+ `"${firstPath}" -v`,
3425
+ target.versionCommand
3380
3426
  ].filter((v) => !!v);
3381
- for (const versionCommand of versionCommands) {
3382
- const versionResult = await execAsync(versionCommand, 3e3);
3383
- if (versionResult) {
3384
- version = parseVersion(versionResult);
3385
- break;
3427
+ try {
3428
+ for (const versionCommand of versionCommands) {
3429
+ const versionResult = await execAsync(versionCommand, 3e3);
3430
+ if (versionResult) {
3431
+ version = parseVersion(versionResult);
3432
+ break;
3433
+ }
3386
3434
  }
3435
+ } catch {
3387
3436
  }
3388
- } catch {
3389
3437
  }
3390
3438
  return { ...target, installed: true, version, path: firstPath };
3391
3439
  } catch {
@@ -3393,7 +3441,7 @@ async function detectCLI(cliId, providerLoader) {
3393
3441
  }
3394
3442
  }
3395
3443
  }
3396
- const all = await detectCLIs(providerLoader);
3444
+ const all = await detectCLIs(providerLoader, options);
3397
3445
  return all.find((c) => c.id === resolvedId && c.installed) || null;
3398
3446
  }
3399
3447
 
@@ -3520,7 +3568,7 @@ var DaemonCdpManager = class {
3520
3568
  * Returns multiple entries if multiple IDE windows are open on same port
3521
3569
  */
3522
3570
  static listAllTargets(port) {
3523
- return new Promise((resolve9) => {
3571
+ return new Promise((resolve12) => {
3524
3572
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3525
3573
  let data = "";
3526
3574
  res.on("data", (chunk) => data += chunk.toString());
@@ -3536,16 +3584,16 @@ var DaemonCdpManager = class {
3536
3584
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
3537
3585
  );
3538
3586
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
3539
- resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
3587
+ resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
3540
3588
  } catch {
3541
- resolve9([]);
3589
+ resolve12([]);
3542
3590
  }
3543
3591
  });
3544
3592
  });
3545
- req.on("error", () => resolve9([]));
3593
+ req.on("error", () => resolve12([]));
3546
3594
  req.setTimeout(2e3, () => {
3547
3595
  req.destroy();
3548
- resolve9([]);
3596
+ resolve12([]);
3549
3597
  });
3550
3598
  });
3551
3599
  }
@@ -3585,7 +3633,7 @@ var DaemonCdpManager = class {
3585
3633
  }
3586
3634
  }
3587
3635
  findTargetOnPort(port) {
3588
- return new Promise((resolve9) => {
3636
+ return new Promise((resolve12) => {
3589
3637
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3590
3638
  let data = "";
3591
3639
  res.on("data", (chunk) => data += chunk.toString());
@@ -3596,7 +3644,7 @@ var DaemonCdpManager = class {
3596
3644
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
3597
3645
  );
3598
3646
  if (pages.length === 0) {
3599
- resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
3647
+ resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
3600
3648
  return;
3601
3649
  }
3602
3650
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -3606,24 +3654,24 @@ var DaemonCdpManager = class {
3606
3654
  const specific = list.find((t) => t.id === this._targetId);
3607
3655
  if (specific) {
3608
3656
  this._pageTitle = specific.title || "";
3609
- resolve9(specific);
3657
+ resolve12(specific);
3610
3658
  } else {
3611
3659
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
3612
- resolve9(null);
3660
+ resolve12(null);
3613
3661
  }
3614
3662
  return;
3615
3663
  }
3616
3664
  this._pageTitle = list[0]?.title || "";
3617
- resolve9(list[0]);
3665
+ resolve12(list[0]);
3618
3666
  } catch {
3619
- resolve9(null);
3667
+ resolve12(null);
3620
3668
  }
3621
3669
  });
3622
3670
  });
3623
- req.on("error", () => resolve9(null));
3671
+ req.on("error", () => resolve12(null));
3624
3672
  req.setTimeout(2e3, () => {
3625
3673
  req.destroy();
3626
- resolve9(null);
3674
+ resolve12(null);
3627
3675
  });
3628
3676
  });
3629
3677
  }
@@ -3634,7 +3682,7 @@ var DaemonCdpManager = class {
3634
3682
  this.extensionProviders = providers;
3635
3683
  }
3636
3684
  connectToTarget(wsUrl) {
3637
- return new Promise((resolve9) => {
3685
+ return new Promise((resolve12) => {
3638
3686
  this.ws = new import_ws.default(wsUrl);
3639
3687
  this.ws.on("open", async () => {
3640
3688
  this._connected = true;
@@ -3644,17 +3692,17 @@ var DaemonCdpManager = class {
3644
3692
  }
3645
3693
  this.connectBrowserWs().catch(() => {
3646
3694
  });
3647
- resolve9(true);
3695
+ resolve12(true);
3648
3696
  });
3649
3697
  this.ws.on("message", (data) => {
3650
3698
  try {
3651
3699
  const msg = JSON.parse(data.toString());
3652
3700
  if (msg.id && this.pending.has(msg.id)) {
3653
- const { resolve: resolve10, reject } = this.pending.get(msg.id);
3701
+ const { resolve: resolve13, reject } = this.pending.get(msg.id);
3654
3702
  this.pending.delete(msg.id);
3655
3703
  this.failureCount = 0;
3656
3704
  if (msg.error) reject(new Error(msg.error.message));
3657
- else resolve10(msg.result);
3705
+ else resolve13(msg.result);
3658
3706
  } else if (msg.method === "Runtime.executionContextCreated") {
3659
3707
  this.contexts.add(msg.params.context.id);
3660
3708
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -3677,7 +3725,7 @@ var DaemonCdpManager = class {
3677
3725
  this.ws.on("error", (err) => {
3678
3726
  this.log(`[CDP] WebSocket error: ${err.message}`);
3679
3727
  this._connected = false;
3680
- resolve9(false);
3728
+ resolve12(false);
3681
3729
  });
3682
3730
  });
3683
3731
  }
@@ -3691,7 +3739,7 @@ var DaemonCdpManager = class {
3691
3739
  return;
3692
3740
  }
3693
3741
  this.log(`[CDP] Connecting browser WS for target discovery...`);
3694
- await new Promise((resolve9, reject) => {
3742
+ await new Promise((resolve12, reject) => {
3695
3743
  this.browserWs = new import_ws.default(browserWsUrl);
3696
3744
  this.browserWs.on("open", async () => {
3697
3745
  this._browserConnected = true;
@@ -3701,16 +3749,16 @@ var DaemonCdpManager = class {
3701
3749
  } catch (e) {
3702
3750
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
3703
3751
  }
3704
- resolve9();
3752
+ resolve12();
3705
3753
  });
3706
3754
  this.browserWs.on("message", (data) => {
3707
3755
  try {
3708
3756
  const msg = JSON.parse(data.toString());
3709
3757
  if (msg.id && this.browserPending.has(msg.id)) {
3710
- const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
3758
+ const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
3711
3759
  this.browserPending.delete(msg.id);
3712
3760
  if (msg.error) reject2(new Error(msg.error.message));
3713
- else resolve10(msg.result);
3761
+ else resolve13(msg.result);
3714
3762
  }
3715
3763
  } catch {
3716
3764
  }
@@ -3730,31 +3778,31 @@ var DaemonCdpManager = class {
3730
3778
  }
3731
3779
  }
3732
3780
  getBrowserWsUrl() {
3733
- return new Promise((resolve9) => {
3781
+ return new Promise((resolve12) => {
3734
3782
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
3735
3783
  let data = "";
3736
3784
  res.on("data", (chunk) => data += chunk.toString());
3737
3785
  res.on("end", () => {
3738
3786
  try {
3739
3787
  const info = JSON.parse(data);
3740
- resolve9(info.webSocketDebuggerUrl || null);
3788
+ resolve12(info.webSocketDebuggerUrl || null);
3741
3789
  } catch {
3742
- resolve9(null);
3790
+ resolve12(null);
3743
3791
  }
3744
3792
  });
3745
3793
  });
3746
- req.on("error", () => resolve9(null));
3794
+ req.on("error", () => resolve12(null));
3747
3795
  req.setTimeout(3e3, () => {
3748
3796
  req.destroy();
3749
- resolve9(null);
3797
+ resolve12(null);
3750
3798
  });
3751
3799
  });
3752
3800
  }
3753
3801
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
3754
- return new Promise((resolve9, reject) => {
3802
+ return new Promise((resolve12, reject) => {
3755
3803
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
3756
3804
  const id = this.browserMsgId++;
3757
- this.browserPending.set(id, { resolve: resolve9, reject });
3805
+ this.browserPending.set(id, { resolve: resolve12, reject });
3758
3806
  this.browserWs.send(JSON.stringify({ id, method, params }));
3759
3807
  setTimeout(() => {
3760
3808
  if (this.browserPending.has(id)) {
@@ -3794,11 +3842,11 @@ var DaemonCdpManager = class {
3794
3842
  }
3795
3843
  // ─── CDP Protocol ────────────────────────────────────────
3796
3844
  sendInternal(method, params = {}, timeoutMs = 15e3) {
3797
- return new Promise((resolve9, reject) => {
3845
+ return new Promise((resolve12, reject) => {
3798
3846
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
3799
3847
  if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
3800
3848
  const id = this.msgId++;
3801
- this.pending.set(id, { resolve: resolve9, reject });
3849
+ this.pending.set(id, { resolve: resolve12, reject });
3802
3850
  this.ws.send(JSON.stringify({ id, method, params }));
3803
3851
  setTimeout(() => {
3804
3852
  if (this.pending.has(id)) {
@@ -4047,7 +4095,7 @@ var DaemonCdpManager = class {
4047
4095
  const browserWs = this.browserWs;
4048
4096
  let msgId = this.browserMsgId;
4049
4097
  const sendWs = (method, params = {}, sessionId) => {
4050
- return new Promise((resolve9, reject) => {
4098
+ return new Promise((resolve12, reject) => {
4051
4099
  const mid = msgId++;
4052
4100
  this.browserMsgId = msgId;
4053
4101
  const handler = (raw) => {
@@ -4056,7 +4104,7 @@ var DaemonCdpManager = class {
4056
4104
  if (msg.id === mid) {
4057
4105
  browserWs.removeListener("message", handler);
4058
4106
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
4059
- else resolve9(msg.result);
4107
+ else resolve12(msg.result);
4060
4108
  }
4061
4109
  } catch {
4062
4110
  }
@@ -4247,14 +4295,14 @@ var DaemonCdpManager = class {
4247
4295
  if (!ws || ws.readyState !== import_ws.default.OPEN) {
4248
4296
  throw new Error("CDP not connected");
4249
4297
  }
4250
- return new Promise((resolve9, reject) => {
4298
+ return new Promise((resolve12, reject) => {
4251
4299
  const id = getNextId();
4252
4300
  pendingMap.set(id, {
4253
4301
  resolve: (result) => {
4254
4302
  if (result?.result?.subtype === "error") {
4255
4303
  reject(new Error(result.result.description));
4256
4304
  } else {
4257
- resolve9(result?.result?.value);
4305
+ resolve12(result?.result?.value);
4258
4306
  }
4259
4307
  },
4260
4308
  reject
@@ -4286,10 +4334,10 @@ var DaemonCdpManager = class {
4286
4334
  throw new Error("CDP not connected");
4287
4335
  }
4288
4336
  const sendViaSession = (method, params = {}) => {
4289
- return new Promise((resolve9, reject) => {
4337
+ return new Promise((resolve12, reject) => {
4290
4338
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
4291
4339
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
4292
- pendingMap.set(id, { resolve: resolve9, reject });
4340
+ pendingMap.set(id, { resolve: resolve12, reject });
4293
4341
  ws.send(JSON.stringify({ id, sessionId, method, params }));
4294
4342
  setTimeout(() => {
4295
4343
  if (pendingMap.has(id)) {
@@ -4917,9 +4965,9 @@ function normalizeControlValue(value) {
4917
4965
 
4918
4966
  // src/config/chat-history.ts
4919
4967
  var fs3 = __toESM(require("fs"));
4920
- var path5 = __toESM(require("path"));
4968
+ var path7 = __toESM(require("path"));
4921
4969
  var os5 = __toESM(require("os"));
4922
- var HISTORY_DIR = path5.join(os5.homedir(), ".adhdev", "history");
4970
+ var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
4923
4971
  var RETAIN_DAYS = 30;
4924
4972
  var ChatHistoryWriter = class {
4925
4973
  /** Last seen message count per agent (deduplication) */
@@ -4964,11 +5012,11 @@ var ChatHistoryWriter = class {
4964
5012
  });
4965
5013
  }
4966
5014
  if (newMessages.length === 0) return;
4967
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
5015
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
4968
5016
  fs3.mkdirSync(dir, { recursive: true });
4969
5017
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4970
5018
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
4971
- const filePath = path5.join(dir, `${filePrefix}${date}.jsonl`);
5019
+ const filePath = path7.join(dir, `${filePrefix}${date}.jsonl`);
4972
5020
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
4973
5021
  fs3.appendFileSync(filePath, lines, "utf-8");
4974
5022
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
@@ -5022,14 +5070,14 @@ var ChatHistoryWriter = class {
5022
5070
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
5023
5071
  this.lastSeenCounts.delete(fromDedupKey);
5024
5072
  }
5025
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
5073
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
5026
5074
  if (!fs3.existsSync(dir)) return;
5027
5075
  const fromPrefix = `${this.sanitize(fromId)}_`;
5028
5076
  const toPrefix = `${this.sanitize(toId)}_`;
5029
5077
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
5030
5078
  for (const file of files) {
5031
- const sourcePath = path5.join(dir, file);
5032
- const targetPath = path5.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
5079
+ const sourcePath = path7.join(dir, file);
5080
+ const targetPath = path7.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
5033
5081
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
5034
5082
  const rewritten = sourceLines.map((line) => {
5035
5083
  try {
@@ -5070,10 +5118,10 @@ var ChatHistoryWriter = class {
5070
5118
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
5071
5119
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
5072
5120
  for (const dir of agentDirs) {
5073
- const dirPath = path5.join(HISTORY_DIR, dir.name);
5121
+ const dirPath = path7.join(HISTORY_DIR, dir.name);
5074
5122
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
5075
5123
  for (const file of files) {
5076
- const filePath = path5.join(dirPath, file);
5124
+ const filePath = path7.join(dirPath, file);
5077
5125
  const stat = fs3.statSync(filePath);
5078
5126
  if (stat.mtimeMs < cutoff) {
5079
5127
  fs3.unlinkSync(filePath);
@@ -5091,7 +5139,7 @@ var ChatHistoryWriter = class {
5091
5139
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
5092
5140
  try {
5093
5141
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
5094
- const dir = path5.join(HISTORY_DIR, sanitized);
5142
+ const dir = path7.join(HISTORY_DIR, sanitized);
5095
5143
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
5096
5144
  const sanitizedInstance = historySessionId?.replace(/[^a-zA-Z0-9_-]/g, "_");
5097
5145
  const files = fs3.readdirSync(dir).filter((f) => {
@@ -5105,7 +5153,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
5105
5153
  const needed = offset + limit + 1;
5106
5154
  for (const file of files) {
5107
5155
  if (allMessages.length >= needed) break;
5108
- const filePath = path5.join(dir, file);
5156
+ const filePath = path7.join(dir, file);
5109
5157
  const content = fs3.readFileSync(filePath, "utf-8");
5110
5158
  const lines = content.trim().split("\n").filter(Boolean);
5111
5159
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -5127,7 +5175,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
5127
5175
  function listSavedHistorySessions(agentType, options = {}) {
5128
5176
  try {
5129
5177
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
5130
- const dir = path5.join(HISTORY_DIR, sanitized);
5178
+ const dir = path7.join(HISTORY_DIR, sanitized);
5131
5179
  if (!fs3.existsSync(dir)) return { sessions: [], hasMore: false };
5132
5180
  const groupedFiles = /* @__PURE__ */ new Map();
5133
5181
  const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
@@ -5148,7 +5196,7 @@ function listSavedHistorySessions(agentType, options = {}) {
5148
5196
  let sessionTitle = "";
5149
5197
  let preview = "";
5150
5198
  for (const file of files.sort()) {
5151
- const filePath = path5.join(dir, file);
5199
+ const filePath = path7.join(dir, file);
5152
5200
  const content = fs3.readFileSync(filePath, "utf-8");
5153
5201
  const lines = content.split("\n").filter(Boolean);
5154
5202
  for (const line of lines) {
@@ -7323,6 +7371,14 @@ async function handleListChats(h, args) {
7323
7371
  } catch {
7324
7372
  }
7325
7373
  }
7374
+ if (parsed?.sessions && Array.isArray(parsed.sessions)) {
7375
+ LOG.info("Command", `[list_chats] OK: ${parsed.sessions.length} chats`);
7376
+ return { success: true, chats: parsed.sessions };
7377
+ }
7378
+ if (parsed?.chats && Array.isArray(parsed.chats)) {
7379
+ LOG.info("Command", `[list_chats] OK: ${parsed.chats.length} chats`);
7380
+ return { success: true, chats: parsed.chats };
7381
+ }
7326
7382
  if (Array.isArray(parsed)) {
7327
7383
  LOG.info("Command", `[list_chats] OK: ${parsed.length} chats`);
7328
7384
  return { success: true, chats: parsed };
@@ -7392,7 +7448,13 @@ async function handleSwitchChat(h, args) {
7392
7448
  } catch (e) {
7393
7449
  return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
7394
7450
  }
7395
- const script = h.getProviderScript("switchSession", { SESSION_ID: JSON.stringify(sessionId) }) || h.getProviderScript("switch_session", { SESSION_ID: JSON.stringify(sessionId) });
7451
+ const switchParams = {
7452
+ sessionId,
7453
+ title: sessionId,
7454
+ id: sessionId,
7455
+ SESSION_ID: JSON.stringify(sessionId)
7456
+ };
7457
+ const script = h.getProviderScript("switchSession", switchParams) || h.getProviderScript("switch_session", switchParams);
7396
7458
  if (!script) return { success: false, error: "switch_session script not available" };
7397
7459
  try {
7398
7460
  const raw = await cdp.evaluate(script, 15e3);
@@ -7471,8 +7533,8 @@ async function handleSetMode(h, args) {
7471
7533
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
7472
7534
  if (adapter) {
7473
7535
  const acpInstance = adapter._acpInstance;
7474
- if (acpInstance && typeof acpInstance.onEvent === "function") {
7475
- acpInstance.onEvent("set_mode", { mode });
7536
+ if (acpInstance && typeof acpInstance.setMode === "function") {
7537
+ await acpInstance.setMode(mode);
7476
7538
  return { success: true, mode };
7477
7539
  }
7478
7540
  }
@@ -7529,9 +7591,9 @@ async function handleChangeModel(h, args) {
7529
7591
  LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
7530
7592
  if (adapter) {
7531
7593
  const acpInstance = adapter._acpInstance;
7532
- if (acpInstance && typeof acpInstance.onEvent === "function") {
7533
- acpInstance.onEvent("change_model", { model });
7534
- LOG.info("Command", `[change_model] Dispatched change_model event to ACP instance`);
7594
+ if (acpInstance && typeof acpInstance.setConfigOption === "function") {
7595
+ await acpInstance.setConfigOption("model", model);
7596
+ LOG.info("Command", `[change_model] Updated ACP model to ${model}`);
7535
7597
  return { success: true, model };
7536
7598
  }
7537
7599
  }
@@ -7651,6 +7713,18 @@ async function handleResolveAction(h, args) {
7651
7713
  const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
7652
7714
  return { success: ok };
7653
7715
  }
7716
+ if (transport === "acp") {
7717
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
7718
+ const acpInstance = adapter?._acpInstance;
7719
+ if (!acpInstance) return { success: false, error: "ACP instance not found" };
7720
+ try {
7721
+ await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
7722
+ LOG.info("Command", `[resolveAction] ACP \u2192 ${action}`);
7723
+ return { success: true, action };
7724
+ } catch (e) {
7725
+ return { success: false, error: e?.message || "ACP resolve action failed" };
7726
+ }
7727
+ }
7654
7728
  if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
7655
7729
  const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
7656
7730
  if (script) {
@@ -7729,7 +7803,7 @@ async function handleResolveAction(h, args) {
7729
7803
 
7730
7804
  // src/commands/cdp-commands.ts
7731
7805
  var fs4 = __toESM(require("fs"));
7732
- var path6 = __toESM(require("path"));
7806
+ var path8 = __toESM(require("path"));
7733
7807
  var os6 = __toESM(require("os"));
7734
7808
  var KEY_TO_VK = {
7735
7809
  Backspace: 8,
@@ -7981,25 +8055,25 @@ function resolveSafePath(requestedPath) {
7981
8055
  const inputPath = rawPath || ".";
7982
8056
  const home = os6.homedir();
7983
8057
  if (inputPath.startsWith("~")) {
7984
- return path6.resolve(path6.join(home, inputPath.slice(1)));
8058
+ return path8.resolve(path8.join(home, inputPath.slice(1)));
7985
8059
  }
7986
8060
  if (process.platform === "win32") {
7987
8061
  const normalized = normalizeWindowsRequestedPath(inputPath);
7988
- if (path6.win32.isAbsolute(normalized)) {
7989
- return path6.win32.normalize(normalized);
8062
+ if (path8.win32.isAbsolute(normalized)) {
8063
+ return path8.win32.normalize(normalized);
7990
8064
  }
7991
- return path6.win32.resolve(normalized);
8065
+ return path8.win32.resolve(normalized);
7992
8066
  }
7993
- if (path6.isAbsolute(inputPath)) {
7994
- return path6.normalize(inputPath);
8067
+ if (path8.isAbsolute(inputPath)) {
8068
+ return path8.normalize(inputPath);
7995
8069
  }
7996
- return path6.resolve(inputPath);
8070
+ return path8.resolve(inputPath);
7997
8071
  }
7998
8072
  function listDirectoryEntriesSafe(dirPath) {
7999
8073
  const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
8000
8074
  const files = [];
8001
8075
  for (const entry of entries) {
8002
- const entryPath = path6.join(dirPath, entry.name);
8076
+ const entryPath = path8.join(dirPath, entry.name);
8003
8077
  try {
8004
8078
  if (entry.isDirectory()) {
8005
8079
  files.push({ name: entry.name, type: "directory" });
@@ -8038,7 +8112,7 @@ async function handleFileRead(h, args) {
8038
8112
  async function handleFileWrite(h, args) {
8039
8113
  try {
8040
8114
  const filePath = resolveSafePath(args?.path);
8041
- fs4.mkdirSync(path6.dirname(filePath), { recursive: true });
8115
+ fs4.mkdirSync(path8.dirname(filePath), { recursive: true });
8042
8116
  fs4.writeFileSync(filePath, args?.content || "", "utf-8");
8043
8117
  return { success: true, path: filePath };
8044
8118
  } catch (e) {
@@ -8126,7 +8200,7 @@ function handleGetProviderSettings(h, args) {
8126
8200
  }
8127
8201
  return { success: true, settings: allSettings, values: allValues };
8128
8202
  }
8129
- function handleSetProviderSetting(h, args) {
8203
+ async function handleSetProviderSetting(h, args) {
8130
8204
  const loader = h.ctx.providerLoader;
8131
8205
  const { providerType, key, value } = args || {};
8132
8206
  if (!providerType || !key || value === void 0) {
@@ -8139,6 +8213,7 @@ function handleSetProviderSetting(h, args) {
8139
8213
  const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
8140
8214
  LOG.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
8141
8215
  }
8216
+ await h.ctx.onProviderSettingChanged?.(providerType, key, value);
8142
8217
  return { success: true, providerType, key, value };
8143
8218
  }
8144
8219
  return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
@@ -8176,10 +8251,10 @@ function getCliScriptCommand(payload) {
8176
8251
  }
8177
8252
  const command = payload.command;
8178
8253
  if (!command || typeof command !== "object") return null;
8179
- if (command.type !== "send_message") return null;
8254
+ if (command.type !== "send_message" && command.type !== "pty_write") return null;
8180
8255
  const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
8181
8256
  if (!text) return null;
8182
- return { type: "send_message", text };
8257
+ return { type: command.type, text };
8183
8258
  }
8184
8259
  function applyProviderPatch(h, args, payload) {
8185
8260
  if (!payload || typeof payload !== "object") return;
@@ -8220,6 +8295,8 @@ async function executeProviderScript(h, args, scriptName) {
8220
8295
  const cliCommand = getCliScriptCommand(parsed.payload);
8221
8296
  if (cliCommand?.type === "send_message" && cliCommand.text) {
8222
8297
  await adapter.sendMessage(cliCommand.text);
8298
+ } else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
8299
+ adapter.writeRaw(cliCommand.text + "\r");
8223
8300
  }
8224
8301
  applyProviderPatch(h, args, parsed.payload);
8225
8302
  return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
@@ -8898,7 +8975,7 @@ var DaemonCommandHandler = class {
8898
8975
  try {
8899
8976
  const http3 = await import("http");
8900
8977
  const postData = JSON.stringify(body);
8901
- const result = await new Promise((resolve9, reject) => {
8978
+ const result = await new Promise((resolve12, reject) => {
8902
8979
  const req = http3.request({
8903
8980
  hostname: "127.0.0.1",
8904
8981
  port: 19280,
@@ -8910,9 +8987,9 @@ var DaemonCommandHandler = class {
8910
8987
  res.on("data", (chunk) => data += chunk);
8911
8988
  res.on("end", () => {
8912
8989
  try {
8913
- resolve9(JSON.parse(data));
8990
+ resolve12(JSON.parse(data));
8914
8991
  } catch {
8915
- resolve9({ raw: data });
8992
+ resolve12({ raw: data });
8916
8993
  }
8917
8994
  });
8918
8995
  });
@@ -8930,15 +9007,15 @@ var DaemonCommandHandler = class {
8930
9007
  if (!providerType) return { success: false, error: "providerType required" };
8931
9008
  try {
8932
9009
  const http3 = await import("http");
8933
- const result = await new Promise((resolve9, reject) => {
9010
+ const result = await new Promise((resolve12, reject) => {
8934
9011
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
8935
9012
  let data = "";
8936
9013
  res.on("data", (chunk) => data += chunk);
8937
9014
  res.on("end", () => {
8938
9015
  try {
8939
- resolve9(JSON.parse(data));
9016
+ resolve12(JSON.parse(data));
8940
9017
  } catch {
8941
- resolve9({ raw: data });
9018
+ resolve12({ raw: data });
8942
9019
  }
8943
9020
  });
8944
9021
  }).on("error", reject);
@@ -8952,7 +9029,7 @@ var DaemonCommandHandler = class {
8952
9029
  try {
8953
9030
  const http3 = await import("http");
8954
9031
  const postData = JSON.stringify(args || {});
8955
- const result = await new Promise((resolve9, reject) => {
9032
+ const result = await new Promise((resolve12, reject) => {
8956
9033
  const req = http3.request({
8957
9034
  hostname: "127.0.0.1",
8958
9035
  port: 19280,
@@ -8964,9 +9041,9 @@ var DaemonCommandHandler = class {
8964
9041
  res.on("data", (chunk) => data += chunk);
8965
9042
  res.on("end", () => {
8966
9043
  try {
8967
- resolve9(JSON.parse(data));
9044
+ resolve12(JSON.parse(data));
8968
9045
  } catch {
8969
- resolve9({ raw: data });
9046
+ resolve12({ raw: data });
8970
9047
  }
8971
9048
  });
8972
9049
  });
@@ -8983,7 +9060,7 @@ var DaemonCommandHandler = class {
8983
9060
 
8984
9061
  // src/commands/cli-manager.ts
8985
9062
  var os10 = __toESM(require("os"));
8986
- var path9 = __toESM(require("path"));
9063
+ var path11 = __toESM(require("path"));
8987
9064
  var crypto4 = __toESM(require("crypto"));
8988
9065
  var import_chalk = __toESM(require("chalk"));
8989
9066
  init_provider_cli_adapter();
@@ -8991,7 +9068,7 @@ init_config();
8991
9068
 
8992
9069
  // src/providers/cli-provider-instance.ts
8993
9070
  var os9 = __toESM(require("os"));
8994
- var path8 = __toESM(require("path"));
9071
+ var path10 = __toESM(require("path"));
8995
9072
  var crypto3 = __toESM(require("crypto"));
8996
9073
  var fs5 = __toESM(require("fs"));
8997
9074
  var import_node_module = require("module");
@@ -9000,7 +9077,7 @@ init_logger();
9000
9077
  var CachedDatabaseSync = null;
9001
9078
  function getDatabaseSync() {
9002
9079
  if (CachedDatabaseSync) return CachedDatabaseSync;
9003
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path8.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
9080
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
9004
9081
  const sqliteModule = requireFn(`node:${"sqlite"}`);
9005
9082
  CachedDatabaseSync = sqliteModule.DatabaseSync;
9006
9083
  if (!CachedDatabaseSync) {
@@ -9829,8 +9906,9 @@ var AcpProviderInstance = class {
9829
9906
  async setConfigOption(category, value) {
9830
9907
  const opt = this.configOptions.find((c) => c.category === category);
9831
9908
  if (!opt) {
9832
- this.log.warn(`[${this.type}] No config option for category: ${category}`);
9833
- return;
9909
+ const message = `[${this.type}] No config option for category: ${category}`;
9910
+ this.log.warn(message);
9911
+ throw new Error(message);
9834
9912
  }
9835
9913
  if (this.useStaticConfig) {
9836
9914
  opt.currentValue = value;
@@ -9842,8 +9920,9 @@ var AcpProviderInstance = class {
9842
9920
  return;
9843
9921
  }
9844
9922
  if (!this.connection || !this.sessionId) {
9845
- this.log.warn(`[${this.type}] Cannot set config: no active connection/session`);
9846
- return;
9923
+ const message = `[${this.type}] Cannot set config: no active connection/session`;
9924
+ this.log.warn(message);
9925
+ throw new Error(message);
9847
9926
  }
9848
9927
  try {
9849
9928
  this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
@@ -9857,7 +9936,9 @@ var AcpProviderInstance = class {
9857
9936
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
9858
9937
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
9859
9938
  } catch (e) {
9860
- this.log.warn(`[${this.type}] set_config_option failed: ${e?.message}`);
9939
+ const message = e?.message || "Unknown ACP config error";
9940
+ this.log.warn(`[${this.type}] set_config_option failed: ${message}`);
9941
+ throw new Error(message);
9861
9942
  }
9862
9943
  }
9863
9944
  async setMode(modeId) {
@@ -9873,8 +9954,9 @@ var AcpProviderInstance = class {
9873
9954
  return;
9874
9955
  }
9875
9956
  if (!this.connection || !this.sessionId) {
9876
- this.log.warn(`[${this.type}] Cannot set mode: no active connection/session`);
9877
- return;
9957
+ const message = `[${this.type}] Cannot set mode: no active connection/session`;
9958
+ this.log.warn(message);
9959
+ throw new Error(message);
9878
9960
  }
9879
9961
  try {
9880
9962
  await this.connection.setSessionMode({
@@ -9884,7 +9966,9 @@ var AcpProviderInstance = class {
9884
9966
  this.currentMode = modeId;
9885
9967
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
9886
9968
  } catch (e) {
9887
- this.log.warn(`[${this.type}] set_mode failed: ${e?.message}`);
9969
+ const message = e?.message || "Unknown ACP mode error";
9970
+ this.log.warn(`[${this.type}] set_mode failed: ${message}`);
9971
+ throw new Error(message);
9888
9972
  }
9889
9973
  }
9890
9974
  /** Static config: kill process and restart with new args */
@@ -9932,7 +10016,7 @@ var AcpProviderInstance = class {
9932
10016
  if (!spawnConfig) {
9933
10017
  throw new Error(`[ACP:${this.type}] No spawn config defined`);
9934
10018
  }
9935
- const command = spawnConfig.command;
10019
+ const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
9936
10020
  let baseArgs = spawnConfig.args || [];
9937
10021
  if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
9938
10022
  baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
@@ -10048,13 +10132,13 @@ var AcpProviderInstance = class {
10048
10132
  }
10049
10133
  this.currentStatus = "waiting_approval";
10050
10134
  this.detectStatusTransition();
10051
- const approved = await new Promise((resolve9) => {
10052
- this.permissionResolvers.push(resolve9);
10135
+ const approved = await new Promise((resolve12) => {
10136
+ this.permissionResolvers.push(resolve12);
10053
10137
  setTimeout(() => {
10054
- const idx = this.permissionResolvers.indexOf(resolve9);
10138
+ const idx = this.permissionResolvers.indexOf(resolve12);
10055
10139
  if (idx >= 0) {
10056
10140
  this.permissionResolvers.splice(idx, 1);
10057
- resolve9(false);
10141
+ resolve12(false);
10058
10142
  }
10059
10143
  }, 3e5);
10060
10144
  });
@@ -10761,7 +10845,7 @@ var DaemonCliManager = class {
10761
10845
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
10762
10846
  const trimmed = (workingDir || "").trim();
10763
10847
  if (!trimmed) throw new Error("working directory required");
10764
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path9.resolve(trimmed);
10848
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path11.resolve(trimmed);
10765
10849
  const normalizedType = this.providerLoader.resolveAlias(cliType);
10766
10850
  const provider = this.providerLoader.getByAlias(cliType);
10767
10851
  const key = crypto4.randomUUID();
@@ -10848,10 +10932,10 @@ ${installInfo}`
10848
10932
  if (!cliInfo) {
10849
10933
  const installHint = provider?.install || "";
10850
10934
  const displayName = provider?.displayName || provider?.name || cliType;
10851
- const spawnCmd = provider?.spawn?.command || cliType;
10935
+ const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
10852
10936
  throw new Error(
10853
10937
  `${displayName} is not installed.
10854
- Command '${spawnCmd}' not found on PATH.
10938
+ Command '${spawnCmd}' is not available.
10855
10939
  ` + (installHint ? `
10856
10940
  ${installHint}
10857
10941
  ` : "") + `
@@ -11211,16 +11295,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
11211
11295
  var import_child_process6 = require("child_process");
11212
11296
  var net = __toESM(require("net"));
11213
11297
  var os12 = __toESM(require("os"));
11214
- var path11 = __toESM(require("path"));
11298
+ var path13 = __toESM(require("path"));
11215
11299
 
11216
11300
  // src/providers/provider-loader.ts
11217
11301
  var fs6 = __toESM(require("fs"));
11218
- var path10 = __toESM(require("path"));
11302
+ var path12 = __toESM(require("path"));
11219
11303
  var os11 = __toESM(require("os"));
11220
11304
  var chokidar = __toESM(require("chokidar"));
11221
11305
  init_logger();
11222
11306
  var ProviderLoader = class _ProviderLoader {
11223
11307
  providers = /* @__PURE__ */ new Map();
11308
+ providerAvailability = /* @__PURE__ */ new Map();
11224
11309
  userDir;
11225
11310
  upstreamDir;
11226
11311
  disableUpstream;
@@ -11236,12 +11321,12 @@ var ProviderLoader = class _ProviderLoader {
11236
11321
  static META_FILE = ".meta.json";
11237
11322
  constructor(options) {
11238
11323
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
11239
- const defaultProvidersDir = path10.join(os11.homedir(), ".adhdev", "providers");
11324
+ const defaultProvidersDir = path12.join(os11.homedir(), ".adhdev", "providers");
11240
11325
  if (options?.userDir) {
11241
11326
  this.userDir = options.userDir;
11242
11327
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
11243
11328
  } else {
11244
- const localRepoPath = path10.resolve(__dirname, "../../../../../adhdev-providers");
11329
+ const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
11245
11330
  if (fs6.existsSync(localRepoPath)) {
11246
11331
  this.userDir = localRepoPath;
11247
11332
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -11250,7 +11335,7 @@ var ProviderLoader = class _ProviderLoader {
11250
11335
  this.log(`Using default user providers directory: ${this.userDir}`);
11251
11336
  }
11252
11337
  }
11253
- this.upstreamDir = path10.join(defaultProvidersDir, ".upstream");
11338
+ this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
11254
11339
  this.disableUpstream = options?.disableUpstream ?? false;
11255
11340
  }
11256
11341
  log(msg) {
@@ -11280,7 +11365,7 @@ var ProviderLoader = class _ProviderLoader {
11280
11365
  * Canonical provider directory shape for a given root.
11281
11366
  */
11282
11367
  getProviderDir(root, category, type) {
11283
- return path10.join(root, category, type);
11368
+ return path12.join(root, category, type);
11284
11369
  }
11285
11370
  /**
11286
11371
  * Canonical user override directory for a provider.
@@ -11307,7 +11392,7 @@ var ProviderLoader = class _ProviderLoader {
11307
11392
  resolveProviderFile(type, ...segments) {
11308
11393
  const dir = this.findProviderDirInternal(type);
11309
11394
  if (!dir) return null;
11310
- return path10.join(dir, ...segments);
11395
+ return path12.join(dir, ...segments);
11311
11396
  }
11312
11397
  /**
11313
11398
  * Load all providers (3-tier priority)
@@ -11318,6 +11403,7 @@ var ProviderLoader = class _ProviderLoader {
11318
11403
  */
11319
11404
  loadAll() {
11320
11405
  this.providers.clear();
11406
+ this.providerAvailability.clear();
11321
11407
  let upstreamCount = 0;
11322
11408
  if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
11323
11409
  upstreamCount = this.loadDir(this.upstreamDir);
@@ -11345,7 +11431,7 @@ var ProviderLoader = class _ProviderLoader {
11345
11431
  if (!fs6.existsSync(this.upstreamDir)) return false;
11346
11432
  try {
11347
11433
  return fs6.readdirSync(this.upstreamDir).some(
11348
- (d) => fs6.statSync(path10.join(this.upstreamDir, d)).isDirectory()
11434
+ (d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
11349
11435
  );
11350
11436
  } catch {
11351
11437
  return false;
@@ -11388,11 +11474,12 @@ var ProviderLoader = class _ProviderLoader {
11388
11474
  if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
11389
11475
  const verCmdConfig = p.versionCommand;
11390
11476
  const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
11477
+ const command = this.getSpawnCommand(p.type, p.spawn.command);
11391
11478
  result.push({
11392
11479
  id: p.type,
11393
11480
  displayName: p.displayName || p.name,
11394
11481
  icon: p.icon || "\u{1F527}",
11395
- command: p.spawn.command,
11482
+ command,
11396
11483
  category: p.category,
11397
11484
  ...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
11398
11485
  });
@@ -11521,6 +11608,71 @@ var ProviderLoader = class _ProviderLoader {
11521
11608
  getAvailableIdeTypes() {
11522
11609
  return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
11523
11610
  }
11611
+ getSpawnCommand(type, fallback) {
11612
+ const override = this.getOptionalStringSetting(type, "executablePath");
11613
+ if (override) return override;
11614
+ return fallback || this.providers.get(type)?.spawn?.command || type;
11615
+ }
11616
+ getIdeCliCommand(type, fallback) {
11617
+ const override = this.getOptionalStringSetting(type, "cliPathOverride");
11618
+ if (override) return override;
11619
+ return fallback || this.providers.get(type)?.cli || null;
11620
+ }
11621
+ getIdePathCandidates(type, fallback) {
11622
+ const override = this.getOptionalStringSetting(type, "appPathOverride");
11623
+ if (override) return [override];
11624
+ if (fallback && fallback.length > 0) return fallback;
11625
+ const osPaths = this.providers.get(type)?.paths?.[process.platform];
11626
+ return Array.isArray(osPaths) ? [...osPaths] : [];
11627
+ }
11628
+ setProviderAvailability(type, state) {
11629
+ this.providerAvailability.set(type, {
11630
+ installed: !!state.installed,
11631
+ detectedPath: state.detectedPath ?? null
11632
+ });
11633
+ }
11634
+ setCliDetectionResults(results, replace = true) {
11635
+ if (replace) {
11636
+ for (const provider of this.providers.values()) {
11637
+ if (provider.category === "cli" || provider.category === "acp") {
11638
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
11639
+ }
11640
+ }
11641
+ }
11642
+ for (const result of results) {
11643
+ this.setProviderAvailability(result.id, {
11644
+ installed: !!result.installed,
11645
+ detectedPath: result.path || null
11646
+ });
11647
+ }
11648
+ }
11649
+ setIdeDetectionResults(results, replace = true) {
11650
+ if (replace) {
11651
+ for (const provider of this.providers.values()) {
11652
+ if (provider.category === "ide") {
11653
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
11654
+ }
11655
+ }
11656
+ }
11657
+ for (const result of results) {
11658
+ this.setProviderAvailability(result.id, {
11659
+ installed: !!result.installed,
11660
+ detectedPath: result.cliCommand || result.path || null
11661
+ });
11662
+ }
11663
+ }
11664
+ getAvailableProviderInfos() {
11665
+ return this.getAll().map((provider) => {
11666
+ const availability = this.providerAvailability.get(provider.type);
11667
+ return {
11668
+ ...provider,
11669
+ ...availability ? {
11670
+ installed: availability.installed,
11671
+ detectedPath: availability.detectedPath
11672
+ } : {}
11673
+ };
11674
+ });
11675
+ }
11524
11676
  /**
11525
11677
  * Register IDE providers to core/detector registry
11526
11678
  * → Enables detectIDEs() to detect provider.js-based IDEs
@@ -11595,8 +11747,8 @@ var ProviderLoader = class _ProviderLoader {
11595
11747
  resolved._resolvedScriptDir = entry.scriptDir;
11596
11748
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
11597
11749
  if (providerDir) {
11598
- const fullDir = path10.join(providerDir, entry.scriptDir);
11599
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11750
+ const fullDir = path12.join(providerDir, entry.scriptDir);
11751
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11600
11752
  }
11601
11753
  matched = true;
11602
11754
  }
@@ -11611,8 +11763,8 @@ var ProviderLoader = class _ProviderLoader {
11611
11763
  resolved._resolvedScriptDir = base.defaultScriptDir;
11612
11764
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
11613
11765
  if (providerDir) {
11614
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
11615
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11766
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
11767
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11616
11768
  }
11617
11769
  }
11618
11770
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -11629,8 +11781,8 @@ var ProviderLoader = class _ProviderLoader {
11629
11781
  resolved._resolvedScriptDir = dirOverride;
11630
11782
  resolved._resolvedScriptsSource = `versions:${range}`;
11631
11783
  if (providerDir) {
11632
- const fullDir = path10.join(providerDir, dirOverride);
11633
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11784
+ const fullDir = path12.join(providerDir, dirOverride);
11785
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11634
11786
  }
11635
11787
  }
11636
11788
  } else if (override.scripts) {
@@ -11646,8 +11798,8 @@ var ProviderLoader = class _ProviderLoader {
11646
11798
  resolved._resolvedScriptDir = base.defaultScriptDir;
11647
11799
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
11648
11800
  if (providerDir) {
11649
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
11650
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11801
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
11802
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11651
11803
  }
11652
11804
  }
11653
11805
  }
@@ -11672,14 +11824,14 @@ var ProviderLoader = class _ProviderLoader {
11672
11824
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
11673
11825
  return null;
11674
11826
  }
11675
- const dir = path10.join(providerDir, scriptDir);
11827
+ const dir = path12.join(providerDir, scriptDir);
11676
11828
  if (!fs6.existsSync(dir)) {
11677
11829
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
11678
11830
  return null;
11679
11831
  }
11680
11832
  const cached = this.scriptsCache.get(dir);
11681
11833
  if (cached) return cached;
11682
- const scriptsJs = path10.join(dir, "scripts.js");
11834
+ const scriptsJs = path12.join(dir, "scripts.js");
11683
11835
  if (fs6.existsSync(scriptsJs)) {
11684
11836
  try {
11685
11837
  delete require.cache[require.resolve(scriptsJs)];
@@ -11721,7 +11873,7 @@ var ProviderLoader = class _ProviderLoader {
11721
11873
  return;
11722
11874
  }
11723
11875
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
11724
- this.log(`File changed: ${path10.basename(filePath)}, reloading...`);
11876
+ this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
11725
11877
  this.reload();
11726
11878
  }
11727
11879
  };
@@ -11776,7 +11928,7 @@ var ProviderLoader = class _ProviderLoader {
11776
11928
  }
11777
11929
  const https = require("https");
11778
11930
  const { execSync: execSync7 } = require("child_process");
11779
- const metaPath = path10.join(this.upstreamDir, _ProviderLoader.META_FILE);
11931
+ const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
11780
11932
  let prevEtag = "";
11781
11933
  let prevTimestamp = 0;
11782
11934
  try {
@@ -11793,7 +11945,7 @@ var ProviderLoader = class _ProviderLoader {
11793
11945
  return { updated: false };
11794
11946
  }
11795
11947
  try {
11796
- const etag = await new Promise((resolve9, reject) => {
11948
+ const etag = await new Promise((resolve12, reject) => {
11797
11949
  const options = {
11798
11950
  method: "HEAD",
11799
11951
  hostname: "github.com",
@@ -11811,7 +11963,7 @@ var ProviderLoader = class _ProviderLoader {
11811
11963
  headers: { "User-Agent": "adhdev-launcher" },
11812
11964
  timeout: 1e4
11813
11965
  }, (res2) => {
11814
- resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
11966
+ resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
11815
11967
  });
11816
11968
  req2.on("error", reject);
11817
11969
  req2.on("timeout", () => {
@@ -11820,7 +11972,7 @@ var ProviderLoader = class _ProviderLoader {
11820
11972
  });
11821
11973
  req2.end();
11822
11974
  } else {
11823
- resolve9(res.headers.etag || res.headers["last-modified"] || "");
11975
+ resolve12(res.headers.etag || res.headers["last-modified"] || "");
11824
11976
  }
11825
11977
  });
11826
11978
  req.on("error", reject);
@@ -11836,17 +11988,17 @@ var ProviderLoader = class _ProviderLoader {
11836
11988
  return { updated: false };
11837
11989
  }
11838
11990
  this.log("Downloading latest providers from GitHub...");
11839
- const tmpTar = path10.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
11840
- const tmpExtract = path10.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
11991
+ const tmpTar = path12.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
11992
+ const tmpExtract = path12.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
11841
11993
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
11842
11994
  fs6.mkdirSync(tmpExtract, { recursive: true });
11843
11995
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
11844
11996
  const extracted = fs6.readdirSync(tmpExtract);
11845
11997
  const rootDir = extracted.find(
11846
- (d) => fs6.statSync(path10.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
11998
+ (d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
11847
11999
  );
11848
12000
  if (!rootDir) throw new Error("Unexpected tarball structure");
11849
- const sourceDir = path10.join(tmpExtract, rootDir);
12001
+ const sourceDir = path12.join(tmpExtract, rootDir);
11850
12002
  const backupDir = this.upstreamDir + ".bak";
11851
12003
  if (fs6.existsSync(this.upstreamDir)) {
11852
12004
  if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
@@ -11884,7 +12036,7 @@ var ProviderLoader = class _ProviderLoader {
11884
12036
  downloadFile(url, destPath) {
11885
12037
  const https = require("https");
11886
12038
  const http3 = require("http");
11887
- return new Promise((resolve9, reject) => {
12039
+ return new Promise((resolve12, reject) => {
11888
12040
  const doRequest = (reqUrl, redirectCount = 0) => {
11889
12041
  if (redirectCount > 5) {
11890
12042
  reject(new Error("Too many redirects"));
@@ -11904,7 +12056,7 @@ var ProviderLoader = class _ProviderLoader {
11904
12056
  res.pipe(ws);
11905
12057
  ws.on("finish", () => {
11906
12058
  ws.close();
11907
- resolve9();
12059
+ resolve12();
11908
12060
  });
11909
12061
  ws.on("error", reject);
11910
12062
  });
@@ -11921,8 +12073,8 @@ var ProviderLoader = class _ProviderLoader {
11921
12073
  copyDirRecursive(src, dest) {
11922
12074
  fs6.mkdirSync(dest, { recursive: true });
11923
12075
  for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
11924
- const srcPath = path10.join(src, entry.name);
11925
- const destPath = path10.join(dest, entry.name);
12076
+ const srcPath = path12.join(src, entry.name);
12077
+ const destPath = path12.join(dest, entry.name);
11926
12078
  if (entry.isDirectory()) {
11927
12079
  this.copyDirRecursive(srcPath, destPath);
11928
12080
  } else {
@@ -11933,7 +12085,7 @@ var ProviderLoader = class _ProviderLoader {
11933
12085
  /** .meta.json save */
11934
12086
  writeMeta(metaPath, etag, timestamp) {
11935
12087
  try {
11936
- fs6.mkdirSync(path10.dirname(metaPath), { recursive: true });
12088
+ fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
11937
12089
  fs6.writeFileSync(metaPath, JSON.stringify({
11938
12090
  etag,
11939
12091
  timestamp,
@@ -11950,7 +12102,7 @@ var ProviderLoader = class _ProviderLoader {
11950
12102
  const scan = (d) => {
11951
12103
  try {
11952
12104
  for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
11953
- if (entry.isDirectory()) scan(path10.join(d, entry.name));
12105
+ if (entry.isDirectory()) scan(path12.join(d, entry.name));
11954
12106
  else if (entry.name === "provider.json") count++;
11955
12107
  }
11956
12108
  } catch {
@@ -11964,9 +12116,8 @@ var ProviderLoader = class _ProviderLoader {
11964
12116
  * Get public settings schema for a provider (for dashboard UI rendering)
11965
12117
  */
11966
12118
  getPublicSettings(type) {
11967
- const provider = this.providers.get(type);
11968
- if (!provider?.settings) return [];
11969
- return Object.entries(provider.settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
12119
+ const settings = this.getSettingsSchema(type);
12120
+ return Object.entries(settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
11970
12121
  }
11971
12122
  /**
11972
12123
  * Get public settings schema for all providers
@@ -11983,8 +12134,7 @@ var ProviderLoader = class _ProviderLoader {
11983
12134
  * Resolved setting value for a provider (default + user override)
11984
12135
  */
11985
12136
  getSettingValue(type, key) {
11986
- const provider = this.providers.get(type);
11987
- const schemaDef = provider?.settings?.[key];
12137
+ const schemaDef = this.getSettingsSchema(type)[key];
11988
12138
  const defaultVal = schemaDef ? schemaDef.default : void 0;
11989
12139
  try {
11990
12140
  const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
@@ -11999,10 +12149,9 @@ var ProviderLoader = class _ProviderLoader {
11999
12149
  * All resolved settings for a provider (default + user override)
12000
12150
  */
12001
12151
  getSettings(type) {
12002
- const provider = this.providers.get(type);
12003
- if (!provider?.settings) return {};
12152
+ const settings = this.getSettingsSchema(type);
12004
12153
  const result = {};
12005
- for (const [key, def] of Object.entries(provider.settings)) {
12154
+ for (const [key] of Object.entries(settings)) {
12006
12155
  result[key] = this.getSettingValue(type, key);
12007
12156
  }
12008
12157
  return result;
@@ -12011,11 +12160,11 @@ var ProviderLoader = class _ProviderLoader {
12011
12160
  * Save provider setting value (writes to config.json)
12012
12161
  */
12013
12162
  setSetting(type, key, value) {
12014
- const provider = this.providers.get(type);
12015
- const schemaDef = provider?.settings?.[key];
12163
+ const schemaDef = this.getSettingsSchema(type)[key];
12016
12164
  if (!schemaDef) return false;
12017
12165
  if (!schemaDef.public) return false;
12018
12166
  if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
12167
+ if (schemaDef.type === "string" && typeof value !== "string") return false;
12019
12168
  if (schemaDef.type === "number") {
12020
12169
  if (typeof value !== "number") return false;
12021
12170
  if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
@@ -12036,6 +12185,53 @@ var ProviderLoader = class _ProviderLoader {
12036
12185
  return false;
12037
12186
  }
12038
12187
  }
12188
+ getOptionalStringSetting(type, key) {
12189
+ const value = this.getSettingValue(type, key);
12190
+ if (typeof value !== "string") return null;
12191
+ const trimmed = value.trim();
12192
+ return trimmed ? trimmed : null;
12193
+ }
12194
+ getSettingsSchema(type) {
12195
+ const provider = this.providers.get(type);
12196
+ if (!provider) return {};
12197
+ return {
12198
+ ...this.getSyntheticSettings(type, provider),
12199
+ ...provider.settings || {}
12200
+ };
12201
+ }
12202
+ getSyntheticSettings(type, provider) {
12203
+ const result = {};
12204
+ if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
12205
+ result.executablePath = {
12206
+ type: "string",
12207
+ default: "",
12208
+ public: true,
12209
+ label: "Executable path",
12210
+ description: "Optional absolute path for this provider binary. Leave blank to use the default PATH lookup."
12211
+ };
12212
+ }
12213
+ if (provider.category === "ide") {
12214
+ if (provider.cli && !provider.settings?.cliPathOverride) {
12215
+ result.cliPathOverride = {
12216
+ type: "string",
12217
+ default: "",
12218
+ public: true,
12219
+ label: "CLI path override",
12220
+ description: "Optional absolute path for the IDE CLI launcher. Leave blank to use the detected default."
12221
+ };
12222
+ }
12223
+ if (provider.paths && !provider.settings?.appPathOverride) {
12224
+ result.appPathOverride = {
12225
+ type: "string",
12226
+ default: "",
12227
+ public: true,
12228
+ label: "App path override",
12229
+ description: "Optional absolute path for the IDE app bundle or executable. Leave blank to use the default install locations."
12230
+ };
12231
+ }
12232
+ }
12233
+ return result;
12234
+ }
12039
12235
  // ─── Private ───────────────────────────────────
12040
12236
  /**
12041
12237
  * Find the on-disk directory for a provider by type.
@@ -12049,17 +12245,17 @@ var ProviderLoader = class _ProviderLoader {
12049
12245
  for (const root of searchRoots) {
12050
12246
  if (!fs6.existsSync(root)) continue;
12051
12247
  const candidate = this.getProviderDir(root, cat, type);
12052
- if (fs6.existsSync(path10.join(candidate, "provider.json"))) return candidate;
12053
- const catDir = path10.join(root, cat);
12248
+ if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
12249
+ const catDir = path12.join(root, cat);
12054
12250
  if (fs6.existsSync(catDir)) {
12055
12251
  try {
12056
12252
  for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
12057
12253
  if (!entry.isDirectory()) continue;
12058
- const jsonPath = path10.join(catDir, entry.name, "provider.json");
12254
+ const jsonPath = path12.join(catDir, entry.name, "provider.json");
12059
12255
  if (fs6.existsSync(jsonPath)) {
12060
12256
  try {
12061
12257
  const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
12062
- if (data.type === type) return path10.join(catDir, entry.name);
12258
+ if (data.type === type) return path12.join(catDir, entry.name);
12063
12259
  } catch {
12064
12260
  }
12065
12261
  }
@@ -12076,7 +12272,7 @@ var ProviderLoader = class _ProviderLoader {
12076
12272
  * (template substitution is NOT applied here — scripts.js handles that)
12077
12273
  */
12078
12274
  buildScriptWrappersFromDir(dir) {
12079
- const scriptsJs = path10.join(dir, "scripts.js");
12275
+ const scriptsJs = path12.join(dir, "scripts.js");
12080
12276
  if (fs6.existsSync(scriptsJs)) {
12081
12277
  try {
12082
12278
  delete require.cache[require.resolve(scriptsJs)];
@@ -12090,7 +12286,7 @@ var ProviderLoader = class _ProviderLoader {
12090
12286
  for (const file of fs6.readdirSync(dir)) {
12091
12287
  if (!file.endsWith(".js")) continue;
12092
12288
  const scriptName = toCamel(file.replace(".js", ""));
12093
- const filePath = path10.join(dir, file);
12289
+ const filePath = path12.join(dir, file);
12094
12290
  result[scriptName] = (...args) => {
12095
12291
  try {
12096
12292
  let content = fs6.readFileSync(filePath, "utf-8");
@@ -12150,7 +12346,7 @@ var ProviderLoader = class _ProviderLoader {
12150
12346
  }
12151
12347
  const hasJson = entries.some((e) => e.name === "provider.json");
12152
12348
  if (hasJson) {
12153
- const jsonPath = path10.join(d, "provider.json");
12349
+ const jsonPath = path12.join(d, "provider.json");
12154
12350
  try {
12155
12351
  const raw = fs6.readFileSync(jsonPath, "utf-8");
12156
12352
  const mod = JSON.parse(raw);
@@ -12163,7 +12359,7 @@ var ProviderLoader = class _ProviderLoader {
12163
12359
  delete mod.extensionIdPattern_flags;
12164
12360
  }
12165
12361
  const hasCompatibility = Array.isArray(mod.compatibility);
12166
- const scriptsPath = path10.join(d, "scripts.js");
12362
+ const scriptsPath = path12.join(d, "scripts.js");
12167
12363
  if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
12168
12364
  try {
12169
12365
  delete require.cache[require.resolve(scriptsPath)];
@@ -12189,7 +12385,7 @@ var ProviderLoader = class _ProviderLoader {
12189
12385
  if (!entry.isDirectory()) continue;
12190
12386
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
12191
12387
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
12192
- scan(path10.join(d, entry.name));
12388
+ scan(path12.join(d, entry.name));
12193
12389
  }
12194
12390
  }
12195
12391
  };
@@ -12285,17 +12481,17 @@ async function findFreePort(ports) {
12285
12481
  throw new Error("No free port found");
12286
12482
  }
12287
12483
  function checkPortFree(port) {
12288
- return new Promise((resolve9) => {
12484
+ return new Promise((resolve12) => {
12289
12485
  const server = net.createServer();
12290
12486
  server.unref();
12291
- server.on("error", () => resolve9(false));
12487
+ server.on("error", () => resolve12(false));
12292
12488
  server.listen(port, "127.0.0.1", () => {
12293
- server.close(() => resolve9(true));
12489
+ server.close(() => resolve12(true));
12294
12490
  });
12295
12491
  });
12296
12492
  }
12297
12493
  async function isCdpActive(port) {
12298
- return new Promise((resolve9) => {
12494
+ return new Promise((resolve12) => {
12299
12495
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
12300
12496
  timeout: 2e3
12301
12497
  }, (res) => {
@@ -12304,16 +12500,16 @@ async function isCdpActive(port) {
12304
12500
  res.on("end", () => {
12305
12501
  try {
12306
12502
  const info = JSON.parse(data);
12307
- resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
12503
+ resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
12308
12504
  } catch {
12309
- resolve9(false);
12505
+ resolve12(false);
12310
12506
  }
12311
12507
  });
12312
12508
  });
12313
- req.on("error", () => resolve9(false));
12509
+ req.on("error", () => resolve12(false));
12314
12510
  req.on("timeout", () => {
12315
12511
  req.destroy();
12316
- resolve9(false);
12512
+ resolve12(false);
12317
12513
  });
12318
12514
  });
12319
12515
  }
@@ -12447,8 +12643,8 @@ function detectCurrentWorkspace(ideId) {
12447
12643
  const appNameMap = getMacAppIdentifiers();
12448
12644
  const appName = appNameMap[ideId];
12449
12645
  if (appName) {
12450
- const storagePath = path11.join(
12451
- process.env.APPDATA || path11.join(os12.homedir(), "AppData", "Roaming"),
12646
+ const storagePath = path13.join(
12647
+ process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
12452
12648
  appName,
12453
12649
  "storage.json"
12454
12650
  );
@@ -12472,7 +12668,7 @@ function detectCurrentWorkspace(ideId) {
12472
12668
  async function launchWithCdp(options = {}) {
12473
12669
  const platform9 = os12.platform();
12474
12670
  let targetIde;
12475
- const ides = await detectIDEs();
12671
+ const ides = await detectIDEs(getProviderLoader());
12476
12672
  if (options.ideId) {
12477
12673
  targetIde = ides.find((i) => i.id === options.ideId && i.installed);
12478
12674
  if (!targetIde) {
@@ -12626,9 +12822,9 @@ init_logger();
12626
12822
 
12627
12823
  // src/logging/command-log.ts
12628
12824
  var fs7 = __toESM(require("fs"));
12629
- var path12 = __toESM(require("path"));
12825
+ var path14 = __toESM(require("path"));
12630
12826
  var os13 = __toESM(require("os"));
12631
- 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");
12827
+ 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");
12632
12828
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
12633
12829
  var MAX_DAYS = 7;
12634
12830
  try {
@@ -12666,13 +12862,13 @@ function getDateStr2() {
12666
12862
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
12667
12863
  }
12668
12864
  var currentDate2 = getDateStr2();
12669
- var currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12865
+ var currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12670
12866
  var writeCount2 = 0;
12671
12867
  function checkRotation() {
12672
12868
  const today = getDateStr2();
12673
12869
  if (today !== currentDate2) {
12674
12870
  currentDate2 = today;
12675
- currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12871
+ currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12676
12872
  cleanOldFiles();
12677
12873
  }
12678
12874
  }
@@ -12686,7 +12882,7 @@ function cleanOldFiles() {
12686
12882
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
12687
12883
  if (dateMatch && dateMatch[1] < cutoffStr) {
12688
12884
  try {
12689
- fs7.unlinkSync(path12.join(LOG_DIR2, file));
12885
+ fs7.unlinkSync(path14.join(LOG_DIR2, file));
12690
12886
  } catch {
12691
12887
  }
12692
12888
  }
@@ -12778,12 +12974,15 @@ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
12778
12974
  }));
12779
12975
  }
12780
12976
  function buildAvailableProviders(providerLoader) {
12781
- return providerLoader.getAll().map((provider) => ({
12977
+ const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
12978
+ return providers.map((provider) => ({
12782
12979
  type: provider.type,
12783
12980
  name: provider.displayName || provider.type,
12784
12981
  displayName: provider.displayName || provider.type,
12785
12982
  icon: provider.icon || "\u{1F4BB}",
12786
- category: provider.category
12983
+ category: provider.category,
12984
+ ...provider.installed !== void 0 ? { installed: provider.installed } : {},
12985
+ ...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
12787
12986
  }));
12788
12987
  }
12789
12988
  function parseMessageTime(value) {
@@ -12911,13 +13110,13 @@ var import_child_process7 = require("child_process");
12911
13110
  var import_child_process8 = require("child_process");
12912
13111
  var fs8 = __toESM(require("fs"));
12913
13112
  var os15 = __toESM(require("os"));
12914
- var path13 = __toESM(require("path"));
13113
+ var path15 = __toESM(require("path"));
12915
13114
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
12916
13115
  function getUpgradeLogPath() {
12917
13116
  const home = os15.homedir();
12918
- const dir = path13.join(home, ".adhdev");
13117
+ const dir = path15.join(home, ".adhdev");
12919
13118
  fs8.mkdirSync(dir, { recursive: true });
12920
- return path13.join(dir, "daemon-upgrade.log");
13119
+ return path15.join(dir, "daemon-upgrade.log");
12921
13120
  }
12922
13121
  function appendUpgradeLog(message) {
12923
13122
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -12950,14 +13149,14 @@ async function waitForPidExit(pid, timeoutMs) {
12950
13149
  while (Date.now() - start < timeoutMs) {
12951
13150
  try {
12952
13151
  process.kill(pid, 0);
12953
- await new Promise((resolve9) => setTimeout(resolve9, 250));
13152
+ await new Promise((resolve12) => setTimeout(resolve12, 250));
12954
13153
  } catch {
12955
13154
  return;
12956
13155
  }
12957
13156
  }
12958
13157
  }
12959
13158
  function stopSessionHostProcesses(appName) {
12960
- const pidFile = path13.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
13159
+ const pidFile = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
12961
13160
  try {
12962
13161
  if (fs8.existsSync(pidFile)) {
12963
13162
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
@@ -12986,7 +13185,7 @@ function stopSessionHostProcesses(appName) {
12986
13185
  }
12987
13186
  }
12988
13187
  function removeDaemonPidFile() {
12989
- const pidFile = path13.join(os15.homedir(), ".adhdev", "daemon.pid");
13188
+ const pidFile = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
12990
13189
  try {
12991
13190
  fs8.unlinkSync(pidFile);
12992
13191
  } catch {
@@ -12997,7 +13196,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
12997
13196
  const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
12998
13197
  if (!npmRoot) return;
12999
13198
  const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
13000
- const binDir = process.platform === "win32" ? npmPrefix : path13.join(npmPrefix, "bin");
13199
+ const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
13001
13200
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
13002
13201
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
13003
13202
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -13005,25 +13204,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
13005
13204
  }
13006
13205
  if (pkgName.startsWith("@")) {
13007
13206
  const [scope, name] = pkgName.split("/");
13008
- const scopeDir = path13.join(npmRoot, scope);
13207
+ const scopeDir = path15.join(npmRoot, scope);
13009
13208
  if (!fs8.existsSync(scopeDir)) return;
13010
13209
  for (const entry of fs8.readdirSync(scopeDir)) {
13011
13210
  if (!entry.startsWith(`.${name}-`)) continue;
13012
- fs8.rmSync(path13.join(scopeDir, entry), { recursive: true, force: true });
13013
- appendUpgradeLog(`Removed stale scoped staging dir: ${path13.join(scopeDir, entry)}`);
13211
+ fs8.rmSync(path15.join(scopeDir, entry), { recursive: true, force: true });
13212
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
13014
13213
  }
13015
13214
  } else {
13016
13215
  for (const entry of fs8.readdirSync(npmRoot)) {
13017
13216
  if (!entry.startsWith(`.${pkgName}-`)) continue;
13018
- fs8.rmSync(path13.join(npmRoot, entry), { recursive: true, force: true });
13019
- appendUpgradeLog(`Removed stale staging dir: ${path13.join(npmRoot, entry)}`);
13217
+ fs8.rmSync(path15.join(npmRoot, entry), { recursive: true, force: true });
13218
+ appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
13020
13219
  }
13021
13220
  }
13022
13221
  if (fs8.existsSync(binDir)) {
13023
13222
  for (const entry of fs8.readdirSync(binDir)) {
13024
13223
  if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
13025
- fs8.rmSync(path13.join(binDir, entry), { recursive: true, force: true });
13026
- appendUpgradeLog(`Removed stale bin staging entry: ${path13.join(binDir, entry)}`);
13224
+ fs8.rmSync(path15.join(binDir, entry), { recursive: true, force: true });
13225
+ appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, entry)}`);
13027
13226
  }
13028
13227
  }
13029
13228
  }
@@ -13065,7 +13264,7 @@ async function runDaemonUpgradeHelper(payload) {
13065
13264
  appendUpgradeLog(installOutput.trim());
13066
13265
  }
13067
13266
  if (process.platform === "win32") {
13068
- await new Promise((resolve9) => setTimeout(resolve9, 500));
13267
+ await new Promise((resolve12) => setTimeout(resolve12, 500));
13069
13268
  cleanupStaleGlobalInstallDirs(payload.packageName);
13070
13269
  appendUpgradeLog("Post-install staging cleanup complete");
13071
13270
  }
@@ -13343,6 +13542,12 @@ var DaemonCommandRouter = class {
13343
13542
  if (!ideType) throw new Error("ideType required");
13344
13543
  const killProcess = args?.killProcess !== false;
13345
13544
  await this.stopIde(ideType, killProcess);
13545
+ try {
13546
+ const results = await detectIDEs(this.deps.providerLoader);
13547
+ this.deps.detectedIdes.value = results;
13548
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
13549
+ } catch {
13550
+ }
13346
13551
  return { success: true, ideType, stopped: true, processKilled: killProcess };
13347
13552
  }
13348
13553
  // ─── IDE restart ───
@@ -13385,6 +13590,12 @@ var DaemonCommandRouter = class {
13385
13590
  }
13386
13591
  }
13387
13592
  this.deps.onIdeConnected?.();
13593
+ try {
13594
+ const results = await detectIDEs(this.deps.providerLoader);
13595
+ this.deps.detectedIdes.value = results;
13596
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
13597
+ } catch {
13598
+ }
13388
13599
  if (result.success && resolvedWorkspace) {
13389
13600
  try {
13390
13601
  const next = appendRecentActivity(loadState(), {
@@ -13412,8 +13623,9 @@ var DaemonCommandRouter = class {
13412
13623
  }
13413
13624
  // ─── Detect IDEs ───
13414
13625
  case "detect_ides": {
13415
- const results = await detectIDEs();
13626
+ const results = await detectIDEs(this.deps.providerLoader);
13416
13627
  this.deps.detectedIdes.value = results;
13628
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
13417
13629
  return { success: true, detectedInfo: results };
13418
13630
  }
13419
13631
  // ─── Set User Name ───
@@ -13927,7 +14139,10 @@ var ProviderStreamAdapter = class {
13927
14139
  const raw = await evaluate(script, 1e4);
13928
14140
  const data = typeof raw === "string" ? JSON.parse(raw) : raw;
13929
14141
  if (data?.error) return [];
13930
- return Array.isArray(data) ? data : [];
14142
+ if (Array.isArray(data)) return data;
14143
+ if (Array.isArray(data?.sessions)) return data.sessions;
14144
+ if (Array.isArray(data?.chats)) return data.chats;
14145
+ return [];
13931
14146
  } catch {
13932
14147
  return [];
13933
14148
  }
@@ -13935,7 +14150,17 @@ var ProviderStreamAdapter = class {
13935
14150
  async switchSession(evaluate, sessionId) {
13936
14151
  const script = this.callScript("switchSession", sessionId);
13937
14152
  if (!script) return false;
13938
- return await evaluate(script, 1e4) === true;
14153
+ const raw = await evaluate(script, 1e4);
14154
+ const data = this.parseMaybeJson(raw);
14155
+ if (data === true) return true;
14156
+ if (typeof data === "string") {
14157
+ const normalized = data.trim().toLowerCase();
14158
+ return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
14159
+ }
14160
+ if (data && typeof data === "object") {
14161
+ return data.switched === true || data.success === true || data.ok === true;
14162
+ }
14163
+ return false;
13939
14164
  }
13940
14165
  async focusEditor(evaluate) {
13941
14166
  const script = this.callScript("focusEditor");
@@ -14625,11 +14850,11 @@ var ProviderInstanceManager = class {
14625
14850
 
14626
14851
  // src/providers/version-archive.ts
14627
14852
  var fs10 = __toESM(require("fs"));
14628
- var path14 = __toESM(require("path"));
14853
+ var path16 = __toESM(require("path"));
14629
14854
  var os16 = __toESM(require("os"));
14630
14855
  var import_child_process9 = require("child_process");
14631
14856
  var import_os3 = require("os");
14632
- var ARCHIVE_PATH = path14.join(os16.homedir(), ".adhdev", "version-history.json");
14857
+ var ARCHIVE_PATH = path16.join(os16.homedir(), ".adhdev", "version-history.json");
14633
14858
  var MAX_ENTRIES_PER_PROVIDER = 20;
14634
14859
  var VersionArchive = class {
14635
14860
  history = {};
@@ -14676,7 +14901,7 @@ var VersionArchive = class {
14676
14901
  }
14677
14902
  save() {
14678
14903
  try {
14679
- fs10.mkdirSync(path14.dirname(ARCHIVE_PATH), { recursive: true });
14904
+ fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
14680
14905
  fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
14681
14906
  } catch {
14682
14907
  }
@@ -14717,7 +14942,7 @@ function checkPathExists2(paths) {
14717
14942
  for (const p of paths) {
14718
14943
  if (p.includes("*")) {
14719
14944
  const home = os16.homedir();
14720
- const resolved = p.replace(/\*/g, home.split(path14.sep).pop() || "");
14945
+ const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
14721
14946
  if (fs10.existsSync(resolved)) return resolved;
14722
14947
  } else {
14723
14948
  if (fs10.existsSync(p)) return p;
@@ -14727,7 +14952,7 @@ function checkPathExists2(paths) {
14727
14952
  }
14728
14953
  function getMacAppVersion(appPath) {
14729
14954
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
14730
- const plistPath = path14.join(appPath, "Contents", "Info.plist");
14955
+ const plistPath = path16.join(appPath, "Contents", "Info.plist");
14731
14956
  if (!fs10.existsSync(plistPath)) return null;
14732
14957
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
14733
14958
  return raw || null;
@@ -14754,7 +14979,7 @@ async function detectAllVersions(loader, archive) {
14754
14979
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
14755
14980
  let resolvedBin = cliBin;
14756
14981
  if (!resolvedBin && appPath && currentOs === "darwin") {
14757
- const bundled = path14.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
14982
+ const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
14758
14983
  if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
14759
14984
  }
14760
14985
  info.installed = !!(appPath || resolvedBin);
@@ -14795,7 +15020,7 @@ async function detectAllVersions(loader, archive) {
14795
15020
  // src/daemon/dev-server.ts
14796
15021
  var http2 = __toESM(require("http"));
14797
15022
  var fs14 = __toESM(require("fs"));
14798
- var path18 = __toESM(require("path"));
15023
+ var path20 = __toESM(require("path"));
14799
15024
 
14800
15025
  // src/daemon/scaffold-template.ts
14801
15026
  function generateFiles(type, name, category, opts = {}) {
@@ -15131,7 +15356,7 @@ init_logger();
15131
15356
 
15132
15357
  // src/daemon/dev-cdp-handlers.ts
15133
15358
  var fs11 = __toESM(require("fs"));
15134
- var path15 = __toESM(require("path"));
15359
+ var path17 = __toESM(require("path"));
15135
15360
  init_logger();
15136
15361
  async function handleCdpEvaluate(ctx, req, res) {
15137
15362
  const body = await ctx.readBody(req);
@@ -15310,17 +15535,17 @@ async function handleScriptHints(ctx, type, _req, res) {
15310
15535
  return;
15311
15536
  }
15312
15537
  let scriptsPath = "";
15313
- const directScripts = path15.join(dir, "scripts.js");
15538
+ const directScripts = path17.join(dir, "scripts.js");
15314
15539
  if (fs11.existsSync(directScripts)) {
15315
15540
  scriptsPath = directScripts;
15316
15541
  } else {
15317
- const scriptsDir = path15.join(dir, "scripts");
15542
+ const scriptsDir = path17.join(dir, "scripts");
15318
15543
  if (fs11.existsSync(scriptsDir)) {
15319
15544
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
15320
- return fs11.statSync(path15.join(scriptsDir, d)).isDirectory();
15545
+ return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
15321
15546
  }).sort().reverse();
15322
15547
  for (const ver of versions) {
15323
- const p = path15.join(scriptsDir, ver, "scripts.js");
15548
+ const p = path17.join(scriptsDir, ver, "scripts.js");
15324
15549
  if (fs11.existsSync(p)) {
15325
15550
  scriptsPath = p;
15326
15551
  break;
@@ -16139,7 +16364,7 @@ async function handleDomContext(ctx, type, req, res) {
16139
16364
 
16140
16365
  // src/daemon/dev-cli-debug.ts
16141
16366
  var fs12 = __toESM(require("fs"));
16142
- var path16 = __toESM(require("path"));
16367
+ var path18 = __toESM(require("path"));
16143
16368
  function slugifyFixtureName(value) {
16144
16369
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
16145
16370
  return normalized || `fixture-${Date.now()}`;
@@ -16149,11 +16374,11 @@ function getCliFixtureDir(ctx, type) {
16149
16374
  if (!providerDir) {
16150
16375
  throw new Error(`Provider directory not found for '${type}'`);
16151
16376
  }
16152
- return path16.join(providerDir, "fixtures");
16377
+ return path18.join(providerDir, "fixtures");
16153
16378
  }
16154
16379
  function readCliFixture(ctx, type, name) {
16155
16380
  const fixtureDir = getCliFixtureDir(ctx, type);
16156
- const filePath = path16.join(fixtureDir, `${name}.json`);
16381
+ const filePath = path18.join(fixtureDir, `${name}.json`);
16157
16382
  if (!fs12.existsSync(filePath)) {
16158
16383
  throw new Error(`Fixture not found: ${filePath}`);
16159
16384
  }
@@ -16313,7 +16538,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
16313
16538
  return { target, instance, adapter };
16314
16539
  }
16315
16540
  function sleep(ms) {
16316
- return new Promise((resolve9) => setTimeout(resolve9, ms));
16541
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
16317
16542
  }
16318
16543
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
16319
16544
  const startedAt = Date.now();
@@ -16912,7 +17137,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
16912
17137
  },
16913
17138
  notes: typeof body?.notes === "string" ? body.notes : void 0
16914
17139
  };
16915
- const filePath = path16.join(fixtureDir, `${name}.json`);
17140
+ const filePath = path18.join(fixtureDir, `${name}.json`);
16916
17141
  fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
16917
17142
  ctx.json(res, 200, {
16918
17143
  saved: true,
@@ -16936,7 +17161,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
16936
17161
  return;
16937
17162
  }
16938
17163
  const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
16939
- const fullPath = path16.join(fixtureDir, file);
17164
+ const fullPath = path18.join(fixtureDir, file);
16940
17165
  try {
16941
17166
  const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
16942
17167
  return {
@@ -17072,7 +17297,7 @@ async function handleCliRaw(ctx, req, res) {
17072
17297
 
17073
17298
  // src/daemon/dev-auto-implement.ts
17074
17299
  var fs13 = __toESM(require("fs"));
17075
- var path17 = __toESM(require("path"));
17300
+ var path19 = __toESM(require("path"));
17076
17301
  var os17 = __toESM(require("os"));
17077
17302
  function getAutoImplPid(ctx) {
17078
17303
  const proc = ctx.autoImplProcess;
@@ -17112,22 +17337,22 @@ function getLatestScriptVersionDir(scriptsDir) {
17112
17337
  if (!fs13.existsSync(scriptsDir)) return null;
17113
17338
  const versions = fs13.readdirSync(scriptsDir).filter((d) => {
17114
17339
  try {
17115
- return fs13.statSync(path17.join(scriptsDir, d)).isDirectory();
17340
+ return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
17116
17341
  } catch {
17117
17342
  return false;
17118
17343
  }
17119
17344
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
17120
17345
  if (versions.length === 0) return null;
17121
- return path17.join(scriptsDir, versions[0]);
17346
+ return path19.join(scriptsDir, versions[0]);
17122
17347
  }
17123
17348
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
17124
- const canonicalUserDir = path17.resolve(ctx.providerLoader.getUserProviderDir(category, type));
17125
- const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
17126
- const upstreamRoot = path17.resolve(ctx.providerLoader.getUpstreamDir());
17127
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
17349
+ const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
17350
+ const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
17351
+ const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
17352
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
17128
17353
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
17129
17354
  }
17130
- if (path17.basename(desiredDir) !== type) {
17355
+ if (path19.basename(desiredDir) !== type) {
17131
17356
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
17132
17357
  }
17133
17358
  const sourceDir = ctx.findProviderDir(type);
@@ -17135,11 +17360,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
17135
17360
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
17136
17361
  }
17137
17362
  if (!fs13.existsSync(desiredDir)) {
17138
- fs13.mkdirSync(path17.dirname(desiredDir), { recursive: true });
17363
+ fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
17139
17364
  fs13.cpSync(sourceDir, desiredDir, { recursive: true });
17140
17365
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
17141
17366
  }
17142
- const providerJson = path17.join(desiredDir, "provider.json");
17367
+ const providerJson = path19.join(desiredDir, "provider.json");
17143
17368
  if (!fs13.existsSync(providerJson)) {
17144
17369
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
17145
17370
  }
@@ -17162,13 +17387,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
17162
17387
  const refDir = ctx.findProviderDir(referenceType);
17163
17388
  if (!refDir || !fs13.existsSync(refDir)) return {};
17164
17389
  const referenceScripts = {};
17165
- const scriptsDir = path17.join(refDir, "scripts");
17390
+ const scriptsDir = path19.join(refDir, "scripts");
17166
17391
  const latestDir = getLatestScriptVersionDir(scriptsDir);
17167
17392
  if (!latestDir) return referenceScripts;
17168
17393
  for (const file of fs13.readdirSync(latestDir)) {
17169
17394
  if (!file.endsWith(".js")) continue;
17170
17395
  try {
17171
- referenceScripts[file] = fs13.readFileSync(path17.join(latestDir, file), "utf-8");
17396
+ referenceScripts[file] = fs13.readFileSync(path19.join(latestDir, file), "utf-8");
17172
17397
  } catch {
17173
17398
  }
17174
17399
  }
@@ -17276,9 +17501,9 @@ async function handleAutoImplement(ctx, type, req, res) {
17276
17501
  });
17277
17502
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
17278
17503
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
17279
- const tmpDir = path17.join(os17.tmpdir(), "adhdev-autoimpl");
17504
+ const tmpDir = path19.join(os17.tmpdir(), "adhdev-autoimpl");
17280
17505
  if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
17281
- const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
17506
+ const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
17282
17507
  fs13.writeFileSync(promptFile, prompt, "utf-8");
17283
17508
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
17284
17509
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -17705,7 +17930,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17705
17930
  setMode: "set_mode.js"
17706
17931
  };
17707
17932
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
17708
- const scriptsDir = path17.join(providerDir, "scripts");
17933
+ const scriptsDir = path19.join(providerDir, "scripts");
17709
17934
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
17710
17935
  if (latestScriptsDir) {
17711
17936
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -17716,7 +17941,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17716
17941
  for (const file of fs13.readdirSync(latestScriptsDir)) {
17717
17942
  if (file.endsWith(".js") && targetFileNames.has(file)) {
17718
17943
  try {
17719
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
17944
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
17720
17945
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
17721
17946
  lines.push("```javascript");
17722
17947
  lines.push(content);
@@ -17733,7 +17958,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17733
17958
  lines.push("");
17734
17959
  for (const file of refFiles) {
17735
17960
  try {
17736
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
17961
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
17737
17962
  lines.push(`### \`${file}\` \u{1F512}`);
17738
17963
  lines.push("```javascript");
17739
17964
  lines.push(content);
@@ -17774,10 +17999,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17774
17999
  lines.push("");
17775
18000
  }
17776
18001
  }
17777
- const docsDir = path17.join(providerDir, "../../docs");
18002
+ const docsDir = path19.join(providerDir, "../../docs");
17778
18003
  const loadGuide = (name) => {
17779
18004
  try {
17780
- const p = path17.join(docsDir, name);
18005
+ const p = path19.join(docsDir, name);
17781
18006
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
17782
18007
  } catch {
17783
18008
  }
@@ -18012,7 +18237,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
18012
18237
  parseApproval: "parse_approval.js"
18013
18238
  };
18014
18239
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
18015
- const scriptsDir = path17.join(providerDir, "scripts");
18240
+ const scriptsDir = path19.join(providerDir, "scripts");
18016
18241
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
18017
18242
  if (latestScriptsDir) {
18018
18243
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -18024,7 +18249,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
18024
18249
  if (!file.endsWith(".js")) continue;
18025
18250
  if (!targetFileNames.has(file)) continue;
18026
18251
  try {
18027
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
18252
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
18028
18253
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
18029
18254
  lines.push("```javascript");
18030
18255
  lines.push(content);
@@ -18040,7 +18265,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
18040
18265
  lines.push("");
18041
18266
  for (const file of refFiles) {
18042
18267
  try {
18043
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
18268
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
18044
18269
  lines.push(`### \`${file}\` \u{1F512}`);
18045
18270
  lines.push("```javascript");
18046
18271
  lines.push(content);
@@ -18073,10 +18298,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
18073
18298
  lines.push("");
18074
18299
  }
18075
18300
  }
18076
- const docsDir = path17.join(providerDir, "../../docs");
18301
+ const docsDir = path19.join(providerDir, "../../docs");
18077
18302
  const loadGuide = (name) => {
18078
18303
  try {
18079
- const p = path17.join(docsDir, name);
18304
+ const p = path19.join(docsDir, name);
18080
18305
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
18081
18306
  } catch {
18082
18307
  }
@@ -18487,8 +18712,8 @@ var DevServer = class _DevServer {
18487
18712
  }
18488
18713
  getEndpointList() {
18489
18714
  return this.routes.map((r) => {
18490
- const path19 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
18491
- return `${r.method.padEnd(5)} ${path19}`;
18715
+ const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
18716
+ return `${r.method.padEnd(5)} ${path21}`;
18492
18717
  });
18493
18718
  }
18494
18719
  async start(port = DEV_SERVER_PORT) {
@@ -18519,15 +18744,15 @@ var DevServer = class _DevServer {
18519
18744
  this.json(res, 500, { error: e.message });
18520
18745
  }
18521
18746
  });
18522
- return new Promise((resolve9, reject) => {
18747
+ return new Promise((resolve12, reject) => {
18523
18748
  this.server.listen(port, "127.0.0.1", () => {
18524
18749
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
18525
- resolve9();
18750
+ resolve12();
18526
18751
  });
18527
18752
  this.server.on("error", (e) => {
18528
18753
  if (e.code === "EADDRINUSE") {
18529
18754
  this.log(`Port ${port} in use, skipping dev server`);
18530
- resolve9();
18755
+ resolve12();
18531
18756
  } else {
18532
18757
  reject(e);
18533
18758
  }
@@ -18610,20 +18835,20 @@ var DevServer = class _DevServer {
18610
18835
  child.stderr?.on("data", (d) => {
18611
18836
  stderr += d.toString().slice(0, 2e3);
18612
18837
  });
18613
- await new Promise((resolve9) => {
18838
+ await new Promise((resolve12) => {
18614
18839
  const timer = setTimeout(() => {
18615
18840
  child.kill();
18616
- resolve9();
18841
+ resolve12();
18617
18842
  }, 3e3);
18618
18843
  child.on("exit", () => {
18619
18844
  clearTimeout(timer);
18620
- resolve9();
18845
+ resolve12();
18621
18846
  });
18622
18847
  child.stdout?.once("data", () => {
18623
18848
  setTimeout(() => {
18624
18849
  child.kill();
18625
18850
  clearTimeout(timer);
18626
- resolve9();
18851
+ resolve12();
18627
18852
  }, 500);
18628
18853
  });
18629
18854
  });
@@ -18770,12 +18995,12 @@ var DevServer = class _DevServer {
18770
18995
  // ─── DevConsole SPA ───
18771
18996
  getConsoleDistDir() {
18772
18997
  const candidates = [
18773
- path18.resolve(__dirname, "../../web-devconsole/dist"),
18774
- path18.resolve(__dirname, "../../../web-devconsole/dist"),
18775
- path18.join(process.cwd(), "packages/web-devconsole/dist")
18998
+ path20.resolve(__dirname, "../../web-devconsole/dist"),
18999
+ path20.resolve(__dirname, "../../../web-devconsole/dist"),
19000
+ path20.join(process.cwd(), "packages/web-devconsole/dist")
18776
19001
  ];
18777
19002
  for (const dir of candidates) {
18778
- if (fs14.existsSync(path18.join(dir, "index.html"))) return dir;
19003
+ if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
18779
19004
  }
18780
19005
  return null;
18781
19006
  }
@@ -18785,7 +19010,7 @@ var DevServer = class _DevServer {
18785
19010
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
18786
19011
  return;
18787
19012
  }
18788
- const htmlPath = path18.join(distDir, "index.html");
19013
+ const htmlPath = path20.join(distDir, "index.html");
18789
19014
  try {
18790
19015
  const html = fs14.readFileSync(htmlPath, "utf-8");
18791
19016
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -18810,15 +19035,15 @@ var DevServer = class _DevServer {
18810
19035
  this.json(res, 404, { error: "Not found" });
18811
19036
  return;
18812
19037
  }
18813
- const safePath = path18.normalize(pathname).replace(/^\.\.\//, "");
18814
- const filePath = path18.join(distDir, safePath);
19038
+ const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
19039
+ const filePath = path20.join(distDir, safePath);
18815
19040
  if (!filePath.startsWith(distDir)) {
18816
19041
  this.json(res, 403, { error: "Forbidden" });
18817
19042
  return;
18818
19043
  }
18819
19044
  try {
18820
19045
  const content = fs14.readFileSync(filePath);
18821
- const ext = path18.extname(filePath);
19046
+ const ext = path20.extname(filePath);
18822
19047
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
18823
19048
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
18824
19049
  res.end(content);
@@ -18931,9 +19156,9 @@ var DevServer = class _DevServer {
18931
19156
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
18932
19157
  if (entry.isDirectory()) {
18933
19158
  files.push({ path: rel, size: 0, type: "dir" });
18934
- scan(path18.join(d, entry.name), rel);
19159
+ scan(path20.join(d, entry.name), rel);
18935
19160
  } else {
18936
- const stat = fs14.statSync(path18.join(d, entry.name));
19161
+ const stat = fs14.statSync(path20.join(d, entry.name));
18937
19162
  files.push({ path: rel, size: stat.size, type: "file" });
18938
19163
  }
18939
19164
  }
@@ -18956,7 +19181,7 @@ var DevServer = class _DevServer {
18956
19181
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
18957
19182
  return;
18958
19183
  }
18959
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
19184
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
18960
19185
  if (!fullPath.startsWith(dir)) {
18961
19186
  this.json(res, 403, { error: "Forbidden" });
18962
19187
  return;
@@ -18981,14 +19206,14 @@ var DevServer = class _DevServer {
18981
19206
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
18982
19207
  return;
18983
19208
  }
18984
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
19209
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
18985
19210
  if (!fullPath.startsWith(dir)) {
18986
19211
  this.json(res, 403, { error: "Forbidden" });
18987
19212
  return;
18988
19213
  }
18989
19214
  try {
18990
19215
  if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
18991
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
19216
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
18992
19217
  fs14.writeFileSync(fullPath, content, "utf-8");
18993
19218
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
18994
19219
  this.providerLoader.reload();
@@ -19005,7 +19230,7 @@ var DevServer = class _DevServer {
19005
19230
  return;
19006
19231
  }
19007
19232
  for (const name of ["scripts.js", "provider.json"]) {
19008
- const p = path18.join(dir, name);
19233
+ const p = path20.join(dir, name);
19009
19234
  if (fs14.existsSync(p)) {
19010
19235
  const source = fs14.readFileSync(p, "utf-8");
19011
19236
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -19026,8 +19251,8 @@ var DevServer = class _DevServer {
19026
19251
  this.json(res, 404, { error: `Provider not found: ${type}` });
19027
19252
  return;
19028
19253
  }
19029
- const target = fs14.existsSync(path18.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
19030
- const targetPath = path18.join(dir, target);
19254
+ const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
19255
+ const targetPath = path20.join(dir, target);
19031
19256
  try {
19032
19257
  if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
19033
19258
  fs14.writeFileSync(targetPath, source, "utf-8");
@@ -19132,14 +19357,14 @@ var DevServer = class _DevServer {
19132
19357
  child.stderr?.on("data", (d) => {
19133
19358
  stderr += d.toString();
19134
19359
  });
19135
- await new Promise((resolve9) => {
19360
+ await new Promise((resolve12) => {
19136
19361
  const timer = setTimeout(() => {
19137
19362
  child.kill();
19138
- resolve9();
19363
+ resolve12();
19139
19364
  }, timeout);
19140
19365
  child.on("exit", () => {
19141
19366
  clearTimeout(timer);
19142
- resolve9();
19367
+ resolve12();
19143
19368
  });
19144
19369
  });
19145
19370
  const elapsed = Date.now() - start;
@@ -19187,7 +19412,7 @@ var DevServer = class _DevServer {
19187
19412
  }
19188
19413
  let targetDir;
19189
19414
  targetDir = this.providerLoader.getUserProviderDir(category, type);
19190
- const jsonPath = path18.join(targetDir, "provider.json");
19415
+ const jsonPath = path20.join(targetDir, "provider.json");
19191
19416
  if (fs14.existsSync(jsonPath)) {
19192
19417
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
19193
19418
  return;
@@ -19199,8 +19424,8 @@ var DevServer = class _DevServer {
19199
19424
  const createdFiles = ["provider.json"];
19200
19425
  if (result.files) {
19201
19426
  for (const [relPath, content] of Object.entries(result.files)) {
19202
- const fullPath = path18.join(targetDir, relPath);
19203
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
19427
+ const fullPath = path20.join(targetDir, relPath);
19428
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
19204
19429
  fs14.writeFileSync(fullPath, content, "utf-8");
19205
19430
  createdFiles.push(relPath);
19206
19431
  }
@@ -19253,22 +19478,22 @@ var DevServer = class _DevServer {
19253
19478
  if (!fs14.existsSync(scriptsDir)) return null;
19254
19479
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
19255
19480
  try {
19256
- return fs14.statSync(path18.join(scriptsDir, d)).isDirectory();
19481
+ return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
19257
19482
  } catch {
19258
19483
  return false;
19259
19484
  }
19260
19485
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
19261
19486
  if (versions.length === 0) return null;
19262
- return path18.join(scriptsDir, versions[0]);
19487
+ return path20.join(scriptsDir, versions[0]);
19263
19488
  }
19264
19489
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
19265
- const canonicalUserDir = path18.resolve(this.providerLoader.getUserProviderDir(category, type));
19266
- const desiredDir = requestedDir ? path18.resolve(requestedDir) : canonicalUserDir;
19267
- const upstreamRoot = path18.resolve(this.providerLoader.getUpstreamDir());
19268
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path18.sep}`)) {
19490
+ const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
19491
+ const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
19492
+ const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
19493
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
19269
19494
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
19270
19495
  }
19271
- if (path18.basename(desiredDir) !== type) {
19496
+ if (path20.basename(desiredDir) !== type) {
19272
19497
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
19273
19498
  }
19274
19499
  const sourceDir = this.findProviderDir(type);
@@ -19276,11 +19501,11 @@ var DevServer = class _DevServer {
19276
19501
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
19277
19502
  }
19278
19503
  if (!fs14.existsSync(desiredDir)) {
19279
- fs14.mkdirSync(path18.dirname(desiredDir), { recursive: true });
19504
+ fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
19280
19505
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
19281
19506
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
19282
19507
  }
19283
- const providerJson = path18.join(desiredDir, "provider.json");
19508
+ const providerJson = path20.join(desiredDir, "provider.json");
19284
19509
  if (!fs14.existsSync(providerJson)) {
19285
19510
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
19286
19511
  }
@@ -19328,7 +19553,7 @@ var DevServer = class _DevServer {
19328
19553
  setMode: "set_mode.js"
19329
19554
  };
19330
19555
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
19331
- const scriptsDir = path18.join(providerDir, "scripts");
19556
+ const scriptsDir = path20.join(providerDir, "scripts");
19332
19557
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
19333
19558
  if (latestScriptsDir) {
19334
19559
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -19339,7 +19564,7 @@ var DevServer = class _DevServer {
19339
19564
  for (const file of fs14.readdirSync(latestScriptsDir)) {
19340
19565
  if (file.endsWith(".js") && targetFileNames.has(file)) {
19341
19566
  try {
19342
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19567
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19343
19568
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
19344
19569
  lines.push("```javascript");
19345
19570
  lines.push(content);
@@ -19356,7 +19581,7 @@ var DevServer = class _DevServer {
19356
19581
  lines.push("");
19357
19582
  for (const file of refFiles) {
19358
19583
  try {
19359
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19584
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19360
19585
  lines.push(`### \`${file}\` \u{1F512}`);
19361
19586
  lines.push("```javascript");
19362
19587
  lines.push(content);
@@ -19397,10 +19622,10 @@ var DevServer = class _DevServer {
19397
19622
  lines.push("");
19398
19623
  }
19399
19624
  }
19400
- const docsDir = path18.join(providerDir, "../../docs");
19625
+ const docsDir = path20.join(providerDir, "../../docs");
19401
19626
  const loadGuide = (name) => {
19402
19627
  try {
19403
- const p = path18.join(docsDir, name);
19628
+ const p = path20.join(docsDir, name);
19404
19629
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
19405
19630
  } catch {
19406
19631
  }
@@ -19574,7 +19799,7 @@ var DevServer = class _DevServer {
19574
19799
  parseApproval: "parse_approval.js"
19575
19800
  };
19576
19801
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
19577
- const scriptsDir = path18.join(providerDir, "scripts");
19802
+ const scriptsDir = path20.join(providerDir, "scripts");
19578
19803
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
19579
19804
  if (latestScriptsDir) {
19580
19805
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -19586,7 +19811,7 @@ var DevServer = class _DevServer {
19586
19811
  if (!file.endsWith(".js")) continue;
19587
19812
  if (!targetFileNames.has(file)) continue;
19588
19813
  try {
19589
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19814
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19590
19815
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
19591
19816
  lines.push("```javascript");
19592
19817
  lines.push(content);
@@ -19602,7 +19827,7 @@ var DevServer = class _DevServer {
19602
19827
  lines.push("");
19603
19828
  for (const file of refFiles) {
19604
19829
  try {
19605
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19830
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19606
19831
  lines.push(`### \`${file}\` \u{1F512}`);
19607
19832
  lines.push("```javascript");
19608
19833
  lines.push(content);
@@ -19635,10 +19860,10 @@ var DevServer = class _DevServer {
19635
19860
  lines.push("");
19636
19861
  }
19637
19862
  }
19638
- const docsDir = path18.join(providerDir, "../../docs");
19863
+ const docsDir = path20.join(providerDir, "../../docs");
19639
19864
  const loadGuide = (name) => {
19640
19865
  try {
19641
- const p = path18.join(docsDir, name);
19866
+ const p = path20.join(docsDir, name);
19642
19867
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
19643
19868
  } catch {
19644
19869
  }
@@ -19814,14 +20039,14 @@ data: ${JSON.stringify(msg.data)}
19814
20039
  res.end(JSON.stringify(data, null, 2));
19815
20040
  }
19816
20041
  async readBody(req) {
19817
- return new Promise((resolve9) => {
20042
+ return new Promise((resolve12) => {
19818
20043
  let body = "";
19819
20044
  req.on("data", (chunk) => body += chunk);
19820
20045
  req.on("end", () => {
19821
20046
  try {
19822
- resolve9(JSON.parse(body));
20047
+ resolve12(JSON.parse(body));
19823
20048
  } catch {
19824
- resolve9({});
20049
+ resolve12({});
19825
20050
  }
19826
20051
  });
19827
20052
  });
@@ -20289,7 +20514,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
20289
20514
  const deadline = Date.now() + timeoutMs;
20290
20515
  while (Date.now() < deadline) {
20291
20516
  if (await canConnect(endpoint)) return;
20292
- await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
20517
+ await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
20293
20518
  }
20294
20519
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
20295
20520
  }
@@ -20445,10 +20670,10 @@ async function installExtension(ide, extension) {
20445
20670
  const buffer = Buffer.from(await res.arrayBuffer());
20446
20671
  const fs15 = await import("fs");
20447
20672
  fs15.writeFileSync(vsixPath, buffer);
20448
- return new Promise((resolve9) => {
20673
+ return new Promise((resolve12) => {
20449
20674
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
20450
20675
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
20451
- resolve9({
20676
+ resolve12({
20452
20677
  extensionId: extension.id,
20453
20678
  marketplaceId: extension.marketplaceId,
20454
20679
  success: !error,
@@ -20461,11 +20686,11 @@ async function installExtension(ide, extension) {
20461
20686
  } catch (e) {
20462
20687
  }
20463
20688
  }
20464
- return new Promise((resolve9) => {
20689
+ return new Promise((resolve12) => {
20465
20690
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
20466
20691
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
20467
20692
  if (error) {
20468
- resolve9({
20693
+ resolve12({
20469
20694
  extensionId: extension.id,
20470
20695
  marketplaceId: extension.marketplaceId,
20471
20696
  success: false,
@@ -20473,7 +20698,7 @@ async function installExtension(ide, extension) {
20473
20698
  error: stderr || error.message
20474
20699
  });
20475
20700
  } else {
20476
- resolve9({
20701
+ resolve12({
20477
20702
  extensionId: extension.id,
20478
20703
  marketplaceId: extension.marketplaceId,
20479
20704
  success: true,
@@ -20609,13 +20834,32 @@ async function initDaemonComponents(config) {
20609
20834
  const detectedIdesRef = { value: [] };
20610
20835
  let agentStreamManager = null;
20611
20836
  let poller = null;
20837
+ const refreshProviderAvailability = async (providerType) => {
20838
+ const targetProvider = providerType ? providerLoader.getMeta(providerLoader.resolveAlias(providerType)) : null;
20839
+ const targetCategory = targetProvider?.category;
20840
+ if (!providerType || targetCategory === "cli" || targetCategory === "acp") {
20841
+ if (providerType && targetProvider) {
20842
+ const detected = await detectCLI(targetProvider.type, providerLoader, { includeVersion: false });
20843
+ providerLoader.setProviderAvailability(targetProvider.type, {
20844
+ installed: !!detected,
20845
+ detectedPath: detected?.path || null
20846
+ });
20847
+ } else {
20848
+ providerLoader.setCliDetectionResults(await detectCLIs(providerLoader, { includeVersion: false }), true);
20849
+ }
20850
+ }
20851
+ if (!providerType || targetCategory === "ide") {
20852
+ detectedIdesRef.value = await detectIDEs(providerLoader);
20853
+ providerLoader.setIdeDetectionResults(detectedIdesRef.value, true);
20854
+ }
20855
+ };
20612
20856
  const cliManager = new DaemonCliManager({
20613
20857
  ...config.cliManagerDeps,
20614
20858
  getInstanceManager: () => instanceManager,
20615
20859
  getSessionRegistry: () => sessionRegistry
20616
20860
  }, providerLoader);
20617
20861
  LOG.info("Init", "Detecting IDEs...");
20618
- detectedIdesRef.value = await detectIDEs();
20862
+ await refreshProviderAvailability();
20619
20863
  const installed = detectedIdesRef.value.filter((i) => i.installed);
20620
20864
  LOG.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
20621
20865
  const cdpSetupContext = {
@@ -20655,7 +20899,11 @@ async function initDaemonComponents(config) {
20655
20899
  adapters: cliManager.adapters,
20656
20900
  providerLoader,
20657
20901
  instanceManager,
20658
- sessionRegistry
20902
+ sessionRegistry,
20903
+ onProviderSettingChanged: async (providerType) => {
20904
+ await refreshProviderAvailability(providerType);
20905
+ config.onStatusChange?.();
20906
+ }
20659
20907
  });
20660
20908
  agentStreamManager = new DaemonAgentStreamManager(
20661
20909
  LOG.forComponent("AgentStream").asLogFn(),