@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.mjs CHANGED
@@ -233,7 +233,7 @@ var init_config = __esm({
233
233
 
234
234
  // src/logging/logger.ts
235
235
  import * as fs2 from "fs";
236
- import * as path4 from "path";
236
+ import * as path6 from "path";
237
237
  import * as os4 from "os";
238
238
  function setLogLevel(level) {
239
239
  currentLevel = level;
@@ -249,13 +249,13 @@ function getDaemonLogDir() {
249
249
  return LOG_DIR;
250
250
  }
251
251
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
252
- return path4.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
252
+ return path6.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
253
253
  }
254
254
  function checkDateRotation() {
255
255
  const today = getDateStr();
256
256
  if (today !== currentDate) {
257
257
  currentDate = today;
258
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
258
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
259
259
  cleanOldLogs();
260
260
  }
261
261
  }
@@ -269,7 +269,7 @@ function cleanOldLogs() {
269
269
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
270
270
  if (dateMatch && dateMatch[1] < cutoffStr) {
271
271
  try {
272
- fs2.unlinkSync(path4.join(LOG_DIR, file));
272
+ fs2.unlinkSync(path6.join(LOG_DIR, file));
273
273
  } catch {
274
274
  }
275
275
  }
@@ -393,7 +393,7 @@ var init_logger = __esm({
393
393
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
394
394
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
395
395
  currentLevel = "info";
396
- 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");
396
+ 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");
397
397
  MAX_LOG_SIZE = 5 * 1024 * 1024;
398
398
  MAX_LOG_DAYS = 7;
399
399
  try {
@@ -401,16 +401,16 @@ var init_logger = __esm({
401
401
  } catch {
402
402
  }
403
403
  currentDate = getDateStr();
404
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
404
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
405
405
  cleanOldLogs();
406
406
  try {
407
- const oldLog = path4.join(LOG_DIR, "daemon.log");
407
+ const oldLog = path6.join(LOG_DIR, "daemon.log");
408
408
  if (fs2.existsSync(oldLog)) {
409
409
  const stat = fs2.statSync(oldLog);
410
410
  const oldDate = stat.mtime.toISOString().slice(0, 10);
411
- fs2.renameSync(oldLog, path4.join(LOG_DIR, `daemon-${oldDate}.log`));
411
+ fs2.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
412
412
  }
413
- const oldLogBackup = path4.join(LOG_DIR, "daemon.log.old");
413
+ const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
414
414
  if (fs2.existsSync(oldLogBackup)) {
415
415
  fs2.unlinkSync(oldLogBackup);
416
416
  }
@@ -442,7 +442,7 @@ var init_logger = __esm({
442
442
  }
443
443
  };
444
444
  interceptorInstalled = false;
445
- LOG_PATH = path4.join(LOG_DIR, `daemon-${getDateStr()}.log`);
445
+ LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
446
446
  }
447
447
  });
448
448
 
@@ -802,7 +802,7 @@ __export(provider_cli_adapter_exports, {
802
802
  normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
803
803
  });
804
804
  import * as os8 from "os";
805
- import * as path7 from "path";
805
+ import * as path9 from "path";
806
806
  import { execSync as execSync3 } from "child_process";
807
807
  function stripAnsi(str) {
808
808
  return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
@@ -873,16 +873,22 @@ function computeTerminalQueryTail(buffer) {
873
873
  return "";
874
874
  }
875
875
  function findBinary(name) {
876
+ const trimmed = String(name || "").trim();
877
+ if (!trimmed) return trimmed;
878
+ const expanded = trimmed.startsWith("~") ? path9.join(os8.homedir(), trimmed.slice(1)) : trimmed;
879
+ if (path9.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
880
+ return path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
881
+ }
876
882
  const isWin = os8.platform() === "win32";
877
883
  try {
878
- const cmd = isWin ? `where ${name}` : `which ${name}`;
884
+ const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
879
885
  return execSync3(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
880
886
  } catch {
881
- return isWin ? `${name}.cmd` : name;
887
+ return isWin ? `${trimmed}.cmd` : trimmed;
882
888
  }
883
889
  }
884
890
  function isScriptBinary(binaryPath) {
885
- if (!path7.isAbsolute(binaryPath)) return false;
891
+ if (!path9.isAbsolute(binaryPath)) return false;
886
892
  try {
887
893
  const fs15 = __require("fs");
888
894
  const resolved = fs15.realpathSync(binaryPath);
@@ -898,7 +904,7 @@ function isScriptBinary(binaryPath) {
898
904
  }
899
905
  }
900
906
  function looksLikeMachOOrElf(filePath) {
901
- if (!path7.isAbsolute(filePath)) return false;
907
+ if (!path9.isAbsolute(filePath)) return false;
902
908
  try {
903
909
  const fs15 = __require("fs");
904
910
  const resolved = fs15.realpathSync(filePath);
@@ -1379,16 +1385,17 @@ var init_provider_cli_adapter = __esm({
1379
1385
  async spawn() {
1380
1386
  if (this.ptyProcess) return;
1381
1387
  const { spawn: spawnConfig } = this.provider;
1382
- const binaryPath = findBinary(spawnConfig.command);
1388
+ const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
1389
+ const binaryPath = findBinary(configuredCommand);
1383
1390
  const isWin = os8.platform() === "win32";
1384
1391
  const allArgs = [...spawnConfig.args, ...this.extraArgs];
1385
1392
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1386
1393
  this.resetTraceSession();
1387
1394
  let shellCmd;
1388
1395
  let shellArgs;
1389
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1396
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1390
1397
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1391
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1398
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1392
1399
  const useShell = isWin ? useShellWin : useShellUnix;
1393
1400
  if (useShell) {
1394
1401
  if (!spawnConfig.shell && !isWin) {
@@ -1762,7 +1769,7 @@ var init_provider_cli_adapter = __esm({
1762
1769
  `[${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)}`
1763
1770
  );
1764
1771
  }
1765
- await new Promise((resolve9) => setTimeout(resolve9, 50));
1772
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
1766
1773
  }
1767
1774
  const finalScreenText = this.terminalScreen.getText() || "";
1768
1775
  LOG.warn(
@@ -2273,7 +2280,7 @@ ${data.message || ""}`.trim();
2273
2280
  const deadline = Date.now() + 1e4;
2274
2281
  while (this.startupParseGate && Date.now() < deadline) {
2275
2282
  this.resolveStartupState("send_wait");
2276
- await new Promise((resolve9) => setTimeout(resolve9, 50));
2283
+ await new Promise((resolve12) => setTimeout(resolve12, 50));
2277
2284
  }
2278
2285
  }
2279
2286
  await this.waitForInteractivePrompt();
@@ -2498,17 +2505,17 @@ ${data.message || ""}`.trim();
2498
2505
  }
2499
2506
  }
2500
2507
  waitForStopped(timeoutMs) {
2501
- return new Promise((resolve9) => {
2508
+ return new Promise((resolve12) => {
2502
2509
  const startedAt = Date.now();
2503
2510
  const timer = setInterval(() => {
2504
2511
  if (!this.ptyProcess || this.currentStatus === "stopped") {
2505
2512
  clearInterval(timer);
2506
- resolve9(true);
2513
+ resolve12(true);
2507
2514
  return;
2508
2515
  }
2509
2516
  if (Date.now() - startedAt >= timeoutMs) {
2510
2517
  clearInterval(timer);
2511
- resolve9(false);
2518
+ resolve12(false);
2512
2519
  }
2513
2520
  }, 100);
2514
2521
  });
@@ -3124,6 +3131,7 @@ function resetState() {
3124
3131
  import { execSync } from "child_process";
3125
3132
  import { existsSync as existsSync4 } from "fs";
3126
3133
  import { platform, homedir as homedir3 } from "os";
3134
+ import * as path4 from "path";
3127
3135
  var BUILTIN_IDE_DEFINITIONS = [];
3128
3136
  var registeredIDEs = /* @__PURE__ */ new Map();
3129
3137
  function registerIDEDefinition(def) {
@@ -3140,9 +3148,16 @@ function getMergedDefinitions() {
3140
3148
  return [...merged.values()];
3141
3149
  }
3142
3150
  function findCliCommand(command) {
3151
+ const trimmed = String(command || "").trim();
3152
+ if (!trimmed) return null;
3153
+ if (path4.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
3154
+ const candidate = trimmed.startsWith("~") ? path4.join(homedir3(), trimmed.slice(1)) : trimmed;
3155
+ const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(candidate);
3156
+ return existsSync4(resolved) ? resolved : null;
3157
+ }
3143
3158
  try {
3144
3159
  const result = execSync(
3145
- platform() === "win32" ? `where ${command}` : `which ${command}`,
3160
+ platform() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
3146
3161
  { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
3147
3162
  ).trim();
3148
3163
  return result.split("\n")[0] || null;
@@ -3165,23 +3180,23 @@ function getIdeVersion(cliCommand) {
3165
3180
  function checkPathExists(paths) {
3166
3181
  const home = homedir3();
3167
3182
  for (const p of paths) {
3168
- if (p.includes("*")) {
3183
+ const normalized = p.startsWith("~") ? path4.join(home, p.slice(1)) : p;
3184
+ if (normalized.includes("*")) {
3169
3185
  const username = home.split(/[\\/]/).pop() || "";
3170
- const resolved = p.replace("*", username);
3186
+ const resolved = normalized.replace("*", username);
3171
3187
  if (existsSync4(resolved)) return resolved;
3172
3188
  } else {
3173
- if (existsSync4(p)) return p;
3189
+ if (existsSync4(normalized)) return normalized;
3174
3190
  }
3175
3191
  }
3176
3192
  return null;
3177
3193
  }
3178
- async function detectIDEs() {
3194
+ async function detectIDEs(providerLoader) {
3179
3195
  const os18 = platform();
3180
3196
  const results = [];
3181
3197
  for (const def of getMergedDefinitions()) {
3182
- const cliPath = findCliCommand(def.cli);
3183
- const appPath = checkPathExists(def.paths[os18] || []);
3184
- const installed = !!(cliPath || appPath);
3198
+ const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
3199
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os18] || []) || []);
3185
3200
  let resolvedCli = cliPath;
3186
3201
  if (!resolvedCli && appPath && os18 === "darwin") {
3187
3202
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
@@ -3204,6 +3219,7 @@ async function detectIDEs() {
3204
3219
  }
3205
3220
  }
3206
3221
  }
3222
+ const installed = os18 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
3207
3223
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
3208
3224
  results.push({
3209
3225
  id: def.id,
@@ -3222,48 +3238,77 @@ async function detectIDEs() {
3222
3238
  // src/detection/cli-detector.ts
3223
3239
  import { exec } from "child_process";
3224
3240
  import * as os2 from "os";
3241
+ import * as path5 from "path";
3242
+ import { existsSync as existsSync5 } from "fs";
3225
3243
  function parseVersion(raw) {
3226
3244
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
3227
3245
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
3228
3246
  }
3247
+ function shellQuote(value) {
3248
+ if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
3249
+ return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
3250
+ }
3251
+ function expandHome(value) {
3252
+ const trimmed = value.trim();
3253
+ if (!trimmed.startsWith("~")) return trimmed;
3254
+ return path5.join(os2.homedir(), trimmed.slice(1));
3255
+ }
3256
+ function isExplicitCommandPath(command) {
3257
+ const trimmed = command.trim();
3258
+ return path5.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
3259
+ }
3260
+ function resolveCommandPath(command) {
3261
+ const trimmed = command.trim();
3262
+ if (!trimmed) return null;
3263
+ if (isExplicitCommandPath(trimmed)) {
3264
+ const expanded = expandHome(trimmed);
3265
+ const candidate = path5.isAbsolute(expanded) ? expanded : path5.resolve(expanded);
3266
+ return existsSync5(candidate) ? candidate : null;
3267
+ }
3268
+ return null;
3269
+ }
3229
3270
  function execAsync(cmd, timeoutMs = 5e3) {
3230
- return new Promise((resolve9) => {
3271
+ return new Promise((resolve12) => {
3231
3272
  const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
3232
3273
  if (err || !stdout?.trim()) {
3233
- resolve9(null);
3274
+ resolve12(null);
3234
3275
  } else {
3235
- resolve9(stdout.trim());
3276
+ resolve12(stdout.trim());
3236
3277
  }
3237
3278
  });
3238
- child.on("error", () => resolve9(null));
3279
+ child.on("error", () => resolve12(null));
3239
3280
  });
3240
3281
  }
3241
- async function detectCLIs(providerLoader) {
3282
+ async function detectCLIs(providerLoader, options) {
3242
3283
  const platform9 = os2.platform();
3243
3284
  const whichCmd = platform9 === "win32" ? "where" : "which";
3285
+ const includeVersion = options?.includeVersion !== false;
3244
3286
  const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
3245
3287
  const results = await Promise.all(
3246
3288
  cliList.map(async (cli) => {
3247
3289
  try {
3248
- const pathResult = await execAsync(`${whichCmd} ${cli.command}`);
3290
+ const explicitPath = resolveCommandPath(cli.command);
3291
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
3249
3292
  if (!pathResult) return { ...cli, installed: false };
3250
- const firstPath = pathResult.split("\n")[0];
3293
+ const firstPath = explicitPath || pathResult.split("\n")[0];
3251
3294
  let version;
3252
- try {
3295
+ if (includeVersion) {
3253
3296
  const versionCommands = [
3254
- cli.versionCommand,
3255
- `${cli.command} --version`,
3256
- `${cli.command} -V`,
3257
- `${cli.command} -v`
3297
+ `"${firstPath}" --version`,
3298
+ `"${firstPath}" -V`,
3299
+ `"${firstPath}" -v`,
3300
+ cli.versionCommand
3258
3301
  ].filter((v) => !!v);
3259
- for (const versionCommand of versionCommands) {
3260
- const versionResult = await execAsync(versionCommand, 3e3);
3261
- if (versionResult) {
3262
- version = parseVersion(versionResult);
3263
- break;
3302
+ try {
3303
+ for (const versionCommand of versionCommands) {
3304
+ const versionResult = await execAsync(versionCommand, 3e3);
3305
+ if (versionResult) {
3306
+ version = parseVersion(versionResult);
3307
+ break;
3308
+ }
3264
3309
  }
3310
+ } catch {
3265
3311
  }
3266
- } catch {
3267
3312
  }
3268
3313
  return { ...cli, installed: true, version, path: firstPath };
3269
3314
  } catch {
@@ -3273,7 +3318,7 @@ async function detectCLIs(providerLoader) {
3273
3318
  );
3274
3319
  return results;
3275
3320
  }
3276
- async function detectCLI(cliId, providerLoader) {
3321
+ async function detectCLI(cliId, providerLoader, options) {
3277
3322
  const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
3278
3323
  if (providerLoader) {
3279
3324
  const cliList = providerLoader.getCliDetectionList();
@@ -3282,25 +3327,28 @@ async function detectCLI(cliId, providerLoader) {
3282
3327
  const platform9 = os2.platform();
3283
3328
  const whichCmd = platform9 === "win32" ? "where" : "which";
3284
3329
  try {
3285
- const pathResult = await execAsync(`${whichCmd} ${target.command}`);
3330
+ const explicitPath = resolveCommandPath(target.command);
3331
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
3286
3332
  if (!pathResult) return null;
3287
- const firstPath = pathResult.split("\n")[0];
3333
+ const firstPath = explicitPath || pathResult.split("\n")[0];
3288
3334
  let version;
3289
- try {
3335
+ if (options?.includeVersion !== false) {
3290
3336
  const versionCommands = [
3291
- target.versionCommand,
3292
- `${target.command} --version`,
3293
- `${target.command} -V`,
3294
- `${target.command} -v`
3337
+ `"${firstPath}" --version`,
3338
+ `"${firstPath}" -V`,
3339
+ `"${firstPath}" -v`,
3340
+ target.versionCommand
3295
3341
  ].filter((v) => !!v);
3296
- for (const versionCommand of versionCommands) {
3297
- const versionResult = await execAsync(versionCommand, 3e3);
3298
- if (versionResult) {
3299
- version = parseVersion(versionResult);
3300
- break;
3342
+ try {
3343
+ for (const versionCommand of versionCommands) {
3344
+ const versionResult = await execAsync(versionCommand, 3e3);
3345
+ if (versionResult) {
3346
+ version = parseVersion(versionResult);
3347
+ break;
3348
+ }
3301
3349
  }
3350
+ } catch {
3302
3351
  }
3303
- } catch {
3304
3352
  }
3305
3353
  return { ...target, installed: true, version, path: firstPath };
3306
3354
  } catch {
@@ -3308,7 +3356,7 @@ async function detectCLI(cliId, providerLoader) {
3308
3356
  }
3309
3357
  }
3310
3358
  }
3311
- const all = await detectCLIs(providerLoader);
3359
+ const all = await detectCLIs(providerLoader, options);
3312
3360
  return all.find((c) => c.id === resolvedId && c.installed) || null;
3313
3361
  }
3314
3362
 
@@ -3435,7 +3483,7 @@ var DaemonCdpManager = class {
3435
3483
  * Returns multiple entries if multiple IDE windows are open on same port
3436
3484
  */
3437
3485
  static listAllTargets(port) {
3438
- return new Promise((resolve9) => {
3486
+ return new Promise((resolve12) => {
3439
3487
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3440
3488
  let data = "";
3441
3489
  res.on("data", (chunk) => data += chunk.toString());
@@ -3451,16 +3499,16 @@ var DaemonCdpManager = class {
3451
3499
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
3452
3500
  );
3453
3501
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
3454
- resolve9(mainPages.length > 0 ? mainPages : fallbackPages);
3502
+ resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
3455
3503
  } catch {
3456
- resolve9([]);
3504
+ resolve12([]);
3457
3505
  }
3458
3506
  });
3459
3507
  });
3460
- req.on("error", () => resolve9([]));
3508
+ req.on("error", () => resolve12([]));
3461
3509
  req.setTimeout(2e3, () => {
3462
3510
  req.destroy();
3463
- resolve9([]);
3511
+ resolve12([]);
3464
3512
  });
3465
3513
  });
3466
3514
  }
@@ -3500,7 +3548,7 @@ var DaemonCdpManager = class {
3500
3548
  }
3501
3549
  }
3502
3550
  findTargetOnPort(port) {
3503
- return new Promise((resolve9) => {
3551
+ return new Promise((resolve12) => {
3504
3552
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3505
3553
  let data = "";
3506
3554
  res.on("data", (chunk) => data += chunk.toString());
@@ -3511,7 +3559,7 @@ var DaemonCdpManager = class {
3511
3559
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
3512
3560
  );
3513
3561
  if (pages.length === 0) {
3514
- resolve9(targets.find((t) => t.webSocketDebuggerUrl) || null);
3562
+ resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
3515
3563
  return;
3516
3564
  }
3517
3565
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -3521,24 +3569,24 @@ var DaemonCdpManager = class {
3521
3569
  const specific = list.find((t) => t.id === this._targetId);
3522
3570
  if (specific) {
3523
3571
  this._pageTitle = specific.title || "";
3524
- resolve9(specific);
3572
+ resolve12(specific);
3525
3573
  } else {
3526
3574
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
3527
- resolve9(null);
3575
+ resolve12(null);
3528
3576
  }
3529
3577
  return;
3530
3578
  }
3531
3579
  this._pageTitle = list[0]?.title || "";
3532
- resolve9(list[0]);
3580
+ resolve12(list[0]);
3533
3581
  } catch {
3534
- resolve9(null);
3582
+ resolve12(null);
3535
3583
  }
3536
3584
  });
3537
3585
  });
3538
- req.on("error", () => resolve9(null));
3586
+ req.on("error", () => resolve12(null));
3539
3587
  req.setTimeout(2e3, () => {
3540
3588
  req.destroy();
3541
- resolve9(null);
3589
+ resolve12(null);
3542
3590
  });
3543
3591
  });
3544
3592
  }
@@ -3549,7 +3597,7 @@ var DaemonCdpManager = class {
3549
3597
  this.extensionProviders = providers;
3550
3598
  }
3551
3599
  connectToTarget(wsUrl) {
3552
- return new Promise((resolve9) => {
3600
+ return new Promise((resolve12) => {
3553
3601
  this.ws = new WebSocket(wsUrl);
3554
3602
  this.ws.on("open", async () => {
3555
3603
  this._connected = true;
@@ -3559,17 +3607,17 @@ var DaemonCdpManager = class {
3559
3607
  }
3560
3608
  this.connectBrowserWs().catch(() => {
3561
3609
  });
3562
- resolve9(true);
3610
+ resolve12(true);
3563
3611
  });
3564
3612
  this.ws.on("message", (data) => {
3565
3613
  try {
3566
3614
  const msg = JSON.parse(data.toString());
3567
3615
  if (msg.id && this.pending.has(msg.id)) {
3568
- const { resolve: resolve10, reject } = this.pending.get(msg.id);
3616
+ const { resolve: resolve13, reject } = this.pending.get(msg.id);
3569
3617
  this.pending.delete(msg.id);
3570
3618
  this.failureCount = 0;
3571
3619
  if (msg.error) reject(new Error(msg.error.message));
3572
- else resolve10(msg.result);
3620
+ else resolve13(msg.result);
3573
3621
  } else if (msg.method === "Runtime.executionContextCreated") {
3574
3622
  this.contexts.add(msg.params.context.id);
3575
3623
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -3592,7 +3640,7 @@ var DaemonCdpManager = class {
3592
3640
  this.ws.on("error", (err) => {
3593
3641
  this.log(`[CDP] WebSocket error: ${err.message}`);
3594
3642
  this._connected = false;
3595
- resolve9(false);
3643
+ resolve12(false);
3596
3644
  });
3597
3645
  });
3598
3646
  }
@@ -3606,7 +3654,7 @@ var DaemonCdpManager = class {
3606
3654
  return;
3607
3655
  }
3608
3656
  this.log(`[CDP] Connecting browser WS for target discovery...`);
3609
- await new Promise((resolve9, reject) => {
3657
+ await new Promise((resolve12, reject) => {
3610
3658
  this.browserWs = new WebSocket(browserWsUrl);
3611
3659
  this.browserWs.on("open", async () => {
3612
3660
  this._browserConnected = true;
@@ -3616,16 +3664,16 @@ var DaemonCdpManager = class {
3616
3664
  } catch (e) {
3617
3665
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
3618
3666
  }
3619
- resolve9();
3667
+ resolve12();
3620
3668
  });
3621
3669
  this.browserWs.on("message", (data) => {
3622
3670
  try {
3623
3671
  const msg = JSON.parse(data.toString());
3624
3672
  if (msg.id && this.browserPending.has(msg.id)) {
3625
- const { resolve: resolve10, reject: reject2 } = this.browserPending.get(msg.id);
3673
+ const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
3626
3674
  this.browserPending.delete(msg.id);
3627
3675
  if (msg.error) reject2(new Error(msg.error.message));
3628
- else resolve10(msg.result);
3676
+ else resolve13(msg.result);
3629
3677
  }
3630
3678
  } catch {
3631
3679
  }
@@ -3645,31 +3693,31 @@ var DaemonCdpManager = class {
3645
3693
  }
3646
3694
  }
3647
3695
  getBrowserWsUrl() {
3648
- return new Promise((resolve9) => {
3696
+ return new Promise((resolve12) => {
3649
3697
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
3650
3698
  let data = "";
3651
3699
  res.on("data", (chunk) => data += chunk.toString());
3652
3700
  res.on("end", () => {
3653
3701
  try {
3654
3702
  const info = JSON.parse(data);
3655
- resolve9(info.webSocketDebuggerUrl || null);
3703
+ resolve12(info.webSocketDebuggerUrl || null);
3656
3704
  } catch {
3657
- resolve9(null);
3705
+ resolve12(null);
3658
3706
  }
3659
3707
  });
3660
3708
  });
3661
- req.on("error", () => resolve9(null));
3709
+ req.on("error", () => resolve12(null));
3662
3710
  req.setTimeout(3e3, () => {
3663
3711
  req.destroy();
3664
- resolve9(null);
3712
+ resolve12(null);
3665
3713
  });
3666
3714
  });
3667
3715
  }
3668
3716
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
3669
- return new Promise((resolve9, reject) => {
3717
+ return new Promise((resolve12, reject) => {
3670
3718
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
3671
3719
  const id = this.browserMsgId++;
3672
- this.browserPending.set(id, { resolve: resolve9, reject });
3720
+ this.browserPending.set(id, { resolve: resolve12, reject });
3673
3721
  this.browserWs.send(JSON.stringify({ id, method, params }));
3674
3722
  setTimeout(() => {
3675
3723
  if (this.browserPending.has(id)) {
@@ -3709,11 +3757,11 @@ var DaemonCdpManager = class {
3709
3757
  }
3710
3758
  // ─── CDP Protocol ────────────────────────────────────────
3711
3759
  sendInternal(method, params = {}, timeoutMs = 15e3) {
3712
- return new Promise((resolve9, reject) => {
3760
+ return new Promise((resolve12, reject) => {
3713
3761
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
3714
3762
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
3715
3763
  const id = this.msgId++;
3716
- this.pending.set(id, { resolve: resolve9, reject });
3764
+ this.pending.set(id, { resolve: resolve12, reject });
3717
3765
  this.ws.send(JSON.stringify({ id, method, params }));
3718
3766
  setTimeout(() => {
3719
3767
  if (this.pending.has(id)) {
@@ -3962,7 +4010,7 @@ var DaemonCdpManager = class {
3962
4010
  const browserWs = this.browserWs;
3963
4011
  let msgId = this.browserMsgId;
3964
4012
  const sendWs = (method, params = {}, sessionId) => {
3965
- return new Promise((resolve9, reject) => {
4013
+ return new Promise((resolve12, reject) => {
3966
4014
  const mid = msgId++;
3967
4015
  this.browserMsgId = msgId;
3968
4016
  const handler = (raw) => {
@@ -3971,7 +4019,7 @@ var DaemonCdpManager = class {
3971
4019
  if (msg.id === mid) {
3972
4020
  browserWs.removeListener("message", handler);
3973
4021
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
3974
- else resolve9(msg.result);
4022
+ else resolve12(msg.result);
3975
4023
  }
3976
4024
  } catch {
3977
4025
  }
@@ -4162,14 +4210,14 @@ var DaemonCdpManager = class {
4162
4210
  if (!ws || ws.readyState !== WebSocket.OPEN) {
4163
4211
  throw new Error("CDP not connected");
4164
4212
  }
4165
- return new Promise((resolve9, reject) => {
4213
+ return new Promise((resolve12, reject) => {
4166
4214
  const id = getNextId();
4167
4215
  pendingMap.set(id, {
4168
4216
  resolve: (result) => {
4169
4217
  if (result?.result?.subtype === "error") {
4170
4218
  reject(new Error(result.result.description));
4171
4219
  } else {
4172
- resolve9(result?.result?.value);
4220
+ resolve12(result?.result?.value);
4173
4221
  }
4174
4222
  },
4175
4223
  reject
@@ -4201,10 +4249,10 @@ var DaemonCdpManager = class {
4201
4249
  throw new Error("CDP not connected");
4202
4250
  }
4203
4251
  const sendViaSession = (method, params = {}) => {
4204
- return new Promise((resolve9, reject) => {
4252
+ return new Promise((resolve12, reject) => {
4205
4253
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
4206
4254
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
4207
- pendingMap.set(id, { resolve: resolve9, reject });
4255
+ pendingMap.set(id, { resolve: resolve12, reject });
4208
4256
  ws.send(JSON.stringify({ id, sessionId, method, params }));
4209
4257
  setTimeout(() => {
4210
4258
  if (pendingMap.has(id)) {
@@ -4832,9 +4880,9 @@ function normalizeControlValue(value) {
4832
4880
 
4833
4881
  // src/config/chat-history.ts
4834
4882
  import * as fs3 from "fs";
4835
- import * as path5 from "path";
4883
+ import * as path7 from "path";
4836
4884
  import * as os5 from "os";
4837
- var HISTORY_DIR = path5.join(os5.homedir(), ".adhdev", "history");
4885
+ var HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
4838
4886
  var RETAIN_DAYS = 30;
4839
4887
  var ChatHistoryWriter = class {
4840
4888
  /** Last seen message count per agent (deduplication) */
@@ -4879,11 +4927,11 @@ var ChatHistoryWriter = class {
4879
4927
  });
4880
4928
  }
4881
4929
  if (newMessages.length === 0) return;
4882
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
4930
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
4883
4931
  fs3.mkdirSync(dir, { recursive: true });
4884
4932
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4885
4933
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
4886
- const filePath = path5.join(dir, `${filePrefix}${date}.jsonl`);
4934
+ const filePath = path7.join(dir, `${filePrefix}${date}.jsonl`);
4887
4935
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
4888
4936
  fs3.appendFileSync(filePath, lines, "utf-8");
4889
4937
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
@@ -4937,14 +4985,14 @@ var ChatHistoryWriter = class {
4937
4985
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
4938
4986
  this.lastSeenCounts.delete(fromDedupKey);
4939
4987
  }
4940
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
4988
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
4941
4989
  if (!fs3.existsSync(dir)) return;
4942
4990
  const fromPrefix = `${this.sanitize(fromId)}_`;
4943
4991
  const toPrefix = `${this.sanitize(toId)}_`;
4944
4992
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
4945
4993
  for (const file of files) {
4946
- const sourcePath = path5.join(dir, file);
4947
- const targetPath = path5.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
4994
+ const sourcePath = path7.join(dir, file);
4995
+ const targetPath = path7.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
4948
4996
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
4949
4997
  const rewritten = sourceLines.map((line) => {
4950
4998
  try {
@@ -4985,10 +5033,10 @@ var ChatHistoryWriter = class {
4985
5033
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
4986
5034
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
4987
5035
  for (const dir of agentDirs) {
4988
- const dirPath = path5.join(HISTORY_DIR, dir.name);
5036
+ const dirPath = path7.join(HISTORY_DIR, dir.name);
4989
5037
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
4990
5038
  for (const file of files) {
4991
- const filePath = path5.join(dirPath, file);
5039
+ const filePath = path7.join(dirPath, file);
4992
5040
  const stat = fs3.statSync(filePath);
4993
5041
  if (stat.mtimeMs < cutoff) {
4994
5042
  fs3.unlinkSync(filePath);
@@ -5006,7 +5054,7 @@ var ChatHistoryWriter = class {
5006
5054
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
5007
5055
  try {
5008
5056
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
5009
- const dir = path5.join(HISTORY_DIR, sanitized);
5057
+ const dir = path7.join(HISTORY_DIR, sanitized);
5010
5058
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
5011
5059
  const sanitizedInstance = historySessionId?.replace(/[^a-zA-Z0-9_-]/g, "_");
5012
5060
  const files = fs3.readdirSync(dir).filter((f) => {
@@ -5020,7 +5068,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
5020
5068
  const needed = offset + limit + 1;
5021
5069
  for (const file of files) {
5022
5070
  if (allMessages.length >= needed) break;
5023
- const filePath = path5.join(dir, file);
5071
+ const filePath = path7.join(dir, file);
5024
5072
  const content = fs3.readFileSync(filePath, "utf-8");
5025
5073
  const lines = content.trim().split("\n").filter(Boolean);
5026
5074
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -5042,7 +5090,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
5042
5090
  function listSavedHistorySessions(agentType, options = {}) {
5043
5091
  try {
5044
5092
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
5045
- const dir = path5.join(HISTORY_DIR, sanitized);
5093
+ const dir = path7.join(HISTORY_DIR, sanitized);
5046
5094
  if (!fs3.existsSync(dir)) return { sessions: [], hasMore: false };
5047
5095
  const groupedFiles = /* @__PURE__ */ new Map();
5048
5096
  const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
@@ -5063,7 +5111,7 @@ function listSavedHistorySessions(agentType, options = {}) {
5063
5111
  let sessionTitle = "";
5064
5112
  let preview = "";
5065
5113
  for (const file of files.sort()) {
5066
- const filePath = path5.join(dir, file);
5114
+ const filePath = path7.join(dir, file);
5067
5115
  const content = fs3.readFileSync(filePath, "utf-8");
5068
5116
  const lines = content.split("\n").filter(Boolean);
5069
5117
  for (const line of lines) {
@@ -7238,6 +7286,14 @@ async function handleListChats(h, args) {
7238
7286
  } catch {
7239
7287
  }
7240
7288
  }
7289
+ if (parsed?.sessions && Array.isArray(parsed.sessions)) {
7290
+ LOG.info("Command", `[list_chats] OK: ${parsed.sessions.length} chats`);
7291
+ return { success: true, chats: parsed.sessions };
7292
+ }
7293
+ if (parsed?.chats && Array.isArray(parsed.chats)) {
7294
+ LOG.info("Command", `[list_chats] OK: ${parsed.chats.length} chats`);
7295
+ return { success: true, chats: parsed.chats };
7296
+ }
7241
7297
  if (Array.isArray(parsed)) {
7242
7298
  LOG.info("Command", `[list_chats] OK: ${parsed.length} chats`);
7243
7299
  return { success: true, chats: parsed };
@@ -7307,7 +7363,13 @@ async function handleSwitchChat(h, args) {
7307
7363
  } catch (e) {
7308
7364
  return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
7309
7365
  }
7310
- const script = h.getProviderScript("switchSession", { SESSION_ID: JSON.stringify(sessionId) }) || h.getProviderScript("switch_session", { SESSION_ID: JSON.stringify(sessionId) });
7366
+ const switchParams = {
7367
+ sessionId,
7368
+ title: sessionId,
7369
+ id: sessionId,
7370
+ SESSION_ID: JSON.stringify(sessionId)
7371
+ };
7372
+ const script = h.getProviderScript("switchSession", switchParams) || h.getProviderScript("switch_session", switchParams);
7311
7373
  if (!script) return { success: false, error: "switch_session script not available" };
7312
7374
  try {
7313
7375
  const raw = await cdp.evaluate(script, 15e3);
@@ -7386,8 +7448,8 @@ async function handleSetMode(h, args) {
7386
7448
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
7387
7449
  if (adapter) {
7388
7450
  const acpInstance = adapter._acpInstance;
7389
- if (acpInstance && typeof acpInstance.onEvent === "function") {
7390
- acpInstance.onEvent("set_mode", { mode });
7451
+ if (acpInstance && typeof acpInstance.setMode === "function") {
7452
+ await acpInstance.setMode(mode);
7391
7453
  return { success: true, mode };
7392
7454
  }
7393
7455
  }
@@ -7444,9 +7506,9 @@ async function handleChangeModel(h, args) {
7444
7506
  LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
7445
7507
  if (adapter) {
7446
7508
  const acpInstance = adapter._acpInstance;
7447
- if (acpInstance && typeof acpInstance.onEvent === "function") {
7448
- acpInstance.onEvent("change_model", { model });
7449
- LOG.info("Command", `[change_model] Dispatched change_model event to ACP instance`);
7509
+ if (acpInstance && typeof acpInstance.setConfigOption === "function") {
7510
+ await acpInstance.setConfigOption("model", model);
7511
+ LOG.info("Command", `[change_model] Updated ACP model to ${model}`);
7450
7512
  return { success: true, model };
7451
7513
  }
7452
7514
  }
@@ -7566,6 +7628,18 @@ async function handleResolveAction(h, args) {
7566
7628
  const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
7567
7629
  return { success: ok };
7568
7630
  }
7631
+ if (transport === "acp") {
7632
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
7633
+ const acpInstance = adapter?._acpInstance;
7634
+ if (!acpInstance) return { success: false, error: "ACP instance not found" };
7635
+ try {
7636
+ await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
7637
+ LOG.info("Command", `[resolveAction] ACP \u2192 ${action}`);
7638
+ return { success: true, action };
7639
+ } catch (e) {
7640
+ return { success: false, error: e?.message || "ACP resolve action failed" };
7641
+ }
7642
+ }
7569
7643
  if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
7570
7644
  const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
7571
7645
  if (script) {
@@ -7644,7 +7718,7 @@ async function handleResolveAction(h, args) {
7644
7718
 
7645
7719
  // src/commands/cdp-commands.ts
7646
7720
  import * as fs4 from "fs";
7647
- import * as path6 from "path";
7721
+ import * as path8 from "path";
7648
7722
  import * as os6 from "os";
7649
7723
  var KEY_TO_VK = {
7650
7724
  Backspace: 8,
@@ -7896,25 +7970,25 @@ function resolveSafePath(requestedPath) {
7896
7970
  const inputPath = rawPath || ".";
7897
7971
  const home = os6.homedir();
7898
7972
  if (inputPath.startsWith("~")) {
7899
- return path6.resolve(path6.join(home, inputPath.slice(1)));
7973
+ return path8.resolve(path8.join(home, inputPath.slice(1)));
7900
7974
  }
7901
7975
  if (process.platform === "win32") {
7902
7976
  const normalized = normalizeWindowsRequestedPath(inputPath);
7903
- if (path6.win32.isAbsolute(normalized)) {
7904
- return path6.win32.normalize(normalized);
7977
+ if (path8.win32.isAbsolute(normalized)) {
7978
+ return path8.win32.normalize(normalized);
7905
7979
  }
7906
- return path6.win32.resolve(normalized);
7980
+ return path8.win32.resolve(normalized);
7907
7981
  }
7908
- if (path6.isAbsolute(inputPath)) {
7909
- return path6.normalize(inputPath);
7982
+ if (path8.isAbsolute(inputPath)) {
7983
+ return path8.normalize(inputPath);
7910
7984
  }
7911
- return path6.resolve(inputPath);
7985
+ return path8.resolve(inputPath);
7912
7986
  }
7913
7987
  function listDirectoryEntriesSafe(dirPath) {
7914
7988
  const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
7915
7989
  const files = [];
7916
7990
  for (const entry of entries) {
7917
- const entryPath = path6.join(dirPath, entry.name);
7991
+ const entryPath = path8.join(dirPath, entry.name);
7918
7992
  try {
7919
7993
  if (entry.isDirectory()) {
7920
7994
  files.push({ name: entry.name, type: "directory" });
@@ -7953,7 +8027,7 @@ async function handleFileRead(h, args) {
7953
8027
  async function handleFileWrite(h, args) {
7954
8028
  try {
7955
8029
  const filePath = resolveSafePath(args?.path);
7956
- fs4.mkdirSync(path6.dirname(filePath), { recursive: true });
8030
+ fs4.mkdirSync(path8.dirname(filePath), { recursive: true });
7957
8031
  fs4.writeFileSync(filePath, args?.content || "", "utf-8");
7958
8032
  return { success: true, path: filePath };
7959
8033
  } catch (e) {
@@ -8041,7 +8115,7 @@ function handleGetProviderSettings(h, args) {
8041
8115
  }
8042
8116
  return { success: true, settings: allSettings, values: allValues };
8043
8117
  }
8044
- function handleSetProviderSetting(h, args) {
8118
+ async function handleSetProviderSetting(h, args) {
8045
8119
  const loader = h.ctx.providerLoader;
8046
8120
  const { providerType, key, value } = args || {};
8047
8121
  if (!providerType || !key || value === void 0) {
@@ -8054,6 +8128,7 @@ function handleSetProviderSetting(h, args) {
8054
8128
  const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
8055
8129
  LOG.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
8056
8130
  }
8131
+ await h.ctx.onProviderSettingChanged?.(providerType, key, value);
8057
8132
  return { success: true, providerType, key, value };
8058
8133
  }
8059
8134
  return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
@@ -8091,10 +8166,10 @@ function getCliScriptCommand(payload) {
8091
8166
  }
8092
8167
  const command = payload.command;
8093
8168
  if (!command || typeof command !== "object") return null;
8094
- if (command.type !== "send_message") return null;
8169
+ if (command.type !== "send_message" && command.type !== "pty_write") return null;
8095
8170
  const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
8096
8171
  if (!text) return null;
8097
- return { type: "send_message", text };
8172
+ return { type: command.type, text };
8098
8173
  }
8099
8174
  function applyProviderPatch(h, args, payload) {
8100
8175
  if (!payload || typeof payload !== "object") return;
@@ -8135,6 +8210,8 @@ async function executeProviderScript(h, args, scriptName) {
8135
8210
  const cliCommand = getCliScriptCommand(parsed.payload);
8136
8211
  if (cliCommand?.type === "send_message" && cliCommand.text) {
8137
8212
  await adapter.sendMessage(cliCommand.text);
8213
+ } else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
8214
+ adapter.writeRaw(cliCommand.text + "\r");
8138
8215
  }
8139
8216
  applyProviderPatch(h, args, parsed.payload);
8140
8217
  return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
@@ -8813,7 +8890,7 @@ var DaemonCommandHandler = class {
8813
8890
  try {
8814
8891
  const http3 = await import("http");
8815
8892
  const postData = JSON.stringify(body);
8816
- const result = await new Promise((resolve9, reject) => {
8893
+ const result = await new Promise((resolve12, reject) => {
8817
8894
  const req = http3.request({
8818
8895
  hostname: "127.0.0.1",
8819
8896
  port: 19280,
@@ -8825,9 +8902,9 @@ var DaemonCommandHandler = class {
8825
8902
  res.on("data", (chunk) => data += chunk);
8826
8903
  res.on("end", () => {
8827
8904
  try {
8828
- resolve9(JSON.parse(data));
8905
+ resolve12(JSON.parse(data));
8829
8906
  } catch {
8830
- resolve9({ raw: data });
8907
+ resolve12({ raw: data });
8831
8908
  }
8832
8909
  });
8833
8910
  });
@@ -8845,15 +8922,15 @@ var DaemonCommandHandler = class {
8845
8922
  if (!providerType) return { success: false, error: "providerType required" };
8846
8923
  try {
8847
8924
  const http3 = await import("http");
8848
- const result = await new Promise((resolve9, reject) => {
8925
+ const result = await new Promise((resolve12, reject) => {
8849
8926
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
8850
8927
  let data = "";
8851
8928
  res.on("data", (chunk) => data += chunk);
8852
8929
  res.on("end", () => {
8853
8930
  try {
8854
- resolve9(JSON.parse(data));
8931
+ resolve12(JSON.parse(data));
8855
8932
  } catch {
8856
- resolve9({ raw: data });
8933
+ resolve12({ raw: data });
8857
8934
  }
8858
8935
  });
8859
8936
  }).on("error", reject);
@@ -8867,7 +8944,7 @@ var DaemonCommandHandler = class {
8867
8944
  try {
8868
8945
  const http3 = await import("http");
8869
8946
  const postData = JSON.stringify(args || {});
8870
- const result = await new Promise((resolve9, reject) => {
8947
+ const result = await new Promise((resolve12, reject) => {
8871
8948
  const req = http3.request({
8872
8949
  hostname: "127.0.0.1",
8873
8950
  port: 19280,
@@ -8879,9 +8956,9 @@ var DaemonCommandHandler = class {
8879
8956
  res.on("data", (chunk) => data += chunk);
8880
8957
  res.on("end", () => {
8881
8958
  try {
8882
- resolve9(JSON.parse(data));
8959
+ resolve12(JSON.parse(data));
8883
8960
  } catch {
8884
- resolve9({ raw: data });
8961
+ resolve12({ raw: data });
8885
8962
  }
8886
8963
  });
8887
8964
  });
@@ -8899,7 +8976,7 @@ var DaemonCommandHandler = class {
8899
8976
  // src/commands/cli-manager.ts
8900
8977
  init_provider_cli_adapter();
8901
8978
  import * as os10 from "os";
8902
- import * as path9 from "path";
8979
+ import * as path11 from "path";
8903
8980
  import * as crypto4 from "crypto";
8904
8981
  import chalk from "chalk";
8905
8982
  init_config();
@@ -8907,7 +8984,7 @@ init_config();
8907
8984
  // src/providers/cli-provider-instance.ts
8908
8985
  init_provider_cli_adapter();
8909
8986
  import * as os9 from "os";
8910
- import * as path8 from "path";
8987
+ import * as path10 from "path";
8911
8988
  import * as crypto3 from "crypto";
8912
8989
  import * as fs5 from "fs";
8913
8990
  import { createRequire } from "module";
@@ -8915,7 +8992,7 @@ init_logger();
8915
8992
  var CachedDatabaseSync = null;
8916
8993
  function getDatabaseSync() {
8917
8994
  if (CachedDatabaseSync) return CachedDatabaseSync;
8918
- const requireFn = typeof __require === "function" ? __require : createRequire(path8.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
8995
+ const requireFn = typeof __require === "function" ? __require : createRequire(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
8919
8996
  const sqliteModule = requireFn(`node:${"sqlite"}`);
8920
8997
  CachedDatabaseSync = sqliteModule.DatabaseSync;
8921
8998
  if (!CachedDatabaseSync) {
@@ -9749,8 +9826,9 @@ var AcpProviderInstance = class {
9749
9826
  async setConfigOption(category, value) {
9750
9827
  const opt = this.configOptions.find((c) => c.category === category);
9751
9828
  if (!opt) {
9752
- this.log.warn(`[${this.type}] No config option for category: ${category}`);
9753
- return;
9829
+ const message = `[${this.type}] No config option for category: ${category}`;
9830
+ this.log.warn(message);
9831
+ throw new Error(message);
9754
9832
  }
9755
9833
  if (this.useStaticConfig) {
9756
9834
  opt.currentValue = value;
@@ -9762,8 +9840,9 @@ var AcpProviderInstance = class {
9762
9840
  return;
9763
9841
  }
9764
9842
  if (!this.connection || !this.sessionId) {
9765
- this.log.warn(`[${this.type}] Cannot set config: no active connection/session`);
9766
- return;
9843
+ const message = `[${this.type}] Cannot set config: no active connection/session`;
9844
+ this.log.warn(message);
9845
+ throw new Error(message);
9767
9846
  }
9768
9847
  try {
9769
9848
  this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
@@ -9777,7 +9856,9 @@ var AcpProviderInstance = class {
9777
9856
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
9778
9857
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
9779
9858
  } catch (e) {
9780
- this.log.warn(`[${this.type}] set_config_option failed: ${e?.message}`);
9859
+ const message = e?.message || "Unknown ACP config error";
9860
+ this.log.warn(`[${this.type}] set_config_option failed: ${message}`);
9861
+ throw new Error(message);
9781
9862
  }
9782
9863
  }
9783
9864
  async setMode(modeId) {
@@ -9793,8 +9874,9 @@ var AcpProviderInstance = class {
9793
9874
  return;
9794
9875
  }
9795
9876
  if (!this.connection || !this.sessionId) {
9796
- this.log.warn(`[${this.type}] Cannot set mode: no active connection/session`);
9797
- return;
9877
+ const message = `[${this.type}] Cannot set mode: no active connection/session`;
9878
+ this.log.warn(message);
9879
+ throw new Error(message);
9798
9880
  }
9799
9881
  try {
9800
9882
  await this.connection.setSessionMode({
@@ -9804,7 +9886,9 @@ var AcpProviderInstance = class {
9804
9886
  this.currentMode = modeId;
9805
9887
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
9806
9888
  } catch (e) {
9807
- this.log.warn(`[${this.type}] set_mode failed: ${e?.message}`);
9889
+ const message = e?.message || "Unknown ACP mode error";
9890
+ this.log.warn(`[${this.type}] set_mode failed: ${message}`);
9891
+ throw new Error(message);
9808
9892
  }
9809
9893
  }
9810
9894
  /** Static config: kill process and restart with new args */
@@ -9852,7 +9936,7 @@ var AcpProviderInstance = class {
9852
9936
  if (!spawnConfig) {
9853
9937
  throw new Error(`[ACP:${this.type}] No spawn config defined`);
9854
9938
  }
9855
- const command = spawnConfig.command;
9939
+ const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
9856
9940
  let baseArgs = spawnConfig.args || [];
9857
9941
  if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
9858
9942
  baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
@@ -9968,13 +10052,13 @@ var AcpProviderInstance = class {
9968
10052
  }
9969
10053
  this.currentStatus = "waiting_approval";
9970
10054
  this.detectStatusTransition();
9971
- const approved = await new Promise((resolve9) => {
9972
- this.permissionResolvers.push(resolve9);
10055
+ const approved = await new Promise((resolve12) => {
10056
+ this.permissionResolvers.push(resolve12);
9973
10057
  setTimeout(() => {
9974
- const idx = this.permissionResolvers.indexOf(resolve9);
10058
+ const idx = this.permissionResolvers.indexOf(resolve12);
9975
10059
  if (idx >= 0) {
9976
10060
  this.permissionResolvers.splice(idx, 1);
9977
- resolve9(false);
10061
+ resolve12(false);
9978
10062
  }
9979
10063
  }, 3e5);
9980
10064
  });
@@ -10681,7 +10765,7 @@ var DaemonCliManager = class {
10681
10765
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
10682
10766
  const trimmed = (workingDir || "").trim();
10683
10767
  if (!trimmed) throw new Error("working directory required");
10684
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path9.resolve(trimmed);
10768
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os10.homedir()) : path11.resolve(trimmed);
10685
10769
  const normalizedType = this.providerLoader.resolveAlias(cliType);
10686
10770
  const provider = this.providerLoader.getByAlias(cliType);
10687
10771
  const key = crypto4.randomUUID();
@@ -10768,10 +10852,10 @@ ${installInfo}`
10768
10852
  if (!cliInfo) {
10769
10853
  const installHint = provider?.install || "";
10770
10854
  const displayName = provider?.displayName || provider?.name || cliType;
10771
- const spawnCmd = provider?.spawn?.command || cliType;
10855
+ const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
10772
10856
  throw new Error(
10773
10857
  `${displayName} is not installed.
10774
- Command '${spawnCmd}' not found on PATH.
10858
+ Command '${spawnCmd}' is not available.
10775
10859
  ` + (installHint ? `
10776
10860
  ${installHint}
10777
10861
  ` : "") + `
@@ -11131,16 +11215,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
11131
11215
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
11132
11216
  import * as net from "net";
11133
11217
  import * as os12 from "os";
11134
- import * as path11 from "path";
11218
+ import * as path13 from "path";
11135
11219
 
11136
11220
  // src/providers/provider-loader.ts
11137
11221
  import * as fs6 from "fs";
11138
- import * as path10 from "path";
11222
+ import * as path12 from "path";
11139
11223
  import * as os11 from "os";
11140
11224
  import * as chokidar from "chokidar";
11141
11225
  init_logger();
11142
11226
  var ProviderLoader = class _ProviderLoader {
11143
11227
  providers = /* @__PURE__ */ new Map();
11228
+ providerAvailability = /* @__PURE__ */ new Map();
11144
11229
  userDir;
11145
11230
  upstreamDir;
11146
11231
  disableUpstream;
@@ -11156,12 +11241,12 @@ var ProviderLoader = class _ProviderLoader {
11156
11241
  static META_FILE = ".meta.json";
11157
11242
  constructor(options) {
11158
11243
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
11159
- const defaultProvidersDir = path10.join(os11.homedir(), ".adhdev", "providers");
11244
+ const defaultProvidersDir = path12.join(os11.homedir(), ".adhdev", "providers");
11160
11245
  if (options?.userDir) {
11161
11246
  this.userDir = options.userDir;
11162
11247
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
11163
11248
  } else {
11164
- const localRepoPath = path10.resolve(__dirname, "../../../../../adhdev-providers");
11249
+ const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
11165
11250
  if (fs6.existsSync(localRepoPath)) {
11166
11251
  this.userDir = localRepoPath;
11167
11252
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -11170,7 +11255,7 @@ var ProviderLoader = class _ProviderLoader {
11170
11255
  this.log(`Using default user providers directory: ${this.userDir}`);
11171
11256
  }
11172
11257
  }
11173
- this.upstreamDir = path10.join(defaultProvidersDir, ".upstream");
11258
+ this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
11174
11259
  this.disableUpstream = options?.disableUpstream ?? false;
11175
11260
  }
11176
11261
  log(msg) {
@@ -11200,7 +11285,7 @@ var ProviderLoader = class _ProviderLoader {
11200
11285
  * Canonical provider directory shape for a given root.
11201
11286
  */
11202
11287
  getProviderDir(root, category, type) {
11203
- return path10.join(root, category, type);
11288
+ return path12.join(root, category, type);
11204
11289
  }
11205
11290
  /**
11206
11291
  * Canonical user override directory for a provider.
@@ -11227,7 +11312,7 @@ var ProviderLoader = class _ProviderLoader {
11227
11312
  resolveProviderFile(type, ...segments) {
11228
11313
  const dir = this.findProviderDirInternal(type);
11229
11314
  if (!dir) return null;
11230
- return path10.join(dir, ...segments);
11315
+ return path12.join(dir, ...segments);
11231
11316
  }
11232
11317
  /**
11233
11318
  * Load all providers (3-tier priority)
@@ -11238,6 +11323,7 @@ var ProviderLoader = class _ProviderLoader {
11238
11323
  */
11239
11324
  loadAll() {
11240
11325
  this.providers.clear();
11326
+ this.providerAvailability.clear();
11241
11327
  let upstreamCount = 0;
11242
11328
  if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
11243
11329
  upstreamCount = this.loadDir(this.upstreamDir);
@@ -11265,7 +11351,7 @@ var ProviderLoader = class _ProviderLoader {
11265
11351
  if (!fs6.existsSync(this.upstreamDir)) return false;
11266
11352
  try {
11267
11353
  return fs6.readdirSync(this.upstreamDir).some(
11268
- (d) => fs6.statSync(path10.join(this.upstreamDir, d)).isDirectory()
11354
+ (d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
11269
11355
  );
11270
11356
  } catch {
11271
11357
  return false;
@@ -11308,11 +11394,12 @@ var ProviderLoader = class _ProviderLoader {
11308
11394
  if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
11309
11395
  const verCmdConfig = p.versionCommand;
11310
11396
  const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
11397
+ const command = this.getSpawnCommand(p.type, p.spawn.command);
11311
11398
  result.push({
11312
11399
  id: p.type,
11313
11400
  displayName: p.displayName || p.name,
11314
11401
  icon: p.icon || "\u{1F527}",
11315
- command: p.spawn.command,
11402
+ command,
11316
11403
  category: p.category,
11317
11404
  ...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
11318
11405
  });
@@ -11441,6 +11528,71 @@ var ProviderLoader = class _ProviderLoader {
11441
11528
  getAvailableIdeTypes() {
11442
11529
  return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
11443
11530
  }
11531
+ getSpawnCommand(type, fallback) {
11532
+ const override = this.getOptionalStringSetting(type, "executablePath");
11533
+ if (override) return override;
11534
+ return fallback || this.providers.get(type)?.spawn?.command || type;
11535
+ }
11536
+ getIdeCliCommand(type, fallback) {
11537
+ const override = this.getOptionalStringSetting(type, "cliPathOverride");
11538
+ if (override) return override;
11539
+ return fallback || this.providers.get(type)?.cli || null;
11540
+ }
11541
+ getIdePathCandidates(type, fallback) {
11542
+ const override = this.getOptionalStringSetting(type, "appPathOverride");
11543
+ if (override) return [override];
11544
+ if (fallback && fallback.length > 0) return fallback;
11545
+ const osPaths = this.providers.get(type)?.paths?.[process.platform];
11546
+ return Array.isArray(osPaths) ? [...osPaths] : [];
11547
+ }
11548
+ setProviderAvailability(type, state) {
11549
+ this.providerAvailability.set(type, {
11550
+ installed: !!state.installed,
11551
+ detectedPath: state.detectedPath ?? null
11552
+ });
11553
+ }
11554
+ setCliDetectionResults(results, replace = true) {
11555
+ if (replace) {
11556
+ for (const provider of this.providers.values()) {
11557
+ if (provider.category === "cli" || provider.category === "acp") {
11558
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
11559
+ }
11560
+ }
11561
+ }
11562
+ for (const result of results) {
11563
+ this.setProviderAvailability(result.id, {
11564
+ installed: !!result.installed,
11565
+ detectedPath: result.path || null
11566
+ });
11567
+ }
11568
+ }
11569
+ setIdeDetectionResults(results, replace = true) {
11570
+ if (replace) {
11571
+ for (const provider of this.providers.values()) {
11572
+ if (provider.category === "ide") {
11573
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
11574
+ }
11575
+ }
11576
+ }
11577
+ for (const result of results) {
11578
+ this.setProviderAvailability(result.id, {
11579
+ installed: !!result.installed,
11580
+ detectedPath: result.cliCommand || result.path || null
11581
+ });
11582
+ }
11583
+ }
11584
+ getAvailableProviderInfos() {
11585
+ return this.getAll().map((provider) => {
11586
+ const availability = this.providerAvailability.get(provider.type);
11587
+ return {
11588
+ ...provider,
11589
+ ...availability ? {
11590
+ installed: availability.installed,
11591
+ detectedPath: availability.detectedPath
11592
+ } : {}
11593
+ };
11594
+ });
11595
+ }
11444
11596
  /**
11445
11597
  * Register IDE providers to core/detector registry
11446
11598
  * → Enables detectIDEs() to detect provider.js-based IDEs
@@ -11515,8 +11667,8 @@ var ProviderLoader = class _ProviderLoader {
11515
11667
  resolved._resolvedScriptDir = entry.scriptDir;
11516
11668
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
11517
11669
  if (providerDir) {
11518
- const fullDir = path10.join(providerDir, entry.scriptDir);
11519
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11670
+ const fullDir = path12.join(providerDir, entry.scriptDir);
11671
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11520
11672
  }
11521
11673
  matched = true;
11522
11674
  }
@@ -11531,8 +11683,8 @@ var ProviderLoader = class _ProviderLoader {
11531
11683
  resolved._resolvedScriptDir = base.defaultScriptDir;
11532
11684
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
11533
11685
  if (providerDir) {
11534
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
11535
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11686
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
11687
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11536
11688
  }
11537
11689
  }
11538
11690
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -11549,8 +11701,8 @@ var ProviderLoader = class _ProviderLoader {
11549
11701
  resolved._resolvedScriptDir = dirOverride;
11550
11702
  resolved._resolvedScriptsSource = `versions:${range}`;
11551
11703
  if (providerDir) {
11552
- const fullDir = path10.join(providerDir, dirOverride);
11553
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11704
+ const fullDir = path12.join(providerDir, dirOverride);
11705
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11554
11706
  }
11555
11707
  }
11556
11708
  } else if (override.scripts) {
@@ -11566,8 +11718,8 @@ var ProviderLoader = class _ProviderLoader {
11566
11718
  resolved._resolvedScriptDir = base.defaultScriptDir;
11567
11719
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
11568
11720
  if (providerDir) {
11569
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
11570
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
11721
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
11722
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
11571
11723
  }
11572
11724
  }
11573
11725
  }
@@ -11592,14 +11744,14 @@ var ProviderLoader = class _ProviderLoader {
11592
11744
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
11593
11745
  return null;
11594
11746
  }
11595
- const dir = path10.join(providerDir, scriptDir);
11747
+ const dir = path12.join(providerDir, scriptDir);
11596
11748
  if (!fs6.existsSync(dir)) {
11597
11749
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
11598
11750
  return null;
11599
11751
  }
11600
11752
  const cached = this.scriptsCache.get(dir);
11601
11753
  if (cached) return cached;
11602
- const scriptsJs = path10.join(dir, "scripts.js");
11754
+ const scriptsJs = path12.join(dir, "scripts.js");
11603
11755
  if (fs6.existsSync(scriptsJs)) {
11604
11756
  try {
11605
11757
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -11641,7 +11793,7 @@ var ProviderLoader = class _ProviderLoader {
11641
11793
  return;
11642
11794
  }
11643
11795
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
11644
- this.log(`File changed: ${path10.basename(filePath)}, reloading...`);
11796
+ this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
11645
11797
  this.reload();
11646
11798
  }
11647
11799
  };
@@ -11696,7 +11848,7 @@ var ProviderLoader = class _ProviderLoader {
11696
11848
  }
11697
11849
  const https = __require("https");
11698
11850
  const { execSync: execSync7 } = __require("child_process");
11699
- const metaPath = path10.join(this.upstreamDir, _ProviderLoader.META_FILE);
11851
+ const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
11700
11852
  let prevEtag = "";
11701
11853
  let prevTimestamp = 0;
11702
11854
  try {
@@ -11713,7 +11865,7 @@ var ProviderLoader = class _ProviderLoader {
11713
11865
  return { updated: false };
11714
11866
  }
11715
11867
  try {
11716
- const etag = await new Promise((resolve9, reject) => {
11868
+ const etag = await new Promise((resolve12, reject) => {
11717
11869
  const options = {
11718
11870
  method: "HEAD",
11719
11871
  hostname: "github.com",
@@ -11731,7 +11883,7 @@ var ProviderLoader = class _ProviderLoader {
11731
11883
  headers: { "User-Agent": "adhdev-launcher" },
11732
11884
  timeout: 1e4
11733
11885
  }, (res2) => {
11734
- resolve9(res2.headers.etag || res2.headers["last-modified"] || "");
11886
+ resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
11735
11887
  });
11736
11888
  req2.on("error", reject);
11737
11889
  req2.on("timeout", () => {
@@ -11740,7 +11892,7 @@ var ProviderLoader = class _ProviderLoader {
11740
11892
  });
11741
11893
  req2.end();
11742
11894
  } else {
11743
- resolve9(res.headers.etag || res.headers["last-modified"] || "");
11895
+ resolve12(res.headers.etag || res.headers["last-modified"] || "");
11744
11896
  }
11745
11897
  });
11746
11898
  req.on("error", reject);
@@ -11756,17 +11908,17 @@ var ProviderLoader = class _ProviderLoader {
11756
11908
  return { updated: false };
11757
11909
  }
11758
11910
  this.log("Downloading latest providers from GitHub...");
11759
- const tmpTar = path10.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
11760
- const tmpExtract = path10.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
11911
+ const tmpTar = path12.join(os11.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
11912
+ const tmpExtract = path12.join(os11.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
11761
11913
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
11762
11914
  fs6.mkdirSync(tmpExtract, { recursive: true });
11763
11915
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
11764
11916
  const extracted = fs6.readdirSync(tmpExtract);
11765
11917
  const rootDir = extracted.find(
11766
- (d) => fs6.statSync(path10.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
11918
+ (d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
11767
11919
  );
11768
11920
  if (!rootDir) throw new Error("Unexpected tarball structure");
11769
- const sourceDir = path10.join(tmpExtract, rootDir);
11921
+ const sourceDir = path12.join(tmpExtract, rootDir);
11770
11922
  const backupDir = this.upstreamDir + ".bak";
11771
11923
  if (fs6.existsSync(this.upstreamDir)) {
11772
11924
  if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
@@ -11804,7 +11956,7 @@ var ProviderLoader = class _ProviderLoader {
11804
11956
  downloadFile(url, destPath) {
11805
11957
  const https = __require("https");
11806
11958
  const http3 = __require("http");
11807
- return new Promise((resolve9, reject) => {
11959
+ return new Promise((resolve12, reject) => {
11808
11960
  const doRequest = (reqUrl, redirectCount = 0) => {
11809
11961
  if (redirectCount > 5) {
11810
11962
  reject(new Error("Too many redirects"));
@@ -11824,7 +11976,7 @@ var ProviderLoader = class _ProviderLoader {
11824
11976
  res.pipe(ws);
11825
11977
  ws.on("finish", () => {
11826
11978
  ws.close();
11827
- resolve9();
11979
+ resolve12();
11828
11980
  });
11829
11981
  ws.on("error", reject);
11830
11982
  });
@@ -11841,8 +11993,8 @@ var ProviderLoader = class _ProviderLoader {
11841
11993
  copyDirRecursive(src, dest) {
11842
11994
  fs6.mkdirSync(dest, { recursive: true });
11843
11995
  for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
11844
- const srcPath = path10.join(src, entry.name);
11845
- const destPath = path10.join(dest, entry.name);
11996
+ const srcPath = path12.join(src, entry.name);
11997
+ const destPath = path12.join(dest, entry.name);
11846
11998
  if (entry.isDirectory()) {
11847
11999
  this.copyDirRecursive(srcPath, destPath);
11848
12000
  } else {
@@ -11853,7 +12005,7 @@ var ProviderLoader = class _ProviderLoader {
11853
12005
  /** .meta.json save */
11854
12006
  writeMeta(metaPath, etag, timestamp) {
11855
12007
  try {
11856
- fs6.mkdirSync(path10.dirname(metaPath), { recursive: true });
12008
+ fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
11857
12009
  fs6.writeFileSync(metaPath, JSON.stringify({
11858
12010
  etag,
11859
12011
  timestamp,
@@ -11870,7 +12022,7 @@ var ProviderLoader = class _ProviderLoader {
11870
12022
  const scan = (d) => {
11871
12023
  try {
11872
12024
  for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
11873
- if (entry.isDirectory()) scan(path10.join(d, entry.name));
12025
+ if (entry.isDirectory()) scan(path12.join(d, entry.name));
11874
12026
  else if (entry.name === "provider.json") count++;
11875
12027
  }
11876
12028
  } catch {
@@ -11884,9 +12036,8 @@ var ProviderLoader = class _ProviderLoader {
11884
12036
  * Get public settings schema for a provider (for dashboard UI rendering)
11885
12037
  */
11886
12038
  getPublicSettings(type) {
11887
- const provider = this.providers.get(type);
11888
- if (!provider?.settings) return [];
11889
- return Object.entries(provider.settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
12039
+ const settings = this.getSettingsSchema(type);
12040
+ return Object.entries(settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
11890
12041
  }
11891
12042
  /**
11892
12043
  * Get public settings schema for all providers
@@ -11903,8 +12054,7 @@ var ProviderLoader = class _ProviderLoader {
11903
12054
  * Resolved setting value for a provider (default + user override)
11904
12055
  */
11905
12056
  getSettingValue(type, key) {
11906
- const provider = this.providers.get(type);
11907
- const schemaDef = provider?.settings?.[key];
12057
+ const schemaDef = this.getSettingsSchema(type)[key];
11908
12058
  const defaultVal = schemaDef ? schemaDef.default : void 0;
11909
12059
  try {
11910
12060
  const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
@@ -11919,10 +12069,9 @@ var ProviderLoader = class _ProviderLoader {
11919
12069
  * All resolved settings for a provider (default + user override)
11920
12070
  */
11921
12071
  getSettings(type) {
11922
- const provider = this.providers.get(type);
11923
- if (!provider?.settings) return {};
12072
+ const settings = this.getSettingsSchema(type);
11924
12073
  const result = {};
11925
- for (const [key, def] of Object.entries(provider.settings)) {
12074
+ for (const [key] of Object.entries(settings)) {
11926
12075
  result[key] = this.getSettingValue(type, key);
11927
12076
  }
11928
12077
  return result;
@@ -11931,11 +12080,11 @@ var ProviderLoader = class _ProviderLoader {
11931
12080
  * Save provider setting value (writes to config.json)
11932
12081
  */
11933
12082
  setSetting(type, key, value) {
11934
- const provider = this.providers.get(type);
11935
- const schemaDef = provider?.settings?.[key];
12083
+ const schemaDef = this.getSettingsSchema(type)[key];
11936
12084
  if (!schemaDef) return false;
11937
12085
  if (!schemaDef.public) return false;
11938
12086
  if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
12087
+ if (schemaDef.type === "string" && typeof value !== "string") return false;
11939
12088
  if (schemaDef.type === "number") {
11940
12089
  if (typeof value !== "number") return false;
11941
12090
  if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
@@ -11956,6 +12105,53 @@ var ProviderLoader = class _ProviderLoader {
11956
12105
  return false;
11957
12106
  }
11958
12107
  }
12108
+ getOptionalStringSetting(type, key) {
12109
+ const value = this.getSettingValue(type, key);
12110
+ if (typeof value !== "string") return null;
12111
+ const trimmed = value.trim();
12112
+ return trimmed ? trimmed : null;
12113
+ }
12114
+ getSettingsSchema(type) {
12115
+ const provider = this.providers.get(type);
12116
+ if (!provider) return {};
12117
+ return {
12118
+ ...this.getSyntheticSettings(type, provider),
12119
+ ...provider.settings || {}
12120
+ };
12121
+ }
12122
+ getSyntheticSettings(type, provider) {
12123
+ const result = {};
12124
+ if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
12125
+ result.executablePath = {
12126
+ type: "string",
12127
+ default: "",
12128
+ public: true,
12129
+ label: "Executable path",
12130
+ description: "Optional absolute path for this provider binary. Leave blank to use the default PATH lookup."
12131
+ };
12132
+ }
12133
+ if (provider.category === "ide") {
12134
+ if (provider.cli && !provider.settings?.cliPathOverride) {
12135
+ result.cliPathOverride = {
12136
+ type: "string",
12137
+ default: "",
12138
+ public: true,
12139
+ label: "CLI path override",
12140
+ description: "Optional absolute path for the IDE CLI launcher. Leave blank to use the detected default."
12141
+ };
12142
+ }
12143
+ if (provider.paths && !provider.settings?.appPathOverride) {
12144
+ result.appPathOverride = {
12145
+ type: "string",
12146
+ default: "",
12147
+ public: true,
12148
+ label: "App path override",
12149
+ description: "Optional absolute path for the IDE app bundle or executable. Leave blank to use the default install locations."
12150
+ };
12151
+ }
12152
+ }
12153
+ return result;
12154
+ }
11959
12155
  // ─── Private ───────────────────────────────────
11960
12156
  /**
11961
12157
  * Find the on-disk directory for a provider by type.
@@ -11969,17 +12165,17 @@ var ProviderLoader = class _ProviderLoader {
11969
12165
  for (const root of searchRoots) {
11970
12166
  if (!fs6.existsSync(root)) continue;
11971
12167
  const candidate = this.getProviderDir(root, cat, type);
11972
- if (fs6.existsSync(path10.join(candidate, "provider.json"))) return candidate;
11973
- const catDir = path10.join(root, cat);
12168
+ if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
12169
+ const catDir = path12.join(root, cat);
11974
12170
  if (fs6.existsSync(catDir)) {
11975
12171
  try {
11976
12172
  for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
11977
12173
  if (!entry.isDirectory()) continue;
11978
- const jsonPath = path10.join(catDir, entry.name, "provider.json");
12174
+ const jsonPath = path12.join(catDir, entry.name, "provider.json");
11979
12175
  if (fs6.existsSync(jsonPath)) {
11980
12176
  try {
11981
12177
  const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
11982
- if (data.type === type) return path10.join(catDir, entry.name);
12178
+ if (data.type === type) return path12.join(catDir, entry.name);
11983
12179
  } catch {
11984
12180
  }
11985
12181
  }
@@ -11996,7 +12192,7 @@ var ProviderLoader = class _ProviderLoader {
11996
12192
  * (template substitution is NOT applied here — scripts.js handles that)
11997
12193
  */
11998
12194
  buildScriptWrappersFromDir(dir) {
11999
- const scriptsJs = path10.join(dir, "scripts.js");
12195
+ const scriptsJs = path12.join(dir, "scripts.js");
12000
12196
  if (fs6.existsSync(scriptsJs)) {
12001
12197
  try {
12002
12198
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -12010,7 +12206,7 @@ var ProviderLoader = class _ProviderLoader {
12010
12206
  for (const file of fs6.readdirSync(dir)) {
12011
12207
  if (!file.endsWith(".js")) continue;
12012
12208
  const scriptName = toCamel(file.replace(".js", ""));
12013
- const filePath = path10.join(dir, file);
12209
+ const filePath = path12.join(dir, file);
12014
12210
  result[scriptName] = (...args) => {
12015
12211
  try {
12016
12212
  let content = fs6.readFileSync(filePath, "utf-8");
@@ -12070,7 +12266,7 @@ var ProviderLoader = class _ProviderLoader {
12070
12266
  }
12071
12267
  const hasJson = entries.some((e) => e.name === "provider.json");
12072
12268
  if (hasJson) {
12073
- const jsonPath = path10.join(d, "provider.json");
12269
+ const jsonPath = path12.join(d, "provider.json");
12074
12270
  try {
12075
12271
  const raw = fs6.readFileSync(jsonPath, "utf-8");
12076
12272
  const mod = JSON.parse(raw);
@@ -12083,7 +12279,7 @@ var ProviderLoader = class _ProviderLoader {
12083
12279
  delete mod.extensionIdPattern_flags;
12084
12280
  }
12085
12281
  const hasCompatibility = Array.isArray(mod.compatibility);
12086
- const scriptsPath = path10.join(d, "scripts.js");
12282
+ const scriptsPath = path12.join(d, "scripts.js");
12087
12283
  if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
12088
12284
  try {
12089
12285
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -12109,7 +12305,7 @@ var ProviderLoader = class _ProviderLoader {
12109
12305
  if (!entry.isDirectory()) continue;
12110
12306
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
12111
12307
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
12112
- scan(path10.join(d, entry.name));
12308
+ scan(path12.join(d, entry.name));
12113
12309
  }
12114
12310
  }
12115
12311
  };
@@ -12205,17 +12401,17 @@ async function findFreePort(ports) {
12205
12401
  throw new Error("No free port found");
12206
12402
  }
12207
12403
  function checkPortFree(port) {
12208
- return new Promise((resolve9) => {
12404
+ return new Promise((resolve12) => {
12209
12405
  const server = net.createServer();
12210
12406
  server.unref();
12211
- server.on("error", () => resolve9(false));
12407
+ server.on("error", () => resolve12(false));
12212
12408
  server.listen(port, "127.0.0.1", () => {
12213
- server.close(() => resolve9(true));
12409
+ server.close(() => resolve12(true));
12214
12410
  });
12215
12411
  });
12216
12412
  }
12217
12413
  async function isCdpActive(port) {
12218
- return new Promise((resolve9) => {
12414
+ return new Promise((resolve12) => {
12219
12415
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
12220
12416
  timeout: 2e3
12221
12417
  }, (res) => {
@@ -12224,16 +12420,16 @@ async function isCdpActive(port) {
12224
12420
  res.on("end", () => {
12225
12421
  try {
12226
12422
  const info = JSON.parse(data);
12227
- resolve9(!!info["WebKit-Version"] || !!info["Browser"]);
12423
+ resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
12228
12424
  } catch {
12229
- resolve9(false);
12425
+ resolve12(false);
12230
12426
  }
12231
12427
  });
12232
12428
  });
12233
- req.on("error", () => resolve9(false));
12429
+ req.on("error", () => resolve12(false));
12234
12430
  req.on("timeout", () => {
12235
12431
  req.destroy();
12236
- resolve9(false);
12432
+ resolve12(false);
12237
12433
  });
12238
12434
  });
12239
12435
  }
@@ -12367,8 +12563,8 @@ function detectCurrentWorkspace(ideId) {
12367
12563
  const appNameMap = getMacAppIdentifiers();
12368
12564
  const appName = appNameMap[ideId];
12369
12565
  if (appName) {
12370
- const storagePath = path11.join(
12371
- process.env.APPDATA || path11.join(os12.homedir(), "AppData", "Roaming"),
12566
+ const storagePath = path13.join(
12567
+ process.env.APPDATA || path13.join(os12.homedir(), "AppData", "Roaming"),
12372
12568
  appName,
12373
12569
  "storage.json"
12374
12570
  );
@@ -12392,7 +12588,7 @@ function detectCurrentWorkspace(ideId) {
12392
12588
  async function launchWithCdp(options = {}) {
12393
12589
  const platform9 = os12.platform();
12394
12590
  let targetIde;
12395
- const ides = await detectIDEs();
12591
+ const ides = await detectIDEs(getProviderLoader());
12396
12592
  if (options.ideId) {
12397
12593
  targetIde = ides.find((i) => i.id === options.ideId && i.installed);
12398
12594
  if (!targetIde) {
@@ -12546,9 +12742,9 @@ init_logger();
12546
12742
 
12547
12743
  // src/logging/command-log.ts
12548
12744
  import * as fs7 from "fs";
12549
- import * as path12 from "path";
12745
+ import * as path14 from "path";
12550
12746
  import * as os13 from "os";
12551
- 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");
12747
+ 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");
12552
12748
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
12553
12749
  var MAX_DAYS = 7;
12554
12750
  try {
@@ -12586,13 +12782,13 @@ function getDateStr2() {
12586
12782
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
12587
12783
  }
12588
12784
  var currentDate2 = getDateStr2();
12589
- var currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12785
+ var currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12590
12786
  var writeCount2 = 0;
12591
12787
  function checkRotation() {
12592
12788
  const today = getDateStr2();
12593
12789
  if (today !== currentDate2) {
12594
12790
  currentDate2 = today;
12595
- currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12791
+ currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
12596
12792
  cleanOldFiles();
12597
12793
  }
12598
12794
  }
@@ -12606,7 +12802,7 @@ function cleanOldFiles() {
12606
12802
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
12607
12803
  if (dateMatch && dateMatch[1] < cutoffStr) {
12608
12804
  try {
12609
- fs7.unlinkSync(path12.join(LOG_DIR2, file));
12805
+ fs7.unlinkSync(path14.join(LOG_DIR2, file));
12610
12806
  } catch {
12611
12807
  }
12612
12808
  }
@@ -12698,12 +12894,15 @@ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
12698
12894
  }));
12699
12895
  }
12700
12896
  function buildAvailableProviders(providerLoader) {
12701
- return providerLoader.getAll().map((provider) => ({
12897
+ const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
12898
+ return providers.map((provider) => ({
12702
12899
  type: provider.type,
12703
12900
  name: provider.displayName || provider.type,
12704
12901
  displayName: provider.displayName || provider.type,
12705
12902
  icon: provider.icon || "\u{1F4BB}",
12706
- category: provider.category
12903
+ category: provider.category,
12904
+ ...provider.installed !== void 0 ? { installed: provider.installed } : {},
12905
+ ...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
12707
12906
  }));
12708
12907
  }
12709
12908
  function parseMessageTime(value) {
@@ -12831,13 +13030,13 @@ import { execFileSync } from "child_process";
12831
13030
  import { spawn as spawn3 } from "child_process";
12832
13031
  import * as fs8 from "fs";
12833
13032
  import * as os15 from "os";
12834
- import * as path13 from "path";
13033
+ import * as path15 from "path";
12835
13034
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
12836
13035
  function getUpgradeLogPath() {
12837
13036
  const home = os15.homedir();
12838
- const dir = path13.join(home, ".adhdev");
13037
+ const dir = path15.join(home, ".adhdev");
12839
13038
  fs8.mkdirSync(dir, { recursive: true });
12840
- return path13.join(dir, "daemon-upgrade.log");
13039
+ return path15.join(dir, "daemon-upgrade.log");
12841
13040
  }
12842
13041
  function appendUpgradeLog(message) {
12843
13042
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -12870,14 +13069,14 @@ async function waitForPidExit(pid, timeoutMs) {
12870
13069
  while (Date.now() - start < timeoutMs) {
12871
13070
  try {
12872
13071
  process.kill(pid, 0);
12873
- await new Promise((resolve9) => setTimeout(resolve9, 250));
13072
+ await new Promise((resolve12) => setTimeout(resolve12, 250));
12874
13073
  } catch {
12875
13074
  return;
12876
13075
  }
12877
13076
  }
12878
13077
  }
12879
13078
  function stopSessionHostProcesses(appName) {
12880
- const pidFile = path13.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
13079
+ const pidFile = path15.join(os15.homedir(), ".adhdev", `${appName}-session-host.pid`);
12881
13080
  try {
12882
13081
  if (fs8.existsSync(pidFile)) {
12883
13082
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
@@ -12906,7 +13105,7 @@ function stopSessionHostProcesses(appName) {
12906
13105
  }
12907
13106
  }
12908
13107
  function removeDaemonPidFile() {
12909
- const pidFile = path13.join(os15.homedir(), ".adhdev", "daemon.pid");
13108
+ const pidFile = path15.join(os15.homedir(), ".adhdev", "daemon.pid");
12910
13109
  try {
12911
13110
  fs8.unlinkSync(pidFile);
12912
13111
  } catch {
@@ -12917,7 +13116,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
12917
13116
  const npmRoot = execFileSync(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
12918
13117
  if (!npmRoot) return;
12919
13118
  const npmPrefix = execFileSync(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
12920
- const binDir = process.platform === "win32" ? npmPrefix : path13.join(npmPrefix, "bin");
13119
+ const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
12921
13120
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
12922
13121
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
12923
13122
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -12925,25 +13124,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
12925
13124
  }
12926
13125
  if (pkgName.startsWith("@")) {
12927
13126
  const [scope, name] = pkgName.split("/");
12928
- const scopeDir = path13.join(npmRoot, scope);
13127
+ const scopeDir = path15.join(npmRoot, scope);
12929
13128
  if (!fs8.existsSync(scopeDir)) return;
12930
13129
  for (const entry of fs8.readdirSync(scopeDir)) {
12931
13130
  if (!entry.startsWith(`.${name}-`)) continue;
12932
- fs8.rmSync(path13.join(scopeDir, entry), { recursive: true, force: true });
12933
- appendUpgradeLog(`Removed stale scoped staging dir: ${path13.join(scopeDir, entry)}`);
13131
+ fs8.rmSync(path15.join(scopeDir, entry), { recursive: true, force: true });
13132
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
12934
13133
  }
12935
13134
  } else {
12936
13135
  for (const entry of fs8.readdirSync(npmRoot)) {
12937
13136
  if (!entry.startsWith(`.${pkgName}-`)) continue;
12938
- fs8.rmSync(path13.join(npmRoot, entry), { recursive: true, force: true });
12939
- appendUpgradeLog(`Removed stale staging dir: ${path13.join(npmRoot, entry)}`);
13137
+ fs8.rmSync(path15.join(npmRoot, entry), { recursive: true, force: true });
13138
+ appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
12940
13139
  }
12941
13140
  }
12942
13141
  if (fs8.existsSync(binDir)) {
12943
13142
  for (const entry of fs8.readdirSync(binDir)) {
12944
13143
  if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
12945
- fs8.rmSync(path13.join(binDir, entry), { recursive: true, force: true });
12946
- appendUpgradeLog(`Removed stale bin staging entry: ${path13.join(binDir, entry)}`);
13144
+ fs8.rmSync(path15.join(binDir, entry), { recursive: true, force: true });
13145
+ appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, entry)}`);
12947
13146
  }
12948
13147
  }
12949
13148
  }
@@ -12985,7 +13184,7 @@ async function runDaemonUpgradeHelper(payload) {
12985
13184
  appendUpgradeLog(installOutput.trim());
12986
13185
  }
12987
13186
  if (process.platform === "win32") {
12988
- await new Promise((resolve9) => setTimeout(resolve9, 500));
13187
+ await new Promise((resolve12) => setTimeout(resolve12, 500));
12989
13188
  cleanupStaleGlobalInstallDirs(payload.packageName);
12990
13189
  appendUpgradeLog("Post-install staging cleanup complete");
12991
13190
  }
@@ -13263,6 +13462,12 @@ var DaemonCommandRouter = class {
13263
13462
  if (!ideType) throw new Error("ideType required");
13264
13463
  const killProcess = args?.killProcess !== false;
13265
13464
  await this.stopIde(ideType, killProcess);
13465
+ try {
13466
+ const results = await detectIDEs(this.deps.providerLoader);
13467
+ this.deps.detectedIdes.value = results;
13468
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
13469
+ } catch {
13470
+ }
13266
13471
  return { success: true, ideType, stopped: true, processKilled: killProcess };
13267
13472
  }
13268
13473
  // ─── IDE restart ───
@@ -13305,6 +13510,12 @@ var DaemonCommandRouter = class {
13305
13510
  }
13306
13511
  }
13307
13512
  this.deps.onIdeConnected?.();
13513
+ try {
13514
+ const results = await detectIDEs(this.deps.providerLoader);
13515
+ this.deps.detectedIdes.value = results;
13516
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
13517
+ } catch {
13518
+ }
13308
13519
  if (result.success && resolvedWorkspace) {
13309
13520
  try {
13310
13521
  const next = appendRecentActivity(loadState(), {
@@ -13332,8 +13543,9 @@ var DaemonCommandRouter = class {
13332
13543
  }
13333
13544
  // ─── Detect IDEs ───
13334
13545
  case "detect_ides": {
13335
- const results = await detectIDEs();
13546
+ const results = await detectIDEs(this.deps.providerLoader);
13336
13547
  this.deps.detectedIdes.value = results;
13548
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
13337
13549
  return { success: true, detectedInfo: results };
13338
13550
  }
13339
13551
  // ─── Set User Name ───
@@ -13847,7 +14059,10 @@ var ProviderStreamAdapter = class {
13847
14059
  const raw = await evaluate(script, 1e4);
13848
14060
  const data = typeof raw === "string" ? JSON.parse(raw) : raw;
13849
14061
  if (data?.error) return [];
13850
- return Array.isArray(data) ? data : [];
14062
+ if (Array.isArray(data)) return data;
14063
+ if (Array.isArray(data?.sessions)) return data.sessions;
14064
+ if (Array.isArray(data?.chats)) return data.chats;
14065
+ return [];
13851
14066
  } catch {
13852
14067
  return [];
13853
14068
  }
@@ -13855,7 +14070,17 @@ var ProviderStreamAdapter = class {
13855
14070
  async switchSession(evaluate, sessionId) {
13856
14071
  const script = this.callScript("switchSession", sessionId);
13857
14072
  if (!script) return false;
13858
- return await evaluate(script, 1e4) === true;
14073
+ const raw = await evaluate(script, 1e4);
14074
+ const data = this.parseMaybeJson(raw);
14075
+ if (data === true) return true;
14076
+ if (typeof data === "string") {
14077
+ const normalized = data.trim().toLowerCase();
14078
+ return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
14079
+ }
14080
+ if (data && typeof data === "object") {
14081
+ return data.switched === true || data.success === true || data.ok === true;
14082
+ }
14083
+ return false;
13859
14084
  }
13860
14085
  async focusEditor(evaluate) {
13861
14086
  const script = this.callScript("focusEditor");
@@ -14545,11 +14770,11 @@ var ProviderInstanceManager = class {
14545
14770
 
14546
14771
  // src/providers/version-archive.ts
14547
14772
  import * as fs10 from "fs";
14548
- import * as path14 from "path";
14773
+ import * as path16 from "path";
14549
14774
  import * as os16 from "os";
14550
14775
  import { execSync as execSync5 } from "child_process";
14551
14776
  import { platform as platform7 } from "os";
14552
- var ARCHIVE_PATH = path14.join(os16.homedir(), ".adhdev", "version-history.json");
14777
+ var ARCHIVE_PATH = path16.join(os16.homedir(), ".adhdev", "version-history.json");
14553
14778
  var MAX_ENTRIES_PER_PROVIDER = 20;
14554
14779
  var VersionArchive = class {
14555
14780
  history = {};
@@ -14596,7 +14821,7 @@ var VersionArchive = class {
14596
14821
  }
14597
14822
  save() {
14598
14823
  try {
14599
- fs10.mkdirSync(path14.dirname(ARCHIVE_PATH), { recursive: true });
14824
+ fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
14600
14825
  fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
14601
14826
  } catch {
14602
14827
  }
@@ -14637,7 +14862,7 @@ function checkPathExists2(paths) {
14637
14862
  for (const p of paths) {
14638
14863
  if (p.includes("*")) {
14639
14864
  const home = os16.homedir();
14640
- const resolved = p.replace(/\*/g, home.split(path14.sep).pop() || "");
14865
+ const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
14641
14866
  if (fs10.existsSync(resolved)) return resolved;
14642
14867
  } else {
14643
14868
  if (fs10.existsSync(p)) return p;
@@ -14647,7 +14872,7 @@ function checkPathExists2(paths) {
14647
14872
  }
14648
14873
  function getMacAppVersion(appPath) {
14649
14874
  if (platform7() !== "darwin" || !appPath.endsWith(".app")) return null;
14650
- const plistPath = path14.join(appPath, "Contents", "Info.plist");
14875
+ const plistPath = path16.join(appPath, "Contents", "Info.plist");
14651
14876
  if (!fs10.existsSync(plistPath)) return null;
14652
14877
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
14653
14878
  return raw || null;
@@ -14674,7 +14899,7 @@ async function detectAllVersions(loader, archive) {
14674
14899
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
14675
14900
  let resolvedBin = cliBin;
14676
14901
  if (!resolvedBin && appPath && currentOs === "darwin") {
14677
- const bundled = path14.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
14902
+ const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
14678
14903
  if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
14679
14904
  }
14680
14905
  info.installed = !!(appPath || resolvedBin);
@@ -14715,7 +14940,7 @@ async function detectAllVersions(loader, archive) {
14715
14940
  // src/daemon/dev-server.ts
14716
14941
  import * as http2 from "http";
14717
14942
  import * as fs14 from "fs";
14718
- import * as path18 from "path";
14943
+ import * as path20 from "path";
14719
14944
 
14720
14945
  // src/daemon/scaffold-template.ts
14721
14946
  function generateFiles(type, name, category, opts = {}) {
@@ -15052,7 +15277,7 @@ init_logger();
15052
15277
  // src/daemon/dev-cdp-handlers.ts
15053
15278
  init_logger();
15054
15279
  import * as fs11 from "fs";
15055
- import * as path15 from "path";
15280
+ import * as path17 from "path";
15056
15281
  async function handleCdpEvaluate(ctx, req, res) {
15057
15282
  const body = await ctx.readBody(req);
15058
15283
  const { expression, timeout, ideType } = body;
@@ -15230,17 +15455,17 @@ async function handleScriptHints(ctx, type, _req, res) {
15230
15455
  return;
15231
15456
  }
15232
15457
  let scriptsPath = "";
15233
- const directScripts = path15.join(dir, "scripts.js");
15458
+ const directScripts = path17.join(dir, "scripts.js");
15234
15459
  if (fs11.existsSync(directScripts)) {
15235
15460
  scriptsPath = directScripts;
15236
15461
  } else {
15237
- const scriptsDir = path15.join(dir, "scripts");
15462
+ const scriptsDir = path17.join(dir, "scripts");
15238
15463
  if (fs11.existsSync(scriptsDir)) {
15239
15464
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
15240
- return fs11.statSync(path15.join(scriptsDir, d)).isDirectory();
15465
+ return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
15241
15466
  }).sort().reverse();
15242
15467
  for (const ver of versions) {
15243
- const p = path15.join(scriptsDir, ver, "scripts.js");
15468
+ const p = path17.join(scriptsDir, ver, "scripts.js");
15244
15469
  if (fs11.existsSync(p)) {
15245
15470
  scriptsPath = p;
15246
15471
  break;
@@ -16059,7 +16284,7 @@ async function handleDomContext(ctx, type, req, res) {
16059
16284
 
16060
16285
  // src/daemon/dev-cli-debug.ts
16061
16286
  import * as fs12 from "fs";
16062
- import * as path16 from "path";
16287
+ import * as path18 from "path";
16063
16288
  function slugifyFixtureName(value) {
16064
16289
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
16065
16290
  return normalized || `fixture-${Date.now()}`;
@@ -16069,11 +16294,11 @@ function getCliFixtureDir(ctx, type) {
16069
16294
  if (!providerDir) {
16070
16295
  throw new Error(`Provider directory not found for '${type}'`);
16071
16296
  }
16072
- return path16.join(providerDir, "fixtures");
16297
+ return path18.join(providerDir, "fixtures");
16073
16298
  }
16074
16299
  function readCliFixture(ctx, type, name) {
16075
16300
  const fixtureDir = getCliFixtureDir(ctx, type);
16076
- const filePath = path16.join(fixtureDir, `${name}.json`);
16301
+ const filePath = path18.join(fixtureDir, `${name}.json`);
16077
16302
  if (!fs12.existsSync(filePath)) {
16078
16303
  throw new Error(`Fixture not found: ${filePath}`);
16079
16304
  }
@@ -16233,7 +16458,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
16233
16458
  return { target, instance, adapter };
16234
16459
  }
16235
16460
  function sleep(ms) {
16236
- return new Promise((resolve9) => setTimeout(resolve9, ms));
16461
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
16237
16462
  }
16238
16463
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
16239
16464
  const startedAt = Date.now();
@@ -16832,7 +17057,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
16832
17057
  },
16833
17058
  notes: typeof body?.notes === "string" ? body.notes : void 0
16834
17059
  };
16835
- const filePath = path16.join(fixtureDir, `${name}.json`);
17060
+ const filePath = path18.join(fixtureDir, `${name}.json`);
16836
17061
  fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
16837
17062
  ctx.json(res, 200, {
16838
17063
  saved: true,
@@ -16856,7 +17081,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
16856
17081
  return;
16857
17082
  }
16858
17083
  const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
16859
- const fullPath = path16.join(fixtureDir, file);
17084
+ const fullPath = path18.join(fixtureDir, file);
16860
17085
  try {
16861
17086
  const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
16862
17087
  return {
@@ -16992,7 +17217,7 @@ async function handleCliRaw(ctx, req, res) {
16992
17217
 
16993
17218
  // src/daemon/dev-auto-implement.ts
16994
17219
  import * as fs13 from "fs";
16995
- import * as path17 from "path";
17220
+ import * as path19 from "path";
16996
17221
  import * as os17 from "os";
16997
17222
  function getAutoImplPid(ctx) {
16998
17223
  const proc = ctx.autoImplProcess;
@@ -17032,22 +17257,22 @@ function getLatestScriptVersionDir(scriptsDir) {
17032
17257
  if (!fs13.existsSync(scriptsDir)) return null;
17033
17258
  const versions = fs13.readdirSync(scriptsDir).filter((d) => {
17034
17259
  try {
17035
- return fs13.statSync(path17.join(scriptsDir, d)).isDirectory();
17260
+ return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
17036
17261
  } catch {
17037
17262
  return false;
17038
17263
  }
17039
17264
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
17040
17265
  if (versions.length === 0) return null;
17041
- return path17.join(scriptsDir, versions[0]);
17266
+ return path19.join(scriptsDir, versions[0]);
17042
17267
  }
17043
17268
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
17044
- const canonicalUserDir = path17.resolve(ctx.providerLoader.getUserProviderDir(category, type));
17045
- const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
17046
- const upstreamRoot = path17.resolve(ctx.providerLoader.getUpstreamDir());
17047
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
17269
+ const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
17270
+ const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
17271
+ const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
17272
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
17048
17273
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
17049
17274
  }
17050
- if (path17.basename(desiredDir) !== type) {
17275
+ if (path19.basename(desiredDir) !== type) {
17051
17276
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
17052
17277
  }
17053
17278
  const sourceDir = ctx.findProviderDir(type);
@@ -17055,11 +17280,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
17055
17280
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
17056
17281
  }
17057
17282
  if (!fs13.existsSync(desiredDir)) {
17058
- fs13.mkdirSync(path17.dirname(desiredDir), { recursive: true });
17283
+ fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
17059
17284
  fs13.cpSync(sourceDir, desiredDir, { recursive: true });
17060
17285
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
17061
17286
  }
17062
- const providerJson = path17.join(desiredDir, "provider.json");
17287
+ const providerJson = path19.join(desiredDir, "provider.json");
17063
17288
  if (!fs13.existsSync(providerJson)) {
17064
17289
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
17065
17290
  }
@@ -17082,13 +17307,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
17082
17307
  const refDir = ctx.findProviderDir(referenceType);
17083
17308
  if (!refDir || !fs13.existsSync(refDir)) return {};
17084
17309
  const referenceScripts = {};
17085
- const scriptsDir = path17.join(refDir, "scripts");
17310
+ const scriptsDir = path19.join(refDir, "scripts");
17086
17311
  const latestDir = getLatestScriptVersionDir(scriptsDir);
17087
17312
  if (!latestDir) return referenceScripts;
17088
17313
  for (const file of fs13.readdirSync(latestDir)) {
17089
17314
  if (!file.endsWith(".js")) continue;
17090
17315
  try {
17091
- referenceScripts[file] = fs13.readFileSync(path17.join(latestDir, file), "utf-8");
17316
+ referenceScripts[file] = fs13.readFileSync(path19.join(latestDir, file), "utf-8");
17092
17317
  } catch {
17093
17318
  }
17094
17319
  }
@@ -17196,9 +17421,9 @@ async function handleAutoImplement(ctx, type, req, res) {
17196
17421
  });
17197
17422
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
17198
17423
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
17199
- const tmpDir = path17.join(os17.tmpdir(), "adhdev-autoimpl");
17424
+ const tmpDir = path19.join(os17.tmpdir(), "adhdev-autoimpl");
17200
17425
  if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
17201
- const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
17426
+ const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
17202
17427
  fs13.writeFileSync(promptFile, prompt, "utf-8");
17203
17428
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
17204
17429
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -17625,7 +17850,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17625
17850
  setMode: "set_mode.js"
17626
17851
  };
17627
17852
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
17628
- const scriptsDir = path17.join(providerDir, "scripts");
17853
+ const scriptsDir = path19.join(providerDir, "scripts");
17629
17854
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
17630
17855
  if (latestScriptsDir) {
17631
17856
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -17636,7 +17861,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17636
17861
  for (const file of fs13.readdirSync(latestScriptsDir)) {
17637
17862
  if (file.endsWith(".js") && targetFileNames.has(file)) {
17638
17863
  try {
17639
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
17864
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
17640
17865
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
17641
17866
  lines.push("```javascript");
17642
17867
  lines.push(content);
@@ -17653,7 +17878,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17653
17878
  lines.push("");
17654
17879
  for (const file of refFiles) {
17655
17880
  try {
17656
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
17881
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
17657
17882
  lines.push(`### \`${file}\` \u{1F512}`);
17658
17883
  lines.push("```javascript");
17659
17884
  lines.push(content);
@@ -17694,10 +17919,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
17694
17919
  lines.push("");
17695
17920
  }
17696
17921
  }
17697
- const docsDir = path17.join(providerDir, "../../docs");
17922
+ const docsDir = path19.join(providerDir, "../../docs");
17698
17923
  const loadGuide = (name) => {
17699
17924
  try {
17700
- const p = path17.join(docsDir, name);
17925
+ const p = path19.join(docsDir, name);
17701
17926
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
17702
17927
  } catch {
17703
17928
  }
@@ -17932,7 +18157,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
17932
18157
  parseApproval: "parse_approval.js"
17933
18158
  };
17934
18159
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
17935
- const scriptsDir = path17.join(providerDir, "scripts");
18160
+ const scriptsDir = path19.join(providerDir, "scripts");
17936
18161
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
17937
18162
  if (latestScriptsDir) {
17938
18163
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -17944,7 +18169,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
17944
18169
  if (!file.endsWith(".js")) continue;
17945
18170
  if (!targetFileNames.has(file)) continue;
17946
18171
  try {
17947
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
18172
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
17948
18173
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
17949
18174
  lines.push("```javascript");
17950
18175
  lines.push(content);
@@ -17960,7 +18185,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
17960
18185
  lines.push("");
17961
18186
  for (const file of refFiles) {
17962
18187
  try {
17963
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file), "utf-8");
18188
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file), "utf-8");
17964
18189
  lines.push(`### \`${file}\` \u{1F512}`);
17965
18190
  lines.push("```javascript");
17966
18191
  lines.push(content);
@@ -17993,10 +18218,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
17993
18218
  lines.push("");
17994
18219
  }
17995
18220
  }
17996
- const docsDir = path17.join(providerDir, "../../docs");
18221
+ const docsDir = path19.join(providerDir, "../../docs");
17997
18222
  const loadGuide = (name) => {
17998
18223
  try {
17999
- const p = path17.join(docsDir, name);
18224
+ const p = path19.join(docsDir, name);
18000
18225
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
18001
18226
  } catch {
18002
18227
  }
@@ -18407,8 +18632,8 @@ var DevServer = class _DevServer {
18407
18632
  }
18408
18633
  getEndpointList() {
18409
18634
  return this.routes.map((r) => {
18410
- const path19 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
18411
- return `${r.method.padEnd(5)} ${path19}`;
18635
+ const path21 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
18636
+ return `${r.method.padEnd(5)} ${path21}`;
18412
18637
  });
18413
18638
  }
18414
18639
  async start(port = DEV_SERVER_PORT) {
@@ -18439,15 +18664,15 @@ var DevServer = class _DevServer {
18439
18664
  this.json(res, 500, { error: e.message });
18440
18665
  }
18441
18666
  });
18442
- return new Promise((resolve9, reject) => {
18667
+ return new Promise((resolve12, reject) => {
18443
18668
  this.server.listen(port, "127.0.0.1", () => {
18444
18669
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
18445
- resolve9();
18670
+ resolve12();
18446
18671
  });
18447
18672
  this.server.on("error", (e) => {
18448
18673
  if (e.code === "EADDRINUSE") {
18449
18674
  this.log(`Port ${port} in use, skipping dev server`);
18450
- resolve9();
18675
+ resolve12();
18451
18676
  } else {
18452
18677
  reject(e);
18453
18678
  }
@@ -18530,20 +18755,20 @@ var DevServer = class _DevServer {
18530
18755
  child.stderr?.on("data", (d) => {
18531
18756
  stderr += d.toString().slice(0, 2e3);
18532
18757
  });
18533
- await new Promise((resolve9) => {
18758
+ await new Promise((resolve12) => {
18534
18759
  const timer = setTimeout(() => {
18535
18760
  child.kill();
18536
- resolve9();
18761
+ resolve12();
18537
18762
  }, 3e3);
18538
18763
  child.on("exit", () => {
18539
18764
  clearTimeout(timer);
18540
- resolve9();
18765
+ resolve12();
18541
18766
  });
18542
18767
  child.stdout?.once("data", () => {
18543
18768
  setTimeout(() => {
18544
18769
  child.kill();
18545
18770
  clearTimeout(timer);
18546
- resolve9();
18771
+ resolve12();
18547
18772
  }, 500);
18548
18773
  });
18549
18774
  });
@@ -18690,12 +18915,12 @@ var DevServer = class _DevServer {
18690
18915
  // ─── DevConsole SPA ───
18691
18916
  getConsoleDistDir() {
18692
18917
  const candidates = [
18693
- path18.resolve(__dirname, "../../web-devconsole/dist"),
18694
- path18.resolve(__dirname, "../../../web-devconsole/dist"),
18695
- path18.join(process.cwd(), "packages/web-devconsole/dist")
18918
+ path20.resolve(__dirname, "../../web-devconsole/dist"),
18919
+ path20.resolve(__dirname, "../../../web-devconsole/dist"),
18920
+ path20.join(process.cwd(), "packages/web-devconsole/dist")
18696
18921
  ];
18697
18922
  for (const dir of candidates) {
18698
- if (fs14.existsSync(path18.join(dir, "index.html"))) return dir;
18923
+ if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
18699
18924
  }
18700
18925
  return null;
18701
18926
  }
@@ -18705,7 +18930,7 @@ var DevServer = class _DevServer {
18705
18930
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
18706
18931
  return;
18707
18932
  }
18708
- const htmlPath = path18.join(distDir, "index.html");
18933
+ const htmlPath = path20.join(distDir, "index.html");
18709
18934
  try {
18710
18935
  const html = fs14.readFileSync(htmlPath, "utf-8");
18711
18936
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -18730,15 +18955,15 @@ var DevServer = class _DevServer {
18730
18955
  this.json(res, 404, { error: "Not found" });
18731
18956
  return;
18732
18957
  }
18733
- const safePath = path18.normalize(pathname).replace(/^\.\.\//, "");
18734
- const filePath = path18.join(distDir, safePath);
18958
+ const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
18959
+ const filePath = path20.join(distDir, safePath);
18735
18960
  if (!filePath.startsWith(distDir)) {
18736
18961
  this.json(res, 403, { error: "Forbidden" });
18737
18962
  return;
18738
18963
  }
18739
18964
  try {
18740
18965
  const content = fs14.readFileSync(filePath);
18741
- const ext = path18.extname(filePath);
18966
+ const ext = path20.extname(filePath);
18742
18967
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
18743
18968
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
18744
18969
  res.end(content);
@@ -18851,9 +19076,9 @@ var DevServer = class _DevServer {
18851
19076
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
18852
19077
  if (entry.isDirectory()) {
18853
19078
  files.push({ path: rel, size: 0, type: "dir" });
18854
- scan(path18.join(d, entry.name), rel);
19079
+ scan(path20.join(d, entry.name), rel);
18855
19080
  } else {
18856
- const stat = fs14.statSync(path18.join(d, entry.name));
19081
+ const stat = fs14.statSync(path20.join(d, entry.name));
18857
19082
  files.push({ path: rel, size: stat.size, type: "file" });
18858
19083
  }
18859
19084
  }
@@ -18876,7 +19101,7 @@ var DevServer = class _DevServer {
18876
19101
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
18877
19102
  return;
18878
19103
  }
18879
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
19104
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
18880
19105
  if (!fullPath.startsWith(dir)) {
18881
19106
  this.json(res, 403, { error: "Forbidden" });
18882
19107
  return;
@@ -18901,14 +19126,14 @@ var DevServer = class _DevServer {
18901
19126
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
18902
19127
  return;
18903
19128
  }
18904
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
19129
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
18905
19130
  if (!fullPath.startsWith(dir)) {
18906
19131
  this.json(res, 403, { error: "Forbidden" });
18907
19132
  return;
18908
19133
  }
18909
19134
  try {
18910
19135
  if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
18911
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
19136
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
18912
19137
  fs14.writeFileSync(fullPath, content, "utf-8");
18913
19138
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
18914
19139
  this.providerLoader.reload();
@@ -18925,7 +19150,7 @@ var DevServer = class _DevServer {
18925
19150
  return;
18926
19151
  }
18927
19152
  for (const name of ["scripts.js", "provider.json"]) {
18928
- const p = path18.join(dir, name);
19153
+ const p = path20.join(dir, name);
18929
19154
  if (fs14.existsSync(p)) {
18930
19155
  const source = fs14.readFileSync(p, "utf-8");
18931
19156
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -18946,8 +19171,8 @@ var DevServer = class _DevServer {
18946
19171
  this.json(res, 404, { error: `Provider not found: ${type}` });
18947
19172
  return;
18948
19173
  }
18949
- const target = fs14.existsSync(path18.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
18950
- const targetPath = path18.join(dir, target);
19174
+ const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
19175
+ const targetPath = path20.join(dir, target);
18951
19176
  try {
18952
19177
  if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
18953
19178
  fs14.writeFileSync(targetPath, source, "utf-8");
@@ -19052,14 +19277,14 @@ var DevServer = class _DevServer {
19052
19277
  child.stderr?.on("data", (d) => {
19053
19278
  stderr += d.toString();
19054
19279
  });
19055
- await new Promise((resolve9) => {
19280
+ await new Promise((resolve12) => {
19056
19281
  const timer = setTimeout(() => {
19057
19282
  child.kill();
19058
- resolve9();
19283
+ resolve12();
19059
19284
  }, timeout);
19060
19285
  child.on("exit", () => {
19061
19286
  clearTimeout(timer);
19062
- resolve9();
19287
+ resolve12();
19063
19288
  });
19064
19289
  });
19065
19290
  const elapsed = Date.now() - start;
@@ -19107,7 +19332,7 @@ var DevServer = class _DevServer {
19107
19332
  }
19108
19333
  let targetDir;
19109
19334
  targetDir = this.providerLoader.getUserProviderDir(category, type);
19110
- const jsonPath = path18.join(targetDir, "provider.json");
19335
+ const jsonPath = path20.join(targetDir, "provider.json");
19111
19336
  if (fs14.existsSync(jsonPath)) {
19112
19337
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
19113
19338
  return;
@@ -19119,8 +19344,8 @@ var DevServer = class _DevServer {
19119
19344
  const createdFiles = ["provider.json"];
19120
19345
  if (result.files) {
19121
19346
  for (const [relPath, content] of Object.entries(result.files)) {
19122
- const fullPath = path18.join(targetDir, relPath);
19123
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
19347
+ const fullPath = path20.join(targetDir, relPath);
19348
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
19124
19349
  fs14.writeFileSync(fullPath, content, "utf-8");
19125
19350
  createdFiles.push(relPath);
19126
19351
  }
@@ -19173,22 +19398,22 @@ var DevServer = class _DevServer {
19173
19398
  if (!fs14.existsSync(scriptsDir)) return null;
19174
19399
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
19175
19400
  try {
19176
- return fs14.statSync(path18.join(scriptsDir, d)).isDirectory();
19401
+ return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
19177
19402
  } catch {
19178
19403
  return false;
19179
19404
  }
19180
19405
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
19181
19406
  if (versions.length === 0) return null;
19182
- return path18.join(scriptsDir, versions[0]);
19407
+ return path20.join(scriptsDir, versions[0]);
19183
19408
  }
19184
19409
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
19185
- const canonicalUserDir = path18.resolve(this.providerLoader.getUserProviderDir(category, type));
19186
- const desiredDir = requestedDir ? path18.resolve(requestedDir) : canonicalUserDir;
19187
- const upstreamRoot = path18.resolve(this.providerLoader.getUpstreamDir());
19188
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path18.sep}`)) {
19410
+ const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
19411
+ const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
19412
+ const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
19413
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
19189
19414
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
19190
19415
  }
19191
- if (path18.basename(desiredDir) !== type) {
19416
+ if (path20.basename(desiredDir) !== type) {
19192
19417
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
19193
19418
  }
19194
19419
  const sourceDir = this.findProviderDir(type);
@@ -19196,11 +19421,11 @@ var DevServer = class _DevServer {
19196
19421
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
19197
19422
  }
19198
19423
  if (!fs14.existsSync(desiredDir)) {
19199
- fs14.mkdirSync(path18.dirname(desiredDir), { recursive: true });
19424
+ fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
19200
19425
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
19201
19426
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
19202
19427
  }
19203
- const providerJson = path18.join(desiredDir, "provider.json");
19428
+ const providerJson = path20.join(desiredDir, "provider.json");
19204
19429
  if (!fs14.existsSync(providerJson)) {
19205
19430
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
19206
19431
  }
@@ -19248,7 +19473,7 @@ var DevServer = class _DevServer {
19248
19473
  setMode: "set_mode.js"
19249
19474
  };
19250
19475
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
19251
- const scriptsDir = path18.join(providerDir, "scripts");
19476
+ const scriptsDir = path20.join(providerDir, "scripts");
19252
19477
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
19253
19478
  if (latestScriptsDir) {
19254
19479
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -19259,7 +19484,7 @@ var DevServer = class _DevServer {
19259
19484
  for (const file of fs14.readdirSync(latestScriptsDir)) {
19260
19485
  if (file.endsWith(".js") && targetFileNames.has(file)) {
19261
19486
  try {
19262
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19487
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19263
19488
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
19264
19489
  lines.push("```javascript");
19265
19490
  lines.push(content);
@@ -19276,7 +19501,7 @@ var DevServer = class _DevServer {
19276
19501
  lines.push("");
19277
19502
  for (const file of refFiles) {
19278
19503
  try {
19279
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19504
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19280
19505
  lines.push(`### \`${file}\` \u{1F512}`);
19281
19506
  lines.push("```javascript");
19282
19507
  lines.push(content);
@@ -19317,10 +19542,10 @@ var DevServer = class _DevServer {
19317
19542
  lines.push("");
19318
19543
  }
19319
19544
  }
19320
- const docsDir = path18.join(providerDir, "../../docs");
19545
+ const docsDir = path20.join(providerDir, "../../docs");
19321
19546
  const loadGuide = (name) => {
19322
19547
  try {
19323
- const p = path18.join(docsDir, name);
19548
+ const p = path20.join(docsDir, name);
19324
19549
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
19325
19550
  } catch {
19326
19551
  }
@@ -19494,7 +19719,7 @@ var DevServer = class _DevServer {
19494
19719
  parseApproval: "parse_approval.js"
19495
19720
  };
19496
19721
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
19497
- const scriptsDir = path18.join(providerDir, "scripts");
19722
+ const scriptsDir = path20.join(providerDir, "scripts");
19498
19723
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
19499
19724
  if (latestScriptsDir) {
19500
19725
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -19506,7 +19731,7 @@ var DevServer = class _DevServer {
19506
19731
  if (!file.endsWith(".js")) continue;
19507
19732
  if (!targetFileNames.has(file)) continue;
19508
19733
  try {
19509
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19734
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19510
19735
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
19511
19736
  lines.push("```javascript");
19512
19737
  lines.push(content);
@@ -19522,7 +19747,7 @@ var DevServer = class _DevServer {
19522
19747
  lines.push("");
19523
19748
  for (const file of refFiles) {
19524
19749
  try {
19525
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file), "utf-8");
19750
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19526
19751
  lines.push(`### \`${file}\` \u{1F512}`);
19527
19752
  lines.push("```javascript");
19528
19753
  lines.push(content);
@@ -19555,10 +19780,10 @@ var DevServer = class _DevServer {
19555
19780
  lines.push("");
19556
19781
  }
19557
19782
  }
19558
- const docsDir = path18.join(providerDir, "../../docs");
19783
+ const docsDir = path20.join(providerDir, "../../docs");
19559
19784
  const loadGuide = (name) => {
19560
19785
  try {
19561
- const p = path18.join(docsDir, name);
19786
+ const p = path20.join(docsDir, name);
19562
19787
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
19563
19788
  } catch {
19564
19789
  }
@@ -19734,14 +19959,14 @@ data: ${JSON.stringify(msg.data)}
19734
19959
  res.end(JSON.stringify(data, null, 2));
19735
19960
  }
19736
19961
  async readBody(req) {
19737
- return new Promise((resolve9) => {
19962
+ return new Promise((resolve12) => {
19738
19963
  let body = "";
19739
19964
  req.on("data", (chunk) => body += chunk);
19740
19965
  req.on("end", () => {
19741
19966
  try {
19742
- resolve9(JSON.parse(body));
19967
+ resolve12(JSON.parse(body));
19743
19968
  } catch {
19744
- resolve9({});
19969
+ resolve12({});
19745
19970
  }
19746
19971
  });
19747
19972
  });
@@ -20214,7 +20439,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
20214
20439
  const deadline = Date.now() + timeoutMs;
20215
20440
  while (Date.now() < deadline) {
20216
20441
  if (await canConnect(endpoint)) return;
20217
- await new Promise((resolve9) => setTimeout(resolve9, STARTUP_POLL_MS));
20442
+ await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
20218
20443
  }
20219
20444
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
20220
20445
  }
@@ -20370,10 +20595,10 @@ async function installExtension(ide, extension) {
20370
20595
  const buffer = Buffer.from(await res.arrayBuffer());
20371
20596
  const fs15 = await import("fs");
20372
20597
  fs15.writeFileSync(vsixPath, buffer);
20373
- return new Promise((resolve9) => {
20598
+ return new Promise((resolve12) => {
20374
20599
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
20375
20600
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
20376
- resolve9({
20601
+ resolve12({
20377
20602
  extensionId: extension.id,
20378
20603
  marketplaceId: extension.marketplaceId,
20379
20604
  success: !error,
@@ -20386,11 +20611,11 @@ async function installExtension(ide, extension) {
20386
20611
  } catch (e) {
20387
20612
  }
20388
20613
  }
20389
- return new Promise((resolve9) => {
20614
+ return new Promise((resolve12) => {
20390
20615
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
20391
20616
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
20392
20617
  if (error) {
20393
- resolve9({
20618
+ resolve12({
20394
20619
  extensionId: extension.id,
20395
20620
  marketplaceId: extension.marketplaceId,
20396
20621
  success: false,
@@ -20398,7 +20623,7 @@ async function installExtension(ide, extension) {
20398
20623
  error: stderr || error.message
20399
20624
  });
20400
20625
  } else {
20401
- resolve9({
20626
+ resolve12({
20402
20627
  extensionId: extension.id,
20403
20628
  marketplaceId: extension.marketplaceId,
20404
20629
  success: true,
@@ -20534,13 +20759,32 @@ async function initDaemonComponents(config) {
20534
20759
  const detectedIdesRef = { value: [] };
20535
20760
  let agentStreamManager = null;
20536
20761
  let poller = null;
20762
+ const refreshProviderAvailability = async (providerType) => {
20763
+ const targetProvider = providerType ? providerLoader.getMeta(providerLoader.resolveAlias(providerType)) : null;
20764
+ const targetCategory = targetProvider?.category;
20765
+ if (!providerType || targetCategory === "cli" || targetCategory === "acp") {
20766
+ if (providerType && targetProvider) {
20767
+ const detected = await detectCLI(targetProvider.type, providerLoader, { includeVersion: false });
20768
+ providerLoader.setProviderAvailability(targetProvider.type, {
20769
+ installed: !!detected,
20770
+ detectedPath: detected?.path || null
20771
+ });
20772
+ } else {
20773
+ providerLoader.setCliDetectionResults(await detectCLIs(providerLoader, { includeVersion: false }), true);
20774
+ }
20775
+ }
20776
+ if (!providerType || targetCategory === "ide") {
20777
+ detectedIdesRef.value = await detectIDEs(providerLoader);
20778
+ providerLoader.setIdeDetectionResults(detectedIdesRef.value, true);
20779
+ }
20780
+ };
20537
20781
  const cliManager = new DaemonCliManager({
20538
20782
  ...config.cliManagerDeps,
20539
20783
  getInstanceManager: () => instanceManager,
20540
20784
  getSessionRegistry: () => sessionRegistry
20541
20785
  }, providerLoader);
20542
20786
  LOG.info("Init", "Detecting IDEs...");
20543
- detectedIdesRef.value = await detectIDEs();
20787
+ await refreshProviderAvailability();
20544
20788
  const installed = detectedIdesRef.value.filter((i) => i.installed);
20545
20789
  LOG.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
20546
20790
  const cdpSetupContext = {
@@ -20580,7 +20824,11 @@ async function initDaemonComponents(config) {
20580
20824
  adapters: cliManager.adapters,
20581
20825
  providerLoader,
20582
20826
  instanceManager,
20583
- sessionRegistry
20827
+ sessionRegistry,
20828
+ onProviderSettingChanged: async (providerType) => {
20829
+ await refreshProviderAvailability(providerType);
20830
+ config.onStatusChange?.();
20831
+ }
20584
20832
  });
20585
20833
  agentStreamManager = new DaemonAgentStreamManager(
20586
20834
  LOG.forComponent("AgentStream").asLogFn(),