adhdev 0.8.25 → 0.8.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -605,9 +605,16 @@ function getMergedDefinitions() {
605
605
  return [...merged.values()];
606
606
  }
607
607
  function findCliCommand(command) {
608
+ const trimmed = String(command || "").trim();
609
+ if (!trimmed) return null;
610
+ if (path4.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
611
+ const candidate = trimmed.startsWith("~") ? path4.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
612
+ const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(candidate);
613
+ return (0, import_fs3.existsSync)(resolved) ? resolved : null;
614
+ }
608
615
  try {
609
616
  const result = (0, import_child_process.execSync)(
610
- (0, import_os2.platform)() === "win32" ? `where ${command}` : `which ${command}`,
617
+ (0, import_os2.platform)() === "win32" ? `where ${trimmed}` : `which ${trimmed}`,
611
618
  { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }
612
619
  ).trim();
613
620
  return result.split("\n")[0] || null;
@@ -630,23 +637,23 @@ function getIdeVersion(cliCommand) {
630
637
  function checkPathExists(paths) {
631
638
  const home = (0, import_os2.homedir)();
632
639
  for (const p of paths) {
633
- if (p.includes("*")) {
640
+ const normalized = p.startsWith("~") ? path4.join(home, p.slice(1)) : p;
641
+ if (normalized.includes("*")) {
634
642
  const username = home.split(/[\\/]/).pop() || "";
635
- const resolved = p.replace("*", username);
643
+ const resolved = normalized.replace("*", username);
636
644
  if ((0, import_fs3.existsSync)(resolved)) return resolved;
637
645
  } else {
638
- if ((0, import_fs3.existsSync)(p)) return p;
646
+ if ((0, import_fs3.existsSync)(normalized)) return normalized;
639
647
  }
640
648
  }
641
649
  return null;
642
650
  }
643
- async function detectIDEs() {
651
+ async function detectIDEs(providerLoader) {
644
652
  const os23 = (0, import_os2.platform)();
645
653
  const results = [];
646
654
  for (const def of getMergedDefinitions()) {
647
- const cliPath = findCliCommand(def.cli);
648
- const appPath = checkPathExists(def.paths[os23] || []);
649
- const installed = !!(cliPath || appPath);
655
+ const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
656
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os23] || []) || []);
650
657
  let resolvedCli = cliPath;
651
658
  if (!resolvedCli && appPath && os23 === "darwin") {
652
659
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
@@ -669,6 +676,7 @@ async function detectIDEs() {
669
676
  }
670
677
  }
671
678
  }
679
+ const installed = os23 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
672
680
  const version2 = resolvedCli ? getIdeVersion(resolvedCli) : null;
673
681
  results.push({
674
682
  id: def.id,
@@ -683,13 +691,14 @@ async function detectIDEs() {
683
691
  }
684
692
  return results;
685
693
  }
686
- var import_child_process, import_fs3, import_os2, BUILTIN_IDE_DEFINITIONS, registeredIDEs;
694
+ var import_child_process, import_fs3, import_os2, path4, BUILTIN_IDE_DEFINITIONS, registeredIDEs;
687
695
  var init_ide_detector = __esm({
688
696
  "../../oss/packages/daemon-core/src/detection/ide-detector.ts"() {
689
697
  "use strict";
690
698
  import_child_process = require("child_process");
691
699
  import_fs3 = require("fs");
692
700
  import_os2 = require("os");
701
+ path4 = __toESM(require("path"));
693
702
  BUILTIN_IDE_DEFINITIONS = [];
694
703
  registeredIDEs = /* @__PURE__ */ new Map();
695
704
  }
@@ -700,44 +709,71 @@ function parseVersion(raw) {
700
709
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
701
710
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
702
711
  }
712
+ function shellQuote(value) {
713
+ if (/^[a-zA-Z0-9_./:@%+=,-]+$/.test(value)) return value;
714
+ return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
715
+ }
716
+ function expandHome(value) {
717
+ const trimmed = value.trim();
718
+ if (!trimmed.startsWith("~")) return trimmed;
719
+ return path5.join(os2.homedir(), trimmed.slice(1));
720
+ }
721
+ function isExplicitCommandPath(command) {
722
+ const trimmed = command.trim();
723
+ return path5.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
724
+ }
725
+ function resolveCommandPath(command) {
726
+ const trimmed = command.trim();
727
+ if (!trimmed) return null;
728
+ if (isExplicitCommandPath(trimmed)) {
729
+ const expanded = expandHome(trimmed);
730
+ const candidate = path5.isAbsolute(expanded) ? expanded : path5.resolve(expanded);
731
+ return (0, import_fs4.existsSync)(candidate) ? candidate : null;
732
+ }
733
+ return null;
734
+ }
703
735
  function execAsync(cmd, timeoutMs = 5e3) {
704
- return new Promise((resolve13) => {
736
+ return new Promise((resolve16) => {
705
737
  const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
706
738
  if (err || !stdout?.trim()) {
707
- resolve13(null);
739
+ resolve16(null);
708
740
  } else {
709
- resolve13(stdout.trim());
741
+ resolve16(stdout.trim());
710
742
  }
711
743
  });
712
- child.on("error", () => resolve13(null));
744
+ child.on("error", () => resolve16(null));
713
745
  });
714
746
  }
715
- async function detectCLIs(providerLoader) {
747
+ async function detectCLIs(providerLoader, options) {
716
748
  const platform11 = os2.platform();
717
749
  const whichCmd = platform11 === "win32" ? "where" : "which";
750
+ const includeVersion = options?.includeVersion !== false;
718
751
  const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
719
752
  const results = await Promise.all(
720
753
  cliList.map(async (cli) => {
721
754
  try {
722
- const pathResult = await execAsync(`${whichCmd} ${cli.command}`);
755
+ const explicitPath = resolveCommandPath(cli.command);
756
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(cli.command)}`);
723
757
  if (!pathResult) return { ...cli, installed: false };
724
- const firstPath = pathResult.split("\n")[0];
758
+ const firstPath = explicitPath || pathResult.split("\n")[0];
725
759
  let version2;
726
- try {
760
+ if (includeVersion) {
727
761
  const versionCommands = [
728
- cli.versionCommand,
729
- `${cli.command} --version`,
730
- `${cli.command} -V`,
731
- `${cli.command} -v`
762
+ `"${firstPath}" --version`,
763
+ `"${firstPath}" -V`,
764
+ `"${firstPath}" -v`,
765
+ cli.versionCommand
732
766
  ].filter((v) => !!v);
733
- for (const versionCommand of versionCommands) {
734
- const versionResult = await execAsync(versionCommand, 3e3);
735
- if (versionResult) {
736
- version2 = parseVersion(versionResult);
737
- break;
767
+ try {
768
+ for (const versionCommand of versionCommands) {
769
+ const versionResult = await execAsync(versionCommand, 3e3);
770
+ if (versionResult) {
771
+ version2 = parseVersion(versionResult);
772
+ break;
773
+ }
738
774
  }
775
+ } catch {
739
776
  }
740
- } catch {
741
777
  }
742
778
  return { ...cli, installed: true, version: version2, path: firstPath };
743
779
  } catch {
@@ -747,7 +783,7 @@ async function detectCLIs(providerLoader) {
747
783
  );
748
784
  return results;
749
785
  }
750
- async function detectCLI(cliId, providerLoader) {
786
+ async function detectCLI(cliId, providerLoader, options) {
751
787
  const resolvedId = providerLoader ? providerLoader.resolveAlias(cliId) : cliId;
752
788
  if (providerLoader) {
753
789
  const cliList = providerLoader.getCliDetectionList();
@@ -756,25 +792,28 @@ async function detectCLI(cliId, providerLoader) {
756
792
  const platform11 = os2.platform();
757
793
  const whichCmd = platform11 === "win32" ? "where" : "which";
758
794
  try {
759
- const pathResult = await execAsync(`${whichCmd} ${target.command}`);
795
+ const explicitPath = resolveCommandPath(target.command);
796
+ const pathResult = explicitPath || await execAsync(`${whichCmd} ${shellQuote(target.command)}`);
760
797
  if (!pathResult) return null;
761
- const firstPath = pathResult.split("\n")[0];
798
+ const firstPath = explicitPath || pathResult.split("\n")[0];
762
799
  let version2;
763
- try {
800
+ if (options?.includeVersion !== false) {
764
801
  const versionCommands = [
765
- target.versionCommand,
766
- `${target.command} --version`,
767
- `${target.command} -V`,
768
- `${target.command} -v`
802
+ `"${firstPath}" --version`,
803
+ `"${firstPath}" -V`,
804
+ `"${firstPath}" -v`,
805
+ target.versionCommand
769
806
  ].filter((v) => !!v);
770
- for (const versionCommand of versionCommands) {
771
- const versionResult = await execAsync(versionCommand, 3e3);
772
- if (versionResult) {
773
- version2 = parseVersion(versionResult);
774
- break;
807
+ try {
808
+ for (const versionCommand of versionCommands) {
809
+ const versionResult = await execAsync(versionCommand, 3e3);
810
+ if (versionResult) {
811
+ version2 = parseVersion(versionResult);
812
+ break;
813
+ }
775
814
  }
815
+ } catch {
776
816
  }
777
- } catch {
778
817
  }
779
818
  return { ...target, installed: true, version: version2, path: firstPath };
780
819
  } catch {
@@ -782,15 +821,17 @@ async function detectCLI(cliId, providerLoader) {
782
821
  }
783
822
  }
784
823
  }
785
- const all = await detectCLIs(providerLoader);
824
+ const all = await detectCLIs(providerLoader, options);
786
825
  return all.find((c) => c.id === resolvedId && c.installed) || null;
787
826
  }
788
- var import_child_process2, os2;
827
+ var import_child_process2, os2, path5, import_fs4;
789
828
  var init_cli_detector = __esm({
790
829
  "../../oss/packages/daemon-core/src/detection/cli-detector.ts"() {
791
830
  "use strict";
792
831
  import_child_process2 = require("child_process");
793
832
  os2 = __toESM(require("os"));
833
+ path5 = __toESM(require("path"));
834
+ import_fs4 = require("fs");
794
835
  }
795
836
  });
796
837
 
@@ -857,13 +898,13 @@ function getDaemonLogDir() {
857
898
  return LOG_DIR;
858
899
  }
859
900
  function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
860
- return path4.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
901
+ return path6.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
861
902
  }
862
903
  function checkDateRotation() {
863
904
  const today = getDateStr();
864
905
  if (today !== currentDate) {
865
906
  currentDate = today;
866
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
907
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
867
908
  cleanOldLogs();
868
909
  }
869
910
  }
@@ -877,7 +918,7 @@ function cleanOldLogs() {
877
918
  const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
878
919
  if (dateMatch && dateMatch[1] < cutoffStr) {
879
920
  try {
880
- fs2.unlinkSync(path4.join(LOG_DIR, file2));
921
+ fs2.unlinkSync(path6.join(LOG_DIR, file2));
881
922
  } catch {
882
923
  }
883
924
  }
@@ -994,17 +1035,17 @@ function installGlobalInterceptor() {
994
1035
  writeToFile(`Log file: ${currentLogFile}`);
995
1036
  writeToFile(`Log level: ${currentLevel}`);
996
1037
  }
997
- var fs2, path4, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
1038
+ var fs2, path6, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
998
1039
  var init_logger = __esm({
999
1040
  "../../oss/packages/daemon-core/src/logging/logger.ts"() {
1000
1041
  "use strict";
1001
1042
  fs2 = __toESM(require("fs"));
1002
- path4 = __toESM(require("path"));
1043
+ path6 = __toESM(require("path"));
1003
1044
  os4 = __toESM(require("os"));
1004
1045
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
1005
1046
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
1006
1047
  currentLevel = "info";
1007
- 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");
1048
+ 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");
1008
1049
  MAX_LOG_SIZE = 5 * 1024 * 1024;
1009
1050
  MAX_LOG_DAYS = 7;
1010
1051
  try {
@@ -1012,16 +1053,16 @@ var init_logger = __esm({
1012
1053
  } catch {
1013
1054
  }
1014
1055
  currentDate = getDateStr();
1015
- currentLogFile = path4.join(LOG_DIR, `daemon-${currentDate}.log`);
1056
+ currentLogFile = path6.join(LOG_DIR, `daemon-${currentDate}.log`);
1016
1057
  cleanOldLogs();
1017
1058
  try {
1018
- const oldLog = path4.join(LOG_DIR, "daemon.log");
1059
+ const oldLog = path6.join(LOG_DIR, "daemon.log");
1019
1060
  if (fs2.existsSync(oldLog)) {
1020
1061
  const stat4 = fs2.statSync(oldLog);
1021
1062
  const oldDate = stat4.mtime.toISOString().slice(0, 10);
1022
- fs2.renameSync(oldLog, path4.join(LOG_DIR, `daemon-${oldDate}.log`));
1063
+ fs2.renameSync(oldLog, path6.join(LOG_DIR, `daemon-${oldDate}.log`));
1023
1064
  }
1024
- const oldLogBackup = path4.join(LOG_DIR, "daemon.log.old");
1065
+ const oldLogBackup = path6.join(LOG_DIR, "daemon.log.old");
1025
1066
  if (fs2.existsSync(oldLogBackup)) {
1026
1067
  fs2.unlinkSync(oldLogBackup);
1027
1068
  }
@@ -1053,7 +1094,7 @@ var init_logger = __esm({
1053
1094
  }
1054
1095
  };
1055
1096
  interceptorInstalled = false;
1056
- LOG_PATH = path4.join(LOG_DIR, `daemon-${getDateStr()}.log`);
1097
+ LOG_PATH = path6.join(LOG_DIR, `daemon-${getDateStr()}.log`);
1057
1098
  }
1058
1099
  });
1059
1100
 
@@ -1142,7 +1183,7 @@ var init_manager = __esm({
1142
1183
  * Returns multiple entries if multiple IDE windows are open on same port
1143
1184
  */
1144
1185
  static listAllTargets(port) {
1145
- return new Promise((resolve13) => {
1186
+ return new Promise((resolve16) => {
1146
1187
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
1147
1188
  let data = "";
1148
1189
  res.on("data", (chunk) => data += chunk.toString());
@@ -1158,16 +1199,16 @@ var init_manager = __esm({
1158
1199
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
1159
1200
  );
1160
1201
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
1161
- resolve13(mainPages.length > 0 ? mainPages : fallbackPages);
1202
+ resolve16(mainPages.length > 0 ? mainPages : fallbackPages);
1162
1203
  } catch {
1163
- resolve13([]);
1204
+ resolve16([]);
1164
1205
  }
1165
1206
  });
1166
1207
  });
1167
- req.on("error", () => resolve13([]));
1208
+ req.on("error", () => resolve16([]));
1168
1209
  req.setTimeout(2e3, () => {
1169
1210
  req.destroy();
1170
- resolve13([]);
1211
+ resolve16([]);
1171
1212
  });
1172
1213
  });
1173
1214
  }
@@ -1207,7 +1248,7 @@ var init_manager = __esm({
1207
1248
  }
1208
1249
  }
1209
1250
  findTargetOnPort(port) {
1210
- return new Promise((resolve13) => {
1251
+ return new Promise((resolve16) => {
1211
1252
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
1212
1253
  let data = "";
1213
1254
  res.on("data", (chunk) => data += chunk.toString());
@@ -1218,7 +1259,7 @@ var init_manager = __esm({
1218
1259
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
1219
1260
  );
1220
1261
  if (pages.length === 0) {
1221
- resolve13(targets.find((t) => t.webSocketDebuggerUrl) || null);
1262
+ resolve16(targets.find((t) => t.webSocketDebuggerUrl) || null);
1222
1263
  return;
1223
1264
  }
1224
1265
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -1228,24 +1269,24 @@ var init_manager = __esm({
1228
1269
  const specific = list.find((t) => t.id === this._targetId);
1229
1270
  if (specific) {
1230
1271
  this._pageTitle = specific.title || "";
1231
- resolve13(specific);
1272
+ resolve16(specific);
1232
1273
  } else {
1233
1274
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
1234
- resolve13(null);
1275
+ resolve16(null);
1235
1276
  }
1236
1277
  return;
1237
1278
  }
1238
1279
  this._pageTitle = list[0]?.title || "";
1239
- resolve13(list[0]);
1280
+ resolve16(list[0]);
1240
1281
  } catch {
1241
- resolve13(null);
1282
+ resolve16(null);
1242
1283
  }
1243
1284
  });
1244
1285
  });
1245
- req.on("error", () => resolve13(null));
1286
+ req.on("error", () => resolve16(null));
1246
1287
  req.setTimeout(2e3, () => {
1247
1288
  req.destroy();
1248
- resolve13(null);
1289
+ resolve16(null);
1249
1290
  });
1250
1291
  });
1251
1292
  }
@@ -1256,7 +1297,7 @@ var init_manager = __esm({
1256
1297
  this.extensionProviders = providers;
1257
1298
  }
1258
1299
  connectToTarget(wsUrl) {
1259
- return new Promise((resolve13) => {
1300
+ return new Promise((resolve16) => {
1260
1301
  this.ws = new import_ws.default(wsUrl);
1261
1302
  this.ws.on("open", async () => {
1262
1303
  this._connected = true;
@@ -1266,17 +1307,17 @@ var init_manager = __esm({
1266
1307
  }
1267
1308
  this.connectBrowserWs().catch(() => {
1268
1309
  });
1269
- resolve13(true);
1310
+ resolve16(true);
1270
1311
  });
1271
1312
  this.ws.on("message", (data) => {
1272
1313
  try {
1273
1314
  const msg = JSON.parse(data.toString());
1274
1315
  if (msg.id && this.pending.has(msg.id)) {
1275
- const { resolve: resolve14, reject } = this.pending.get(msg.id);
1316
+ const { resolve: resolve17, reject } = this.pending.get(msg.id);
1276
1317
  this.pending.delete(msg.id);
1277
1318
  this.failureCount = 0;
1278
1319
  if (msg.error) reject(new Error(msg.error.message));
1279
- else resolve14(msg.result);
1320
+ else resolve17(msg.result);
1280
1321
  } else if (msg.method === "Runtime.executionContextCreated") {
1281
1322
  this.contexts.add(msg.params.context.id);
1282
1323
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -1299,7 +1340,7 @@ var init_manager = __esm({
1299
1340
  this.ws.on("error", (err) => {
1300
1341
  this.log(`[CDP] WebSocket error: ${err.message}`);
1301
1342
  this._connected = false;
1302
- resolve13(false);
1343
+ resolve16(false);
1303
1344
  });
1304
1345
  });
1305
1346
  }
@@ -1313,7 +1354,7 @@ var init_manager = __esm({
1313
1354
  return;
1314
1355
  }
1315
1356
  this.log(`[CDP] Connecting browser WS for target discovery...`);
1316
- await new Promise((resolve13, reject) => {
1357
+ await new Promise((resolve16, reject) => {
1317
1358
  this.browserWs = new import_ws.default(browserWsUrl);
1318
1359
  this.browserWs.on("open", async () => {
1319
1360
  this._browserConnected = true;
@@ -1323,16 +1364,16 @@ var init_manager = __esm({
1323
1364
  } catch (e) {
1324
1365
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
1325
1366
  }
1326
- resolve13();
1367
+ resolve16();
1327
1368
  });
1328
1369
  this.browserWs.on("message", (data) => {
1329
1370
  try {
1330
1371
  const msg = JSON.parse(data.toString());
1331
1372
  if (msg.id && this.browserPending.has(msg.id)) {
1332
- const { resolve: resolve14, reject: reject2 } = this.browserPending.get(msg.id);
1373
+ const { resolve: resolve17, reject: reject2 } = this.browserPending.get(msg.id);
1333
1374
  this.browserPending.delete(msg.id);
1334
1375
  if (msg.error) reject2(new Error(msg.error.message));
1335
- else resolve14(msg.result);
1376
+ else resolve17(msg.result);
1336
1377
  }
1337
1378
  } catch {
1338
1379
  }
@@ -1352,31 +1393,31 @@ var init_manager = __esm({
1352
1393
  }
1353
1394
  }
1354
1395
  getBrowserWsUrl() {
1355
- return new Promise((resolve13) => {
1396
+ return new Promise((resolve16) => {
1356
1397
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
1357
1398
  let data = "";
1358
1399
  res.on("data", (chunk) => data += chunk.toString());
1359
1400
  res.on("end", () => {
1360
1401
  try {
1361
1402
  const info = JSON.parse(data);
1362
- resolve13(info.webSocketDebuggerUrl || null);
1403
+ resolve16(info.webSocketDebuggerUrl || null);
1363
1404
  } catch {
1364
- resolve13(null);
1405
+ resolve16(null);
1365
1406
  }
1366
1407
  });
1367
1408
  });
1368
- req.on("error", () => resolve13(null));
1409
+ req.on("error", () => resolve16(null));
1369
1410
  req.setTimeout(3e3, () => {
1370
1411
  req.destroy();
1371
- resolve13(null);
1412
+ resolve16(null);
1372
1413
  });
1373
1414
  });
1374
1415
  }
1375
1416
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
1376
- return new Promise((resolve13, reject) => {
1417
+ return new Promise((resolve16, reject) => {
1377
1418
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
1378
1419
  const id = this.browserMsgId++;
1379
- this.browserPending.set(id, { resolve: resolve13, reject });
1420
+ this.browserPending.set(id, { resolve: resolve16, reject });
1380
1421
  this.browserWs.send(JSON.stringify({ id, method, params }));
1381
1422
  setTimeout(() => {
1382
1423
  if (this.browserPending.has(id)) {
@@ -1416,11 +1457,11 @@ var init_manager = __esm({
1416
1457
  }
1417
1458
  // ─── CDP Protocol ────────────────────────────────────────
1418
1459
  sendInternal(method, params = {}, timeoutMs = 15e3) {
1419
- return new Promise((resolve13, reject) => {
1460
+ return new Promise((resolve16, reject) => {
1420
1461
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
1421
1462
  if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
1422
1463
  const id = this.msgId++;
1423
- this.pending.set(id, { resolve: resolve13, reject });
1464
+ this.pending.set(id, { resolve: resolve16, reject });
1424
1465
  this.ws.send(JSON.stringify({ id, method, params }));
1425
1466
  setTimeout(() => {
1426
1467
  if (this.pending.has(id)) {
@@ -1669,7 +1710,7 @@ var init_manager = __esm({
1669
1710
  const browserWs = this.browserWs;
1670
1711
  let msgId = this.browserMsgId;
1671
1712
  const sendWs = (method, params = {}, sessionId) => {
1672
- return new Promise((resolve13, reject) => {
1713
+ return new Promise((resolve16, reject) => {
1673
1714
  const mid = msgId++;
1674
1715
  this.browserMsgId = msgId;
1675
1716
  const handler = (raw) => {
@@ -1678,7 +1719,7 @@ var init_manager = __esm({
1678
1719
  if (msg.id === mid) {
1679
1720
  browserWs.removeListener("message", handler);
1680
1721
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
1681
- else resolve13(msg.result);
1722
+ else resolve16(msg.result);
1682
1723
  }
1683
1724
  } catch {
1684
1725
  }
@@ -1869,14 +1910,14 @@ var init_manager = __esm({
1869
1910
  if (!ws || ws.readyState !== import_ws.default.OPEN) {
1870
1911
  throw new Error("CDP not connected");
1871
1912
  }
1872
- return new Promise((resolve13, reject) => {
1913
+ return new Promise((resolve16, reject) => {
1873
1914
  const id = getNextId();
1874
1915
  pendingMap.set(id, {
1875
1916
  resolve: (result) => {
1876
1917
  if (result?.result?.subtype === "error") {
1877
1918
  reject(new Error(result.result.description));
1878
1919
  } else {
1879
- resolve13(result?.result?.value);
1920
+ resolve16(result?.result?.value);
1880
1921
  }
1881
1922
  },
1882
1923
  reject
@@ -1908,10 +1949,10 @@ var init_manager = __esm({
1908
1949
  throw new Error("CDP not connected");
1909
1950
  }
1910
1951
  const sendViaSession = (method, params = {}) => {
1911
- return new Promise((resolve13, reject) => {
1952
+ return new Promise((resolve16, reject) => {
1912
1953
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
1913
1954
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
1914
- pendingMap.set(id, { resolve: resolve13, reject });
1955
+ pendingMap.set(id, { resolve: resolve16, reject });
1915
1956
  ws.send(JSON.stringify({ id, sessionId, method, params }));
1916
1957
  setTimeout(() => {
1917
1958
  if (pendingMap.has(id)) {
@@ -2557,7 +2598,7 @@ var init_control_effects = __esm({
2557
2598
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
2558
2599
  try {
2559
2600
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
2560
- const dir = path5.join(HISTORY_DIR, sanitized);
2601
+ const dir = path7.join(HISTORY_DIR, sanitized);
2561
2602
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
2562
2603
  const sanitizedInstance = historySessionId?.replace(/[^a-zA-Z0-9_-]/g, "_");
2563
2604
  const files = fs3.readdirSync(dir).filter((f) => {
@@ -2571,7 +2612,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
2571
2612
  const needed = offset + limit + 1;
2572
2613
  for (const file2 of files) {
2573
2614
  if (allMessages.length >= needed) break;
2574
- const filePath = path5.join(dir, file2);
2615
+ const filePath = path7.join(dir, file2);
2575
2616
  const content = fs3.readFileSync(filePath, "utf-8");
2576
2617
  const lines = content.trim().split("\n").filter(Boolean);
2577
2618
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -2593,7 +2634,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId) {
2593
2634
  function listSavedHistorySessions(agentType, options = {}) {
2594
2635
  try {
2595
2636
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
2596
- const dir = path5.join(HISTORY_DIR, sanitized);
2637
+ const dir = path7.join(HISTORY_DIR, sanitized);
2597
2638
  if (!fs3.existsSync(dir)) return { sessions: [], hasMore: false };
2598
2639
  const groupedFiles = /* @__PURE__ */ new Map();
2599
2640
  const filePattern = /^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/;
@@ -2614,7 +2655,7 @@ function listSavedHistorySessions(agentType, options = {}) {
2614
2655
  let sessionTitle = "";
2615
2656
  let preview = "";
2616
2657
  for (const file2 of files.sort()) {
2617
- const filePath = path5.join(dir, file2);
2658
+ const filePath = path7.join(dir, file2);
2618
2659
  const content = fs3.readFileSync(filePath, "utf-8");
2619
2660
  const lines = content.split("\n").filter(Boolean);
2620
2661
  for (const line of lines) {
@@ -2654,14 +2695,14 @@ function listSavedHistorySessions(agentType, options = {}) {
2654
2695
  return { sessions: [], hasMore: false };
2655
2696
  }
2656
2697
  }
2657
- var fs3, path5, os5, HISTORY_DIR, RETAIN_DAYS, ChatHistoryWriter;
2698
+ var fs3, path7, os5, HISTORY_DIR, RETAIN_DAYS, ChatHistoryWriter;
2658
2699
  var init_chat_history = __esm({
2659
2700
  "../../oss/packages/daemon-core/src/config/chat-history.ts"() {
2660
2701
  "use strict";
2661
2702
  fs3 = __toESM(require("fs"));
2662
- path5 = __toESM(require("path"));
2703
+ path7 = __toESM(require("path"));
2663
2704
  os5 = __toESM(require("os"));
2664
- HISTORY_DIR = path5.join(os5.homedir(), ".adhdev", "history");
2705
+ HISTORY_DIR = path7.join(os5.homedir(), ".adhdev", "history");
2665
2706
  RETAIN_DAYS = 30;
2666
2707
  ChatHistoryWriter = class {
2667
2708
  /** Last seen message count per agent (deduplication) */
@@ -2706,11 +2747,11 @@ var init_chat_history = __esm({
2706
2747
  });
2707
2748
  }
2708
2749
  if (newMessages.length === 0) return;
2709
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
2750
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
2710
2751
  fs3.mkdirSync(dir, { recursive: true });
2711
2752
  const date5 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2712
2753
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
2713
- const filePath = path5.join(dir, `${filePrefix}${date5}.jsonl`);
2754
+ const filePath = path7.join(dir, `${filePrefix}${date5}.jsonl`);
2714
2755
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
2715
2756
  fs3.appendFileSync(filePath, lines, "utf-8");
2716
2757
  const prevCount = this.lastSeenCounts.get(dedupKey) || 0;
@@ -2764,14 +2805,14 @@ var init_chat_history = __esm({
2764
2805
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
2765
2806
  this.lastSeenCounts.delete(fromDedupKey);
2766
2807
  }
2767
- const dir = path5.join(HISTORY_DIR, this.sanitize(agentType));
2808
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
2768
2809
  if (!fs3.existsSync(dir)) return;
2769
2810
  const fromPrefix = `${this.sanitize(fromId)}_`;
2770
2811
  const toPrefix = `${this.sanitize(toId)}_`;
2771
2812
  const files = fs3.readdirSync(dir).filter((file2) => file2.startsWith(fromPrefix) && file2.endsWith(".jsonl"));
2772
2813
  for (const file2 of files) {
2773
- const sourcePath = path5.join(dir, file2);
2774
- const targetPath = path5.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
2814
+ const sourcePath = path7.join(dir, file2);
2815
+ const targetPath = path7.join(dir, `${toPrefix}${file2.slice(fromPrefix.length)}`);
2775
2816
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
2776
2817
  const rewritten = sourceLines.map((line) => {
2777
2818
  try {
@@ -2812,10 +2853,10 @@ var init_chat_history = __esm({
2812
2853
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
2813
2854
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
2814
2855
  for (const dir of agentDirs) {
2815
- const dirPath = path5.join(HISTORY_DIR, dir.name);
2856
+ const dirPath = path7.join(HISTORY_DIR, dir.name);
2816
2857
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
2817
2858
  for (const file2 of files) {
2818
- const filePath = path5.join(dirPath, file2);
2859
+ const filePath = path7.join(dirPath, file2);
2819
2860
  const stat4 = fs3.statSync(filePath);
2820
2861
  if (stat4.mtimeMs < cutoff) {
2821
2862
  fs3.unlinkSync(filePath);
@@ -2852,6 +2893,7 @@ var init_extension_provider_instance = __esm({
2852
2893
  currentStatus = "idle";
2853
2894
  agentStreams = [];
2854
2895
  messages = [];
2896
+ prevMessageHashes = /* @__PURE__ */ new Map();
2855
2897
  activeModal = null;
2856
2898
  currentModel = "";
2857
2899
  currentMode = "";
@@ -2917,7 +2959,7 @@ var init_extension_provider_instance = __esm({
2917
2959
  onEvent(event, data) {
2918
2960
  if (event === "stream_update") {
2919
2961
  if (data?.streams) this.agentStreams = data.streams;
2920
- if (data?.messages) this.messages = data.messages;
2962
+ if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
2921
2963
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
2922
2964
  if (data?.model) this.currentModel = data.model;
2923
2965
  if (data?.mode) this.currentMode = data.mode;
@@ -2943,6 +2985,7 @@ var init_extension_provider_instance = __esm({
2943
2985
  dispose() {
2944
2986
  this.agentStreams = [];
2945
2987
  this.messages = [];
2988
+ this.prevMessageHashes.clear();
2946
2989
  this.monitor.reset();
2947
2990
  this.appliedEffectKeys.clear();
2948
2991
  this.runtimeMessages = [];
@@ -3098,6 +3141,23 @@ var init_extension_provider_instance = __esm({
3098
3141
  this.chatId || this.instanceId
3099
3142
  );
3100
3143
  }
3144
+ /**
3145
+ * Assign stable receivedAt to extension messages.
3146
+ * Same pattern as IdeProviderInstance.readChat() prevByHash —
3147
+ * preserves first-seen timestamp across polling cycles.
3148
+ */
3149
+ assignReceivedAt(messages) {
3150
+ const now = Date.now();
3151
+ const nextHashes = /* @__PURE__ */ new Map();
3152
+ for (const msg of messages) {
3153
+ const hash2 = `${msg.role}:${(msg.content || "").slice(0, 100)}`;
3154
+ const prevTime = this.prevMessageHashes.get(hash2);
3155
+ msg.receivedAt = prevTime || now;
3156
+ nextHashes.set(hash2, msg.receivedAt);
3157
+ }
3158
+ this.prevMessageHashes = nextHashes;
3159
+ return messages;
3160
+ }
3101
3161
  mergeConversationMessages(messages) {
3102
3162
  if (this.runtimeMessages.length === 0) return messages;
3103
3163
  return [...messages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
@@ -3154,6 +3214,7 @@ ${effect.notification.body || ""}`.trim();
3154
3214
  }
3155
3215
  this.agentStreams = [];
3156
3216
  this.messages = [];
3217
+ this.prevMessageHashes.clear();
3157
3218
  this.activeModal = null;
3158
3219
  this.currentModel = "";
3159
3220
  this.currentMode = "";
@@ -4161,16 +4222,28 @@ function trimMessageForStatus(message, stringLimit) {
4161
4222
  if (!message || typeof message !== "object") return message;
4162
4223
  return trimStructuredStrings(message, stringLimit);
4163
4224
  }
4225
+ function normalizeMessageTime(message) {
4226
+ if (!message || typeof message !== "object") return message;
4227
+ const msg = message;
4228
+ if (msg.receivedAt == null) {
4229
+ const fallback = msg.timestamp ?? msg.createdAt;
4230
+ if (fallback != null) {
4231
+ const ts2 = typeof fallback === "string" ? Date.parse(fallback) : Number(fallback);
4232
+ if (Number.isFinite(ts2) && ts2 > 0) msg.receivedAt = ts2;
4233
+ }
4234
+ }
4235
+ return msg;
4236
+ }
4164
4237
  function trimMessagesForStatus(messages) {
4165
4238
  if (!Array.isArray(messages) || messages.length === 0) return [];
4166
4239
  const recent = messages.slice(-STATUS_ACTIVE_CHAT_MESSAGE_LIMIT);
4167
4240
  const kept = [];
4168
4241
  let totalBytes = 0;
4169
4242
  for (let i = recent.length - 1; i >= 0; i -= 1) {
4170
- let normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT);
4243
+ let normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_STRING_LIMIT));
4171
4244
  let size = estimateBytes(normalized);
4172
4245
  if (size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
4173
- normalized = trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT);
4246
+ normalized = normalizeMessageTime(trimMessageForStatus(recent[i], STATUS_ACTIVE_CHAT_FALLBACK_STRING_LIMIT));
4174
4247
  size = estimateBytes(normalized);
4175
4248
  }
4176
4249
  if (kept.length > 0 && totalBytes + size > STATUS_ACTIVE_CHAT_TOTAL_BYTES_LIMIT) {
@@ -4820,7 +4893,7 @@ async function handleSendChat(h, args) {
4820
4893
  if (isExtensionTransport(transport)) {
4821
4894
  _log(`Extension: ${provider?.type || "unknown_extension"}`);
4822
4895
  try {
4823
- const evalResult = await h.evaluateProviderScript("sendMessage", { MESSAGE: text }, 3e4);
4896
+ const evalResult = await h.evaluateProviderScript("sendMessage", { message: text }, 3e4);
4824
4897
  if (evalResult?.result) {
4825
4898
  const parsed = parseMaybeJson(evalResult.result);
4826
4899
  if (didProviderConfirmSend(parsed)) {
@@ -4851,7 +4924,7 @@ async function handleSendChat(h, args) {
4851
4924
  return { success: false, error: `CDP for ${managerKey || "unknown"} not connected` };
4852
4925
  }
4853
4926
  _log(`Targeting IDE: ${getCurrentManagerKey(h)}`);
4854
- const sendScript = h.getProviderScript("sendMessage", { MESSAGE: text });
4927
+ const sendScript = h.getProviderScript("sendMessage", { message: text });
4855
4928
  if (sendScript) {
4856
4929
  try {
4857
4930
  const result = await targetCdp.evaluate(sendScript, 3e4);
@@ -4991,6 +5064,14 @@ async function handleListChats(h, args) {
4991
5064
  } catch {
4992
5065
  }
4993
5066
  }
5067
+ if (parsed?.sessions && Array.isArray(parsed.sessions)) {
5068
+ LOG.info("Command", `[list_chats] OK: ${parsed.sessions.length} chats`);
5069
+ return { success: true, chats: parsed.sessions };
5070
+ }
5071
+ if (parsed?.chats && Array.isArray(parsed.chats)) {
5072
+ LOG.info("Command", `[list_chats] OK: ${parsed.chats.length} chats`);
5073
+ return { success: true, chats: parsed.chats };
5074
+ }
4994
5075
  if (Array.isArray(parsed)) {
4995
5076
  LOG.info("Command", `[list_chats] OK: ${parsed.length} chats`);
4996
5077
  return { success: true, chats: parsed };
@@ -5060,7 +5141,13 @@ async function handleSwitchChat(h, args) {
5060
5141
  } catch (e) {
5061
5142
  return { success: false, error: `webviewSwitchSession failed: ${e.message}` };
5062
5143
  }
5063
- const script = h.getProviderScript("switchSession", { SESSION_ID: JSON.stringify(sessionId) }) || h.getProviderScript("switch_session", { SESSION_ID: JSON.stringify(sessionId) });
5144
+ const switchParams = {
5145
+ sessionId,
5146
+ title: sessionId,
5147
+ id: sessionId,
5148
+ SESSION_ID: JSON.stringify(sessionId)
5149
+ };
5150
+ const script = h.getProviderScript("switchSession", switchParams) || h.getProviderScript("switch_session", switchParams);
5064
5151
  if (!script) return { success: false, error: "switch_session script not available" };
5065
5152
  try {
5066
5153
  const raw = await cdp.evaluate(script, 15e3);
@@ -5139,8 +5226,8 @@ async function handleSetMode(h, args) {
5139
5226
  const adapter = getTargetedCliAdapter(h, args, provider?.type);
5140
5227
  if (adapter) {
5141
5228
  const acpInstance = adapter._acpInstance;
5142
- if (acpInstance && typeof acpInstance.onEvent === "function") {
5143
- acpInstance.onEvent("set_mode", { mode });
5229
+ if (acpInstance && typeof acpInstance.setMode === "function") {
5230
+ await acpInstance.setMode(mode);
5144
5231
  return { success: true, mode };
5145
5232
  }
5146
5233
  }
@@ -5197,9 +5284,9 @@ async function handleChangeModel(h, args) {
5197
5284
  LOG.info("Command", `[change_model] ACP adapter found: ${!!adapter}, type=${adapter?.cliType}, hasAcpInstance=${!!adapter?._acpInstance}`);
5198
5285
  if (adapter) {
5199
5286
  const acpInstance = adapter._acpInstance;
5200
- if (acpInstance && typeof acpInstance.onEvent === "function") {
5201
- acpInstance.onEvent("change_model", { model });
5202
- LOG.info("Command", `[change_model] Dispatched change_model event to ACP instance`);
5287
+ if (acpInstance && typeof acpInstance.setConfigOption === "function") {
5288
+ await acpInstance.setConfigOption("model", model);
5289
+ LOG.info("Command", `[change_model] Updated ACP model to ${model}`);
5203
5290
  return { success: true, model };
5204
5291
  }
5205
5292
  }
@@ -5319,6 +5406,18 @@ async function handleResolveAction(h, args) {
5319
5406
  const ok = await h.agentStream.resolveSessionAction(h.getCdp(), h.currentSession.sessionId, action);
5320
5407
  return { success: ok };
5321
5408
  }
5409
+ if (transport === "acp") {
5410
+ const adapter = getTargetedCliAdapter(h, args, provider?.type);
5411
+ const acpInstance = adapter?._acpInstance;
5412
+ if (!acpInstance) return { success: false, error: "ACP instance not found" };
5413
+ try {
5414
+ await acpInstance.resolvePermission(action === "approve" || action === "accept" || action === "always");
5415
+ LOG.info("Command", `[resolveAction] ACP \u2192 ${action}`);
5416
+ return { success: true, action };
5417
+ } catch (e) {
5418
+ return { success: false, error: e?.message || "ACP resolve action failed" };
5419
+ }
5420
+ }
5322
5421
  if (provider?.scripts?.webviewResolveAction || provider?.scripts?.webview_resolve_action) {
5323
5422
  const script = h.getProviderScript("webviewResolveAction", { action, button, buttonText: button }) || h.getProviderScript("webview_resolve_action", { action, button, buttonText: button });
5324
5423
  if (script) {
@@ -5621,25 +5720,25 @@ function resolveSafePath(requestedPath) {
5621
5720
  const inputPath = rawPath || ".";
5622
5721
  const home = os6.homedir();
5623
5722
  if (inputPath.startsWith("~")) {
5624
- return path6.resolve(path6.join(home, inputPath.slice(1)));
5723
+ return path8.resolve(path8.join(home, inputPath.slice(1)));
5625
5724
  }
5626
5725
  if (process.platform === "win32") {
5627
5726
  const normalized = normalizeWindowsRequestedPath(inputPath);
5628
- if (path6.win32.isAbsolute(normalized)) {
5629
- return path6.win32.normalize(normalized);
5727
+ if (path8.win32.isAbsolute(normalized)) {
5728
+ return path8.win32.normalize(normalized);
5630
5729
  }
5631
- return path6.win32.resolve(normalized);
5730
+ return path8.win32.resolve(normalized);
5632
5731
  }
5633
- if (path6.isAbsolute(inputPath)) {
5634
- return path6.normalize(inputPath);
5732
+ if (path8.isAbsolute(inputPath)) {
5733
+ return path8.normalize(inputPath);
5635
5734
  }
5636
- return path6.resolve(inputPath);
5735
+ return path8.resolve(inputPath);
5637
5736
  }
5638
5737
  function listDirectoryEntriesSafe(dirPath) {
5639
5738
  const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
5640
5739
  const files = [];
5641
5740
  for (const entry of entries) {
5642
- const entryPath = path6.join(dirPath, entry.name);
5741
+ const entryPath = path8.join(dirPath, entry.name);
5643
5742
  try {
5644
5743
  if (entry.isDirectory()) {
5645
5744
  files.push({ name: entry.name, type: "directory" });
@@ -5678,7 +5777,7 @@ async function handleFileRead(h, args) {
5678
5777
  async function handleFileWrite(h, args) {
5679
5778
  try {
5680
5779
  const filePath = resolveSafePath(args?.path);
5681
- fs4.mkdirSync(path6.dirname(filePath), { recursive: true });
5780
+ fs4.mkdirSync(path8.dirname(filePath), { recursive: true });
5682
5781
  fs4.writeFileSync(filePath, args?.content || "", "utf-8");
5683
5782
  return { success: true, path: filePath };
5684
5783
  } catch (e) {
@@ -5703,12 +5802,12 @@ async function handleFileListBrowse(h, args) {
5703
5802
  return { success: false, error: e.message };
5704
5803
  }
5705
5804
  }
5706
- var fs4, path6, os6, KEY_TO_VK;
5805
+ var fs4, path8, os6, KEY_TO_VK;
5707
5806
  var init_cdp_commands = __esm({
5708
5807
  "../../oss/packages/daemon-core/src/commands/cdp-commands.ts"() {
5709
5808
  "use strict";
5710
5809
  fs4 = __toESM(require("fs"));
5711
- path6 = __toESM(require("path"));
5810
+ path8 = __toESM(require("path"));
5712
5811
  os6 = __toESM(require("os"));
5713
5812
  KEY_TO_VK = {
5714
5813
  Backspace: 8,
@@ -5809,7 +5908,7 @@ function handleGetProviderSettings(h, args) {
5809
5908
  }
5810
5909
  return { success: true, settings: allSettings, values: allValues };
5811
5910
  }
5812
- function handleSetProviderSetting(h, args) {
5911
+ async function handleSetProviderSetting(h, args) {
5813
5912
  const loader = h.ctx.providerLoader;
5814
5913
  const { providerType, key, value } = args || {};
5815
5914
  if (!providerType || !key || value === void 0) {
@@ -5822,6 +5921,7 @@ function handleSetProviderSetting(h, args) {
5822
5921
  const updated = h.ctx.instanceManager.updateInstanceSettings(providerType, allSettings);
5823
5922
  LOG.info("Command", `[set_provider_setting] ${providerType}.${key}=${JSON.stringify(value)} \u2192 ${updated} instance(s) updated`);
5824
5923
  }
5924
+ await h.ctx.onProviderSettingChanged?.(providerType, key, value);
5825
5925
  return { success: true, providerType, key, value };
5826
5926
  }
5827
5927
  return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
@@ -5859,10 +5959,10 @@ function getCliScriptCommand(payload) {
5859
5959
  }
5860
5960
  const command = payload.command;
5861
5961
  if (!command || typeof command !== "object") return null;
5862
- if (command.type !== "send_message") return null;
5962
+ if (command.type !== "send_message" && command.type !== "pty_write") return null;
5863
5963
  const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
5864
5964
  if (!text) return null;
5865
- return { type: "send_message", text };
5965
+ return { type: command.type, text };
5866
5966
  }
5867
5967
  function applyProviderPatch(h, args, payload) {
5868
5968
  if (!payload || typeof payload !== "object") return;
@@ -5903,6 +6003,8 @@ async function executeProviderScript(h, args, scriptName) {
5903
6003
  const cliCommand = getCliScriptCommand(parsed.payload);
5904
6004
  if (cliCommand?.type === "send_message" && cliCommand.text) {
5905
6005
  await adapter.sendMessage(cliCommand.text);
6006
+ } else if (cliCommand?.type === "pty_write" && cliCommand.text && adapter.writeRaw) {
6007
+ adapter.writeRaw(cliCommand.text + "\r");
5906
6008
  }
5907
6009
  applyProviderPatch(h, args, parsed.payload);
5908
6010
  return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
@@ -6293,9 +6395,26 @@ var init_handler = __esm({
6293
6395
  if (provider?.scripts) {
6294
6396
  const fn = provider.scripts[scriptName];
6295
6397
  if (typeof fn === "function") {
6296
- const firstVal = params ? Object.values(params)[0] : void 0;
6297
- const script = firstVal ? fn(firstVal) : fn();
6298
- if (script) return script;
6398
+ if (params && Object.keys(params).length > 0) {
6399
+ const firstVal = Object.values(params)[0];
6400
+ if (scriptName === "sendMessage" && typeof firstVal === "string") {
6401
+ const legacyScript = fn(firstVal);
6402
+ if (legacyScript) return legacyScript;
6403
+ }
6404
+ const script = fn(params);
6405
+ if (script) {
6406
+ const likelyLegacyObjectLeak = typeof script === "string" && script.includes("[object Object]") && typeof firstVal === "string";
6407
+ if (!likelyLegacyObjectLeak) return script;
6408
+ }
6409
+ if (firstVal !== void 0) {
6410
+ const legacyScript = fn(firstVal);
6411
+ if (legacyScript) return legacyScript;
6412
+ }
6413
+ if (script) return script;
6414
+ } else {
6415
+ const script = fn();
6416
+ if (script) return script;
6417
+ }
6299
6418
  }
6300
6419
  }
6301
6420
  return null;
@@ -6589,7 +6708,7 @@ var init_handler = __esm({
6589
6708
  try {
6590
6709
  const http3 = await import("http");
6591
6710
  const postData = JSON.stringify(body);
6592
- const result = await new Promise((resolve13, reject) => {
6711
+ const result = await new Promise((resolve16, reject) => {
6593
6712
  const req = http3.request({
6594
6713
  hostname: "127.0.0.1",
6595
6714
  port: 19280,
@@ -6601,9 +6720,9 @@ var init_handler = __esm({
6601
6720
  res.on("data", (chunk) => data += chunk);
6602
6721
  res.on("end", () => {
6603
6722
  try {
6604
- resolve13(JSON.parse(data));
6723
+ resolve16(JSON.parse(data));
6605
6724
  } catch {
6606
- resolve13({ raw: data });
6725
+ resolve16({ raw: data });
6607
6726
  }
6608
6727
  });
6609
6728
  });
@@ -6621,15 +6740,15 @@ var init_handler = __esm({
6621
6740
  if (!providerType) return { success: false, error: "providerType required" };
6622
6741
  try {
6623
6742
  const http3 = await import("http");
6624
- const result = await new Promise((resolve13, reject) => {
6743
+ const result = await new Promise((resolve16, reject) => {
6625
6744
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
6626
6745
  let data = "";
6627
6746
  res.on("data", (chunk) => data += chunk);
6628
6747
  res.on("end", () => {
6629
6748
  try {
6630
- resolve13(JSON.parse(data));
6749
+ resolve16(JSON.parse(data));
6631
6750
  } catch {
6632
- resolve13({ raw: data });
6751
+ resolve16({ raw: data });
6633
6752
  }
6634
6753
  });
6635
6754
  }).on("error", reject);
@@ -6643,7 +6762,7 @@ var init_handler = __esm({
6643
6762
  try {
6644
6763
  const http3 = await import("http");
6645
6764
  const postData = JSON.stringify(args || {});
6646
- const result = await new Promise((resolve13, reject) => {
6765
+ const result = await new Promise((resolve16, reject) => {
6647
6766
  const req = http3.request({
6648
6767
  hostname: "127.0.0.1",
6649
6768
  port: 19280,
@@ -6655,9 +6774,9 @@ var init_handler = __esm({
6655
6774
  res.on("data", (chunk) => data += chunk);
6656
6775
  res.on("end", () => {
6657
6776
  try {
6658
- resolve13(JSON.parse(data));
6777
+ resolve16(JSON.parse(data));
6659
6778
  } catch {
6660
- resolve13({ raw: data });
6779
+ resolve16({ raw: data });
6661
6780
  }
6662
6781
  });
6663
6782
  });
@@ -7294,16 +7413,22 @@ function computeTerminalQueryTail(buffer) {
7294
7413
  return "";
7295
7414
  }
7296
7415
  function findBinary(name) {
7416
+ const trimmed = String(name || "").trim();
7417
+ if (!trimmed) return trimmed;
7418
+ const expanded = trimmed.startsWith("~") ? path9.join(os9.homedir(), trimmed.slice(1)) : trimmed;
7419
+ if (path9.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
7420
+ return path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
7421
+ }
7297
7422
  const isWin = os9.platform() === "win32";
7298
7423
  try {
7299
- const cmd = isWin ? `where ${name}` : `which ${name}`;
7424
+ const cmd = isWin ? `where ${trimmed}` : `which ${trimmed}`;
7300
7425
  return (0, import_child_process4.execSync)(cmd, { encoding: "utf-8", timeout: 5e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n")[0].trim();
7301
7426
  } catch {
7302
- return isWin ? `${name}.cmd` : name;
7427
+ return isWin ? `${trimmed}.cmd` : trimmed;
7303
7428
  }
7304
7429
  }
7305
7430
  function isScriptBinary(binaryPath) {
7306
- if (!path7.isAbsolute(binaryPath)) return false;
7431
+ if (!path9.isAbsolute(binaryPath)) return false;
7307
7432
  try {
7308
7433
  const fs18 = require("fs");
7309
7434
  const resolved = fs18.realpathSync(binaryPath);
@@ -7319,7 +7444,7 @@ function isScriptBinary(binaryPath) {
7319
7444
  }
7320
7445
  }
7321
7446
  function looksLikeMachOOrElf(filePath) {
7322
- if (!path7.isAbsolute(filePath)) return false;
7447
+ if (!path9.isAbsolute(filePath)) return false;
7323
7448
  try {
7324
7449
  const fs18 = require("fs");
7325
7450
  const resolved = fs18.realpathSync(filePath);
@@ -7443,12 +7568,12 @@ function normalizeCliProviderForRuntime(raw) {
7443
7568
  }
7444
7569
  };
7445
7570
  }
7446
- var os9, path7, import_child_process4, buildCliSpawnEnv, ProviderCliAdapter;
7571
+ var os9, path9, import_child_process4, buildCliSpawnEnv, ProviderCliAdapter;
7447
7572
  var init_provider_cli_adapter = __esm({
7448
7573
  "../../oss/packages/daemon-core/src/cli-adapters/provider-cli-adapter.ts"() {
7449
7574
  "use strict";
7450
7575
  os9 = __toESM(require("os"));
7451
- path7 = __toESM(require("path"));
7576
+ path9 = __toESM(require("path"));
7452
7577
  import_child_process4 = require("child_process");
7453
7578
  init_logger();
7454
7579
  init_terminal_screen();
@@ -7803,16 +7928,17 @@ var init_provider_cli_adapter = __esm({
7803
7928
  async spawn() {
7804
7929
  if (this.ptyProcess) return;
7805
7930
  const { spawn: spawnConfig } = this.provider;
7806
- const binaryPath = findBinary(spawnConfig.command);
7931
+ const configuredCommand = typeof this.runtimeSettings.executablePath === "string" && this.runtimeSettings.executablePath.trim() ? this.runtimeSettings.executablePath.trim() : spawnConfig.command;
7932
+ const binaryPath = findBinary(configuredCommand);
7807
7933
  const isWin = os9.platform() === "win32";
7808
7934
  const allArgs = [...spawnConfig.args, ...this.extraArgs];
7809
7935
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
7810
7936
  this.resetTraceSession();
7811
7937
  let shellCmd;
7812
7938
  let shellArgs;
7813
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
7939
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
7814
7940
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
7815
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path7.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
7941
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path9.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
7816
7942
  const useShell = isWin ? useShellWin : useShellUnix;
7817
7943
  if (useShell) {
7818
7944
  if (!spawnConfig.shell && !isWin) {
@@ -8186,7 +8312,7 @@ var init_provider_cli_adapter = __esm({
8186
8312
  `[${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)}`
8187
8313
  );
8188
8314
  }
8189
- await new Promise((resolve13) => setTimeout(resolve13, 50));
8315
+ await new Promise((resolve16) => setTimeout(resolve16, 50));
8190
8316
  }
8191
8317
  const finalScreenText = this.terminalScreen.getText() || "";
8192
8318
  LOG.warn(
@@ -8697,7 +8823,7 @@ ${data.message || ""}`.trim();
8697
8823
  const deadline = Date.now() + 1e4;
8698
8824
  while (this.startupParseGate && Date.now() < deadline) {
8699
8825
  this.resolveStartupState("send_wait");
8700
- await new Promise((resolve13) => setTimeout(resolve13, 50));
8826
+ await new Promise((resolve16) => setTimeout(resolve16, 50));
8701
8827
  }
8702
8828
  }
8703
8829
  await this.waitForInteractivePrompt();
@@ -8922,17 +9048,17 @@ ${data.message || ""}`.trim();
8922
9048
  }
8923
9049
  }
8924
9050
  waitForStopped(timeoutMs) {
8925
- return new Promise((resolve13) => {
9051
+ return new Promise((resolve16) => {
8926
9052
  const startedAt = Date.now();
8927
9053
  const timer = setInterval(() => {
8928
9054
  if (!this.ptyProcess || this.currentStatus === "stopped") {
8929
9055
  clearInterval(timer);
8930
- resolve13(true);
9056
+ resolve16(true);
8931
9057
  return;
8932
9058
  }
8933
9059
  if (Date.now() - startedAt >= timeoutMs) {
8934
9060
  clearInterval(timer);
8935
- resolve13(false);
9061
+ resolve16(false);
8936
9062
  }
8937
9063
  }, 100);
8938
9064
  });
@@ -9220,7 +9346,7 @@ ${data.message || ""}`.trim();
9220
9346
  // ../../oss/packages/daemon-core/src/providers/cli-provider-instance.ts
9221
9347
  function getDatabaseSync() {
9222
9348
  if (CachedDatabaseSync) return CachedDatabaseSync;
9223
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path8.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
9349
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path10.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
9224
9350
  const sqliteModule = requireFn(`node:${"sqlite"}`);
9225
9351
  CachedDatabaseSync = sqliteModule.DatabaseSync;
9226
9352
  if (!CachedDatabaseSync) {
@@ -9228,12 +9354,12 @@ function getDatabaseSync() {
9228
9354
  }
9229
9355
  return CachedDatabaseSync;
9230
9356
  }
9231
- var os10, path8, crypto3, fs5, import_node_module, CachedDatabaseSync, CliProviderInstance;
9357
+ var os10, path10, crypto3, fs5, import_node_module, CachedDatabaseSync, CliProviderInstance;
9232
9358
  var init_cli_provider_instance = __esm({
9233
9359
  "../../oss/packages/daemon-core/src/providers/cli-provider-instance.ts"() {
9234
9360
  "use strict";
9235
9361
  os10 = __toESM(require("os"));
9236
- path8 = __toESM(require("path"));
9362
+ path10 = __toESM(require("path"));
9237
9363
  crypto3 = __toESM(require("crypto"));
9238
9364
  fs5 = __toESM(require("fs"));
9239
9365
  import_node_module = require("module");
@@ -9300,6 +9426,7 @@ var init_cli_provider_instance = __esm({
9300
9426
  this.detectStatusTransition();
9301
9427
  });
9302
9428
  await this.adapter.spawn();
9429
+ this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
9303
9430
  if (this.providerSessionId) {
9304
9431
  const restoredHistory = readChatHistory(this.type, 0, 200, this.providerSessionId);
9305
9432
  if (restoredHistory.messages.length > 0) {
@@ -9394,6 +9521,7 @@ var init_cli_provider_instance = __esm({
9394
9521
  this.promoteProviderSessionId(parsedProviderSessionId);
9395
9522
  }
9396
9523
  const runtime = this.adapter.getRuntimeMetadata();
9524
+ this.maybeAppendRuntimeRecoveryMessage(runtime);
9397
9525
  const parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
9398
9526
  const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
9399
9527
  if (controlValues) {
@@ -9720,6 +9848,28 @@ ${effect.notification.body || ""}`.trim();
9720
9848
  const pad = (value) => String(value).padStart(2, "0");
9721
9849
  return `${date5.getFullYear()}-${pad(date5.getMonth() + 1)}-${pad(date5.getDate())} ${pad(date5.getHours())}:${pad(date5.getMinutes())}:${pad(date5.getSeconds())}`;
9722
9850
  }
9851
+ maybeAppendRuntimeRecoveryMessage(runtime) {
9852
+ if (!runtime?.restoredFromStorage || !runtime.runtimeId) return;
9853
+ const recoveryState = String(runtime.recoveryState || "").trim();
9854
+ if (!recoveryState) return;
9855
+ let content = "";
9856
+ if (recoveryState === "auto_resumed") {
9857
+ content = "Session host restored this CLI after restart and reattached it from a saved snapshot.";
9858
+ } else if (recoveryState === "resume_failed") {
9859
+ const errorSuffix = runtime.recoveryError ? ` Resume failed: ${runtime.recoveryError}` : "";
9860
+ content = `Session host found this CLI after restart, but automatic resume failed.${errorSuffix}`;
9861
+ } else if (recoveryState === "host_restart_interrupted") {
9862
+ content = "Session host found this CLI in interrupted state after restart and is attempting to resume it.";
9863
+ } else if (recoveryState === "orphan_snapshot") {
9864
+ content = "Session host restored the last snapshot for this CLI, but the original runtime was not resumed automatically.";
9865
+ } else {
9866
+ content = `Session host restored this CLI after restart (${recoveryState}).`;
9867
+ }
9868
+ this.appendRuntimeSystemMessage(
9869
+ content,
9870
+ `runtime_recovery:${runtime.runtimeId}:${recoveryState}`
9871
+ );
9872
+ }
9723
9873
  appendRuntimeSystemMessage(content, dedupKey, receivedAt = Date.now()) {
9724
9874
  const normalizedContent = String(content || "").trim();
9725
9875
  if (!normalizedContent) return;
@@ -10078,10 +10228,10 @@ function mergeDefs(...defs) {
10078
10228
  function cloneDef(schema) {
10079
10229
  return mergeDefs(schema._zod.def);
10080
10230
  }
10081
- function getElementAtPath(obj, path23) {
10082
- if (!path23)
10231
+ function getElementAtPath(obj, path25) {
10232
+ if (!path25)
10083
10233
  return obj;
10084
- return path23.reduce((acc, key) => acc?.[key], obj);
10234
+ return path25.reduce((acc, key) => acc?.[key], obj);
10085
10235
  }
10086
10236
  function promiseAllObject(promisesObj) {
10087
10237
  const keys = Object.keys(promisesObj);
@@ -10393,11 +10543,11 @@ function aborted(x, startIndex = 0) {
10393
10543
  }
10394
10544
  return false;
10395
10545
  }
10396
- function prefixIssues(path23, issues) {
10546
+ function prefixIssues(path25, issues) {
10397
10547
  return issues.map((iss) => {
10398
10548
  var _a2;
10399
10549
  (_a2 = iss).path ?? (_a2.path = []);
10400
- iss.path.unshift(path23);
10550
+ iss.path.unshift(path25);
10401
10551
  return iss;
10402
10552
  });
10403
10553
  }
@@ -10640,7 +10790,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
10640
10790
  }
10641
10791
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
10642
10792
  const result = { errors: [] };
10643
- const processError = (error49, path23 = []) => {
10793
+ const processError = (error49, path25 = []) => {
10644
10794
  var _a2, _b;
10645
10795
  for (const issue2 of error49.issues) {
10646
10796
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -10650,7 +10800,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
10650
10800
  } else if (issue2.code === "invalid_element") {
10651
10801
  processError({ issues: issue2.issues }, issue2.path);
10652
10802
  } else {
10653
- const fullpath = [...path23, ...issue2.path];
10803
+ const fullpath = [...path25, ...issue2.path];
10654
10804
  if (fullpath.length === 0) {
10655
10805
  result.errors.push(mapper(issue2));
10656
10806
  continue;
@@ -10682,8 +10832,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
10682
10832
  }
10683
10833
  function toDotPath(_path) {
10684
10834
  const segs = [];
10685
- const path23 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
10686
- for (const seg of path23) {
10835
+ const path25 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
10836
+ for (const seg of path25) {
10687
10837
  if (typeof seg === "number")
10688
10838
  segs.push(`[${seg}]`);
10689
10839
  else if (typeof seg === "symbol")
@@ -23447,13 +23597,13 @@ function resolveRef(ref, ctx) {
23447
23597
  if (!ref.startsWith("#")) {
23448
23598
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
23449
23599
  }
23450
- const path23 = ref.slice(1).split("/").filter(Boolean);
23451
- if (path23.length === 0) {
23600
+ const path25 = ref.slice(1).split("/").filter(Boolean);
23601
+ if (path25.length === 0) {
23452
23602
  return ctx.rootSchema;
23453
23603
  }
23454
23604
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
23455
- if (path23[0] === defsKey) {
23456
- const key = path23[1];
23605
+ if (path25[0] === defsKey) {
23606
+ const key = path25[1];
23457
23607
  if (!key || !ctx.defs[key]) {
23458
23608
  throw new Error(`Reference not found: ${ref}`);
23459
23609
  }
@@ -25880,8 +26030,8 @@ var init_acp = __esm({
25880
26030
  this.#requestHandler = requestHandler;
25881
26031
  this.#notificationHandler = notificationHandler;
25882
26032
  this.#stream = stream;
25883
- this.#closedPromise = new Promise((resolve13) => {
25884
- this.#abortController.signal.addEventListener("abort", () => resolve13());
26033
+ this.#closedPromise = new Promise((resolve16) => {
26034
+ this.#abortController.signal.addEventListener("abort", () => resolve16());
25885
26035
  });
25886
26036
  this.#receive();
25887
26037
  }
@@ -26030,8 +26180,8 @@ var init_acp = __esm({
26030
26180
  }
26031
26181
  async sendRequest(method, params) {
26032
26182
  const id = this.#nextRequestId++;
26033
- const responsePromise = new Promise((resolve13, reject) => {
26034
- this.#pendingResponses.set(id, { resolve: resolve13, reject });
26183
+ const responsePromise = new Promise((resolve16, reject) => {
26184
+ this.#pendingResponses.set(id, { resolve: resolve16, reject });
26035
26185
  });
26036
26186
  await this.#sendMessage({ jsonrpc: "2.0", id, method, params });
26037
26187
  return responsePromise;
@@ -26352,8 +26502,9 @@ var init_acp_provider_instance = __esm({
26352
26502
  async setConfigOption(category, value) {
26353
26503
  const opt = this.configOptions.find((c) => c.category === category);
26354
26504
  if (!opt) {
26355
- this.log.warn(`[${this.type}] No config option for category: ${category}`);
26356
- return;
26505
+ const message = `[${this.type}] No config option for category: ${category}`;
26506
+ this.log.warn(message);
26507
+ throw new Error(message);
26357
26508
  }
26358
26509
  if (this.useStaticConfig) {
26359
26510
  opt.currentValue = value;
@@ -26365,8 +26516,9 @@ var init_acp_provider_instance = __esm({
26365
26516
  return;
26366
26517
  }
26367
26518
  if (!this.connection || !this.sessionId) {
26368
- this.log.warn(`[${this.type}] Cannot set config: no active connection/session`);
26369
- return;
26519
+ const message = `[${this.type}] Cannot set config: no active connection/session`;
26520
+ this.log.warn(message);
26521
+ throw new Error(message);
26370
26522
  }
26371
26523
  try {
26372
26524
  this.log.info(`[${this.type}] Sending session/set_config_option: configId=${opt.configId} value=${value} sessionId=${this.sessionId}`);
@@ -26380,7 +26532,9 @@ var init_acp_provider_instance = __esm({
26380
26532
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
26381
26533
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
26382
26534
  } catch (e) {
26383
- this.log.warn(`[${this.type}] set_config_option failed: ${e?.message}`);
26535
+ const message = e?.message || "Unknown ACP config error";
26536
+ this.log.warn(`[${this.type}] set_config_option failed: ${message}`);
26537
+ throw new Error(message);
26384
26538
  }
26385
26539
  }
26386
26540
  async setMode(modeId) {
@@ -26396,8 +26550,9 @@ var init_acp_provider_instance = __esm({
26396
26550
  return;
26397
26551
  }
26398
26552
  if (!this.connection || !this.sessionId) {
26399
- this.log.warn(`[${this.type}] Cannot set mode: no active connection/session`);
26400
- return;
26553
+ const message = `[${this.type}] Cannot set mode: no active connection/session`;
26554
+ this.log.warn(message);
26555
+ throw new Error(message);
26401
26556
  }
26402
26557
  try {
26403
26558
  await this.connection.setSessionMode({
@@ -26407,7 +26562,9 @@ var init_acp_provider_instance = __esm({
26407
26562
  this.currentMode = modeId;
26408
26563
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
26409
26564
  } catch (e) {
26410
- this.log.warn(`[${this.type}] set_mode failed: ${e?.message}`);
26565
+ const message = e?.message || "Unknown ACP mode error";
26566
+ this.log.warn(`[${this.type}] set_mode failed: ${message}`);
26567
+ throw new Error(message);
26411
26568
  }
26412
26569
  }
26413
26570
  /** Static config: kill process and restart with new args */
@@ -26455,7 +26612,7 @@ var init_acp_provider_instance = __esm({
26455
26612
  if (!spawnConfig) {
26456
26613
  throw new Error(`[ACP:${this.type}] No spawn config defined`);
26457
26614
  }
26458
- const command = spawnConfig.command;
26615
+ const command = typeof this.settings.executablePath === "string" && this.settings.executablePath.trim() ? this.settings.executablePath.trim() : spawnConfig.command;
26459
26616
  let baseArgs = spawnConfig.args || [];
26460
26617
  if (this.provider.spawnArgBuilder && Object.keys(this.selectedConfig).length > 0) {
26461
26618
  baseArgs = this.provider.spawnArgBuilder(this.selectedConfig);
@@ -26571,13 +26728,13 @@ var init_acp_provider_instance = __esm({
26571
26728
  }
26572
26729
  this.currentStatus = "waiting_approval";
26573
26730
  this.detectStatusTransition();
26574
- const approved = await new Promise((resolve13) => {
26575
- this.permissionResolvers.push(resolve13);
26731
+ const approved = await new Promise((resolve16) => {
26732
+ this.permissionResolvers.push(resolve16);
26576
26733
  setTimeout(() => {
26577
- const idx = this.permissionResolvers.indexOf(resolve13);
26734
+ const idx = this.permissionResolvers.indexOf(resolve16);
26578
26735
  if (idx >= 0) {
26579
26736
  this.permissionResolvers.splice(idx, 1);
26580
- resolve13(false);
26737
+ resolve16(false);
26581
26738
  }
26582
26739
  }, 3e5);
26583
26740
  });
@@ -27146,12 +27303,12 @@ function resolveCliSessionBinding(provider, normalizedType, cliArgs, requestedRe
27146
27303
  launchMode: "new"
27147
27304
  };
27148
27305
  }
27149
- var os11, path9, crypto4, import_chalk, chalkApi, DaemonCliManager;
27306
+ var os11, path11, crypto4, import_chalk, chalkApi, DaemonCliManager;
27150
27307
  var init_cli_manager = __esm({
27151
27308
  "../../oss/packages/daemon-core/src/commands/cli-manager.ts"() {
27152
27309
  "use strict";
27153
27310
  os11 = __toESM(require("os"));
27154
- path9 = __toESM(require("path"));
27311
+ path11 = __toESM(require("path"));
27155
27312
  crypto4 = __toESM(require("crypto"));
27156
27313
  import_chalk = __toESM(require("chalk"));
27157
27314
  init_provider_cli_adapter();
@@ -27303,7 +27460,7 @@ var init_cli_manager = __esm({
27303
27460
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
27304
27461
  const trimmed = (workingDir || "").trim();
27305
27462
  if (!trimmed) throw new Error("working directory required");
27306
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os11.homedir()) : path9.resolve(trimmed);
27463
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os11.homedir()) : path11.resolve(trimmed);
27307
27464
  const normalizedType = this.providerLoader.resolveAlias(cliType);
27308
27465
  const provider = this.providerLoader.getByAlias(cliType);
27309
27466
  const key = crypto4.randomUUID();
@@ -27390,10 +27547,10 @@ ${installInfo}`
27390
27547
  if (!cliInfo) {
27391
27548
  const installHint = provider?.install || "";
27392
27549
  const displayName = provider?.displayName || provider?.name || cliType;
27393
- const spawnCmd = provider?.spawn?.command || cliType;
27550
+ const spawnCmd = this.providerLoader.getSpawnCommand(normalizedType, provider?.spawn?.command || cliType);
27394
27551
  throw new Error(
27395
27552
  `${displayName} is not installed.
27396
- Command '${spawnCmd}' not found on PATH.
27553
+ Command '${spawnCmd}' is not available.
27397
27554
  ` + (installHint ? `
27398
27555
  ${installHint}
27399
27556
  ` : "") + `
@@ -27855,7 +28012,7 @@ var init_readdirp = __esm({
27855
28012
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
27856
28013
  const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
27857
28014
  if (wantBigintFsStats) {
27858
- this._stat = (path23) => statMethod(path23, { bigint: true });
28015
+ this._stat = (path25) => statMethod(path25, { bigint: true });
27859
28016
  } else {
27860
28017
  this._stat = statMethod;
27861
28018
  }
@@ -27880,8 +28037,8 @@ var init_readdirp = __esm({
27880
28037
  const par = this.parent;
27881
28038
  const fil = par && par.files;
27882
28039
  if (fil && fil.length > 0) {
27883
- const { path: path23, depth } = par;
27884
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path23));
28040
+ const { path: path25, depth } = par;
28041
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path25));
27885
28042
  const awaited = await Promise.all(slice);
27886
28043
  for (const entry of awaited) {
27887
28044
  if (!entry)
@@ -27921,20 +28078,20 @@ var init_readdirp = __esm({
27921
28078
  this.reading = false;
27922
28079
  }
27923
28080
  }
27924
- async _exploreDir(path23, depth) {
28081
+ async _exploreDir(path25, depth) {
27925
28082
  let files;
27926
28083
  try {
27927
- files = await (0, import_promises.readdir)(path23, this._rdOptions);
28084
+ files = await (0, import_promises.readdir)(path25, this._rdOptions);
27928
28085
  } catch (error48) {
27929
28086
  this._onError(error48);
27930
28087
  }
27931
- return { files, depth, path: path23 };
28088
+ return { files, depth, path: path25 };
27932
28089
  }
27933
- async _formatEntry(dirent, path23) {
28090
+ async _formatEntry(dirent, path25) {
27934
28091
  let entry;
27935
28092
  const basename7 = this._isDirent ? dirent.name : dirent;
27936
28093
  try {
27937
- const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path23, basename7));
28094
+ const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path25, basename7));
27938
28095
  entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename7 };
27939
28096
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
27940
28097
  } catch (err) {
@@ -27991,16 +28148,16 @@ var init_readdirp = __esm({
27991
28148
  });
27992
28149
 
27993
28150
  // ../../oss/packages/daemon-core/node_modules/chokidar/handler.js
27994
- function createFsWatchInstance(path23, options, listener, errHandler, emitRaw) {
28151
+ function createFsWatchInstance(path25, options, listener, errHandler, emitRaw) {
27995
28152
  const handleEvent = (rawEvent, evPath) => {
27996
- listener(path23);
27997
- emitRaw(rawEvent, evPath, { watchedPath: path23 });
27998
- if (evPath && path23 !== evPath) {
27999
- fsWatchBroadcast(sp.resolve(path23, evPath), KEY_LISTENERS, sp.join(path23, evPath));
28153
+ listener(path25);
28154
+ emitRaw(rawEvent, evPath, { watchedPath: path25 });
28155
+ if (evPath && path25 !== evPath) {
28156
+ fsWatchBroadcast(sp.resolve(path25, evPath), KEY_LISTENERS, sp.join(path25, evPath));
28000
28157
  }
28001
28158
  };
28002
28159
  try {
28003
- return (0, import_node_fs.watch)(path23, {
28160
+ return (0, import_node_fs.watch)(path25, {
28004
28161
  persistent: options.persistent
28005
28162
  }, handleEvent);
28006
28163
  } catch (error48) {
@@ -28349,12 +28506,12 @@ var init_handler2 = __esm({
28349
28506
  listener(val1, val2, val3);
28350
28507
  });
28351
28508
  };
28352
- setFsWatchListener = (path23, fullPath, options, handlers) => {
28509
+ setFsWatchListener = (path25, fullPath, options, handlers) => {
28353
28510
  const { listener, errHandler, rawEmitter } = handlers;
28354
28511
  let cont = FsWatchInstances.get(fullPath);
28355
28512
  let watcher;
28356
28513
  if (!options.persistent) {
28357
- watcher = createFsWatchInstance(path23, options, listener, errHandler, rawEmitter);
28514
+ watcher = createFsWatchInstance(path25, options, listener, errHandler, rawEmitter);
28358
28515
  if (!watcher)
28359
28516
  return;
28360
28517
  return watcher.close.bind(watcher);
@@ -28365,7 +28522,7 @@ var init_handler2 = __esm({
28365
28522
  addAndConvert(cont, KEY_RAW, rawEmitter);
28366
28523
  } else {
28367
28524
  watcher = createFsWatchInstance(
28368
- path23,
28525
+ path25,
28369
28526
  options,
28370
28527
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
28371
28528
  errHandler,
@@ -28380,7 +28537,7 @@ var init_handler2 = __esm({
28380
28537
  cont.watcherUnusable = true;
28381
28538
  if (isWindows && error48.code === "EPERM") {
28382
28539
  try {
28383
- const fd = await (0, import_promises2.open)(path23, "r");
28540
+ const fd = await (0, import_promises2.open)(path25, "r");
28384
28541
  await fd.close();
28385
28542
  broadcastErr(error48);
28386
28543
  } catch (err) {
@@ -28411,7 +28568,7 @@ var init_handler2 = __esm({
28411
28568
  };
28412
28569
  };
28413
28570
  FsWatchFileInstances = /* @__PURE__ */ new Map();
28414
- setFsWatchFileListener = (path23, fullPath, options, handlers) => {
28571
+ setFsWatchFileListener = (path25, fullPath, options, handlers) => {
28415
28572
  const { listener, rawEmitter } = handlers;
28416
28573
  let cont = FsWatchFileInstances.get(fullPath);
28417
28574
  const copts = cont && cont.options;
@@ -28433,7 +28590,7 @@ var init_handler2 = __esm({
28433
28590
  });
28434
28591
  const currmtime = curr.mtimeMs;
28435
28592
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
28436
- foreach(cont.listeners, (listener2) => listener2(path23, curr));
28593
+ foreach(cont.listeners, (listener2) => listener2(path25, curr));
28437
28594
  }
28438
28595
  })
28439
28596
  };
@@ -28463,13 +28620,13 @@ var init_handler2 = __esm({
28463
28620
  * @param listener on fs change
28464
28621
  * @returns closer for the watcher instance
28465
28622
  */
28466
- _watchWithNodeFs(path23, listener) {
28623
+ _watchWithNodeFs(path25, listener) {
28467
28624
  const opts = this.fsw.options;
28468
- const directory = sp.dirname(path23);
28469
- const basename7 = sp.basename(path23);
28625
+ const directory = sp.dirname(path25);
28626
+ const basename7 = sp.basename(path25);
28470
28627
  const parent = this.fsw._getWatchedDir(directory);
28471
28628
  parent.add(basename7);
28472
- const absolutePath = sp.resolve(path23);
28629
+ const absolutePath = sp.resolve(path25);
28473
28630
  const options = {
28474
28631
  persistent: opts.persistent
28475
28632
  };
@@ -28479,12 +28636,12 @@ var init_handler2 = __esm({
28479
28636
  if (opts.usePolling) {
28480
28637
  const enableBin = opts.interval !== opts.binaryInterval;
28481
28638
  options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
28482
- closer = setFsWatchFileListener(path23, absolutePath, options, {
28639
+ closer = setFsWatchFileListener(path25, absolutePath, options, {
28483
28640
  listener,
28484
28641
  rawEmitter: this.fsw._emitRaw
28485
28642
  });
28486
28643
  } else {
28487
- closer = setFsWatchListener(path23, absolutePath, options, {
28644
+ closer = setFsWatchListener(path25, absolutePath, options, {
28488
28645
  listener,
28489
28646
  errHandler: this._boundHandleError,
28490
28647
  rawEmitter: this.fsw._emitRaw
@@ -28506,7 +28663,7 @@ var init_handler2 = __esm({
28506
28663
  let prevStats = stats;
28507
28664
  if (parent.has(basename7))
28508
28665
  return;
28509
- const listener = async (path23, newStats) => {
28666
+ const listener = async (path25, newStats) => {
28510
28667
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
28511
28668
  return;
28512
28669
  if (!newStats || newStats.mtimeMs === 0) {
@@ -28520,11 +28677,11 @@ var init_handler2 = __esm({
28520
28677
  this.fsw._emit(EV.CHANGE, file2, newStats2);
28521
28678
  }
28522
28679
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
28523
- this.fsw._closeFile(path23);
28680
+ this.fsw._closeFile(path25);
28524
28681
  prevStats = newStats2;
28525
28682
  const closer2 = this._watchWithNodeFs(file2, listener);
28526
28683
  if (closer2)
28527
- this.fsw._addPathCloser(path23, closer2);
28684
+ this.fsw._addPathCloser(path25, closer2);
28528
28685
  } else {
28529
28686
  prevStats = newStats2;
28530
28687
  }
@@ -28556,7 +28713,7 @@ var init_handler2 = __esm({
28556
28713
  * @param item basename of this item
28557
28714
  * @returns true if no more processing is needed for this entry.
28558
28715
  */
28559
- async _handleSymlink(entry, directory, path23, item) {
28716
+ async _handleSymlink(entry, directory, path25, item) {
28560
28717
  if (this.fsw.closed) {
28561
28718
  return;
28562
28719
  }
@@ -28566,7 +28723,7 @@ var init_handler2 = __esm({
28566
28723
  this.fsw._incrReadyCount();
28567
28724
  let linkPath;
28568
28725
  try {
28569
- linkPath = await (0, import_promises2.realpath)(path23);
28726
+ linkPath = await (0, import_promises2.realpath)(path25);
28570
28727
  } catch (e) {
28571
28728
  this.fsw._emitReady();
28572
28729
  return true;
@@ -28576,12 +28733,12 @@ var init_handler2 = __esm({
28576
28733
  if (dir.has(item)) {
28577
28734
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
28578
28735
  this.fsw._symlinkPaths.set(full, linkPath);
28579
- this.fsw._emit(EV.CHANGE, path23, entry.stats);
28736
+ this.fsw._emit(EV.CHANGE, path25, entry.stats);
28580
28737
  }
28581
28738
  } else {
28582
28739
  dir.add(item);
28583
28740
  this.fsw._symlinkPaths.set(full, linkPath);
28584
- this.fsw._emit(EV.ADD, path23, entry.stats);
28741
+ this.fsw._emit(EV.ADD, path25, entry.stats);
28585
28742
  }
28586
28743
  this.fsw._emitReady();
28587
28744
  return true;
@@ -28611,9 +28768,9 @@ var init_handler2 = __esm({
28611
28768
  return;
28612
28769
  }
28613
28770
  const item = entry.path;
28614
- let path23 = sp.join(directory, item);
28771
+ let path25 = sp.join(directory, item);
28615
28772
  current.add(item);
28616
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path23, item)) {
28773
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path25, item)) {
28617
28774
  return;
28618
28775
  }
28619
28776
  if (this.fsw.closed) {
@@ -28622,11 +28779,11 @@ var init_handler2 = __esm({
28622
28779
  }
28623
28780
  if (item === target || !target && !previous.has(item)) {
28624
28781
  this.fsw._incrReadyCount();
28625
- path23 = sp.join(dir, sp.relative(dir, path23));
28626
- this._addToNodeFs(path23, initialAdd, wh, depth + 1);
28782
+ path25 = sp.join(dir, sp.relative(dir, path25));
28783
+ this._addToNodeFs(path25, initialAdd, wh, depth + 1);
28627
28784
  }
28628
28785
  }).on(EV.ERROR, this._boundHandleError);
28629
- return new Promise((resolve13, reject) => {
28786
+ return new Promise((resolve16, reject) => {
28630
28787
  if (!stream)
28631
28788
  return reject();
28632
28789
  stream.once(STR_END, () => {
@@ -28635,7 +28792,7 @@ var init_handler2 = __esm({
28635
28792
  return;
28636
28793
  }
28637
28794
  const wasThrottled = throttler ? throttler.clear() : false;
28638
- resolve13(void 0);
28795
+ resolve16(void 0);
28639
28796
  previous.getChildren().filter((item) => {
28640
28797
  return item !== directory && !current.has(item);
28641
28798
  }).forEach((item) => {
@@ -28692,13 +28849,13 @@ var init_handler2 = __esm({
28692
28849
  * @param depth Child path actually targeted for watch
28693
28850
  * @param target Child path actually targeted for watch
28694
28851
  */
28695
- async _addToNodeFs(path23, initialAdd, priorWh, depth, target) {
28852
+ async _addToNodeFs(path25, initialAdd, priorWh, depth, target) {
28696
28853
  const ready = this.fsw._emitReady;
28697
- if (this.fsw._isIgnored(path23) || this.fsw.closed) {
28854
+ if (this.fsw._isIgnored(path25) || this.fsw.closed) {
28698
28855
  ready();
28699
28856
  return false;
28700
28857
  }
28701
- const wh = this.fsw._getWatchHelpers(path23);
28858
+ const wh = this.fsw._getWatchHelpers(path25);
28702
28859
  if (priorWh) {
28703
28860
  wh.filterPath = (entry) => priorWh.filterPath(entry);
28704
28861
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -28714,8 +28871,8 @@ var init_handler2 = __esm({
28714
28871
  const follow = this.fsw.options.followSymlinks;
28715
28872
  let closer;
28716
28873
  if (stats.isDirectory()) {
28717
- const absPath = sp.resolve(path23);
28718
- const targetPath = follow ? await (0, import_promises2.realpath)(path23) : path23;
28874
+ const absPath = sp.resolve(path25);
28875
+ const targetPath = follow ? await (0, import_promises2.realpath)(path25) : path25;
28719
28876
  if (this.fsw.closed)
28720
28877
  return;
28721
28878
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -28725,29 +28882,29 @@ var init_handler2 = __esm({
28725
28882
  this.fsw._symlinkPaths.set(absPath, targetPath);
28726
28883
  }
28727
28884
  } else if (stats.isSymbolicLink()) {
28728
- const targetPath = follow ? await (0, import_promises2.realpath)(path23) : path23;
28885
+ const targetPath = follow ? await (0, import_promises2.realpath)(path25) : path25;
28729
28886
  if (this.fsw.closed)
28730
28887
  return;
28731
28888
  const parent = sp.dirname(wh.watchPath);
28732
28889
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
28733
28890
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
28734
- closer = await this._handleDir(parent, stats, initialAdd, depth, path23, wh, targetPath);
28891
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path25, wh, targetPath);
28735
28892
  if (this.fsw.closed)
28736
28893
  return;
28737
28894
  if (targetPath !== void 0) {
28738
- this.fsw._symlinkPaths.set(sp.resolve(path23), targetPath);
28895
+ this.fsw._symlinkPaths.set(sp.resolve(path25), targetPath);
28739
28896
  }
28740
28897
  } else {
28741
28898
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
28742
28899
  }
28743
28900
  ready();
28744
28901
  if (closer)
28745
- this.fsw._addPathCloser(path23, closer);
28902
+ this.fsw._addPathCloser(path25, closer);
28746
28903
  return false;
28747
28904
  } catch (error48) {
28748
28905
  if (this.fsw._handleError(error48)) {
28749
28906
  ready();
28750
- return path23;
28907
+ return path25;
28751
28908
  }
28752
28909
  }
28753
28910
  }
@@ -28782,24 +28939,24 @@ function createPattern(matcher) {
28782
28939
  }
28783
28940
  return () => false;
28784
28941
  }
28785
- function normalizePath(path23) {
28786
- if (typeof path23 !== "string")
28942
+ function normalizePath(path25) {
28943
+ if (typeof path25 !== "string")
28787
28944
  throw new Error("string expected");
28788
- path23 = sp2.normalize(path23);
28789
- path23 = path23.replace(/\\/g, "/");
28945
+ path25 = sp2.normalize(path25);
28946
+ path25 = path25.replace(/\\/g, "/");
28790
28947
  let prepend = false;
28791
- if (path23.startsWith("//"))
28948
+ if (path25.startsWith("//"))
28792
28949
  prepend = true;
28793
- path23 = path23.replace(DOUBLE_SLASH_RE, "/");
28950
+ path25 = path25.replace(DOUBLE_SLASH_RE, "/");
28794
28951
  if (prepend)
28795
- path23 = "/" + path23;
28796
- return path23;
28952
+ path25 = "/" + path25;
28953
+ return path25;
28797
28954
  }
28798
28955
  function matchPatterns(patterns, testString, stats) {
28799
- const path23 = normalizePath(testString);
28956
+ const path25 = normalizePath(testString);
28800
28957
  for (let index = 0; index < patterns.length; index++) {
28801
28958
  const pattern = patterns[index];
28802
- if (pattern(path23, stats)) {
28959
+ if (pattern(path25, stats)) {
28803
28960
  return true;
28804
28961
  }
28805
28962
  }
@@ -28862,19 +29019,19 @@ var init_chokidar = __esm({
28862
29019
  }
28863
29020
  return str;
28864
29021
  };
28865
- normalizePathToUnix = (path23) => toUnix(sp2.normalize(toUnix(path23)));
28866
- normalizeIgnored = (cwd = "") => (path23) => {
28867
- if (typeof path23 === "string") {
28868
- return normalizePathToUnix(sp2.isAbsolute(path23) ? path23 : sp2.join(cwd, path23));
29022
+ normalizePathToUnix = (path25) => toUnix(sp2.normalize(toUnix(path25)));
29023
+ normalizeIgnored = (cwd = "") => (path25) => {
29024
+ if (typeof path25 === "string") {
29025
+ return normalizePathToUnix(sp2.isAbsolute(path25) ? path25 : sp2.join(cwd, path25));
28869
29026
  } else {
28870
- return path23;
29027
+ return path25;
28871
29028
  }
28872
29029
  };
28873
- getAbsolutePath = (path23, cwd) => {
28874
- if (sp2.isAbsolute(path23)) {
28875
- return path23;
29030
+ getAbsolutePath = (path25, cwd) => {
29031
+ if (sp2.isAbsolute(path25)) {
29032
+ return path25;
28876
29033
  }
28877
- return sp2.join(cwd, path23);
29034
+ return sp2.join(cwd, path25);
28878
29035
  };
28879
29036
  EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
28880
29037
  DirEntry = class {
@@ -28939,10 +29096,10 @@ var init_chokidar = __esm({
28939
29096
  dirParts;
28940
29097
  followSymlinks;
28941
29098
  statMethod;
28942
- constructor(path23, follow, fsw) {
29099
+ constructor(path25, follow, fsw) {
28943
29100
  this.fsw = fsw;
28944
- const watchPath = path23;
28945
- this.path = path23 = path23.replace(REPLACER_RE, "");
29101
+ const watchPath = path25;
29102
+ this.path = path25 = path25.replace(REPLACER_RE, "");
28946
29103
  this.watchPath = watchPath;
28947
29104
  this.fullWatchPath = sp2.resolve(watchPath);
28948
29105
  this.dirParts = [];
@@ -29082,20 +29239,20 @@ var init_chokidar = __esm({
29082
29239
  this._closePromise = void 0;
29083
29240
  let paths = unifyPaths(paths_);
29084
29241
  if (cwd) {
29085
- paths = paths.map((path23) => {
29086
- const absPath = getAbsolutePath(path23, cwd);
29242
+ paths = paths.map((path25) => {
29243
+ const absPath = getAbsolutePath(path25, cwd);
29087
29244
  return absPath;
29088
29245
  });
29089
29246
  }
29090
- paths.forEach((path23) => {
29091
- this._removeIgnoredPath(path23);
29247
+ paths.forEach((path25) => {
29248
+ this._removeIgnoredPath(path25);
29092
29249
  });
29093
29250
  this._userIgnored = void 0;
29094
29251
  if (!this._readyCount)
29095
29252
  this._readyCount = 0;
29096
29253
  this._readyCount += paths.length;
29097
- Promise.all(paths.map(async (path23) => {
29098
- const res = await this._nodeFsHandler._addToNodeFs(path23, !_internal, void 0, 0, _origAdd);
29254
+ Promise.all(paths.map(async (path25) => {
29255
+ const res = await this._nodeFsHandler._addToNodeFs(path25, !_internal, void 0, 0, _origAdd);
29099
29256
  if (res)
29100
29257
  this._emitReady();
29101
29258
  return res;
@@ -29117,17 +29274,17 @@ var init_chokidar = __esm({
29117
29274
  return this;
29118
29275
  const paths = unifyPaths(paths_);
29119
29276
  const { cwd } = this.options;
29120
- paths.forEach((path23) => {
29121
- if (!sp2.isAbsolute(path23) && !this._closers.has(path23)) {
29277
+ paths.forEach((path25) => {
29278
+ if (!sp2.isAbsolute(path25) && !this._closers.has(path25)) {
29122
29279
  if (cwd)
29123
- path23 = sp2.join(cwd, path23);
29124
- path23 = sp2.resolve(path23);
29280
+ path25 = sp2.join(cwd, path25);
29281
+ path25 = sp2.resolve(path25);
29125
29282
  }
29126
- this._closePath(path23);
29127
- this._addIgnoredPath(path23);
29128
- if (this._watched.has(path23)) {
29283
+ this._closePath(path25);
29284
+ this._addIgnoredPath(path25);
29285
+ if (this._watched.has(path25)) {
29129
29286
  this._addIgnoredPath({
29130
- path: path23,
29287
+ path: path25,
29131
29288
  recursive: true
29132
29289
  });
29133
29290
  }
@@ -29191,38 +29348,38 @@ var init_chokidar = __esm({
29191
29348
  * @param stats arguments to be passed with event
29192
29349
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
29193
29350
  */
29194
- async _emit(event, path23, stats) {
29351
+ async _emit(event, path25, stats) {
29195
29352
  if (this.closed)
29196
29353
  return;
29197
29354
  const opts = this.options;
29198
29355
  if (isWindows)
29199
- path23 = sp2.normalize(path23);
29356
+ path25 = sp2.normalize(path25);
29200
29357
  if (opts.cwd)
29201
- path23 = sp2.relative(opts.cwd, path23);
29202
- const args = [path23];
29358
+ path25 = sp2.relative(opts.cwd, path25);
29359
+ const args = [path25];
29203
29360
  if (stats != null)
29204
29361
  args.push(stats);
29205
29362
  const awf = opts.awaitWriteFinish;
29206
29363
  let pw;
29207
- if (awf && (pw = this._pendingWrites.get(path23))) {
29364
+ if (awf && (pw = this._pendingWrites.get(path25))) {
29208
29365
  pw.lastChange = /* @__PURE__ */ new Date();
29209
29366
  return this;
29210
29367
  }
29211
29368
  if (opts.atomic) {
29212
29369
  if (event === EVENTS.UNLINK) {
29213
- this._pendingUnlinks.set(path23, [event, ...args]);
29370
+ this._pendingUnlinks.set(path25, [event, ...args]);
29214
29371
  setTimeout(() => {
29215
- this._pendingUnlinks.forEach((entry, path24) => {
29372
+ this._pendingUnlinks.forEach((entry, path26) => {
29216
29373
  this.emit(...entry);
29217
29374
  this.emit(EVENTS.ALL, ...entry);
29218
- this._pendingUnlinks.delete(path24);
29375
+ this._pendingUnlinks.delete(path26);
29219
29376
  });
29220
29377
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
29221
29378
  return this;
29222
29379
  }
29223
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path23)) {
29380
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path25)) {
29224
29381
  event = EVENTS.CHANGE;
29225
- this._pendingUnlinks.delete(path23);
29382
+ this._pendingUnlinks.delete(path25);
29226
29383
  }
29227
29384
  }
29228
29385
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -29240,16 +29397,16 @@ var init_chokidar = __esm({
29240
29397
  this.emitWithAll(event, args);
29241
29398
  }
29242
29399
  };
29243
- this._awaitWriteFinish(path23, awf.stabilityThreshold, event, awfEmit);
29400
+ this._awaitWriteFinish(path25, awf.stabilityThreshold, event, awfEmit);
29244
29401
  return this;
29245
29402
  }
29246
29403
  if (event === EVENTS.CHANGE) {
29247
- const isThrottled = !this._throttle(EVENTS.CHANGE, path23, 50);
29404
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path25, 50);
29248
29405
  if (isThrottled)
29249
29406
  return this;
29250
29407
  }
29251
29408
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
29252
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path23) : path23;
29409
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path25) : path25;
29253
29410
  let stats2;
29254
29411
  try {
29255
29412
  stats2 = await (0, import_promises3.stat)(fullPath);
@@ -29280,23 +29437,23 @@ var init_chokidar = __esm({
29280
29437
  * @param timeout duration of time to suppress duplicate actions
29281
29438
  * @returns tracking object or false if action should be suppressed
29282
29439
  */
29283
- _throttle(actionType, path23, timeout) {
29440
+ _throttle(actionType, path25, timeout) {
29284
29441
  if (!this._throttled.has(actionType)) {
29285
29442
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
29286
29443
  }
29287
29444
  const action = this._throttled.get(actionType);
29288
29445
  if (!action)
29289
29446
  throw new Error("invalid throttle");
29290
- const actionPath = action.get(path23);
29447
+ const actionPath = action.get(path25);
29291
29448
  if (actionPath) {
29292
29449
  actionPath.count++;
29293
29450
  return false;
29294
29451
  }
29295
29452
  let timeoutObject;
29296
29453
  const clear = () => {
29297
- const item = action.get(path23);
29454
+ const item = action.get(path25);
29298
29455
  const count = item ? item.count : 0;
29299
- action.delete(path23);
29456
+ action.delete(path25);
29300
29457
  clearTimeout(timeoutObject);
29301
29458
  if (item)
29302
29459
  clearTimeout(item.timeoutObject);
@@ -29304,7 +29461,7 @@ var init_chokidar = __esm({
29304
29461
  };
29305
29462
  timeoutObject = setTimeout(clear, timeout);
29306
29463
  const thr = { timeoutObject, clear, count: 0 };
29307
- action.set(path23, thr);
29464
+ action.set(path25, thr);
29308
29465
  return thr;
29309
29466
  }
29310
29467
  _incrReadyCount() {
@@ -29318,44 +29475,44 @@ var init_chokidar = __esm({
29318
29475
  * @param event
29319
29476
  * @param awfEmit Callback to be called when ready for event to be emitted.
29320
29477
  */
29321
- _awaitWriteFinish(path23, threshold, event, awfEmit) {
29478
+ _awaitWriteFinish(path25, threshold, event, awfEmit) {
29322
29479
  const awf = this.options.awaitWriteFinish;
29323
29480
  if (typeof awf !== "object")
29324
29481
  return;
29325
29482
  const pollInterval = awf.pollInterval;
29326
29483
  let timeoutHandler;
29327
- let fullPath = path23;
29328
- if (this.options.cwd && !sp2.isAbsolute(path23)) {
29329
- fullPath = sp2.join(this.options.cwd, path23);
29484
+ let fullPath = path25;
29485
+ if (this.options.cwd && !sp2.isAbsolute(path25)) {
29486
+ fullPath = sp2.join(this.options.cwd, path25);
29330
29487
  }
29331
29488
  const now = /* @__PURE__ */ new Date();
29332
29489
  const writes = this._pendingWrites;
29333
29490
  function awaitWriteFinishFn(prevStat) {
29334
29491
  (0, import_node_fs2.stat)(fullPath, (err, curStat) => {
29335
- if (err || !writes.has(path23)) {
29492
+ if (err || !writes.has(path25)) {
29336
29493
  if (err && err.code !== "ENOENT")
29337
29494
  awfEmit(err);
29338
29495
  return;
29339
29496
  }
29340
29497
  const now2 = Number(/* @__PURE__ */ new Date());
29341
29498
  if (prevStat && curStat.size !== prevStat.size) {
29342
- writes.get(path23).lastChange = now2;
29499
+ writes.get(path25).lastChange = now2;
29343
29500
  }
29344
- const pw = writes.get(path23);
29501
+ const pw = writes.get(path25);
29345
29502
  const df = now2 - pw.lastChange;
29346
29503
  if (df >= threshold) {
29347
- writes.delete(path23);
29504
+ writes.delete(path25);
29348
29505
  awfEmit(void 0, curStat);
29349
29506
  } else {
29350
29507
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
29351
29508
  }
29352
29509
  });
29353
29510
  }
29354
- if (!writes.has(path23)) {
29355
- writes.set(path23, {
29511
+ if (!writes.has(path25)) {
29512
+ writes.set(path25, {
29356
29513
  lastChange: now,
29357
29514
  cancelWait: () => {
29358
- writes.delete(path23);
29515
+ writes.delete(path25);
29359
29516
  clearTimeout(timeoutHandler);
29360
29517
  return event;
29361
29518
  }
@@ -29366,8 +29523,8 @@ var init_chokidar = __esm({
29366
29523
  /**
29367
29524
  * Determines whether user has asked to ignore this path.
29368
29525
  */
29369
- _isIgnored(path23, stats) {
29370
- if (this.options.atomic && DOT_RE.test(path23))
29526
+ _isIgnored(path25, stats) {
29527
+ if (this.options.atomic && DOT_RE.test(path25))
29371
29528
  return true;
29372
29529
  if (!this._userIgnored) {
29373
29530
  const { cwd } = this.options;
@@ -29377,17 +29534,17 @@ var init_chokidar = __esm({
29377
29534
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
29378
29535
  this._userIgnored = anymatch(list, void 0);
29379
29536
  }
29380
- return this._userIgnored(path23, stats);
29537
+ return this._userIgnored(path25, stats);
29381
29538
  }
29382
- _isntIgnored(path23, stat4) {
29383
- return !this._isIgnored(path23, stat4);
29539
+ _isntIgnored(path25, stat4) {
29540
+ return !this._isIgnored(path25, stat4);
29384
29541
  }
29385
29542
  /**
29386
29543
  * Provides a set of common helpers and properties relating to symlink handling.
29387
29544
  * @param path file or directory pattern being watched
29388
29545
  */
29389
- _getWatchHelpers(path23) {
29390
- return new WatchHelper(path23, this.options.followSymlinks, this);
29546
+ _getWatchHelpers(path25) {
29547
+ return new WatchHelper(path25, this.options.followSymlinks, this);
29391
29548
  }
29392
29549
  // Directory helpers
29393
29550
  // -----------------
@@ -29419,63 +29576,63 @@ var init_chokidar = __esm({
29419
29576
  * @param item base path of item/directory
29420
29577
  */
29421
29578
  _remove(directory, item, isDirectory) {
29422
- const path23 = sp2.join(directory, item);
29423
- const fullPath = sp2.resolve(path23);
29424
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path23) || this._watched.has(fullPath);
29425
- if (!this._throttle("remove", path23, 100))
29579
+ const path25 = sp2.join(directory, item);
29580
+ const fullPath = sp2.resolve(path25);
29581
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path25) || this._watched.has(fullPath);
29582
+ if (!this._throttle("remove", path25, 100))
29426
29583
  return;
29427
29584
  if (!isDirectory && this._watched.size === 1) {
29428
29585
  this.add(directory, item, true);
29429
29586
  }
29430
- const wp = this._getWatchedDir(path23);
29587
+ const wp = this._getWatchedDir(path25);
29431
29588
  const nestedDirectoryChildren = wp.getChildren();
29432
- nestedDirectoryChildren.forEach((nested) => this._remove(path23, nested));
29589
+ nestedDirectoryChildren.forEach((nested) => this._remove(path25, nested));
29433
29590
  const parent = this._getWatchedDir(directory);
29434
29591
  const wasTracked = parent.has(item);
29435
29592
  parent.remove(item);
29436
29593
  if (this._symlinkPaths.has(fullPath)) {
29437
29594
  this._symlinkPaths.delete(fullPath);
29438
29595
  }
29439
- let relPath = path23;
29596
+ let relPath = path25;
29440
29597
  if (this.options.cwd)
29441
- relPath = sp2.relative(this.options.cwd, path23);
29598
+ relPath = sp2.relative(this.options.cwd, path25);
29442
29599
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
29443
29600
  const event = this._pendingWrites.get(relPath).cancelWait();
29444
29601
  if (event === EVENTS.ADD)
29445
29602
  return;
29446
29603
  }
29447
- this._watched.delete(path23);
29604
+ this._watched.delete(path25);
29448
29605
  this._watched.delete(fullPath);
29449
29606
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
29450
- if (wasTracked && !this._isIgnored(path23))
29451
- this._emit(eventName, path23);
29452
- this._closePath(path23);
29607
+ if (wasTracked && !this._isIgnored(path25))
29608
+ this._emit(eventName, path25);
29609
+ this._closePath(path25);
29453
29610
  }
29454
29611
  /**
29455
29612
  * Closes all watchers for a path
29456
29613
  */
29457
- _closePath(path23) {
29458
- this._closeFile(path23);
29459
- const dir = sp2.dirname(path23);
29460
- this._getWatchedDir(dir).remove(sp2.basename(path23));
29614
+ _closePath(path25) {
29615
+ this._closeFile(path25);
29616
+ const dir = sp2.dirname(path25);
29617
+ this._getWatchedDir(dir).remove(sp2.basename(path25));
29461
29618
  }
29462
29619
  /**
29463
29620
  * Closes only file-specific watchers
29464
29621
  */
29465
- _closeFile(path23) {
29466
- const closers = this._closers.get(path23);
29622
+ _closeFile(path25) {
29623
+ const closers = this._closers.get(path25);
29467
29624
  if (!closers)
29468
29625
  return;
29469
29626
  closers.forEach((closer) => closer());
29470
- this._closers.delete(path23);
29627
+ this._closers.delete(path25);
29471
29628
  }
29472
- _addPathCloser(path23, closer) {
29629
+ _addPathCloser(path25, closer) {
29473
29630
  if (!closer)
29474
29631
  return;
29475
- let list = this._closers.get(path23);
29632
+ let list = this._closers.get(path25);
29476
29633
  if (!list) {
29477
29634
  list = [];
29478
- this._closers.set(path23, list);
29635
+ this._closers.set(path25, list);
29479
29636
  }
29480
29637
  list.push(closer);
29481
29638
  }
@@ -29501,18 +29658,19 @@ var init_chokidar = __esm({
29501
29658
  });
29502
29659
 
29503
29660
  // ../../oss/packages/daemon-core/src/providers/provider-loader.ts
29504
- var fs6, path10, os12, ProviderLoader;
29661
+ var fs6, path12, os12, ProviderLoader;
29505
29662
  var init_provider_loader = __esm({
29506
29663
  "../../oss/packages/daemon-core/src/providers/provider-loader.ts"() {
29507
29664
  "use strict";
29508
29665
  fs6 = __toESM(require("fs"));
29509
- path10 = __toESM(require("path"));
29666
+ path12 = __toESM(require("path"));
29510
29667
  os12 = __toESM(require("os"));
29511
29668
  init_chokidar();
29512
29669
  init_ide_detector();
29513
29670
  init_logger();
29514
29671
  ProviderLoader = class _ProviderLoader {
29515
29672
  providers = /* @__PURE__ */ new Map();
29673
+ providerAvailability = /* @__PURE__ */ new Map();
29516
29674
  userDir;
29517
29675
  upstreamDir;
29518
29676
  disableUpstream;
@@ -29528,12 +29686,12 @@ var init_provider_loader = __esm({
29528
29686
  static META_FILE = ".meta.json";
29529
29687
  constructor(options) {
29530
29688
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
29531
- const defaultProvidersDir = path10.join(os12.homedir(), ".adhdev", "providers");
29689
+ const defaultProvidersDir = path12.join(os12.homedir(), ".adhdev", "providers");
29532
29690
  if (options?.userDir) {
29533
29691
  this.userDir = options.userDir;
29534
29692
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
29535
29693
  } else {
29536
- const localRepoPath = path10.resolve(__dirname, "../../../../../adhdev-providers");
29694
+ const localRepoPath = path12.resolve(__dirname, "../../../../../adhdev-providers");
29537
29695
  if (fs6.existsSync(localRepoPath)) {
29538
29696
  this.userDir = localRepoPath;
29539
29697
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -29542,7 +29700,7 @@ var init_provider_loader = __esm({
29542
29700
  this.log(`Using default user providers directory: ${this.userDir}`);
29543
29701
  }
29544
29702
  }
29545
- this.upstreamDir = path10.join(defaultProvidersDir, ".upstream");
29703
+ this.upstreamDir = path12.join(defaultProvidersDir, ".upstream");
29546
29704
  this.disableUpstream = options?.disableUpstream ?? false;
29547
29705
  }
29548
29706
  log(msg) {
@@ -29572,7 +29730,7 @@ var init_provider_loader = __esm({
29572
29730
  * Canonical provider directory shape for a given root.
29573
29731
  */
29574
29732
  getProviderDir(root, category, type) {
29575
- return path10.join(root, category, type);
29733
+ return path12.join(root, category, type);
29576
29734
  }
29577
29735
  /**
29578
29736
  * Canonical user override directory for a provider.
@@ -29599,7 +29757,7 @@ var init_provider_loader = __esm({
29599
29757
  resolveProviderFile(type, ...segments) {
29600
29758
  const dir = this.findProviderDirInternal(type);
29601
29759
  if (!dir) return null;
29602
- return path10.join(dir, ...segments);
29760
+ return path12.join(dir, ...segments);
29603
29761
  }
29604
29762
  /**
29605
29763
  * Load all providers (3-tier priority)
@@ -29610,6 +29768,7 @@ var init_provider_loader = __esm({
29610
29768
  */
29611
29769
  loadAll() {
29612
29770
  this.providers.clear();
29771
+ this.providerAvailability.clear();
29613
29772
  let upstreamCount = 0;
29614
29773
  if (!this.disableUpstream && fs6.existsSync(this.upstreamDir)) {
29615
29774
  upstreamCount = this.loadDir(this.upstreamDir);
@@ -29637,7 +29796,7 @@ var init_provider_loader = __esm({
29637
29796
  if (!fs6.existsSync(this.upstreamDir)) return false;
29638
29797
  try {
29639
29798
  return fs6.readdirSync(this.upstreamDir).some(
29640
- (d) => fs6.statSync(path10.join(this.upstreamDir, d)).isDirectory()
29799
+ (d) => fs6.statSync(path12.join(this.upstreamDir, d)).isDirectory()
29641
29800
  );
29642
29801
  } catch {
29643
29802
  return false;
@@ -29680,11 +29839,12 @@ var init_provider_loader = __esm({
29680
29839
  if ((p.category === "cli" || p.category === "acp") && p.spawn?.command) {
29681
29840
  const verCmdConfig = p.versionCommand;
29682
29841
  const versionCommand = typeof verCmdConfig === "object" && verCmdConfig !== null ? verCmdConfig[process.platform] : verCmdConfig;
29842
+ const command = this.getSpawnCommand(p.type, p.spawn.command);
29683
29843
  result.push({
29684
29844
  id: p.type,
29685
29845
  displayName: p.displayName || p.name,
29686
29846
  icon: p.icon || "\u{1F527}",
29687
- command: p.spawn.command,
29847
+ command,
29688
29848
  category: p.category,
29689
29849
  ...typeof versionCommand === "string" && versionCommand.trim() ? { versionCommand: versionCommand.trim() } : {}
29690
29850
  });
@@ -29813,6 +29973,71 @@ var init_provider_loader = __esm({
29813
29973
  getAvailableIdeTypes() {
29814
29974
  return [...this.providers.values()].filter((p) => p.category === "ide" && p.cdpPorts).map((p) => p.type);
29815
29975
  }
29976
+ getSpawnCommand(type, fallback) {
29977
+ const override = this.getOptionalStringSetting(type, "executablePath");
29978
+ if (override) return override;
29979
+ return fallback || this.providers.get(type)?.spawn?.command || type;
29980
+ }
29981
+ getIdeCliCommand(type, fallback) {
29982
+ const override = this.getOptionalStringSetting(type, "cliPathOverride");
29983
+ if (override) return override;
29984
+ return fallback || this.providers.get(type)?.cli || null;
29985
+ }
29986
+ getIdePathCandidates(type, fallback) {
29987
+ const override = this.getOptionalStringSetting(type, "appPathOverride");
29988
+ if (override) return [override];
29989
+ if (fallback && fallback.length > 0) return fallback;
29990
+ const osPaths = this.providers.get(type)?.paths?.[process.platform];
29991
+ return Array.isArray(osPaths) ? [...osPaths] : [];
29992
+ }
29993
+ setProviderAvailability(type, state) {
29994
+ this.providerAvailability.set(type, {
29995
+ installed: !!state.installed,
29996
+ detectedPath: state.detectedPath ?? null
29997
+ });
29998
+ }
29999
+ setCliDetectionResults(results, replace = true) {
30000
+ if (replace) {
30001
+ for (const provider of this.providers.values()) {
30002
+ if (provider.category === "cli" || provider.category === "acp") {
30003
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
30004
+ }
30005
+ }
30006
+ }
30007
+ for (const result of results) {
30008
+ this.setProviderAvailability(result.id, {
30009
+ installed: !!result.installed,
30010
+ detectedPath: result.path || null
30011
+ });
30012
+ }
30013
+ }
30014
+ setIdeDetectionResults(results, replace = true) {
30015
+ if (replace) {
30016
+ for (const provider of this.providers.values()) {
30017
+ if (provider.category === "ide") {
30018
+ this.providerAvailability.set(provider.type, { installed: false, detectedPath: null });
30019
+ }
30020
+ }
30021
+ }
30022
+ for (const result of results) {
30023
+ this.setProviderAvailability(result.id, {
30024
+ installed: !!result.installed,
30025
+ detectedPath: result.cliCommand || result.path || null
30026
+ });
30027
+ }
30028
+ }
30029
+ getAvailableProviderInfos() {
30030
+ return this.getAll().map((provider) => {
30031
+ const availability = this.providerAvailability.get(provider.type);
30032
+ return {
30033
+ ...provider,
30034
+ ...availability ? {
30035
+ installed: availability.installed,
30036
+ detectedPath: availability.detectedPath
30037
+ } : {}
30038
+ };
30039
+ });
30040
+ }
29816
30041
  /**
29817
30042
  * Register IDE providers to core/detector registry
29818
30043
  * → Enables detectIDEs() to detect provider.js-based IDEs
@@ -29887,8 +30112,8 @@ var init_provider_loader = __esm({
29887
30112
  resolved._resolvedScriptDir = entry.scriptDir;
29888
30113
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
29889
30114
  if (providerDir) {
29890
- const fullDir = path10.join(providerDir, entry.scriptDir);
29891
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
30115
+ const fullDir = path12.join(providerDir, entry.scriptDir);
30116
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
29892
30117
  }
29893
30118
  matched = true;
29894
30119
  }
@@ -29903,8 +30128,8 @@ var init_provider_loader = __esm({
29903
30128
  resolved._resolvedScriptDir = base.defaultScriptDir;
29904
30129
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
29905
30130
  if (providerDir) {
29906
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
29907
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
30131
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
30132
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
29908
30133
  }
29909
30134
  }
29910
30135
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -29921,8 +30146,8 @@ var init_provider_loader = __esm({
29921
30146
  resolved._resolvedScriptDir = dirOverride;
29922
30147
  resolved._resolvedScriptsSource = `versions:${range}`;
29923
30148
  if (providerDir) {
29924
- const fullDir = path10.join(providerDir, dirOverride);
29925
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
30149
+ const fullDir = path12.join(providerDir, dirOverride);
30150
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
29926
30151
  }
29927
30152
  }
29928
30153
  } else if (override.scripts) {
@@ -29938,8 +30163,8 @@ var init_provider_loader = __esm({
29938
30163
  resolved._resolvedScriptDir = base.defaultScriptDir;
29939
30164
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
29940
30165
  if (providerDir) {
29941
- const fullDir = path10.join(providerDir, base.defaultScriptDir);
29942
- resolved._resolvedScriptsPath = fs6.existsSync(path10.join(fullDir, "scripts.js")) ? path10.join(fullDir, "scripts.js") : fullDir;
30166
+ const fullDir = path12.join(providerDir, base.defaultScriptDir);
30167
+ resolved._resolvedScriptsPath = fs6.existsSync(path12.join(fullDir, "scripts.js")) ? path12.join(fullDir, "scripts.js") : fullDir;
29943
30168
  }
29944
30169
  }
29945
30170
  }
@@ -29964,14 +30189,14 @@ var init_provider_loader = __esm({
29964
30189
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
29965
30190
  return null;
29966
30191
  }
29967
- const dir = path10.join(providerDir, scriptDir);
30192
+ const dir = path12.join(providerDir, scriptDir);
29968
30193
  if (!fs6.existsSync(dir)) {
29969
30194
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
29970
30195
  return null;
29971
30196
  }
29972
30197
  const cached2 = this.scriptsCache.get(dir);
29973
30198
  if (cached2) return cached2;
29974
- const scriptsJs = path10.join(dir, "scripts.js");
30199
+ const scriptsJs = path12.join(dir, "scripts.js");
29975
30200
  if (fs6.existsSync(scriptsJs)) {
29976
30201
  try {
29977
30202
  delete require.cache[require.resolve(scriptsJs)];
@@ -30013,7 +30238,7 @@ var init_provider_loader = __esm({
30013
30238
  return;
30014
30239
  }
30015
30240
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
30016
- this.log(`File changed: ${path10.basename(filePath)}, reloading...`);
30241
+ this.log(`File changed: ${path12.basename(filePath)}, reloading...`);
30017
30242
  this.reload();
30018
30243
  }
30019
30244
  };
@@ -30068,7 +30293,7 @@ var init_provider_loader = __esm({
30068
30293
  }
30069
30294
  const https = require("https");
30070
30295
  const { execSync: execSync7 } = require("child_process");
30071
- const metaPath = path10.join(this.upstreamDir, _ProviderLoader.META_FILE);
30296
+ const metaPath = path12.join(this.upstreamDir, _ProviderLoader.META_FILE);
30072
30297
  let prevEtag = "";
30073
30298
  let prevTimestamp = 0;
30074
30299
  try {
@@ -30085,7 +30310,7 @@ var init_provider_loader = __esm({
30085
30310
  return { updated: false };
30086
30311
  }
30087
30312
  try {
30088
- const etag = await new Promise((resolve13, reject) => {
30313
+ const etag = await new Promise((resolve16, reject) => {
30089
30314
  const options = {
30090
30315
  method: "HEAD",
30091
30316
  hostname: "github.com",
@@ -30103,7 +30328,7 @@ var init_provider_loader = __esm({
30103
30328
  headers: { "User-Agent": "adhdev-launcher" },
30104
30329
  timeout: 1e4
30105
30330
  }, (res2) => {
30106
- resolve13(res2.headers.etag || res2.headers["last-modified"] || "");
30331
+ resolve16(res2.headers.etag || res2.headers["last-modified"] || "");
30107
30332
  });
30108
30333
  req2.on("error", reject);
30109
30334
  req2.on("timeout", () => {
@@ -30112,7 +30337,7 @@ var init_provider_loader = __esm({
30112
30337
  });
30113
30338
  req2.end();
30114
30339
  } else {
30115
- resolve13(res.headers.etag || res.headers["last-modified"] || "");
30340
+ resolve16(res.headers.etag || res.headers["last-modified"] || "");
30116
30341
  }
30117
30342
  });
30118
30343
  req.on("error", reject);
@@ -30128,17 +30353,17 @@ var init_provider_loader = __esm({
30128
30353
  return { updated: false };
30129
30354
  }
30130
30355
  this.log("Downloading latest providers from GitHub...");
30131
- const tmpTar = path10.join(os12.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
30132
- const tmpExtract = path10.join(os12.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
30356
+ const tmpTar = path12.join(os12.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
30357
+ const tmpExtract = path12.join(os12.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
30133
30358
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
30134
30359
  fs6.mkdirSync(tmpExtract, { recursive: true });
30135
30360
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
30136
30361
  const extracted = fs6.readdirSync(tmpExtract);
30137
30362
  const rootDir = extracted.find(
30138
- (d) => fs6.statSync(path10.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
30363
+ (d) => fs6.statSync(path12.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
30139
30364
  );
30140
30365
  if (!rootDir) throw new Error("Unexpected tarball structure");
30141
- const sourceDir = path10.join(tmpExtract, rootDir);
30366
+ const sourceDir = path12.join(tmpExtract, rootDir);
30142
30367
  const backupDir = this.upstreamDir + ".bak";
30143
30368
  if (fs6.existsSync(this.upstreamDir)) {
30144
30369
  if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
@@ -30176,7 +30401,7 @@ var init_provider_loader = __esm({
30176
30401
  downloadFile(url2, destPath) {
30177
30402
  const https = require("https");
30178
30403
  const http3 = require("http");
30179
- return new Promise((resolve13, reject) => {
30404
+ return new Promise((resolve16, reject) => {
30180
30405
  const doRequest = (reqUrl, redirectCount = 0) => {
30181
30406
  if (redirectCount > 5) {
30182
30407
  reject(new Error("Too many redirects"));
@@ -30196,7 +30421,7 @@ var init_provider_loader = __esm({
30196
30421
  res.pipe(ws);
30197
30422
  ws.on("finish", () => {
30198
30423
  ws.close();
30199
- resolve13();
30424
+ resolve16();
30200
30425
  });
30201
30426
  ws.on("error", reject);
30202
30427
  });
@@ -30213,8 +30438,8 @@ var init_provider_loader = __esm({
30213
30438
  copyDirRecursive(src, dest) {
30214
30439
  fs6.mkdirSync(dest, { recursive: true });
30215
30440
  for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
30216
- const srcPath = path10.join(src, entry.name);
30217
- const destPath = path10.join(dest, entry.name);
30441
+ const srcPath = path12.join(src, entry.name);
30442
+ const destPath = path12.join(dest, entry.name);
30218
30443
  if (entry.isDirectory()) {
30219
30444
  this.copyDirRecursive(srcPath, destPath);
30220
30445
  } else {
@@ -30225,7 +30450,7 @@ var init_provider_loader = __esm({
30225
30450
  /** .meta.json save */
30226
30451
  writeMeta(metaPath, etag, timestamp) {
30227
30452
  try {
30228
- fs6.mkdirSync(path10.dirname(metaPath), { recursive: true });
30453
+ fs6.mkdirSync(path12.dirname(metaPath), { recursive: true });
30229
30454
  fs6.writeFileSync(metaPath, JSON.stringify({
30230
30455
  etag,
30231
30456
  timestamp,
@@ -30242,7 +30467,7 @@ var init_provider_loader = __esm({
30242
30467
  const scan = (d) => {
30243
30468
  try {
30244
30469
  for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
30245
- if (entry.isDirectory()) scan(path10.join(d, entry.name));
30470
+ if (entry.isDirectory()) scan(path12.join(d, entry.name));
30246
30471
  else if (entry.name === "provider.json") count++;
30247
30472
  }
30248
30473
  } catch {
@@ -30256,9 +30481,8 @@ var init_provider_loader = __esm({
30256
30481
  * Get public settings schema for a provider (for dashboard UI rendering)
30257
30482
  */
30258
30483
  getPublicSettings(type) {
30259
- const provider = this.providers.get(type);
30260
- if (!provider?.settings) return [];
30261
- return Object.entries(provider.settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
30484
+ const settings = this.getSettingsSchema(type);
30485
+ return Object.entries(settings).filter(([, def]) => def.public === true).map(([key, def]) => ({ key, ...def }));
30262
30486
  }
30263
30487
  /**
30264
30488
  * Get public settings schema for all providers
@@ -30275,8 +30499,7 @@ var init_provider_loader = __esm({
30275
30499
  * Resolved setting value for a provider (default + user override)
30276
30500
  */
30277
30501
  getSettingValue(type, key) {
30278
- const provider = this.providers.get(type);
30279
- const schemaDef = provider?.settings?.[key];
30502
+ const schemaDef = this.getSettingsSchema(type)[key];
30280
30503
  const defaultVal = schemaDef ? schemaDef.default : void 0;
30281
30504
  try {
30282
30505
  const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
@@ -30291,10 +30514,9 @@ var init_provider_loader = __esm({
30291
30514
  * All resolved settings for a provider (default + user override)
30292
30515
  */
30293
30516
  getSettings(type) {
30294
- const provider = this.providers.get(type);
30295
- if (!provider?.settings) return {};
30517
+ const settings = this.getSettingsSchema(type);
30296
30518
  const result = {};
30297
- for (const [key, def] of Object.entries(provider.settings)) {
30519
+ for (const [key] of Object.entries(settings)) {
30298
30520
  result[key] = this.getSettingValue(type, key);
30299
30521
  }
30300
30522
  return result;
@@ -30303,11 +30525,11 @@ var init_provider_loader = __esm({
30303
30525
  * Save provider setting value (writes to config.json)
30304
30526
  */
30305
30527
  setSetting(type, key, value) {
30306
- const provider = this.providers.get(type);
30307
- const schemaDef = provider?.settings?.[key];
30528
+ const schemaDef = this.getSettingsSchema(type)[key];
30308
30529
  if (!schemaDef) return false;
30309
30530
  if (!schemaDef.public) return false;
30310
30531
  if (schemaDef.type === "boolean" && typeof value !== "boolean") return false;
30532
+ if (schemaDef.type === "string" && typeof value !== "string") return false;
30311
30533
  if (schemaDef.type === "number") {
30312
30534
  if (typeof value !== "number") return false;
30313
30535
  if (schemaDef.min !== void 0 && value < schemaDef.min) return false;
@@ -30328,6 +30550,53 @@ var init_provider_loader = __esm({
30328
30550
  return false;
30329
30551
  }
30330
30552
  }
30553
+ getOptionalStringSetting(type, key) {
30554
+ const value = this.getSettingValue(type, key);
30555
+ if (typeof value !== "string") return null;
30556
+ const trimmed = value.trim();
30557
+ return trimmed ? trimmed : null;
30558
+ }
30559
+ getSettingsSchema(type) {
30560
+ const provider = this.providers.get(type);
30561
+ if (!provider) return {};
30562
+ return {
30563
+ ...this.getSyntheticSettings(type, provider),
30564
+ ...provider.settings || {}
30565
+ };
30566
+ }
30567
+ getSyntheticSettings(type, provider) {
30568
+ const result = {};
30569
+ if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
30570
+ result.executablePath = {
30571
+ type: "string",
30572
+ default: "",
30573
+ public: true,
30574
+ label: "Executable path",
30575
+ description: "Optional absolute path for this provider binary. Leave blank to use the default PATH lookup."
30576
+ };
30577
+ }
30578
+ if (provider.category === "ide") {
30579
+ if (provider.cli && !provider.settings?.cliPathOverride) {
30580
+ result.cliPathOverride = {
30581
+ type: "string",
30582
+ default: "",
30583
+ public: true,
30584
+ label: "CLI path override",
30585
+ description: "Optional absolute path for the IDE CLI launcher. Leave blank to use the detected default."
30586
+ };
30587
+ }
30588
+ if (provider.paths && !provider.settings?.appPathOverride) {
30589
+ result.appPathOverride = {
30590
+ type: "string",
30591
+ default: "",
30592
+ public: true,
30593
+ label: "App path override",
30594
+ description: "Optional absolute path for the IDE app bundle or executable. Leave blank to use the default install locations."
30595
+ };
30596
+ }
30597
+ }
30598
+ return result;
30599
+ }
30331
30600
  // ─── Private ───────────────────────────────────
30332
30601
  /**
30333
30602
  * Find the on-disk directory for a provider by type.
@@ -30341,17 +30610,17 @@ var init_provider_loader = __esm({
30341
30610
  for (const root of searchRoots) {
30342
30611
  if (!fs6.existsSync(root)) continue;
30343
30612
  const candidate = this.getProviderDir(root, cat, type);
30344
- if (fs6.existsSync(path10.join(candidate, "provider.json"))) return candidate;
30345
- const catDir = path10.join(root, cat);
30613
+ if (fs6.existsSync(path12.join(candidate, "provider.json"))) return candidate;
30614
+ const catDir = path12.join(root, cat);
30346
30615
  if (fs6.existsSync(catDir)) {
30347
30616
  try {
30348
30617
  for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
30349
30618
  if (!entry.isDirectory()) continue;
30350
- const jsonPath = path10.join(catDir, entry.name, "provider.json");
30619
+ const jsonPath = path12.join(catDir, entry.name, "provider.json");
30351
30620
  if (fs6.existsSync(jsonPath)) {
30352
30621
  try {
30353
30622
  const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
30354
- if (data.type === type) return path10.join(catDir, entry.name);
30623
+ if (data.type === type) return path12.join(catDir, entry.name);
30355
30624
  } catch {
30356
30625
  }
30357
30626
  }
@@ -30368,7 +30637,7 @@ var init_provider_loader = __esm({
30368
30637
  * (template substitution is NOT applied here — scripts.js handles that)
30369
30638
  */
30370
30639
  buildScriptWrappersFromDir(dir) {
30371
- const scriptsJs = path10.join(dir, "scripts.js");
30640
+ const scriptsJs = path12.join(dir, "scripts.js");
30372
30641
  if (fs6.existsSync(scriptsJs)) {
30373
30642
  try {
30374
30643
  delete require.cache[require.resolve(scriptsJs)];
@@ -30382,7 +30651,7 @@ var init_provider_loader = __esm({
30382
30651
  for (const file2 of fs6.readdirSync(dir)) {
30383
30652
  if (!file2.endsWith(".js")) continue;
30384
30653
  const scriptName = toCamel(file2.replace(".js", ""));
30385
- const filePath = path10.join(dir, file2);
30654
+ const filePath = path12.join(dir, file2);
30386
30655
  result[scriptName] = (...args) => {
30387
30656
  try {
30388
30657
  let content = fs6.readFileSync(filePath, "utf-8");
@@ -30442,7 +30711,7 @@ var init_provider_loader = __esm({
30442
30711
  }
30443
30712
  const hasJson = entries.some((e) => e.name === "provider.json");
30444
30713
  if (hasJson) {
30445
- const jsonPath = path10.join(d, "provider.json");
30714
+ const jsonPath = path12.join(d, "provider.json");
30446
30715
  try {
30447
30716
  const raw = fs6.readFileSync(jsonPath, "utf-8");
30448
30717
  const mod = JSON.parse(raw);
@@ -30455,7 +30724,7 @@ var init_provider_loader = __esm({
30455
30724
  delete mod.extensionIdPattern_flags;
30456
30725
  }
30457
30726
  const hasCompatibility = Array.isArray(mod.compatibility);
30458
- const scriptsPath = path10.join(d, "scripts.js");
30727
+ const scriptsPath = path12.join(d, "scripts.js");
30459
30728
  if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
30460
30729
  try {
30461
30730
  delete require.cache[require.resolve(scriptsPath)];
@@ -30481,7 +30750,7 @@ var init_provider_loader = __esm({
30481
30750
  if (!entry.isDirectory()) continue;
30482
30751
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
30483
30752
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
30484
- scan(path10.join(d, entry.name));
30753
+ scan(path12.join(d, entry.name));
30485
30754
  }
30486
30755
  }
30487
30756
  };
@@ -30578,17 +30847,17 @@ async function findFreePort(ports) {
30578
30847
  throw new Error("No free port found");
30579
30848
  }
30580
30849
  function checkPortFree(port) {
30581
- return new Promise((resolve13) => {
30850
+ return new Promise((resolve16) => {
30582
30851
  const server = net2.createServer();
30583
30852
  server.unref();
30584
- server.on("error", () => resolve13(false));
30853
+ server.on("error", () => resolve16(false));
30585
30854
  server.listen(port, "127.0.0.1", () => {
30586
- server.close(() => resolve13(true));
30855
+ server.close(() => resolve16(true));
30587
30856
  });
30588
30857
  });
30589
30858
  }
30590
30859
  async function isCdpActive(port) {
30591
- return new Promise((resolve13) => {
30860
+ return new Promise((resolve16) => {
30592
30861
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
30593
30862
  timeout: 2e3
30594
30863
  }, (res) => {
@@ -30597,16 +30866,16 @@ async function isCdpActive(port) {
30597
30866
  res.on("end", () => {
30598
30867
  try {
30599
30868
  const info = JSON.parse(data);
30600
- resolve13(!!info["WebKit-Version"] || !!info["Browser"]);
30869
+ resolve16(!!info["WebKit-Version"] || !!info["Browser"]);
30601
30870
  } catch {
30602
- resolve13(false);
30871
+ resolve16(false);
30603
30872
  }
30604
30873
  });
30605
30874
  });
30606
- req.on("error", () => resolve13(false));
30875
+ req.on("error", () => resolve16(false));
30607
30876
  req.on("timeout", () => {
30608
30877
  req.destroy();
30609
- resolve13(false);
30878
+ resolve16(false);
30610
30879
  });
30611
30880
  });
30612
30881
  }
@@ -30740,8 +31009,8 @@ function detectCurrentWorkspace(ideId) {
30740
31009
  const appNameMap = getMacAppIdentifiers();
30741
31010
  const appName = appNameMap[ideId];
30742
31011
  if (appName) {
30743
- const storagePath = path11.join(
30744
- process.env.APPDATA || path11.join(os13.homedir(), "AppData", "Roaming"),
31012
+ const storagePath = path13.join(
31013
+ process.env.APPDATA || path13.join(os13.homedir(), "AppData", "Roaming"),
30745
31014
  appName,
30746
31015
  "storage.json"
30747
31016
  );
@@ -30765,7 +31034,7 @@ function detectCurrentWorkspace(ideId) {
30765
31034
  async function launchWithCdp(options = {}) {
30766
31035
  const platform11 = os13.platform();
30767
31036
  let targetIde;
30768
- const ides = await detectIDEs();
31037
+ const ides = await detectIDEs(getProviderLoader());
30769
31038
  if (options.ideId) {
30770
31039
  targetIde = ides.find((i) => i.id === options.ideId && i.installed);
30771
31040
  if (!targetIde) {
@@ -30912,14 +31181,14 @@ async function launchLinux(ide, port, workspace, newWindow) {
30912
31181
  function getAvailableIdeIds() {
30913
31182
  return getProviderLoader().getAvailableIdeTypes();
30914
31183
  }
30915
- var import_child_process6, net2, os13, path11, _providerLoader;
31184
+ var import_child_process6, net2, os13, path13, _providerLoader;
30916
31185
  var init_launch = __esm({
30917
31186
  "../../oss/packages/daemon-core/src/launch.ts"() {
30918
31187
  "use strict";
30919
31188
  import_child_process6 = require("child_process");
30920
31189
  net2 = __toESM(require("net"));
30921
31190
  os13 = __toESM(require("os"));
30922
- path11 = __toESM(require("path"));
31191
+ path13 = __toESM(require("path"));
30923
31192
  init_ide_detector();
30924
31193
  init_provider_loader();
30925
31194
  _providerLoader = null;
@@ -30950,7 +31219,7 @@ function checkRotation() {
30950
31219
  const today = getDateStr2();
30951
31220
  if (today !== currentDate2) {
30952
31221
  currentDate2 = today;
30953
- currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
31222
+ currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
30954
31223
  cleanOldFiles();
30955
31224
  }
30956
31225
  }
@@ -30964,7 +31233,7 @@ function cleanOldFiles() {
30964
31233
  const dateMatch = file2.match(/commands-(\d{4}-\d{2}-\d{2})/);
30965
31234
  if (dateMatch && dateMatch[1] < cutoffStr) {
30966
31235
  try {
30967
- fs7.unlinkSync(path12.join(LOG_DIR2, file2));
31236
+ fs7.unlinkSync(path14.join(LOG_DIR2, file2));
30968
31237
  } catch {
30969
31238
  }
30970
31239
  }
@@ -31031,14 +31300,14 @@ function getRecentCommands(count = 50) {
31031
31300
  return [];
31032
31301
  }
31033
31302
  }
31034
- var fs7, path12, os14, LOG_DIR2, MAX_FILE_SIZE, MAX_DAYS, SENSITIVE_KEYS, currentDate2, currentFile, writeCount2, SKIP_COMMANDS;
31303
+ var fs7, path14, os14, LOG_DIR2, MAX_FILE_SIZE, MAX_DAYS, SENSITIVE_KEYS, currentDate2, currentFile, writeCount2, SKIP_COMMANDS;
31035
31304
  var init_command_log = __esm({
31036
31305
  "../../oss/packages/daemon-core/src/logging/command-log.ts"() {
31037
31306
  "use strict";
31038
31307
  fs7 = __toESM(require("fs"));
31039
- path12 = __toESM(require("path"));
31308
+ path14 = __toESM(require("path"));
31040
31309
  os14 = __toESM(require("os"));
31041
- LOG_DIR2 = process.platform === "win32" ? path12.join(process.env.LOCALAPPDATA || process.env.APPDATA || path12.join(os14.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path12.join(os14.homedir(), "Library", "Logs", "adhdev") : path12.join(os14.homedir(), ".local", "share", "adhdev", "logs");
31310
+ LOG_DIR2 = process.platform === "win32" ? path14.join(process.env.LOCALAPPDATA || process.env.APPDATA || path14.join(os14.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path14.join(os14.homedir(), "Library", "Logs", "adhdev") : path14.join(os14.homedir(), ".local", "share", "adhdev", "logs");
31042
31311
  MAX_FILE_SIZE = 5 * 1024 * 1024;
31043
31312
  MAX_DAYS = 7;
31044
31313
  try {
@@ -31057,7 +31326,7 @@ var init_command_log = __esm({
31057
31326
  "text"
31058
31327
  ]);
31059
31328
  currentDate2 = getDateStr2();
31060
- currentFile = path12.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
31329
+ currentFile = path14.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
31061
31330
  writeCount2 = 0;
31062
31331
  SKIP_COMMANDS = /* @__PURE__ */ new Set([
31063
31332
  "heartbeat",
@@ -31078,12 +31347,15 @@ function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
31078
31347
  }));
31079
31348
  }
31080
31349
  function buildAvailableProviders(providerLoader) {
31081
- return providerLoader.getAll().map((provider) => ({
31350
+ const providers = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
31351
+ return providers.map((provider) => ({
31082
31352
  type: provider.type,
31083
31353
  name: provider.displayName || provider.type,
31084
31354
  displayName: provider.displayName || provider.type,
31085
31355
  icon: provider.icon || "\u{1F4BB}",
31086
- category: provider.category
31356
+ category: provider.category,
31357
+ ...provider.installed !== void 0 ? { installed: provider.installed } : {},
31358
+ ...provider.detectedPath !== void 0 ? { detectedPath: provider.detectedPath } : {}
31087
31359
  }));
31088
31360
  }
31089
31361
  function parseMessageTime(value) {
@@ -31097,17 +31369,17 @@ function parseMessageTime(value) {
31097
31369
  function getSessionMessageUpdatedAt(session) {
31098
31370
  const lastMessage = session.activeChat?.messages?.at?.(-1);
31099
31371
  if (!lastMessage) return 0;
31100
- return parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt) || 0;
31372
+ return parseMessageTime(lastMessage.receivedAt) || 0;
31101
31373
  }
31102
31374
  function getSessionCompletionMarker(session) {
31103
31375
  const lastMessage = session.activeChat?.messages?.at?.(-1);
31104
31376
  if (!lastMessage) return "";
31105
31377
  const role = typeof lastMessage.role === "string" ? lastMessage.role : "";
31106
- if (role === "user" || role === "human") return "";
31378
+ if (role === "user" || role === "human" || role === "system") return "";
31107
31379
  if (typeof lastMessage._turnKey === "string" && lastMessage._turnKey) return `turn:${lastMessage._turnKey}`;
31108
31380
  if (typeof lastMessage.id === "string" && lastMessage.id) return `id:${lastMessage.id}`;
31109
31381
  if (typeof lastMessage.index === "number" && Number.isFinite(lastMessage.index)) return `idx:${lastMessage.index}`;
31110
- const timestamp = parseMessageTime(lastMessage.timestamp) || parseMessageTime(lastMessage.receivedAt) || parseMessageTime(lastMessage.createdAt);
31382
+ const timestamp = parseMessageTime(lastMessage.receivedAt);
31111
31383
  return timestamp > 0 ? `ts:${timestamp}` : "";
31112
31384
  }
31113
31385
  function getSessionLastUsedAt(session) {
@@ -31124,7 +31396,7 @@ function getUnreadState(hasContentChange, status, lastUsedAt, lastSeenAt, lastRo
31124
31396
  if (status === "generating" || status === "starting") {
31125
31397
  return { unread: false, inboxBucket: "working" };
31126
31398
  }
31127
- const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human";
31399
+ const unread = completionMarker ? completionMarker !== seenCompletionMarker : hasContentChange && lastUsedAt > lastSeenAt && lastRole !== "user" && lastRole !== "human" && lastRole !== "system";
31128
31400
  return { unread, inboxBucket: unread ? "task_complete" : "idle" };
31129
31401
  }
31130
31402
  function buildRecentLaunches(recentActivity) {
@@ -31225,9 +31497,9 @@ var init_snapshot = __esm({
31225
31497
  // ../../oss/packages/daemon-core/src/commands/upgrade-helper.ts
31226
31498
  function getUpgradeLogPath() {
31227
31499
  const home = os16.homedir();
31228
- const dir = path13.join(home, ".adhdev");
31500
+ const dir = path15.join(home, ".adhdev");
31229
31501
  fs8.mkdirSync(dir, { recursive: true });
31230
- return path13.join(dir, "daemon-upgrade.log");
31502
+ return path15.join(dir, "daemon-upgrade.log");
31231
31503
  }
31232
31504
  function appendUpgradeLog(message) {
31233
31505
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -31260,14 +31532,14 @@ async function waitForPidExit(pid, timeoutMs) {
31260
31532
  while (Date.now() - start < timeoutMs) {
31261
31533
  try {
31262
31534
  process.kill(pid, 0);
31263
- await new Promise((resolve13) => setTimeout(resolve13, 250));
31535
+ await new Promise((resolve16) => setTimeout(resolve16, 250));
31264
31536
  } catch {
31265
31537
  return;
31266
31538
  }
31267
31539
  }
31268
31540
  }
31269
31541
  function stopSessionHostProcesses(appName) {
31270
- const pidFile = path13.join(os16.homedir(), ".adhdev", `${appName}-session-host.pid`);
31542
+ const pidFile = path15.join(os16.homedir(), ".adhdev", `${appName}-session-host.pid`);
31271
31543
  try {
31272
31544
  if (fs8.existsSync(pidFile)) {
31273
31545
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
@@ -31296,7 +31568,7 @@ function stopSessionHostProcesses(appName) {
31296
31568
  }
31297
31569
  }
31298
31570
  function removeDaemonPidFile() {
31299
- const pidFile = path13.join(os16.homedir(), ".adhdev", "daemon.pid");
31571
+ const pidFile = path15.join(os16.homedir(), ".adhdev", "daemon.pid");
31300
31572
  try {
31301
31573
  fs8.unlinkSync(pidFile);
31302
31574
  } catch {
@@ -31307,7 +31579,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
31307
31579
  const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
31308
31580
  if (!npmRoot) return;
31309
31581
  const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
31310
- const binDir = process.platform === "win32" ? npmPrefix : path13.join(npmPrefix, "bin");
31582
+ const binDir = process.platform === "win32" ? npmPrefix : path15.join(npmPrefix, "bin");
31311
31583
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
31312
31584
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
31313
31585
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -31315,25 +31587,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
31315
31587
  }
31316
31588
  if (pkgName.startsWith("@")) {
31317
31589
  const [scope, name] = pkgName.split("/");
31318
- const scopeDir = path13.join(npmRoot, scope);
31590
+ const scopeDir = path15.join(npmRoot, scope);
31319
31591
  if (!fs8.existsSync(scopeDir)) return;
31320
31592
  for (const entry of fs8.readdirSync(scopeDir)) {
31321
31593
  if (!entry.startsWith(`.${name}-`)) continue;
31322
- fs8.rmSync(path13.join(scopeDir, entry), { recursive: true, force: true });
31323
- appendUpgradeLog(`Removed stale scoped staging dir: ${path13.join(scopeDir, entry)}`);
31594
+ fs8.rmSync(path15.join(scopeDir, entry), { recursive: true, force: true });
31595
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path15.join(scopeDir, entry)}`);
31324
31596
  }
31325
31597
  } else {
31326
31598
  for (const entry of fs8.readdirSync(npmRoot)) {
31327
31599
  if (!entry.startsWith(`.${pkgName}-`)) continue;
31328
- fs8.rmSync(path13.join(npmRoot, entry), { recursive: true, force: true });
31329
- appendUpgradeLog(`Removed stale staging dir: ${path13.join(npmRoot, entry)}`);
31600
+ fs8.rmSync(path15.join(npmRoot, entry), { recursive: true, force: true });
31601
+ appendUpgradeLog(`Removed stale staging dir: ${path15.join(npmRoot, entry)}`);
31330
31602
  }
31331
31603
  }
31332
31604
  if (fs8.existsSync(binDir)) {
31333
31605
  for (const entry of fs8.readdirSync(binDir)) {
31334
31606
  if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
31335
- fs8.rmSync(path13.join(binDir, entry), { recursive: true, force: true });
31336
- appendUpgradeLog(`Removed stale bin staging entry: ${path13.join(binDir, entry)}`);
31607
+ fs8.rmSync(path15.join(binDir, entry), { recursive: true, force: true });
31608
+ appendUpgradeLog(`Removed stale bin staging entry: ${path15.join(binDir, entry)}`);
31337
31609
  }
31338
31610
  }
31339
31611
  }
@@ -31375,7 +31647,7 @@ async function runDaemonUpgradeHelper(payload) {
31375
31647
  appendUpgradeLog(installOutput.trim());
31376
31648
  }
31377
31649
  if (process.platform === "win32") {
31378
- await new Promise((resolve13) => setTimeout(resolve13, 500));
31650
+ await new Promise((resolve16) => setTimeout(resolve16, 500));
31379
31651
  cleanupStaleGlobalInstallDirs(payload.packageName);
31380
31652
  appendUpgradeLog("Post-install staging cleanup complete");
31381
31653
  }
@@ -31408,7 +31680,7 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
31408
31680
  process.exit(1);
31409
31681
  }
31410
31682
  }
31411
- var import_child_process7, import_child_process8, fs8, os16, path13, UPGRADE_HELPER_ENV;
31683
+ var import_child_process7, import_child_process8, fs8, os16, path15, UPGRADE_HELPER_ENV;
31412
31684
  var init_upgrade_helper = __esm({
31413
31685
  "../../oss/packages/daemon-core/src/commands/upgrade-helper.ts"() {
31414
31686
  "use strict";
@@ -31416,12 +31688,31 @@ var init_upgrade_helper = __esm({
31416
31688
  import_child_process8 = require("child_process");
31417
31689
  fs8 = __toESM(require("fs"));
31418
31690
  os16 = __toESM(require("os"));
31419
- path13 = __toESM(require("path"));
31691
+ path15 = __toESM(require("path"));
31420
31692
  UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
31421
31693
  }
31422
31694
  });
31423
31695
 
31424
31696
  // ../../oss/packages/daemon-core/src/commands/router.ts
31697
+ function toHostedCliRuntimeDescriptor(record2) {
31698
+ if (!record2 || typeof record2 !== "object") return null;
31699
+ const runtimeId = typeof record2.sessionId === "string" ? record2.sessionId : "";
31700
+ const cliType = typeof record2.providerType === "string" ? record2.providerType : "";
31701
+ const workspace = typeof record2.workspace === "string" ? record2.workspace : "";
31702
+ if (!runtimeId || !cliType || !workspace) return null;
31703
+ return {
31704
+ runtimeId,
31705
+ runtimeKey: typeof record2.runtimeKey === "string" ? record2.runtimeKey : void 0,
31706
+ displayName: typeof record2.displayName === "string" ? record2.displayName : void 0,
31707
+ workspaceLabel: typeof record2.workspaceLabel === "string" ? record2.workspaceLabel : void 0,
31708
+ lifecycle: typeof record2.lifecycle === "string" ? record2.lifecycle : void 0,
31709
+ recoveryState: typeof record2.meta?.runtimeRecoveryState === "string" ? String(record2.meta.runtimeRecoveryState) : null,
31710
+ cliType,
31711
+ workspace,
31712
+ cliArgs: Array.isArray(record2.meta?.cliArgs) ? record2.meta.cliArgs : [],
31713
+ providerSessionId: typeof record2.meta?.providerSessionId === "string" ? String(record2.meta.providerSessionId) : void 0
31714
+ };
31715
+ }
31425
31716
  var fs9, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter;
31426
31717
  var init_router = __esm({
31427
31718
  "../../oss/packages/daemon-core/src/commands/router.ts"() {
@@ -31525,6 +31816,90 @@ var init_router = __esm({
31525
31816
  return { success: false, error: e.message };
31526
31817
  }
31527
31818
  }
31819
+ case "session_host_get_diagnostics": {
31820
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31821
+ const diagnostics = await this.deps.sessionHostControl.getDiagnostics({
31822
+ includeSessions: args?.includeSessions !== false,
31823
+ limit: Number(args?.limit) || void 0
31824
+ });
31825
+ return { success: true, diagnostics };
31826
+ }
31827
+ case "session_host_list_sessions": {
31828
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31829
+ const sessions = await this.deps.sessionHostControl.listSessions();
31830
+ return { success: true, sessions };
31831
+ }
31832
+ case "session_host_stop_session": {
31833
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31834
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
31835
+ if (!sessionId) return { success: false, error: "sessionId required" };
31836
+ const record2 = await this.deps.sessionHostControl.stopSession(sessionId);
31837
+ return { success: true, record: record2 };
31838
+ }
31839
+ case "session_host_resume_session": {
31840
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31841
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
31842
+ if (!sessionId) return { success: false, error: "sessionId required" };
31843
+ const record2 = await this.deps.sessionHostControl.resumeSession(sessionId);
31844
+ const hosted = toHostedCliRuntimeDescriptor(record2);
31845
+ if (hosted) {
31846
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
31847
+ }
31848
+ return { success: true, record: record2 };
31849
+ }
31850
+ case "session_host_restart_session": {
31851
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31852
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
31853
+ if (!sessionId) return { success: false, error: "sessionId required" };
31854
+ const record2 = await this.deps.sessionHostControl.restartSession(sessionId);
31855
+ const hosted = toHostedCliRuntimeDescriptor(record2);
31856
+ if (hosted) {
31857
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
31858
+ }
31859
+ return { success: true, record: record2 };
31860
+ }
31861
+ case "session_host_send_signal": {
31862
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31863
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
31864
+ const signal = typeof args?.signal === "string" ? args.signal : "";
31865
+ if (!sessionId) return { success: false, error: "sessionId required" };
31866
+ if (!signal) return { success: false, error: "signal required" };
31867
+ const record2 = await this.deps.sessionHostControl.sendSignal(sessionId, signal);
31868
+ return { success: true, record: record2 };
31869
+ }
31870
+ case "session_host_force_detach_client": {
31871
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31872
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
31873
+ const clientId = typeof args?.clientId === "string" ? args.clientId : "";
31874
+ if (!sessionId) return { success: false, error: "sessionId required" };
31875
+ if (!clientId) return { success: false, error: "clientId required" };
31876
+ const record2 = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
31877
+ return { success: true, record: record2 };
31878
+ }
31879
+ case "session_host_acquire_write": {
31880
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31881
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
31882
+ const clientId = typeof args?.clientId === "string" ? args.clientId : "";
31883
+ const ownerType = args?.ownerType === "agent" ? "agent" : "user";
31884
+ if (!sessionId) return { success: false, error: "sessionId required" };
31885
+ if (!clientId) return { success: false, error: "clientId required" };
31886
+ const record2 = await this.deps.sessionHostControl.acquireWrite({
31887
+ sessionId,
31888
+ clientId,
31889
+ ownerType,
31890
+ force: args?.force !== false
31891
+ });
31892
+ return { success: true, record: record2 };
31893
+ }
31894
+ case "session_host_release_write": {
31895
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
31896
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
31897
+ const clientId = typeof args?.clientId === "string" ? args.clientId : "";
31898
+ if (!sessionId) return { success: false, error: "sessionId required" };
31899
+ if (!clientId) return { success: false, error: "clientId required" };
31900
+ const record2 = await this.deps.sessionHostControl.releaseWrite({ sessionId, clientId });
31901
+ return { success: true, record: record2 };
31902
+ }
31528
31903
  case "list_saved_sessions": {
31529
31904
  const providerType = typeof args?.providerType === "string" ? args.providerType.trim() : typeof args?.agentType === "string" ? args.agentType.trim() : "";
31530
31905
  const kind = args?.kind === "acp" ? "acp" : "cli";
@@ -31583,6 +31958,12 @@ var init_router = __esm({
31583
31958
  if (!ideType) throw new Error("ideType required");
31584
31959
  const killProcess = args?.killProcess !== false;
31585
31960
  await this.stopIde(ideType, killProcess);
31961
+ try {
31962
+ const results = await detectIDEs(this.deps.providerLoader);
31963
+ this.deps.detectedIdes.value = results;
31964
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
31965
+ } catch {
31966
+ }
31586
31967
  return { success: true, ideType, stopped: true, processKilled: killProcess };
31587
31968
  }
31588
31969
  // ─── IDE restart ───
@@ -31625,6 +32006,12 @@ var init_router = __esm({
31625
32006
  }
31626
32007
  }
31627
32008
  this.deps.onIdeConnected?.();
32009
+ try {
32010
+ const results = await detectIDEs(this.deps.providerLoader);
32011
+ this.deps.detectedIdes.value = results;
32012
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
32013
+ } catch {
32014
+ }
31628
32015
  if (result.success && resolvedWorkspace) {
31629
32016
  try {
31630
32017
  const next = appendRecentActivity(loadState(), {
@@ -31652,8 +32039,9 @@ var init_router = __esm({
31652
32039
  }
31653
32040
  // ─── Detect IDEs ───
31654
32041
  case "detect_ides": {
31655
- const results = await detectIDEs();
32042
+ const results = await detectIDEs(this.deps.providerLoader);
31656
32043
  this.deps.detectedIdes.value = results;
32044
+ this.deps.providerLoader.setIdeDetectionResults(results, true);
31657
32045
  return { success: true, detectedInfo: results };
31658
32046
  }
31659
32047
  // ─── Set User Name ───
@@ -32071,6 +32459,14 @@ var init_provider_adapter = __esm({
32071
32459
  hasScript(name) {
32072
32460
  return typeof this.provider.scripts?.[name] === "function";
32073
32461
  }
32462
+ parseMaybeJson(raw) {
32463
+ if (typeof raw !== "string") return raw;
32464
+ try {
32465
+ return JSON.parse(raw);
32466
+ } catch {
32467
+ return raw;
32468
+ }
32469
+ }
32074
32470
  summarizeRaw(raw) {
32075
32471
  try {
32076
32472
  if (typeof raw === "string") return raw.replace(/\s+/g, " ").trim().slice(0, 240);
@@ -32131,12 +32527,30 @@ var init_provider_adapter = __esm({
32131
32527
  }
32132
32528
  }
32133
32529
  async sendMessage(evaluate, text) {
32134
- const script = this.callScript("sendMessage", text);
32530
+ const params = { message: text };
32531
+ const script = this.callScript("sendMessage", params) || this.callScript("sendMessage", text);
32135
32532
  if (!script) throw new Error(`[${this.agentName}] sendMessage script not available`);
32136
32533
  const result = await evaluate(script);
32137
32534
  if (result && typeof result === "string" && result.startsWith("error:")) {
32138
32535
  throw new Error(`[${this.agentName}] sendMessage failed: ${result}`);
32139
32536
  }
32537
+ const parsed = this.parseMaybeJson(result);
32538
+ if (parsed === true) return;
32539
+ if (typeof parsed === "string") {
32540
+ const normalized = parsed.trim().toLowerCase();
32541
+ if (normalized === "ok" || normalized === "sent" || normalized === "success" || normalized === "true") {
32542
+ return;
32543
+ }
32544
+ }
32545
+ if (parsed && typeof parsed === "object") {
32546
+ if (parsed.sent === true || parsed.success === true || parsed.ok === true || parsed.submitted === true || parsed.dispatched === true) {
32547
+ return;
32548
+ }
32549
+ if (typeof parsed.error === "string" && parsed.error.trim()) {
32550
+ throw new Error(`[${this.agentName}] sendMessage failed: ${parsed.error}`);
32551
+ }
32552
+ }
32553
+ throw new Error(`[${this.agentName}] sendMessage was not confirmed`);
32140
32554
  }
32141
32555
  async resolveAction(evaluate, action, button) {
32142
32556
  const script = this.callScript("resolveAction", { action, button });
@@ -32159,7 +32573,10 @@ var init_provider_adapter = __esm({
32159
32573
  const raw = await evaluate(script, 1e4);
32160
32574
  const data = typeof raw === "string" ? JSON.parse(raw) : raw;
32161
32575
  if (data?.error) return [];
32162
- return Array.isArray(data) ? data : [];
32576
+ if (Array.isArray(data)) return data;
32577
+ if (Array.isArray(data?.sessions)) return data.sessions;
32578
+ if (Array.isArray(data?.chats)) return data.chats;
32579
+ return [];
32163
32580
  } catch {
32164
32581
  return [];
32165
32582
  }
@@ -32167,7 +32584,17 @@ var init_provider_adapter = __esm({
32167
32584
  async switchSession(evaluate, sessionId) {
32168
32585
  const script = this.callScript("switchSession", sessionId);
32169
32586
  if (!script) return false;
32170
- return await evaluate(script, 1e4) === true;
32587
+ const raw = await evaluate(script, 1e4);
32588
+ const data = this.parseMaybeJson(raw);
32589
+ if (data === true) return true;
32590
+ if (typeof data === "string") {
32591
+ const normalized = data.trim().toLowerCase();
32592
+ return normalized === "true" || normalized === "ok" || normalized === "switched" || normalized === "success";
32593
+ }
32594
+ if (data && typeof data === "object") {
32595
+ return data.switched === true || data.success === true || data.ok === true;
32596
+ }
32597
+ return false;
32171
32598
  }
32172
32599
  async focusEditor(evaluate) {
32173
32600
  const script = this.callScript("focusEditor");
@@ -32937,7 +33364,7 @@ function checkPathExists2(paths) {
32937
33364
  for (const p of paths) {
32938
33365
  if (p.includes("*")) {
32939
33366
  const home = os17.homedir();
32940
- const resolved = p.replace(/\*/g, home.split(path14.sep).pop() || "");
33367
+ const resolved = p.replace(/\*/g, home.split(path16.sep).pop() || "");
32941
33368
  if (fs10.existsSync(resolved)) return resolved;
32942
33369
  } else {
32943
33370
  if (fs10.existsSync(p)) return p;
@@ -32947,7 +33374,7 @@ function checkPathExists2(paths) {
32947
33374
  }
32948
33375
  function getMacAppVersion(appPath) {
32949
33376
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
32950
- const plistPath = path14.join(appPath, "Contents", "Info.plist");
33377
+ const plistPath = path16.join(appPath, "Contents", "Info.plist");
32951
33378
  if (!fs10.existsSync(plistPath)) return null;
32952
33379
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
32953
33380
  return raw || null;
@@ -32974,7 +33401,7 @@ async function detectAllVersions(loader, archive) {
32974
33401
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
32975
33402
  let resolvedBin = cliBin;
32976
33403
  if (!resolvedBin && appPath && currentOs === "darwin") {
32977
- const bundled = path14.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
33404
+ const bundled = path16.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
32978
33405
  if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
32979
33406
  }
32980
33407
  info.installed = !!(appPath || resolvedBin);
@@ -33011,16 +33438,16 @@ async function detectAllVersions(loader, archive) {
33011
33438
  }
33012
33439
  return results;
33013
33440
  }
33014
- var fs10, path14, os17, import_child_process9, import_os3, ARCHIVE_PATH, MAX_ENTRIES_PER_PROVIDER, VersionArchive;
33441
+ var fs10, path16, os17, import_child_process9, import_os3, ARCHIVE_PATH, MAX_ENTRIES_PER_PROVIDER, VersionArchive;
33015
33442
  var init_version_archive = __esm({
33016
33443
  "../../oss/packages/daemon-core/src/providers/version-archive.ts"() {
33017
33444
  "use strict";
33018
33445
  fs10 = __toESM(require("fs"));
33019
- path14 = __toESM(require("path"));
33446
+ path16 = __toESM(require("path"));
33020
33447
  os17 = __toESM(require("os"));
33021
33448
  import_child_process9 = require("child_process");
33022
33449
  import_os3 = require("os");
33023
- ARCHIVE_PATH = path14.join(os17.homedir(), ".adhdev", "version-history.json");
33450
+ ARCHIVE_PATH = path16.join(os17.homedir(), ".adhdev", "version-history.json");
33024
33451
  MAX_ENTRIES_PER_PROVIDER = 20;
33025
33452
  VersionArchive = class {
33026
33453
  history = {};
@@ -33067,7 +33494,7 @@ var init_version_archive = __esm({
33067
33494
  }
33068
33495
  save() {
33069
33496
  try {
33070
- fs10.mkdirSync(path14.dirname(ARCHIVE_PATH), { recursive: true });
33497
+ fs10.mkdirSync(path16.dirname(ARCHIVE_PATH), { recursive: true });
33071
33498
  fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
33072
33499
  } catch {
33073
33500
  }
@@ -33588,17 +34015,17 @@ async function handleScriptHints(ctx, type, _req, res) {
33588
34015
  return;
33589
34016
  }
33590
34017
  let scriptsPath = "";
33591
- const directScripts = path15.join(dir, "scripts.js");
34018
+ const directScripts = path17.join(dir, "scripts.js");
33592
34019
  if (fs11.existsSync(directScripts)) {
33593
34020
  scriptsPath = directScripts;
33594
34021
  } else {
33595
- const scriptsDir = path15.join(dir, "scripts");
34022
+ const scriptsDir = path17.join(dir, "scripts");
33596
34023
  if (fs11.existsSync(scriptsDir)) {
33597
34024
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
33598
- return fs11.statSync(path15.join(scriptsDir, d)).isDirectory();
34025
+ return fs11.statSync(path17.join(scriptsDir, d)).isDirectory();
33599
34026
  }).sort().reverse();
33600
34027
  for (const ver of versions) {
33601
- const p = path15.join(scriptsDir, ver, "scripts.js");
34028
+ const p = path17.join(scriptsDir, ver, "scripts.js");
33602
34029
  if (fs11.existsSync(p)) {
33603
34030
  scriptsPath = p;
33604
34031
  break;
@@ -34414,12 +34841,12 @@ async function handleDomContext(ctx, type, req, res) {
34414
34841
  ctx.json(res, 500, { error: `DOM context collection failed: ${e.message}` });
34415
34842
  }
34416
34843
  }
34417
- var fs11, path15;
34844
+ var fs11, path17;
34418
34845
  var init_dev_cdp_handlers = __esm({
34419
34846
  "../../oss/packages/daemon-core/src/daemon/dev-cdp-handlers.ts"() {
34420
34847
  "use strict";
34421
34848
  fs11 = __toESM(require("fs"));
34422
- path15 = __toESM(require("path"));
34849
+ path17 = __toESM(require("path"));
34423
34850
  init_logger();
34424
34851
  }
34425
34852
  });
@@ -34434,11 +34861,11 @@ function getCliFixtureDir(ctx, type) {
34434
34861
  if (!providerDir) {
34435
34862
  throw new Error(`Provider directory not found for '${type}'`);
34436
34863
  }
34437
- return path16.join(providerDir, "fixtures");
34864
+ return path18.join(providerDir, "fixtures");
34438
34865
  }
34439
34866
  function readCliFixture(ctx, type, name) {
34440
34867
  const fixtureDir = getCliFixtureDir(ctx, type);
34441
- const filePath = path16.join(fixtureDir, `${name}.json`);
34868
+ const filePath = path18.join(fixtureDir, `${name}.json`);
34442
34869
  if (!fs12.existsSync(filePath)) {
34443
34870
  throw new Error(`Fixture not found: ${filePath}`);
34444
34871
  }
@@ -34598,7 +35025,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
34598
35025
  return { target, instance, adapter };
34599
35026
  }
34600
35027
  function sleep(ms) {
34601
- return new Promise((resolve13) => setTimeout(resolve13, ms));
35028
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
34602
35029
  }
34603
35030
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
34604
35031
  const startedAt = Date.now();
@@ -35197,7 +35624,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
35197
35624
  },
35198
35625
  notes: typeof body?.notes === "string" ? body.notes : void 0
35199
35626
  };
35200
- const filePath = path16.join(fixtureDir, `${name}.json`);
35627
+ const filePath = path18.join(fixtureDir, `${name}.json`);
35201
35628
  fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
35202
35629
  ctx.json(res, 200, {
35203
35630
  saved: true,
@@ -35221,7 +35648,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
35221
35648
  return;
35222
35649
  }
35223
35650
  const fixtures = fs12.readdirSync(fixtureDir).filter((file2) => file2.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file2) => {
35224
- const fullPath = path16.join(fixtureDir, file2);
35651
+ const fullPath = path18.join(fixtureDir, file2);
35225
35652
  try {
35226
35653
  const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
35227
35654
  return {
@@ -35354,12 +35781,12 @@ async function handleCliRaw(ctx, req, res) {
35354
35781
  ctx.json(res, 500, { error: `Raw send failed: ${e.message}` });
35355
35782
  }
35356
35783
  }
35357
- var fs12, path16;
35784
+ var fs12, path18;
35358
35785
  var init_dev_cli_debug = __esm({
35359
35786
  "../../oss/packages/daemon-core/src/daemon/dev-cli-debug.ts"() {
35360
35787
  "use strict";
35361
35788
  fs12 = __toESM(require("fs"));
35362
- path16 = __toESM(require("path"));
35789
+ path18 = __toESM(require("path"));
35363
35790
  }
35364
35791
  });
35365
35792
 
@@ -35402,22 +35829,22 @@ function getLatestScriptVersionDir(scriptsDir) {
35402
35829
  if (!fs13.existsSync(scriptsDir)) return null;
35403
35830
  const versions = fs13.readdirSync(scriptsDir).filter((d) => {
35404
35831
  try {
35405
- return fs13.statSync(path17.join(scriptsDir, d)).isDirectory();
35832
+ return fs13.statSync(path19.join(scriptsDir, d)).isDirectory();
35406
35833
  } catch {
35407
35834
  return false;
35408
35835
  }
35409
35836
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
35410
35837
  if (versions.length === 0) return null;
35411
- return path17.join(scriptsDir, versions[0]);
35838
+ return path19.join(scriptsDir, versions[0]);
35412
35839
  }
35413
35840
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
35414
- const canonicalUserDir = path17.resolve(ctx.providerLoader.getUserProviderDir(category, type));
35415
- const desiredDir = requestedDir ? path17.resolve(requestedDir) : canonicalUserDir;
35416
- const upstreamRoot = path17.resolve(ctx.providerLoader.getUpstreamDir());
35417
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path17.sep}`)) {
35841
+ const canonicalUserDir = path19.resolve(ctx.providerLoader.getUserProviderDir(category, type));
35842
+ const desiredDir = requestedDir ? path19.resolve(requestedDir) : canonicalUserDir;
35843
+ const upstreamRoot = path19.resolve(ctx.providerLoader.getUpstreamDir());
35844
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path19.sep}`)) {
35418
35845
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
35419
35846
  }
35420
- if (path17.basename(desiredDir) !== type) {
35847
+ if (path19.basename(desiredDir) !== type) {
35421
35848
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
35422
35849
  }
35423
35850
  const sourceDir = ctx.findProviderDir(type);
@@ -35425,11 +35852,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
35425
35852
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
35426
35853
  }
35427
35854
  if (!fs13.existsSync(desiredDir)) {
35428
- fs13.mkdirSync(path17.dirname(desiredDir), { recursive: true });
35855
+ fs13.mkdirSync(path19.dirname(desiredDir), { recursive: true });
35429
35856
  fs13.cpSync(sourceDir, desiredDir, { recursive: true });
35430
35857
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
35431
35858
  }
35432
- const providerJson = path17.join(desiredDir, "provider.json");
35859
+ const providerJson = path19.join(desiredDir, "provider.json");
35433
35860
  if (!fs13.existsSync(providerJson)) {
35434
35861
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
35435
35862
  }
@@ -35452,13 +35879,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
35452
35879
  const refDir = ctx.findProviderDir(referenceType);
35453
35880
  if (!refDir || !fs13.existsSync(refDir)) return {};
35454
35881
  const referenceScripts = {};
35455
- const scriptsDir = path17.join(refDir, "scripts");
35882
+ const scriptsDir = path19.join(refDir, "scripts");
35456
35883
  const latestDir = getLatestScriptVersionDir(scriptsDir);
35457
35884
  if (!latestDir) return referenceScripts;
35458
35885
  for (const file2 of fs13.readdirSync(latestDir)) {
35459
35886
  if (!file2.endsWith(".js")) continue;
35460
35887
  try {
35461
- referenceScripts[file2] = fs13.readFileSync(path17.join(latestDir, file2), "utf-8");
35888
+ referenceScripts[file2] = fs13.readFileSync(path19.join(latestDir, file2), "utf-8");
35462
35889
  } catch {
35463
35890
  }
35464
35891
  }
@@ -35566,9 +35993,9 @@ async function handleAutoImplement(ctx, type, req, res) {
35566
35993
  });
35567
35994
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
35568
35995
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
35569
- const tmpDir = path17.join(os18.tmpdir(), "adhdev-autoimpl");
35996
+ const tmpDir = path19.join(os18.tmpdir(), "adhdev-autoimpl");
35570
35997
  if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
35571
- const promptFile = path17.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
35998
+ const promptFile = path19.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
35572
35999
  fs13.writeFileSync(promptFile, prompt, "utf-8");
35573
36000
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
35574
36001
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -35995,7 +36422,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
35995
36422
  setMode: "set_mode.js"
35996
36423
  };
35997
36424
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
35998
- const scriptsDir = path17.join(providerDir, "scripts");
36425
+ const scriptsDir = path19.join(providerDir, "scripts");
35999
36426
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
36000
36427
  if (latestScriptsDir) {
36001
36428
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -36006,7 +36433,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
36006
36433
  for (const file2 of fs13.readdirSync(latestScriptsDir)) {
36007
36434
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
36008
36435
  try {
36009
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
36436
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
36010
36437
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
36011
36438
  lines.push("```javascript");
36012
36439
  lines.push(content);
@@ -36023,7 +36450,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
36023
36450
  lines.push("");
36024
36451
  for (const file2 of refFiles) {
36025
36452
  try {
36026
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
36453
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
36027
36454
  lines.push(`### \`${file2}\` \u{1F512}`);
36028
36455
  lines.push("```javascript");
36029
36456
  lines.push(content);
@@ -36064,10 +36491,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
36064
36491
  lines.push("");
36065
36492
  }
36066
36493
  }
36067
- const docsDir = path17.join(providerDir, "../../docs");
36494
+ const docsDir = path19.join(providerDir, "../../docs");
36068
36495
  const loadGuide = (name) => {
36069
36496
  try {
36070
- const p = path17.join(docsDir, name);
36497
+ const p = path19.join(docsDir, name);
36071
36498
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
36072
36499
  } catch {
36073
36500
  }
@@ -36302,7 +36729,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
36302
36729
  parseApproval: "parse_approval.js"
36303
36730
  };
36304
36731
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
36305
- const scriptsDir = path17.join(providerDir, "scripts");
36732
+ const scriptsDir = path19.join(providerDir, "scripts");
36306
36733
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
36307
36734
  if (latestScriptsDir) {
36308
36735
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -36314,7 +36741,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
36314
36741
  if (!file2.endsWith(".js")) continue;
36315
36742
  if (!targetFileNames.has(file2)) continue;
36316
36743
  try {
36317
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
36744
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
36318
36745
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
36319
36746
  lines.push("```javascript");
36320
36747
  lines.push(content);
@@ -36330,7 +36757,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
36330
36757
  lines.push("");
36331
36758
  for (const file2 of refFiles) {
36332
36759
  try {
36333
- const content = fs13.readFileSync(path17.join(latestScriptsDir, file2), "utf-8");
36760
+ const content = fs13.readFileSync(path19.join(latestScriptsDir, file2), "utf-8");
36334
36761
  lines.push(`### \`${file2}\` \u{1F512}`);
36335
36762
  lines.push("```javascript");
36336
36763
  lines.push(content);
@@ -36363,10 +36790,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
36363
36790
  lines.push("");
36364
36791
  }
36365
36792
  }
36366
- const docsDir = path17.join(providerDir, "../../docs");
36793
+ const docsDir = path19.join(providerDir, "../../docs");
36367
36794
  const loadGuide = (name) => {
36368
36795
  try {
36369
- const p = path17.join(docsDir, name);
36796
+ const p = path19.join(docsDir, name);
36370
36797
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
36371
36798
  } catch {
36372
36799
  }
@@ -36678,12 +37105,12 @@ data: ${JSON.stringify(msg.data)}
36678
37105
  }
36679
37106
  }
36680
37107
  }
36681
- var fs13, path17, os18;
37108
+ var fs13, path19, os18;
36682
37109
  var init_dev_auto_implement = __esm({
36683
37110
  "../../oss/packages/daemon-core/src/daemon/dev-auto-implement.ts"() {
36684
37111
  "use strict";
36685
37112
  fs13 = __toESM(require("fs"));
36686
- path17 = __toESM(require("path"));
37113
+ path19 = __toESM(require("path"));
36687
37114
  os18 = __toESM(require("os"));
36688
37115
  init_dev_server();
36689
37116
  init_dev_cli_debug();
@@ -36691,13 +37118,13 @@ var init_dev_auto_implement = __esm({
36691
37118
  });
36692
37119
 
36693
37120
  // ../../oss/packages/daemon-core/src/daemon/dev-server.ts
36694
- var http2, fs14, path18, DEV_SERVER_PORT, DevServer;
37121
+ var http2, fs14, path20, DEV_SERVER_PORT, DevServer;
36695
37122
  var init_dev_server = __esm({
36696
37123
  "../../oss/packages/daemon-core/src/daemon/dev-server.ts"() {
36697
37124
  "use strict";
36698
37125
  http2 = __toESM(require("http"));
36699
37126
  fs14 = __toESM(require("fs"));
36700
- path18 = __toESM(require("path"));
37127
+ path20 = __toESM(require("path"));
36701
37128
  init_scaffold_template();
36702
37129
  init_version_archive();
36703
37130
  init_logger();
@@ -36801,8 +37228,8 @@ var init_dev_server = __esm({
36801
37228
  }
36802
37229
  getEndpointList() {
36803
37230
  return this.routes.map((r) => {
36804
- const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
36805
- return `${r.method.padEnd(5)} ${path23}`;
37231
+ const path25 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
37232
+ return `${r.method.padEnd(5)} ${path25}`;
36806
37233
  });
36807
37234
  }
36808
37235
  async start(port = DEV_SERVER_PORT) {
@@ -36833,15 +37260,15 @@ var init_dev_server = __esm({
36833
37260
  this.json(res, 500, { error: e.message });
36834
37261
  }
36835
37262
  });
36836
- return new Promise((resolve13, reject) => {
37263
+ return new Promise((resolve16, reject) => {
36837
37264
  this.server.listen(port, "127.0.0.1", () => {
36838
37265
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
36839
- resolve13();
37266
+ resolve16();
36840
37267
  });
36841
37268
  this.server.on("error", (e) => {
36842
37269
  if (e.code === "EADDRINUSE") {
36843
37270
  this.log(`Port ${port} in use, skipping dev server`);
36844
- resolve13();
37271
+ resolve16();
36845
37272
  } else {
36846
37273
  reject(e);
36847
37274
  }
@@ -36924,20 +37351,20 @@ var init_dev_server = __esm({
36924
37351
  child.stderr?.on("data", (d) => {
36925
37352
  stderr += d.toString().slice(0, 2e3);
36926
37353
  });
36927
- await new Promise((resolve13) => {
37354
+ await new Promise((resolve16) => {
36928
37355
  const timer = setTimeout(() => {
36929
37356
  child.kill();
36930
- resolve13();
37357
+ resolve16();
36931
37358
  }, 3e3);
36932
37359
  child.on("exit", () => {
36933
37360
  clearTimeout(timer);
36934
- resolve13();
37361
+ resolve16();
36935
37362
  });
36936
37363
  child.stdout?.once("data", () => {
36937
37364
  setTimeout(() => {
36938
37365
  child.kill();
36939
37366
  clearTimeout(timer);
36940
- resolve13();
37367
+ resolve16();
36941
37368
  }, 500);
36942
37369
  });
36943
37370
  });
@@ -37084,12 +37511,12 @@ var init_dev_server = __esm({
37084
37511
  // ─── DevConsole SPA ───
37085
37512
  getConsoleDistDir() {
37086
37513
  const candidates = [
37087
- path18.resolve(__dirname, "../../web-devconsole/dist"),
37088
- path18.resolve(__dirname, "../../../web-devconsole/dist"),
37089
- path18.join(process.cwd(), "packages/web-devconsole/dist")
37514
+ path20.resolve(__dirname, "../../web-devconsole/dist"),
37515
+ path20.resolve(__dirname, "../../../web-devconsole/dist"),
37516
+ path20.join(process.cwd(), "packages/web-devconsole/dist")
37090
37517
  ];
37091
37518
  for (const dir of candidates) {
37092
- if (fs14.existsSync(path18.join(dir, "index.html"))) return dir;
37519
+ if (fs14.existsSync(path20.join(dir, "index.html"))) return dir;
37093
37520
  }
37094
37521
  return null;
37095
37522
  }
@@ -37099,7 +37526,7 @@ var init_dev_server = __esm({
37099
37526
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
37100
37527
  return;
37101
37528
  }
37102
- const htmlPath = path18.join(distDir, "index.html");
37529
+ const htmlPath = path20.join(distDir, "index.html");
37103
37530
  try {
37104
37531
  const html = fs14.readFileSync(htmlPath, "utf-8");
37105
37532
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -37124,15 +37551,15 @@ var init_dev_server = __esm({
37124
37551
  this.json(res, 404, { error: "Not found" });
37125
37552
  return;
37126
37553
  }
37127
- const safePath = path18.normalize(pathname).replace(/^\.\.\//, "");
37128
- const filePath = path18.join(distDir, safePath);
37554
+ const safePath = path20.normalize(pathname).replace(/^\.\.\//, "");
37555
+ const filePath = path20.join(distDir, safePath);
37129
37556
  if (!filePath.startsWith(distDir)) {
37130
37557
  this.json(res, 403, { error: "Forbidden" });
37131
37558
  return;
37132
37559
  }
37133
37560
  try {
37134
37561
  const content = fs14.readFileSync(filePath);
37135
- const ext = path18.extname(filePath);
37562
+ const ext = path20.extname(filePath);
37136
37563
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
37137
37564
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
37138
37565
  res.end(content);
@@ -37245,9 +37672,9 @@ var init_dev_server = __esm({
37245
37672
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
37246
37673
  if (entry.isDirectory()) {
37247
37674
  files.push({ path: rel, size: 0, type: "dir" });
37248
- scan(path18.join(d, entry.name), rel);
37675
+ scan(path20.join(d, entry.name), rel);
37249
37676
  } else {
37250
- const stat4 = fs14.statSync(path18.join(d, entry.name));
37677
+ const stat4 = fs14.statSync(path20.join(d, entry.name));
37251
37678
  files.push({ path: rel, size: stat4.size, type: "file" });
37252
37679
  }
37253
37680
  }
@@ -37270,7 +37697,7 @@ var init_dev_server = __esm({
37270
37697
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
37271
37698
  return;
37272
37699
  }
37273
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
37700
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
37274
37701
  if (!fullPath.startsWith(dir)) {
37275
37702
  this.json(res, 403, { error: "Forbidden" });
37276
37703
  return;
@@ -37295,14 +37722,14 @@ var init_dev_server = __esm({
37295
37722
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
37296
37723
  return;
37297
37724
  }
37298
- const fullPath = path18.resolve(dir, path18.normalize(filePath));
37725
+ const fullPath = path20.resolve(dir, path20.normalize(filePath));
37299
37726
  if (!fullPath.startsWith(dir)) {
37300
37727
  this.json(res, 403, { error: "Forbidden" });
37301
37728
  return;
37302
37729
  }
37303
37730
  try {
37304
37731
  if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
37305
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
37732
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
37306
37733
  fs14.writeFileSync(fullPath, content, "utf-8");
37307
37734
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
37308
37735
  this.providerLoader.reload();
@@ -37319,7 +37746,7 @@ var init_dev_server = __esm({
37319
37746
  return;
37320
37747
  }
37321
37748
  for (const name of ["scripts.js", "provider.json"]) {
37322
- const p = path18.join(dir, name);
37749
+ const p = path20.join(dir, name);
37323
37750
  if (fs14.existsSync(p)) {
37324
37751
  const source = fs14.readFileSync(p, "utf-8");
37325
37752
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -37340,8 +37767,8 @@ var init_dev_server = __esm({
37340
37767
  this.json(res, 404, { error: `Provider not found: ${type}` });
37341
37768
  return;
37342
37769
  }
37343
- const target = fs14.existsSync(path18.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
37344
- const targetPath = path18.join(dir, target);
37770
+ const target = fs14.existsSync(path20.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
37771
+ const targetPath = path20.join(dir, target);
37345
37772
  try {
37346
37773
  if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
37347
37774
  fs14.writeFileSync(targetPath, source, "utf-8");
@@ -37446,14 +37873,14 @@ var init_dev_server = __esm({
37446
37873
  child.stderr?.on("data", (d) => {
37447
37874
  stderr += d.toString();
37448
37875
  });
37449
- await new Promise((resolve13) => {
37876
+ await new Promise((resolve16) => {
37450
37877
  const timer = setTimeout(() => {
37451
37878
  child.kill();
37452
- resolve13();
37879
+ resolve16();
37453
37880
  }, timeout);
37454
37881
  child.on("exit", () => {
37455
37882
  clearTimeout(timer);
37456
- resolve13();
37883
+ resolve16();
37457
37884
  });
37458
37885
  });
37459
37886
  const elapsed = Date.now() - start;
@@ -37501,7 +37928,7 @@ var init_dev_server = __esm({
37501
37928
  }
37502
37929
  let targetDir;
37503
37930
  targetDir = this.providerLoader.getUserProviderDir(category, type);
37504
- const jsonPath = path18.join(targetDir, "provider.json");
37931
+ const jsonPath = path20.join(targetDir, "provider.json");
37505
37932
  if (fs14.existsSync(jsonPath)) {
37506
37933
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
37507
37934
  return;
@@ -37513,8 +37940,8 @@ var init_dev_server = __esm({
37513
37940
  const createdFiles = ["provider.json"];
37514
37941
  if (result.files) {
37515
37942
  for (const [relPath, content] of Object.entries(result.files)) {
37516
- const fullPath = path18.join(targetDir, relPath);
37517
- fs14.mkdirSync(path18.dirname(fullPath), { recursive: true });
37943
+ const fullPath = path20.join(targetDir, relPath);
37944
+ fs14.mkdirSync(path20.dirname(fullPath), { recursive: true });
37518
37945
  fs14.writeFileSync(fullPath, content, "utf-8");
37519
37946
  createdFiles.push(relPath);
37520
37947
  }
@@ -37567,22 +37994,22 @@ var init_dev_server = __esm({
37567
37994
  if (!fs14.existsSync(scriptsDir)) return null;
37568
37995
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
37569
37996
  try {
37570
- return fs14.statSync(path18.join(scriptsDir, d)).isDirectory();
37997
+ return fs14.statSync(path20.join(scriptsDir, d)).isDirectory();
37571
37998
  } catch {
37572
37999
  return false;
37573
38000
  }
37574
38001
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
37575
38002
  if (versions.length === 0) return null;
37576
- return path18.join(scriptsDir, versions[0]);
38003
+ return path20.join(scriptsDir, versions[0]);
37577
38004
  }
37578
38005
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
37579
- const canonicalUserDir = path18.resolve(this.providerLoader.getUserProviderDir(category, type));
37580
- const desiredDir = requestedDir ? path18.resolve(requestedDir) : canonicalUserDir;
37581
- const upstreamRoot = path18.resolve(this.providerLoader.getUpstreamDir());
37582
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path18.sep}`)) {
38006
+ const canonicalUserDir = path20.resolve(this.providerLoader.getUserProviderDir(category, type));
38007
+ const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
38008
+ const upstreamRoot = path20.resolve(this.providerLoader.getUpstreamDir());
38009
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
37583
38010
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
37584
38011
  }
37585
- if (path18.basename(desiredDir) !== type) {
38012
+ if (path20.basename(desiredDir) !== type) {
37586
38013
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
37587
38014
  }
37588
38015
  const sourceDir = this.findProviderDir(type);
@@ -37590,11 +38017,11 @@ var init_dev_server = __esm({
37590
38017
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
37591
38018
  }
37592
38019
  if (!fs14.existsSync(desiredDir)) {
37593
- fs14.mkdirSync(path18.dirname(desiredDir), { recursive: true });
38020
+ fs14.mkdirSync(path20.dirname(desiredDir), { recursive: true });
37594
38021
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
37595
38022
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
37596
38023
  }
37597
- const providerJson = path18.join(desiredDir, "provider.json");
38024
+ const providerJson = path20.join(desiredDir, "provider.json");
37598
38025
  if (!fs14.existsSync(providerJson)) {
37599
38026
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
37600
38027
  }
@@ -37642,7 +38069,7 @@ var init_dev_server = __esm({
37642
38069
  setMode: "set_mode.js"
37643
38070
  };
37644
38071
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
37645
- const scriptsDir = path18.join(providerDir, "scripts");
38072
+ const scriptsDir = path20.join(providerDir, "scripts");
37646
38073
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
37647
38074
  if (latestScriptsDir) {
37648
38075
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -37653,7 +38080,7 @@ var init_dev_server = __esm({
37653
38080
  for (const file2 of fs14.readdirSync(latestScriptsDir)) {
37654
38081
  if (file2.endsWith(".js") && targetFileNames.has(file2)) {
37655
38082
  try {
37656
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
38083
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
37657
38084
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
37658
38085
  lines.push("```javascript");
37659
38086
  lines.push(content);
@@ -37670,7 +38097,7 @@ var init_dev_server = __esm({
37670
38097
  lines.push("");
37671
38098
  for (const file2 of refFiles) {
37672
38099
  try {
37673
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
38100
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
37674
38101
  lines.push(`### \`${file2}\` \u{1F512}`);
37675
38102
  lines.push("```javascript");
37676
38103
  lines.push(content);
@@ -37711,10 +38138,10 @@ var init_dev_server = __esm({
37711
38138
  lines.push("");
37712
38139
  }
37713
38140
  }
37714
- const docsDir = path18.join(providerDir, "../../docs");
38141
+ const docsDir = path20.join(providerDir, "../../docs");
37715
38142
  const loadGuide = (name) => {
37716
38143
  try {
37717
- const p = path18.join(docsDir, name);
38144
+ const p = path20.join(docsDir, name);
37718
38145
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
37719
38146
  } catch {
37720
38147
  }
@@ -37888,7 +38315,7 @@ var init_dev_server = __esm({
37888
38315
  parseApproval: "parse_approval.js"
37889
38316
  };
37890
38317
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
37891
- const scriptsDir = path18.join(providerDir, "scripts");
38318
+ const scriptsDir = path20.join(providerDir, "scripts");
37892
38319
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
37893
38320
  if (latestScriptsDir) {
37894
38321
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -37900,7 +38327,7 @@ var init_dev_server = __esm({
37900
38327
  if (!file2.endsWith(".js")) continue;
37901
38328
  if (!targetFileNames.has(file2)) continue;
37902
38329
  try {
37903
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
38330
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
37904
38331
  lines.push(`### \`${file2}\` \u270F\uFE0F EDIT`);
37905
38332
  lines.push("```javascript");
37906
38333
  lines.push(content);
@@ -37916,7 +38343,7 @@ var init_dev_server = __esm({
37916
38343
  lines.push("");
37917
38344
  for (const file2 of refFiles) {
37918
38345
  try {
37919
- const content = fs14.readFileSync(path18.join(latestScriptsDir, file2), "utf-8");
38346
+ const content = fs14.readFileSync(path20.join(latestScriptsDir, file2), "utf-8");
37920
38347
  lines.push(`### \`${file2}\` \u{1F512}`);
37921
38348
  lines.push("```javascript");
37922
38349
  lines.push(content);
@@ -37949,10 +38376,10 @@ var init_dev_server = __esm({
37949
38376
  lines.push("");
37950
38377
  }
37951
38378
  }
37952
- const docsDir = path18.join(providerDir, "../../docs");
38379
+ const docsDir = path20.join(providerDir, "../../docs");
37953
38380
  const loadGuide = (name) => {
37954
38381
  try {
37955
- const p = path18.join(docsDir, name);
38382
+ const p = path20.join(docsDir, name);
37956
38383
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
37957
38384
  } catch {
37958
38385
  }
@@ -38128,14 +38555,14 @@ data: ${JSON.stringify(msg.data)}
38128
38555
  res.end(JSON.stringify(data, null, 2));
38129
38556
  }
38130
38557
  async readBody(req) {
38131
- return new Promise((resolve13) => {
38558
+ return new Promise((resolve16) => {
38132
38559
  let body = "";
38133
38560
  req.on("data", (chunk) => body += chunk);
38134
38561
  req.on("end", () => {
38135
38562
  try {
38136
- resolve13(JSON.parse(body));
38563
+ resolve16(JSON.parse(body));
38137
38564
  } catch {
38138
- resolve13({});
38565
+ resolve16({});
38139
38566
  }
38140
38567
  });
38141
38568
  });
@@ -38471,6 +38898,7 @@ var init_session_host_transport = __esm({
38471
38898
  }
38472
38899
  }
38473
38900
  handleEvent(event) {
38901
+ if (!("sessionId" in event)) return;
38474
38902
  if (event.sessionId !== this.options.runtimeId) return;
38475
38903
  if ((event.type === "session_started" || event.type === "session_resumed") && typeof event.pid === "number") {
38476
38904
  this.currentPid = event.pid;
@@ -38546,7 +38974,10 @@ var init_session_host_transport = __esm({
38546
38974
  clientId: client.clientId,
38547
38975
  type: client.type,
38548
38976
  readOnly: client.readOnly
38549
- }))
38977
+ })),
38978
+ restoredFromStorage: record2.meta?.restoredFromStorage === true,
38979
+ recoveryState: typeof record2.meta?.runtimeRecoveryState === "string" ? String(record2.meta.runtimeRecoveryState) : null,
38980
+ recoveryError: typeof record2.meta?.runtimeRecoveryError === "string" ? String(record2.meta.runtimeRecoveryError) : null
38550
38981
  };
38551
38982
  }
38552
38983
  enqueue(action) {
@@ -38600,7 +39031,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
38600
39031
  const deadline = Date.now() + timeoutMs;
38601
39032
  while (Date.now() < deadline) {
38602
39033
  if (await canConnect(endpoint)) return;
38603
- await new Promise((resolve13) => setTimeout(resolve13, STARTUP_POLL_MS));
39034
+ await new Promise((resolve16) => setTimeout(resolve16, STARTUP_POLL_MS));
38604
39035
  }
38605
39036
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
38606
39037
  }
@@ -38691,10 +39122,10 @@ async function installExtension(ide, extension) {
38691
39122
  const buffer = Buffer.from(await res.arrayBuffer());
38692
39123
  const fs18 = await import("fs");
38693
39124
  fs18.writeFileSync(vsixPath, buffer);
38694
- return new Promise((resolve13) => {
39125
+ return new Promise((resolve16) => {
38695
39126
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
38696
39127
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, _stdout, stderr) => {
38697
- resolve13({
39128
+ resolve16({
38698
39129
  extensionId: extension.id,
38699
39130
  marketplaceId: extension.marketplaceId,
38700
39131
  success: !error48,
@@ -38707,11 +39138,11 @@ async function installExtension(ide, extension) {
38707
39138
  } catch (e) {
38708
39139
  }
38709
39140
  }
38710
- return new Promise((resolve13) => {
39141
+ return new Promise((resolve16) => {
38711
39142
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
38712
39143
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error48, stdout, stderr) => {
38713
39144
  if (error48) {
38714
- resolve13({
39145
+ resolve16({
38715
39146
  extensionId: extension.id,
38716
39147
  marketplaceId: extension.marketplaceId,
38717
39148
  success: false,
@@ -38719,7 +39150,7 @@ async function installExtension(ide, extension) {
38719
39150
  error: stderr || error48.message
38720
39151
  });
38721
39152
  } else {
38722
- resolve13({
39153
+ resolve16({
38723
39154
  extensionId: extension.id,
38724
39155
  marketplaceId: extension.marketplaceId,
38725
39156
  success: true,
@@ -38939,13 +39370,32 @@ async function initDaemonComponents(config2) {
38939
39370
  const detectedIdesRef = { value: [] };
38940
39371
  let agentStreamManager = null;
38941
39372
  let poller = null;
39373
+ const refreshProviderAvailability = async (providerType) => {
39374
+ const targetProvider = providerType ? providerLoader.getMeta(providerLoader.resolveAlias(providerType)) : null;
39375
+ const targetCategory = targetProvider?.category;
39376
+ if (!providerType || targetCategory === "cli" || targetCategory === "acp") {
39377
+ if (providerType && targetProvider) {
39378
+ const detected = await detectCLI(targetProvider.type, providerLoader, { includeVersion: false });
39379
+ providerLoader.setProviderAvailability(targetProvider.type, {
39380
+ installed: !!detected,
39381
+ detectedPath: detected?.path || null
39382
+ });
39383
+ } else {
39384
+ providerLoader.setCliDetectionResults(await detectCLIs(providerLoader, { includeVersion: false }), true);
39385
+ }
39386
+ }
39387
+ if (!providerType || targetCategory === "ide") {
39388
+ detectedIdesRef.value = await detectIDEs(providerLoader);
39389
+ providerLoader.setIdeDetectionResults(detectedIdesRef.value, true);
39390
+ }
39391
+ };
38942
39392
  const cliManager = new DaemonCliManager({
38943
39393
  ...config2.cliManagerDeps,
38944
39394
  getInstanceManager: () => instanceManager,
38945
39395
  getSessionRegistry: () => sessionRegistry
38946
39396
  }, providerLoader);
38947
39397
  LOG.info("Init", "Detecting IDEs...");
38948
- detectedIdesRef.value = await detectIDEs();
39398
+ await refreshProviderAvailability();
38949
39399
  const installed = detectedIdesRef.value.filter((i) => i.installed);
38950
39400
  LOG.info("Init", `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(", ") || "none"}`);
38951
39401
  const cdpSetupContext = {
@@ -38985,7 +39435,11 @@ async function initDaemonComponents(config2) {
38985
39435
  adapters: cliManager.adapters,
38986
39436
  providerLoader,
38987
39437
  instanceManager,
38988
- sessionRegistry
39438
+ sessionRegistry,
39439
+ onProviderSettingChanged: async (providerType) => {
39440
+ await refreshProviderAvailability(providerType);
39441
+ config2.onStatusChange?.();
39442
+ }
38989
39443
  });
38990
39444
  agentStreamManager = new DaemonAgentStreamManager(
38991
39445
  LOG.forComponent("AgentStream").asLogFn(),
@@ -39008,6 +39462,7 @@ async function initDaemonComponents(config2) {
39008
39462
  onIdeConnected: () => poller?.start(),
39009
39463
  onStatusChange: config2.onStatusChange,
39010
39464
  onPostChatCommand: config2.onPostChatCommand,
39465
+ sessionHostControl: config2.sessionHostControl,
39011
39466
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn())
39012
39467
  });
39013
39468
  poller = new AgentStreamPoller({
@@ -39099,6 +39554,7 @@ var init_daemon_lifecycle = __esm({
39099
39554
  init_provider_instance_manager();
39100
39555
  init_dev_server();
39101
39556
  init_ide_detector();
39557
+ init_cli_detector();
39102
39558
  init_registry();
39103
39559
  init_logger();
39104
39560
  init_config();
@@ -39536,17 +39992,17 @@ function canPeerUsePrivilegedShareCommand(commandType, permission) {
39536
39992
  return false;
39537
39993
  }
39538
39994
  }
39539
- var fs15, path19, os19, import_node_module2, esmRequire, logFile, log, logDebug, DaemonP2PSender;
39995
+ var fs15, path21, os19, import_node_module2, esmRequire, logFile, log, logDebug, DaemonP2PSender;
39540
39996
  var init_daemon_p2p = __esm({
39541
39997
  "src/daemon-p2p.ts"() {
39542
39998
  "use strict";
39543
39999
  fs15 = __toESM(require("fs"));
39544
40000
  init_src();
39545
- path19 = __toESM(require("path"));
40001
+ path21 = __toESM(require("path"));
39546
40002
  os19 = __toESM(require("os"));
39547
40003
  import_node_module2 = require("module");
39548
40004
  esmRequire = (0, import_node_module2.createRequire)(__filename);
39549
- logFile = path19.join(os19.tmpdir(), "adhdev_daemon_p2p.log");
40005
+ logFile = path21.join(os19.tmpdir(), "adhdev_daemon_p2p.log");
39550
40006
  log = (msg) => {
39551
40007
  LOG.info("P2P", `[${(/* @__PURE__ */ new Date()).toISOString()}] [P2P] ${msg}`);
39552
40008
  };
@@ -39614,15 +40070,15 @@ ${e?.stack || ""}`);
39614
40070
  const prebuildKey = `${platform11}-${arch3}`;
39615
40071
  try {
39616
40072
  const candidates = [
39617
- path19.join(__dirname, "node_modules", "node-datachannel"),
39618
- path19.join(__dirname, "..", "node_modules", "node-datachannel"),
39619
- path19.join(__dirname, "..", "..", "node_modules", "node-datachannel")
40073
+ path21.join(__dirname, "node_modules", "node-datachannel"),
40074
+ path21.join(__dirname, "..", "node_modules", "node-datachannel"),
40075
+ path21.join(__dirname, "..", "..", "node_modules", "node-datachannel")
39620
40076
  ];
39621
40077
  for (const candidate of candidates) {
39622
- const prebuildPath = path19.join(candidate, "prebuilds", prebuildKey, "node_datachannel.node");
40078
+ const prebuildPath = path21.join(candidate, "prebuilds", prebuildKey, "node_datachannel.node");
39623
40079
  if (fs15.existsSync(prebuildPath)) {
39624
- const targetDir = path19.join(candidate, "build", "Release");
39625
- const targetPath = path19.join(targetDir, "node_datachannel.node");
40080
+ const targetDir = path21.join(candidate, "build", "Release");
40081
+ const targetPath = path21.join(targetDir, "node_datachannel.node");
39626
40082
  fs15.mkdirSync(targetDir, { recursive: true });
39627
40083
  fs15.copyFileSync(prebuildPath, targetPath);
39628
40084
  try {
@@ -39705,13 +40161,13 @@ ${e?.stack || ""}`);
39705
40161
  } catch {
39706
40162
  }
39707
40163
  const http3 = esmRequire("https");
39708
- const data = await new Promise((resolve13, reject) => {
40164
+ const data = await new Promise((resolve16, reject) => {
39709
40165
  const req = http3.get(`${serverUrl}/api/v1/turn/credentials`, {
39710
40166
  headers: { "Authorization": `Bearer ${token}` }
39711
40167
  }, (res) => {
39712
40168
  let d = "";
39713
40169
  res.on("data", (c) => d += c);
39714
- res.on("end", () => resolve13(d));
40170
+ res.on("end", () => resolve16(d));
39715
40171
  });
39716
40172
  req.on("error", reject);
39717
40173
  req.setTimeout(5e3, () => {
@@ -40402,22 +40858,22 @@ var require_filesystem = __commonJS({
40402
40858
  var LDD_PATH = "/usr/bin/ldd";
40403
40859
  var SELF_PATH = "/proc/self/exe";
40404
40860
  var MAX_LENGTH = 2048;
40405
- var readFileSync17 = (path23) => {
40406
- const fd = fs18.openSync(path23, "r");
40861
+ var readFileSync17 = (path25) => {
40862
+ const fd = fs18.openSync(path25, "r");
40407
40863
  const buffer = Buffer.alloc(MAX_LENGTH);
40408
40864
  const bytesRead = fs18.readSync(fd, buffer, 0, MAX_LENGTH, 0);
40409
40865
  fs18.close(fd, () => {
40410
40866
  });
40411
40867
  return buffer.subarray(0, bytesRead);
40412
40868
  };
40413
- var readFile = (path23) => new Promise((resolve13, reject) => {
40414
- fs18.open(path23, "r", (err, fd) => {
40869
+ var readFile = (path25) => new Promise((resolve16, reject) => {
40870
+ fs18.open(path25, "r", (err, fd) => {
40415
40871
  if (err) {
40416
40872
  reject(err);
40417
40873
  } else {
40418
40874
  const buffer = Buffer.alloc(MAX_LENGTH);
40419
40875
  fs18.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
40420
- resolve13(buffer.subarray(0, bytesRead));
40876
+ resolve16(buffer.subarray(0, bytesRead));
40421
40877
  fs18.close(fd, () => {
40422
40878
  });
40423
40879
  });
@@ -40485,10 +40941,10 @@ var require_detect_libc = __commonJS({
40485
40941
  var commandOut = "";
40486
40942
  var safeCommand = () => {
40487
40943
  if (!commandOut) {
40488
- return new Promise((resolve13) => {
40944
+ return new Promise((resolve16) => {
40489
40945
  childProcess.exec(command, (err, out) => {
40490
40946
  commandOut = err ? " " : out;
40491
- resolve13(commandOut);
40947
+ resolve16(commandOut);
40492
40948
  });
40493
40949
  });
40494
40950
  }
@@ -40530,11 +40986,11 @@ var require_detect_libc = __commonJS({
40530
40986
  }
40531
40987
  return null;
40532
40988
  };
40533
- var familyFromInterpreterPath = (path23) => {
40534
- if (path23) {
40535
- if (path23.includes("/ld-musl-")) {
40989
+ var familyFromInterpreterPath = (path25) => {
40990
+ if (path25) {
40991
+ if (path25.includes("/ld-musl-")) {
40536
40992
  return MUSL;
40537
- } else if (path23.includes("/ld-linux-")) {
40993
+ } else if (path25.includes("/ld-linux-")) {
40538
40994
  return GLIBC;
40539
40995
  }
40540
40996
  }
@@ -40581,8 +41037,8 @@ var require_detect_libc = __commonJS({
40581
41037
  cachedFamilyInterpreter = null;
40582
41038
  try {
40583
41039
  const selfContent = await readFile(SELF_PATH);
40584
- const path23 = interpreterPath(selfContent);
40585
- cachedFamilyInterpreter = familyFromInterpreterPath(path23);
41040
+ const path25 = interpreterPath(selfContent);
41041
+ cachedFamilyInterpreter = familyFromInterpreterPath(path25);
40586
41042
  } catch (e) {
40587
41043
  }
40588
41044
  return cachedFamilyInterpreter;
@@ -40594,8 +41050,8 @@ var require_detect_libc = __commonJS({
40594
41050
  cachedFamilyInterpreter = null;
40595
41051
  try {
40596
41052
  const selfContent = readFileSync17(SELF_PATH);
40597
- const path23 = interpreterPath(selfContent);
40598
- cachedFamilyInterpreter = familyFromInterpreterPath(path23);
41053
+ const path25 = interpreterPath(selfContent);
41054
+ cachedFamilyInterpreter = familyFromInterpreterPath(path25);
40599
41055
  } catch (e) {
40600
41056
  }
40601
41057
  return cachedFamilyInterpreter;
@@ -42314,18 +42770,18 @@ var require_sharp = __commonJS({
42314
42770
  `@img/sharp-${runtimePlatform}/sharp.node`,
42315
42771
  "@img/sharp-wasm32/sharp.node"
42316
42772
  ];
42317
- var path23;
42773
+ var path25;
42318
42774
  var sharp;
42319
42775
  var errors = [];
42320
- for (path23 of paths) {
42776
+ for (path25 of paths) {
42321
42777
  try {
42322
- sharp = require(path23);
42778
+ sharp = require(path25);
42323
42779
  break;
42324
42780
  } catch (err) {
42325
42781
  errors.push(err);
42326
42782
  }
42327
42783
  }
42328
- if (sharp && path23.startsWith("@img/sharp-linux-x64") && !sharp._isUsingX64V2()) {
42784
+ if (sharp && path25.startsWith("@img/sharp-linux-x64") && !sharp._isUsingX64V2()) {
42329
42785
  const err = new Error("Prebuilt binaries for linux-x64 require v2 microarchitecture");
42330
42786
  err.code = "Unsupported CPU";
42331
42787
  errors.push(err);
@@ -43168,14 +43624,14 @@ var require_input = __commonJS({
43168
43624
  return this;
43169
43625
  } else {
43170
43626
  if (this._isStreamInput()) {
43171
- return new Promise((resolve13, reject) => {
43627
+ return new Promise((resolve16, reject) => {
43172
43628
  const finished = () => {
43173
43629
  this._flattenBufferIn();
43174
43630
  sharp.metadata(this.options, (err, metadata2) => {
43175
43631
  if (err) {
43176
43632
  reject(is.nativeError(err, stack));
43177
43633
  } else {
43178
- resolve13(metadata2);
43634
+ resolve16(metadata2);
43179
43635
  }
43180
43636
  });
43181
43637
  };
@@ -43186,12 +43642,12 @@ var require_input = __commonJS({
43186
43642
  }
43187
43643
  });
43188
43644
  } else {
43189
- return new Promise((resolve13, reject) => {
43645
+ return new Promise((resolve16, reject) => {
43190
43646
  sharp.metadata(this.options, (err, metadata2) => {
43191
43647
  if (err) {
43192
43648
  reject(is.nativeError(err, stack));
43193
43649
  } else {
43194
- resolve13(metadata2);
43650
+ resolve16(metadata2);
43195
43651
  }
43196
43652
  });
43197
43653
  });
@@ -43224,25 +43680,25 @@ var require_input = __commonJS({
43224
43680
  return this;
43225
43681
  } else {
43226
43682
  if (this._isStreamInput()) {
43227
- return new Promise((resolve13, reject) => {
43683
+ return new Promise((resolve16, reject) => {
43228
43684
  this.on("finish", function() {
43229
43685
  this._flattenBufferIn();
43230
43686
  sharp.stats(this.options, (err, stats2) => {
43231
43687
  if (err) {
43232
43688
  reject(is.nativeError(err, stack));
43233
43689
  } else {
43234
- resolve13(stats2);
43690
+ resolve16(stats2);
43235
43691
  }
43236
43692
  });
43237
43693
  });
43238
43694
  });
43239
43695
  } else {
43240
- return new Promise((resolve13, reject) => {
43696
+ return new Promise((resolve16, reject) => {
43241
43697
  sharp.stats(this.options, (err, stats2) => {
43242
43698
  if (err) {
43243
43699
  reject(is.nativeError(err, stack));
43244
43700
  } else {
43245
- resolve13(stats2);
43701
+ resolve16(stats2);
43246
43702
  }
43247
43703
  });
43248
43704
  });
@@ -45234,15 +45690,15 @@ var require_color = __commonJS({
45234
45690
  };
45235
45691
  }
45236
45692
  function wrapConversion(toModel, graph) {
45237
- const path23 = [graph[toModel].parent, toModel];
45693
+ const path25 = [graph[toModel].parent, toModel];
45238
45694
  let fn = conversions_default[graph[toModel].parent][toModel];
45239
45695
  let cur = graph[toModel].parent;
45240
45696
  while (graph[cur].parent) {
45241
- path23.unshift(graph[cur].parent);
45697
+ path25.unshift(graph[cur].parent);
45242
45698
  fn = link(conversions_default[graph[cur].parent][cur], fn);
45243
45699
  cur = graph[cur].parent;
45244
45700
  }
45245
- fn.conversion = path23;
45701
+ fn.conversion = path25;
45246
45702
  return fn;
45247
45703
  }
45248
45704
  function route(fromModel) {
@@ -45859,7 +46315,7 @@ var require_channel = __commonJS({
45859
46315
  var require_output = __commonJS({
45860
46316
  "../../node_modules/sharp/lib/output.js"(exports2, module2) {
45861
46317
  "use strict";
45862
- var path23 = require("path");
46318
+ var path25 = require("path");
45863
46319
  var is = require_is();
45864
46320
  var sharp = require_sharp();
45865
46321
  var formats = /* @__PURE__ */ new Map([
@@ -45890,9 +46346,9 @@ var require_output = __commonJS({
45890
46346
  let err;
45891
46347
  if (!is.string(fileOut)) {
45892
46348
  err = new Error("Missing output file path");
45893
- } else if (is.string(this.options.input.file) && path23.resolve(this.options.input.file) === path23.resolve(fileOut)) {
46349
+ } else if (is.string(this.options.input.file) && path25.resolve(this.options.input.file) === path25.resolve(fileOut)) {
45894
46350
  err = new Error("Cannot use same file for input and output");
45895
- } else if (jp2Regex.test(path23.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
46351
+ } else if (jp2Regex.test(path25.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
45896
46352
  err = errJp2Save();
45897
46353
  }
45898
46354
  if (err) {
@@ -46664,7 +47120,7 @@ var require_output = __commonJS({
46664
47120
  return this;
46665
47121
  } else {
46666
47122
  if (this._isStreamInput()) {
46667
- return new Promise((resolve13, reject) => {
47123
+ return new Promise((resolve16, reject) => {
46668
47124
  this.once("finish", () => {
46669
47125
  this._flattenBufferIn();
46670
47126
  sharp.pipeline(this.options, (err, data, info) => {
@@ -46672,24 +47128,24 @@ var require_output = __commonJS({
46672
47128
  reject(is.nativeError(err, stack));
46673
47129
  } else {
46674
47130
  if (this.options.resolveWithObject) {
46675
- resolve13({ data, info });
47131
+ resolve16({ data, info });
46676
47132
  } else {
46677
- resolve13(data);
47133
+ resolve16(data);
46678
47134
  }
46679
47135
  }
46680
47136
  });
46681
47137
  });
46682
47138
  });
46683
47139
  } else {
46684
- return new Promise((resolve13, reject) => {
47140
+ return new Promise((resolve16, reject) => {
46685
47141
  sharp.pipeline(this.options, (err, data, info) => {
46686
47142
  if (err) {
46687
47143
  reject(is.nativeError(err, stack));
46688
47144
  } else {
46689
47145
  if (this.options.resolveWithObject) {
46690
- resolve13({ data, info });
47146
+ resolve16({ data, info });
46691
47147
  } else {
46692
- resolve13(data);
47148
+ resolve16(data);
46693
47149
  }
46694
47150
  }
46695
47151
  });
@@ -47097,8 +47553,8 @@ function buildSessionHostEnv(baseEnv) {
47097
47553
  }
47098
47554
  function resolveSessionHostEntry() {
47099
47555
  const packagedCandidates = [
47100
- path20.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
47101
- path20.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
47556
+ path23.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
47557
+ path23.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
47102
47558
  ];
47103
47559
  for (const candidate of packagedCandidates) {
47104
47560
  if (fs16.existsSync(candidate)) {
@@ -47108,7 +47564,7 @@ function resolveSessionHostEntry() {
47108
47564
  return require.resolve("@adhdev/session-host-daemon");
47109
47565
  }
47110
47566
  function getSessionHostPidFile() {
47111
- return path20.join(os20.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
47567
+ return path23.join(os20.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
47112
47568
  }
47113
47569
  function killPid2(pid) {
47114
47570
  try {
@@ -47205,9 +47661,9 @@ function stopSessionHost() {
47205
47661
  async function ensureSessionHostReady2() {
47206
47662
  const spawnHost = () => {
47207
47663
  const entry = resolveSessionHostEntry();
47208
- const logDir = path20.join(os20.homedir(), ".adhdev", "logs");
47664
+ const logDir = path23.join(os20.homedir(), ".adhdev", "logs");
47209
47665
  fs16.mkdirSync(logDir, { recursive: true });
47210
- const logFd = fs16.openSync(path20.join(logDir, "session-host.log"), "a");
47666
+ const logFd = fs16.openSync(path23.join(logDir, "session-host.log"), "a");
47211
47667
  const child = (0, import_child_process11.spawn)(process.execPath, [entry], {
47212
47668
  detached: true,
47213
47669
  stdio: ["ignore", logFd, logFd],
@@ -47242,14 +47698,14 @@ async function ensureSessionHostReady2() {
47242
47698
  async function listHostedCliRuntimes2(endpoint) {
47243
47699
  return listHostedCliRuntimes(endpoint);
47244
47700
  }
47245
- var import_child_process11, fs16, os20, path20, SESSION_HOST_APP_NAME, SESSION_HOST_START_TIMEOUT_MS;
47701
+ var import_child_process11, fs16, os20, path23, SESSION_HOST_APP_NAME, SESSION_HOST_START_TIMEOUT_MS;
47246
47702
  var init_session_host = __esm({
47247
47703
  "src/session-host.ts"() {
47248
47704
  "use strict";
47249
47705
  import_child_process11 = require("child_process");
47250
47706
  fs16 = __toESM(require("fs"));
47251
47707
  os20 = __toESM(require("os"));
47252
- path20 = __toESM(require("path"));
47708
+ path23 = __toESM(require("path"));
47253
47709
  init_src();
47254
47710
  init_dist();
47255
47711
  SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
@@ -47257,6 +47713,151 @@ var init_session_host = __esm({
47257
47713
  }
47258
47714
  });
47259
47715
 
47716
+ // src/session-host-controller.ts
47717
+ var SessionHostController;
47718
+ var init_session_host_controller = __esm({
47719
+ "src/session-host-controller.ts"() {
47720
+ "use strict";
47721
+ init_src();
47722
+ init_dist();
47723
+ SessionHostController = class {
47724
+ constructor(endpoint, onEvent) {
47725
+ this.onEvent = onEvent;
47726
+ this.client = new SessionHostClient({ endpoint });
47727
+ }
47728
+ client;
47729
+ reconnectTimer = null;
47730
+ unsubscribe = null;
47731
+ started = false;
47732
+ async start() {
47733
+ if (this.started) return;
47734
+ this.started = true;
47735
+ this.unsubscribe = this.client.onEvent((event) => this.handleEvent(event));
47736
+ await this.ensureConnected();
47737
+ this.reconnectTimer = setInterval(() => {
47738
+ void this.ensureConnected();
47739
+ }, 2e3);
47740
+ }
47741
+ async stop() {
47742
+ this.started = false;
47743
+ if (this.reconnectTimer) {
47744
+ clearInterval(this.reconnectTimer);
47745
+ this.reconnectTimer = null;
47746
+ }
47747
+ try {
47748
+ this.unsubscribe?.();
47749
+ this.unsubscribe = null;
47750
+ } catch {
47751
+ }
47752
+ await this.client.close().catch(() => {
47753
+ });
47754
+ }
47755
+ async getDiagnostics(payload = {}) {
47756
+ return this.request({
47757
+ type: "get_host_diagnostics",
47758
+ payload
47759
+ });
47760
+ }
47761
+ async listSessions() {
47762
+ return this.request({
47763
+ type: "list_sessions",
47764
+ payload: {}
47765
+ });
47766
+ }
47767
+ async stopSession(sessionId) {
47768
+ return this.request({
47769
+ type: "stop_session",
47770
+ payload: { sessionId }
47771
+ });
47772
+ }
47773
+ async resumeSession(sessionId) {
47774
+ return this.request({
47775
+ type: "resume_session",
47776
+ payload: { sessionId }
47777
+ });
47778
+ }
47779
+ async restartSession(sessionId) {
47780
+ return this.request({
47781
+ type: "restart_session",
47782
+ payload: { sessionId }
47783
+ });
47784
+ }
47785
+ async sendSignal(sessionId, signal) {
47786
+ return this.request({
47787
+ type: "send_signal",
47788
+ payload: { sessionId, signal }
47789
+ });
47790
+ }
47791
+ async forceDetachClient(sessionId, clientId) {
47792
+ return this.request({
47793
+ type: "force_detach_client",
47794
+ payload: { sessionId, clientId }
47795
+ });
47796
+ }
47797
+ async acquireWrite(payload) {
47798
+ return this.request({
47799
+ type: "acquire_write",
47800
+ payload
47801
+ });
47802
+ }
47803
+ async releaseWrite(payload) {
47804
+ return this.request({
47805
+ type: "release_write",
47806
+ payload
47807
+ });
47808
+ }
47809
+ async request(request) {
47810
+ await this.ensureConnected();
47811
+ const response = await this.client.request(request);
47812
+ if (!response.success) {
47813
+ throw new Error(response.error || `Session host request failed: ${request.type}`);
47814
+ }
47815
+ return response.result ?? null;
47816
+ }
47817
+ async ensureConnected() {
47818
+ try {
47819
+ await this.client.connect();
47820
+ } catch (error48) {
47821
+ if (!this.started) return;
47822
+ LOG.debug("SessionHost", `connect failed: ${error48?.message || error48}`);
47823
+ }
47824
+ }
47825
+ handleEvent(event) {
47826
+ if (event.type === "host_log") {
47827
+ const line = event.entry.sessionId ? `${event.entry.message} (session=${event.entry.sessionId})` : event.entry.message;
47828
+ switch (event.entry.level) {
47829
+ case "debug":
47830
+ LOG.debug("SessionHost", line);
47831
+ break;
47832
+ case "warn":
47833
+ LOG.warn("SessionHost", line);
47834
+ break;
47835
+ case "error":
47836
+ LOG.error("SessionHost", line);
47837
+ break;
47838
+ default:
47839
+ LOG.info("SessionHost", line);
47840
+ break;
47841
+ }
47842
+ } else if (event.type === "request_trace") {
47843
+ const line = `${event.trace.type} ${event.trace.success ? "ok" : "failed"} ${event.trace.durationMs}ms` + (event.trace.sessionId ? ` session=${event.trace.sessionId}` : "") + (event.trace.error ? ` error=${event.trace.error}` : "");
47844
+ if (event.trace.success) LOG.debug("SessionHost", line);
47845
+ else LOG.warn("SessionHost", line);
47846
+ } else if (event.type === "runtime_transition") {
47847
+ const line = `${event.transition.action} ${event.transition.success === false ? "failed" : "ok"}` + (event.transition.lifecycle ? ` lifecycle=${event.transition.lifecycle}` : "") + (event.transition.detail ? ` detail=${event.transition.detail}` : "") + (event.transition.error ? ` error=${event.transition.error}` : "");
47848
+ if (event.transition.success === false) LOG.warn("SessionHost", `[${event.transition.sessionId}] ${line}`);
47849
+ else LOG.info("SessionHost", `[${event.transition.sessionId}] ${line}`);
47850
+ }
47851
+ try {
47852
+ this.onEvent?.(event);
47853
+ } catch (error48) {
47854
+ LOG.warn("SessionHost", `event callback failed: ${error48?.message || error48}`);
47855
+ }
47856
+ }
47857
+ };
47858
+ }
47859
+ });
47860
+
47260
47861
  // src/version.ts
47261
47862
  function resolvePackageVersion(options) {
47262
47863
  const injectedVersion = options?.injectedVersion || "unknown";
@@ -47268,18 +47869,18 @@ function resolvePackageVersion(options) {
47268
47869
  ];
47269
47870
  for (const p of possiblePaths) {
47270
47871
  try {
47271
- const data = JSON.parse((0, import_fs4.readFileSync)(p, "utf-8"));
47872
+ const data = JSON.parse((0, import_fs5.readFileSync)(p, "utf-8"));
47272
47873
  if (data.version) return data.version;
47273
47874
  } catch {
47274
47875
  }
47275
47876
  }
47276
47877
  return injectedVersion;
47277
47878
  }
47278
- var import_fs4, import_path3;
47879
+ var import_fs5, import_path3;
47279
47880
  var init_version = __esm({
47280
47881
  "src/version.ts"() {
47281
47882
  "use strict";
47282
- import_fs4 = require("fs");
47883
+ import_fs5 = require("fs");
47283
47884
  import_path3 = require("path");
47284
47885
  }
47285
47886
  });
@@ -47293,9 +47894,9 @@ __export(adhdev_daemon_exports, {
47293
47894
  stopDaemon: () => stopDaemon
47294
47895
  });
47295
47896
  function getDaemonPidFile() {
47296
- const dir = path21.join(os21.homedir(), ".adhdev");
47897
+ const dir = path24.join(os21.homedir(), ".adhdev");
47297
47898
  if (!fs17.existsSync(dir)) fs17.mkdirSync(dir, { recursive: true });
47298
- return path21.join(dir, "daemon.pid");
47899
+ return path24.join(dir, "daemon.pid");
47299
47900
  }
47300
47901
  function writeDaemonPid(pid) {
47301
47902
  fs17.writeFileSync(getDaemonPidFile(), String(pid), "utf-8");
@@ -47341,7 +47942,7 @@ function stopDaemon() {
47341
47942
  return false;
47342
47943
  }
47343
47944
  }
47344
- var os21, fs17, path21, import_http, import_ws3, import_chalk2, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
47945
+ var os21, fs17, path24, import_http, import_ws3, import_chalk2, pkgVersion, DANGEROUS_PATTERNS, AdhdevDaemon;
47345
47946
  var init_adhdev_daemon = __esm({
47346
47947
  "src/adhdev-daemon.ts"() {
47347
47948
  "use strict";
@@ -47351,14 +47952,15 @@ var init_adhdev_daemon = __esm({
47351
47952
  init_screenshot_controller();
47352
47953
  init_session_host();
47353
47954
  init_dist();
47955
+ init_session_host_controller();
47354
47956
  os21 = __toESM(require("os"));
47355
47957
  fs17 = __toESM(require("fs"));
47356
- path21 = __toESM(require("path"));
47958
+ path24 = __toESM(require("path"));
47357
47959
  import_http = require("http");
47358
47960
  import_ws3 = require("ws");
47359
47961
  import_chalk2 = __toESM(require("chalk"));
47360
47962
  init_version();
47361
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.25" });
47963
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.8.28" });
47362
47964
  DANGEROUS_PATTERNS = [
47363
47965
  /\brm\s+(-[a-z]*f|-[a-z]*r|--force|--recursive)/i,
47364
47966
  /\bsudo\b/i,
@@ -47381,6 +47983,7 @@ var init_adhdev_daemon = __esm({
47381
47983
  statusReporter = null;
47382
47984
  components = null;
47383
47985
  sessionHostEndpoint = null;
47986
+ sessionHostController = null;
47384
47987
  running = false;
47385
47988
  localPort;
47386
47989
  ideType = "unknown";
@@ -47431,6 +48034,11 @@ ${err?.stack || ""}`);
47431
48034
  }
47432
48035
  const sessionHostEndpoint = await ensureSessionHostReady2();
47433
48036
  this.sessionHostEndpoint = sessionHostEndpoint;
48037
+ this.sessionHostController = new SessionHostController(
48038
+ sessionHostEndpoint,
48039
+ (event) => this.broadcastLocalIpcMessage("daemon:session_host_event", event)
48040
+ );
48041
+ await this.sessionHostController.start();
47434
48042
  this.components = await initDaemonComponents({
47435
48043
  providerLogFn: LOG.forComponent("Provider").asLogFn(),
47436
48044
  cliManagerDeps: {
@@ -47468,6 +48076,7 @@ ${err?.stack || ""}`);
47468
48076
  setTimeout(() => this.statusReporter?.throttledReport(), 1e3);
47469
48077
  setTimeout(() => this.statusReporter?.throttledReport(), 3e3);
47470
48078
  },
48079
+ sessionHostControl: this.sessionHostController,
47471
48080
  getCdpLogFn: (ideType) => LOG.forComponent(`CDP:${ideType}`).asLogFn(),
47472
48081
  onCdpManagerSetup: (ideType) => {
47473
48082
  if (this.ideType === "unknown") this.ideType = ideType;
@@ -47782,7 +48391,7 @@ ${err?.stack || ""}`);
47782
48391
  this.localWss.emit("connection", ws, req);
47783
48392
  });
47784
48393
  });
47785
- await new Promise((resolve13, reject) => {
48394
+ await new Promise((resolve16, reject) => {
47786
48395
  const cleanup = () => {
47787
48396
  this.localHttpServer?.off("error", onError);
47788
48397
  this.localHttpServer?.off("listening", onListening);
@@ -47793,7 +48402,7 @@ ${err?.stack || ""}`);
47793
48402
  };
47794
48403
  const onListening = () => {
47795
48404
  cleanup();
47796
- resolve13();
48405
+ resolve16();
47797
48406
  };
47798
48407
  this.localHttpServer.once("error", onError);
47799
48408
  this.localHttpServer.once("listening", onListening);
@@ -47824,13 +48433,24 @@ ${err?.stack || ""}`);
47824
48433
  serverConnected: this.serverConn?.isConnected() ?? false,
47825
48434
  cdpConnected: (this.components?.cdpManagers.size || 0) > 0,
47826
48435
  localPort: this.localPort,
47827
- cliAgents
48436
+ cliAgents,
48437
+ sessionHostConnected: !!this.sessionHostController
47828
48438
  }
47829
48439
  }));
47830
48440
  } catch (error48) {
47831
48441
  LOG.warn("IPC", `Failed to send welcome: ${error48?.message || error48}`);
47832
48442
  }
47833
48443
  }
48444
+ broadcastLocalIpcMessage(type, payload) {
48445
+ const message = JSON.stringify({ type, payload });
48446
+ for (const client of this.localClients) {
48447
+ if (client.readyState !== import_ws3.WebSocket.OPEN) continue;
48448
+ try {
48449
+ client.send(message);
48450
+ } catch {
48451
+ }
48452
+ }
48453
+ }
47834
48454
  async handleLocalIpcMessage(ws, raw) {
47835
48455
  let msg;
47836
48456
  try {
@@ -47921,6 +48541,11 @@ ${err?.stack || ""}`);
47921
48541
  this.serverConn?.disconnect();
47922
48542
  } catch {
47923
48543
  }
48544
+ try {
48545
+ await this.sessionHostController?.stop();
48546
+ this.sessionHostController = null;
48547
+ } catch {
48548
+ }
47924
48549
  try {
47925
48550
  for (const client of this.localClients) {
47926
48551
  client.close();
@@ -47928,12 +48553,12 @@ ${err?.stack || ""}`);
47928
48553
  this.localClients.clear();
47929
48554
  this.localWss?.close();
47930
48555
  this.localWss = null;
47931
- await new Promise((resolve13) => {
48556
+ await new Promise((resolve16) => {
47932
48557
  if (!this.localHttpServer) {
47933
- resolve13();
48558
+ resolve16();
47934
48559
  return;
47935
48560
  }
47936
- this.localHttpServer.close(() => resolve13());
48561
+ this.localHttpServer.close(() => resolve16());
47937
48562
  this.localHttpServer = null;
47938
48563
  });
47939
48564
  } catch {