@adhdev/daemon-core 0.9.82-rc.139 → 0.9.82-rc.140

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -429,6 +429,7 @@ var config_exports = {};
429
429
  __export(config_exports, {
430
430
  generateMachineId: () => generateMachineId,
431
431
  getConfigDir: () => getConfigDir,
432
+ getDaemonDataDir: () => getDaemonDataDir,
432
433
  isSetupComplete: () => isSetupComplete,
433
434
  isStableMachineId: () => isStableMachineId,
434
435
  loadConfig: () => loadConfig,
@@ -541,6 +542,13 @@ function getConfigDir() {
541
542
  }
542
543
  return dir;
543
544
  }
545
+ function getDaemonDataDir() {
546
+ const dir = join2(getConfigDir(), "daemon");
547
+ if (!existsSync2(dir)) {
548
+ mkdirSync(dir, { recursive: true });
549
+ }
550
+ return dir;
551
+ }
544
552
  function getConfigPath() {
545
553
  return join2(getConfigDir(), "config.json");
546
554
  }
@@ -1297,8 +1305,8 @@ __export(mesh_ledger_exports, {
1297
1305
  readLedgerEntries: () => readLedgerEntries,
1298
1306
  readLedgerSlice: () => readLedgerSlice
1299
1307
  });
1300
- import { appendFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync5, statSync as statSync2, renameSync, writeFileSync as writeFileSync3 } from "fs";
1301
- import { join as join7 } from "path";
1308
+ import { appendFileSync, existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync6, statSync as statSync2, renameSync, writeFileSync as writeFileSync4 } from "fs";
1309
+ import { join as join8 } from "path";
1302
1310
  import { randomUUID as randomUUID4 } from "crypto";
1303
1311
  import { EventEmitter } from "events";
1304
1312
  function isIntentionalCleanupStopEntry(entry) {
@@ -1307,35 +1315,35 @@ function isIntentionalCleanupStopEntry(entry) {
1307
1315
  return payload.intentional === true && (payload.reason === "operator_cleanup" || payload.intentionalStopReason === "operator_cleanup" || payload.source === "mesh_cleanup_sessions" || payload.source === "mesh_remove_node");
1308
1316
  }
1309
1317
  function getLedgerDir() {
1310
- const dir = join7(getConfigDir(), LEDGER_DIR_NAME);
1311
- if (!existsSync7(dir)) {
1318
+ const dir = join8(getConfigDir(), LEDGER_DIR_NAME);
1319
+ if (!existsSync8(dir)) {
1312
1320
  mkdirSync3(dir, { recursive: true, mode: 448 });
1313
1321
  }
1314
1322
  return dir;
1315
1323
  }
1316
1324
  function getLedgerPath(meshId) {
1317
1325
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1318
- return join7(getLedgerDir(), `${safe}.jsonl`);
1326
+ return join8(getLedgerDir(), `${safe}.jsonl`);
1319
1327
  }
1320
1328
  function getRotatedPath(meshId, index) {
1321
1329
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1322
- return join7(getLedgerDir(), `${safe}.${index}.jsonl`);
1330
+ return join8(getLedgerDir(), `${safe}.${index}.jsonl`);
1323
1331
  }
1324
1332
  function getArchivePath(meshId) {
1325
1333
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1326
- return join7(getLedgerDir(), `${safe}.archive.jsonl`);
1334
+ return join8(getLedgerDir(), `${safe}.archive.jsonl`);
1327
1335
  }
1328
1336
  function getRotatedArchivePath(meshId, index) {
1329
1337
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1330
- return join7(getLedgerDir(), `${safe}.archive.${index}.jsonl`);
1338
+ return join8(getLedgerDir(), `${safe}.archive.${index}.jsonl`);
1331
1339
  }
1332
1340
  function getArchivedCountsPath(meshId) {
1333
1341
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1334
- return join7(getLedgerDir(), `${safe}.archived-counts.json`);
1342
+ return join8(getLedgerDir(), `${safe}.archived-counts.json`);
1335
1343
  }
1336
1344
  function rotateArchiveFile(meshId, archivePath) {
1337
1345
  let index = 1;
1338
- while (existsSync7(getRotatedArchivePath(meshId, index))) {
1346
+ while (existsSync8(getRotatedArchivePath(meshId, index))) {
1339
1347
  index++;
1340
1348
  if (index > 5) break;
1341
1349
  }
@@ -1349,9 +1357,9 @@ function rotateArchiveFile(meshId, archivePath) {
1349
1357
  }
1350
1358
  function readArchivedCounts(meshId) {
1351
1359
  const path28 = getArchivedCountsPath(meshId);
1352
- if (!existsSync7(path28)) return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
1360
+ if (!existsSync8(path28)) return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
1353
1361
  try {
1354
- return JSON.parse(readFileSync5(path28, "utf-8"));
1362
+ return JSON.parse(readFileSync6(path28, "utf-8"));
1355
1363
  } catch {
1356
1364
  return { taskCompleted: 0, taskFailed: 0, taskStalled: 0, recoveryAttempted: 0, totalArchived: 0, lastArchivedAt: "" };
1357
1365
  }
@@ -1367,7 +1375,7 @@ function updateArchivedCounts(meshId, archived) {
1367
1375
  counts.totalArchived += archived.length;
1368
1376
  counts.lastArchivedAt = (/* @__PURE__ */ new Date()).toISOString();
1369
1377
  try {
1370
- writeFileSync3(getArchivedCountsPath(meshId), JSON.stringify(counts), { encoding: "utf-8", mode: 384 });
1378
+ writeFileSync4(getArchivedCountsPath(meshId), JSON.stringify(counts), { encoding: "utf-8", mode: 384 });
1371
1379
  } catch {
1372
1380
  }
1373
1381
  }
@@ -1390,7 +1398,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
1390
1398
  }
1391
1399
  function compactLedger(meshId) {
1392
1400
  const filePath = getLedgerPath(meshId);
1393
- if (!existsSync7(filePath)) return { archivedCount: 0, retainedCount: 0 };
1401
+ if (!existsSync8(filePath)) return { archivedCount: 0, retainedCount: 0 };
1394
1402
  const cutoff = Date.now() - ARCHIVE_TERMINAL_OLDER_THAN_MS;
1395
1403
  const entries = readLedgerEntries(meshId);
1396
1404
  const keep = [];
@@ -1405,7 +1413,7 @@ function compactLedger(meshId) {
1405
1413
  if (archive.length === 0) return { archivedCount: 0, retainedCount: keep.length };
1406
1414
  const archivePath = getArchivePath(meshId);
1407
1415
  try {
1408
- if (existsSync7(archivePath) && statSync2(archivePath).size > 50 * 1024 * 1024) {
1416
+ if (existsSync8(archivePath) && statSync2(archivePath).size > 50 * 1024 * 1024) {
1409
1417
  rotateArchiveFile(meshId, archivePath);
1410
1418
  }
1411
1419
  const archiveLines = archive.map((e) => JSON.stringify(e)).join("\n") + "\n";
@@ -1418,7 +1426,7 @@ function compactLedger(meshId) {
1418
1426
  }
1419
1427
  try {
1420
1428
  const keepLines = keep.length ? keep.map((e) => JSON.stringify(e)).join("\n") + "\n" : "";
1421
- writeFileSync3(filePath, keepLines, { encoding: "utf-8", mode: 384 });
1429
+ writeFileSync4(filePath, keepLines, { encoding: "utf-8", mode: 384 });
1422
1430
  invalidateLedgerCache(meshId);
1423
1431
  } catch (e) {
1424
1432
  process.stderr.write(`[adhdev-mesh] Ledger compaction rewrite failed for mesh ${meshId}: ${e?.message || e}
@@ -1550,7 +1558,7 @@ function appendLedgerEntry(meshId, partial) {
1550
1558
  ...partial
1551
1559
  };
1552
1560
  const filePath = getLedgerPath(meshId);
1553
- if (existsSync7(filePath)) {
1561
+ if (existsSync8(filePath)) {
1554
1562
  try {
1555
1563
  const stat2 = statSync2(filePath);
1556
1564
  if (stat2.size >= MAX_FILE_SIZE_BYTES) {
@@ -1621,10 +1629,10 @@ function appendRemoteLedgerEntries(meshId, entries) {
1621
1629
  }
1622
1630
  function readLedgerFile(meshId) {
1623
1631
  const filePath = getLedgerPath(meshId);
1624
- if (!existsSync7(filePath)) return [];
1632
+ if (!existsSync8(filePath)) return [];
1625
1633
  let content;
1626
1634
  try {
1627
- content = readFileSync5(filePath, "utf-8");
1635
+ content = readFileSync6(filePath, "utf-8");
1628
1636
  } catch {
1629
1637
  return [];
1630
1638
  }
@@ -1825,7 +1833,7 @@ function getSessionRecoveryContext(meshId, opts) {
1825
1833
  }
1826
1834
  function rotateLedgerFile(meshId, currentPath) {
1827
1835
  let index = 1;
1828
- while (existsSync7(getRotatedPath(meshId, index))) {
1836
+ while (existsSync8(getRotatedPath(meshId, index))) {
1829
1837
  index++;
1830
1838
  if (index > 10) break;
1831
1839
  }
@@ -1862,8 +1870,8 @@ var init_mesh_ledger = __esm({
1862
1870
  });
1863
1871
 
1864
1872
  // src/mesh/beads-db.ts
1865
- import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync6, statSync as statSync3 } from "fs";
1866
- import { dirname as dirname2, join as join8 } from "path";
1873
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
1874
+ import { dirname as dirname2, join as join9 } from "path";
1867
1875
  import { createRequire } from "module";
1868
1876
  function loadDatabaseCtor() {
1869
1877
  if (DatabaseCtor) return DatabaseCtor;
@@ -1875,7 +1883,7 @@ function safeMeshId(meshId) {
1875
1883
  return meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
1876
1884
  }
1877
1885
  function legacyQueuePath(meshId) {
1878
- return join8(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
1886
+ return join9(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
1879
1887
  }
1880
1888
  var DatabaseCtor, BeadsDB;
1881
1889
  var init_beads_db = __esm({
@@ -1894,7 +1902,7 @@ var init_beads_db = __esm({
1894
1902
  // 50 MB
1895
1903
  constructor(dbPath) {
1896
1904
  const dir = dirname2(dbPath);
1897
- if (!existsSync8(dir)) mkdirSync4(dir, { recursive: true });
1905
+ if (!existsSync9(dir)) mkdirSync4(dir, { recursive: true });
1898
1906
  this.dbPath = dbPath;
1899
1907
  this.db = new (loadDatabaseCtor())(dbPath);
1900
1908
  this.db.pragma("journal_mode = WAL");
@@ -1905,7 +1913,7 @@ var init_beads_db = __esm({
1905
1913
  }
1906
1914
  static getInstance() {
1907
1915
  if (!this.instance) {
1908
- this.instance = new _BeadsDB(join8(getLedgerDir(), "beads.db"));
1916
+ this.instance = new _BeadsDB(join9(getLedgerDir(), "beads.db"));
1909
1917
  }
1910
1918
  return this.instance;
1911
1919
  }
@@ -1985,7 +1993,7 @@ var init_beads_db = __esm({
1985
1993
  this.walWriteCounter = 0;
1986
1994
  try {
1987
1995
  const walPath = `${this.dbPath}-wal`;
1988
- if (!existsSync8(walPath)) return;
1996
+ if (!existsSync9(walPath)) return;
1989
1997
  const size = statSync3(walPath).size;
1990
1998
  if (size < _BeadsDB.WAL_MAX_BYTES) return;
1991
1999
  process.stderr.write(
@@ -2002,9 +2010,9 @@ var init_beads_db = __esm({
2002
2010
  const count = this.db.prepare("SELECT COUNT(*) AS count FROM mesh_queue WHERE mesh_id = ?").get(meshId);
2003
2011
  if (count.count > 0) return;
2004
2012
  const path28 = legacyQueuePath(meshId);
2005
- if (!existsSync8(path28)) return;
2013
+ if (!existsSync9(path28)) return;
2006
2014
  try {
2007
- const entries = JSON.parse(readFileSync6(path28, "utf-8"));
2015
+ const entries = JSON.parse(readFileSync7(path28, "utf-8"));
2008
2016
  if (!Array.isArray(entries)) return;
2009
2017
  const insert = this.db.prepare(`
2010
2018
  INSERT OR REPLACE INTO mesh_queue (
@@ -2501,7 +2509,7 @@ var init_mesh_work_queue = __esm({
2501
2509
  import { exec } from "child_process";
2502
2510
  import * as os2 from "os";
2503
2511
  import * as path8 from "path";
2504
- import { existsSync as existsSync9 } from "fs";
2512
+ import { existsSync as existsSync10 } from "fs";
2505
2513
  function parseVersion(raw) {
2506
2514
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
2507
2515
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
@@ -2525,7 +2533,7 @@ function resolveCommandPath(command) {
2525
2533
  if (isExplicitCommandPath(trimmed)) {
2526
2534
  const expanded = expandHome(trimmed);
2527
2535
  const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
2528
- return existsSync9(candidate) ? candidate : null;
2536
+ return existsSync10(candidate) ? candidate : null;
2529
2537
  }
2530
2538
  return null;
2531
2539
  }
@@ -2912,8 +2920,8 @@ __export(mesh_events_exports, {
2912
2920
  triggerMeshQueue: () => triggerMeshQueue,
2913
2921
  tryAssignQueueTask: () => tryAssignQueueTask
2914
2922
  });
2915
- import { appendFileSync as appendFileSync2, existsSync as existsSync11, readFileSync as readFileSync7, renameSync as renameSync3, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
2916
- import { join as join11 } from "path";
2923
+ import { appendFileSync as appendFileSync2, existsSync as existsSync12, readFileSync as readFileSync8, renameSync as renameSync3, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "fs";
2924
+ import { join as join12 } from "path";
2917
2925
  function getCachedMeshByWorkspace(workspace) {
2918
2926
  const now = Date.now();
2919
2927
  const cached = meshByWorkspaceCache.get(workspace);
@@ -2976,18 +2984,18 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
2976
2984
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
2977
2985
  if (coordinatorDaemonId) {
2978
2986
  const safeDaemon = coordinatorDaemonId.replace(/[^a-zA-Z0-9_-]/g, "_");
2979
- return join11(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
2987
+ return join12(getLedgerDir(), `${safe}-${safeDaemon}.pending-events.jsonl`);
2980
2988
  }
2981
- return join11(getLedgerDir(), `${safe}.pending-events.jsonl`);
2989
+ return join12(getLedgerDir(), `${safe}.pending-events.jsonl`);
2982
2990
  }
2983
2991
  function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
2984
2992
  if (!meshId) return [];
2985
2993
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
2986
2994
  const events = [];
2987
2995
  for (const path28 of paths) {
2988
- if (!existsSync11(path28)) continue;
2996
+ if (!existsSync12(path28)) continue;
2989
2997
  try {
2990
- const raw = readFileSync7(path28, "utf-8");
2998
+ const raw = readFileSync8(path28, "utf-8");
2991
2999
  const parsed = raw.split("\n").filter(Boolean).flatMap((line) => {
2992
3000
  try {
2993
3001
  return [JSON.parse(line)];
@@ -3066,11 +3074,11 @@ function reconcilePendingMeshCoordinatorEvents(meshId, events) {
3066
3074
  }
3067
3075
  function trimPendingEventsIfNeeded(path28) {
3068
3076
  try {
3069
- if (!existsSync11(path28)) return;
3077
+ if (!existsSync12(path28)) return;
3070
3078
  if (statSync5(path28).size <= MAX_PENDING_EVENTS_BYTES) return;
3071
- const lines = readFileSync7(path28, "utf-8").split("\n").filter(Boolean);
3079
+ const lines = readFileSync8(path28, "utf-8").split("\n").filter(Boolean);
3072
3080
  if (lines.length <= MAX_PENDING_EVENTS_KEEP) return;
3073
- writeFileSync4(path28, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
3081
+ writeFileSync5(path28, lines.slice(-MAX_PENDING_EVENTS_KEEP).join("\n") + "\n", "utf-8");
3074
3082
  } catch {
3075
3083
  }
3076
3084
  }
@@ -3101,7 +3109,7 @@ function atomicDrainFile(path28) {
3101
3109
  return null;
3102
3110
  }
3103
3111
  try {
3104
- const content = readFileSync7(tmpPath, "utf-8");
3112
+ const content = readFileSync8(tmpPath, "utf-8");
3105
3113
  try {
3106
3114
  unlinkSync2(tmpPath);
3107
3115
  } catch {
@@ -3143,7 +3151,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
3143
3151
  if (!meshId) return;
3144
3152
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
3145
3153
  for (const path28 of paths) {
3146
- if (existsSync11(path28)) try {
3154
+ if (existsSync12(path28)) try {
3147
3155
  unlinkSync2(path28);
3148
3156
  } catch {
3149
3157
  }
@@ -5188,6 +5196,15 @@ var init_cli_state_engine = __esm({
5188
5196
  // ── Approval ─────────────────────────────────────
5189
5197
  lastApprovalResolvedAt = 0;
5190
5198
  lastResolvedModalMessage = "";
5199
+ /**
5200
+ * When the engine previously held a modal but the latest parse failed
5201
+ * to extract one, we record the timestamp here and only drop the modal
5202
+ * after the configured `approvalCooldown` to avoid flapping between
5203
+ * waiting_approval and generating on every Claude TUI redraw — that
5204
+ * flapping is what fed auto-approve a fresh modal signature on each
5205
+ * paint and made the engine type "1" repeatedly into the prompt.
5206
+ */
5207
+ modalLostAt = 0;
5191
5208
  approvalExitTimeout = null;
5192
5209
  // ── Response tracking ────────────────────────────
5193
5210
  responseEpoch = 0;
@@ -5292,7 +5309,9 @@ var init_cli_state_engine = __esm({
5292
5309
  } catch {
5293
5310
  }
5294
5311
  }
5295
- if (!this.transport.isAlive() || this.currentStatus !== "waiting_approval" && !modal) return;
5312
+ if (!this.transport.isAlive()) return;
5313
+ const buttonsValid = Array.isArray(modal?.buttons) && modal.buttons.some((b) => typeof b === "string" && b.trim());
5314
+ if (!modal || !buttonsValid) return;
5296
5315
  const currentModalMessage = typeof modal?.message === "string" ? modal.message.trim() : "";
5297
5316
  const inCooldown = !!this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
5298
5317
  if (inCooldown && currentModalMessage === this.lastResolvedModalMessage) return;
@@ -5642,13 +5661,19 @@ var init_cli_state_engine = __esm({
5642
5661
  if (!inCooldown) {
5643
5662
  if (!modal) {
5644
5663
  LOG.warn("CLI", `[${this.provider.type}] detectStatus=waiting_approval but parseApproval returned null; ignoring`);
5645
- if (this.currentStatus === "waiting_approval") {
5646
- this.activeModal = null;
5647
- this.setStatus("generating", "approval_lost_modal");
5648
- this.callbacks.onStatusChange();
5664
+ if (this.currentStatus === "waiting_approval" && this.activeModal) {
5665
+ const lostAt = this.modalLostAt || Date.now();
5666
+ if (!this.modalLostAt) this.modalLostAt = lostAt;
5667
+ if (Date.now() - lostAt >= this.timeouts.approvalCooldown) {
5668
+ this.activeModal = null;
5669
+ this.modalLostAt = 0;
5670
+ this.setStatus("generating", "approval_lost_modal");
5671
+ this.callbacks.onStatusChange();
5672
+ }
5649
5673
  }
5650
5674
  return;
5651
5675
  }
5676
+ this.modalLostAt = 0;
5652
5677
  this.isWaitingForResponse = true;
5653
5678
  this.setStatus("waiting_approval", "script_detect");
5654
5679
  const prev = this.activeModal;
@@ -6775,19 +6800,12 @@ ${lastSnapshot}`;
6775
6800
  const liveDetect = this.runDetectStatus(this.recentOutputBuffer || this.terminalScreen.getText());
6776
6801
  if (liveDetect === "waiting_approval") {
6777
6802
  const liveModal = this.runParseApproval(this.terminalScreen.getText()) || this.runParseApproval(this.recentOutputBuffer);
6778
- if (liveModal) {
6803
+ const buttonsOk = liveModal && Array.isArray(liveModal.buttons) && liveModal.buttons.some((b) => typeof b === "string" && b.trim());
6804
+ if (liveModal && buttonsOk) {
6779
6805
  effectiveModal = liveModal;
6780
6806
  if (!this.engine.activeModal) this.engine.activeModal = liveModal;
6781
- } else {
6782
- LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: detect=waiting_approval but parseApproval still null (recentLen=${this.recentOutputBuffer.length} screenLen=${this.terminalScreen.getText().length})`);
6783
6807
  }
6784
- } else if (liveDetect && liveDetect !== "generating" && liveDetect !== "idle") {
6785
- LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: detect=${liveDetect} (not waiting_approval)`);
6786
- } else if (this.engine.currentStatus === "waiting_approval" && liveDetect !== "waiting_approval") {
6787
- LOG.warn("CLI", `[${this.cliType}] getStatus live re-extract: engine.status=waiting_approval but live detect=${liveDetect}`);
6788
6808
  }
6789
- } else if (!effectiveModal && this.engine.currentStatus === "waiting_approval") {
6790
- LOG.warn("CLI", `[${this.cliType}] getStatus skipped live re-extract: allowParse=${allowParse} isWaitingForResponse=${this.engine.isWaitingForResponse}`);
6791
6809
  }
6792
6810
  if (startupDetectedStatus === "waiting_approval" && effectiveModal) {
6793
6811
  effectiveStatus = "waiting_approval";
@@ -7700,7 +7718,8 @@ ${lastSnapshot}`;
7700
7718
  if (parsedDebugState?.status === "error") {
7701
7719
  effectiveStatus = "error";
7702
7720
  }
7703
- if (startupDetectedStatus === "waiting_approval") {
7721
+ const debugEffectiveModal = startupModal || this.engine.activeModal;
7722
+ if (startupDetectedStatus === "waiting_approval" && debugEffectiveModal) {
7704
7723
  effectiveStatus = "waiting_approval";
7705
7724
  }
7706
7725
  if (effectiveStatus === "idle" && parsedDebugState?.status === "generating" && !hasFinalAssistant(parsedDebugState)) {
@@ -9545,9 +9564,58 @@ function getSavedProviderSessions(state, filters) {
9545
9564
  init_mesh_config();
9546
9565
  init_coordinator_prompt();
9547
9566
 
9548
- // src/mesh/refine-config.ts
9549
- import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
9567
+ // src/mesh/coordinator-registry.ts
9568
+ init_config();
9550
9569
  import { join as join5 } from "path";
9570
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
9571
+ var _registry = /* @__PURE__ */ new Map();
9572
+ function getRegistryPath() {
9573
+ return join5(getDaemonDataDir(), "mesh-coordinators.json");
9574
+ }
9575
+ function loadMeshCoordinatorRegistry() {
9576
+ const path28 = getRegistryPath();
9577
+ if (!existsSync5(path28)) return;
9578
+ try {
9579
+ const raw = JSON.parse(readFileSync3(path28, "utf-8"));
9580
+ if (!Array.isArray(raw)) return;
9581
+ _registry.clear();
9582
+ for (const entry of raw) {
9583
+ if (typeof entry?.sessionId === "string" && typeof entry?.meshId === "string") {
9584
+ _registry.set(entry.sessionId, entry);
9585
+ }
9586
+ }
9587
+ } catch {
9588
+ }
9589
+ }
9590
+ function saveRegistry() {
9591
+ try {
9592
+ writeFileSync3(
9593
+ getRegistryPath(),
9594
+ JSON.stringify([..._registry.values()], null, 2),
9595
+ { encoding: "utf-8", mode: 384 }
9596
+ );
9597
+ } catch {
9598
+ }
9599
+ }
9600
+ function registerMeshCoordinator(entry) {
9601
+ _registry.set(entry.sessionId, entry);
9602
+ saveRegistry();
9603
+ }
9604
+ function unregisterMeshCoordinator(sessionId) {
9605
+ if (_registry.delete(sessionId)) {
9606
+ saveRegistry();
9607
+ }
9608
+ }
9609
+ function getCoordinatorForSession(sessionId) {
9610
+ return _registry.get(sessionId);
9611
+ }
9612
+ function listCoordinatorsForWorkspace(workspace) {
9613
+ return [..._registry.values()].filter((e) => e.workspace === workspace);
9614
+ }
9615
+
9616
+ // src/mesh/refine-config.ts
9617
+ import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
9618
+ import { join as join6 } from "path";
9551
9619
  import * as yaml from "js-yaml";
9552
9620
  var MESH_REFINE_VALIDATION_CATEGORIES = ["typecheck", "test", "lint", "build"];
9553
9621
  var MESH_REFINE_CONFIG_LOCATIONS = [
@@ -9730,10 +9798,10 @@ function loadMeshRefineConfig(mesh, workspace) {
9730
9798
  return { config: inline, source: "mesh.policy.refineConfig", sourceType: "mesh_policy" };
9731
9799
  }
9732
9800
  for (const relative3 of MESH_REFINE_CONFIG_LOCATIONS) {
9733
- const configPath = join5(workspace, relative3);
9734
- if (!existsSync5(configPath)) continue;
9801
+ const configPath = join6(workspace, relative3);
9802
+ if (!existsSync6(configPath)) continue;
9735
9803
  try {
9736
- const parsed = parseConfigText(configPath, readFileSync3(configPath, "utf-8"));
9804
+ const parsed = parseConfigText(configPath, readFileSync4(configPath, "utf-8"));
9737
9805
  const validation = validateMeshRefineConfig(parsed, relative3);
9738
9806
  if (!validation.valid) return { source: relative3, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
9739
9807
  return { config: parsed, source: relative3, sourceType: "repo_file", path: configPath };
@@ -9749,7 +9817,7 @@ function loadMeshRefineConfig(mesh, workspace) {
9749
9817
  }
9750
9818
  function readPackageScripts(workspace) {
9751
9819
  try {
9752
- const parsed = JSON.parse(readFileSync3(join5(workspace, "package.json"), "utf-8"));
9820
+ const parsed = JSON.parse(readFileSync4(join6(workspace, "package.json"), "utf-8"));
9753
9821
  return isRecord(parsed?.scripts) ? parsed.scripts : {};
9754
9822
  } catch {
9755
9823
  return {};
@@ -9822,8 +9890,8 @@ function resolveMeshRefineValidationPlan(mesh, workspace) {
9822
9890
  }
9823
9891
 
9824
9892
  // src/mesh/worktree-bootstrap-config.ts
9825
- import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
9826
- import { join as join6, resolve as pathResolve } from "path";
9893
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
9894
+ import { join as join7, resolve as pathResolve } from "path";
9827
9895
  import { execFile as execFile3 } from "child_process";
9828
9896
  import { promisify as promisify3 } from "util";
9829
9897
  import * as yaml2 from "js-yaml";
@@ -9913,10 +9981,10 @@ function loadMeshWorktreeBootstrapConfig(mesh, workspace) {
9913
9981
  return { config: inline, source: "mesh.policy.worktreeBootstrapConfig", sourceType: "mesh_policy" };
9914
9982
  }
9915
9983
  for (const relative3 of MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS) {
9916
- const configPath = join6(workspace, relative3);
9917
- if (!existsSync6(configPath)) continue;
9984
+ const configPath = join7(workspace, relative3);
9985
+ if (!existsSync7(configPath)) continue;
9918
9986
  try {
9919
- const parsed = parseConfigText2(configPath, readFileSync4(configPath, "utf-8"));
9987
+ const parsed = parseConfigText2(configPath, readFileSync5(configPath, "utf-8"));
9920
9988
  const validation = validateMeshWorktreeBootstrapConfig(parsed, relative3);
9921
9989
  if (!validation.valid) return { source: relative3, sourceType: "invalid", path: configPath, error: String(validation.rejectedCommands[0]?.reason || validation.errors.join("; ")) };
9922
9990
  return { config: parsed, source: relative3, sourceType: "repo_file", path: configPath };
@@ -9950,10 +10018,10 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
9950
10018
  staleInputs: loaded.config.staleInputs
9951
10019
  };
9952
10020
  const staleInputPaths = loaded.config.staleInputs ?? [];
9953
- const initiallyAbsent = staleInputPaths.filter((p) => !existsSync6(join6(workspace, p)));
10021
+ const initiallyAbsent = staleInputPaths.filter((p) => !existsSync7(join7(workspace, p)));
9954
10022
  for (const command of validation.commands) {
9955
10023
  if (initiallyAbsent.length > 0) {
9956
- const appearedNow = initiallyAbsent.filter((p) => existsSync6(join6(workspace, p)));
10024
+ const appearedNow = initiallyAbsent.filter((p) => existsSync7(join7(workspace, p)));
9957
10025
  if (appearedNow.length > 0) {
9958
10026
  state.status = "stale";
9959
10027
  state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -11017,8 +11085,8 @@ var P2pRelayFailureError = class extends Error {
11017
11085
 
11018
11086
  // src/config/state-store.ts
11019
11087
  init_config();
11020
- import { existsSync as existsSync12, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
11021
- import { join as join12 } from "path";
11088
+ import { existsSync as existsSync13, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
11089
+ import { join as join13 } from "path";
11022
11090
  var DEFAULT_STATE = {
11023
11091
  recentActivity: [],
11024
11092
  savedProviderSessions: [],
@@ -11031,7 +11099,7 @@ function isPlainObject2(value) {
11031
11099
  return !!value && typeof value === "object" && !Array.isArray(value);
11032
11100
  }
11033
11101
  function getStatePath() {
11034
- return join12(getConfigDir(), "state.json");
11102
+ return join13(getConfigDir(), "state.json");
11035
11103
  }
11036
11104
  function normalizeState(raw) {
11037
11105
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -11067,11 +11135,11 @@ function normalizeState(raw) {
11067
11135
  }
11068
11136
  function loadState() {
11069
11137
  const statePath = getStatePath();
11070
- if (!existsSync12(statePath)) {
11138
+ if (!existsSync13(statePath)) {
11071
11139
  return { ...DEFAULT_STATE };
11072
11140
  }
11073
11141
  try {
11074
- const raw = readFileSync8(statePath, "utf-8");
11142
+ const raw = readFileSync9(statePath, "utf-8");
11075
11143
  return normalizeState(JSON.parse(raw));
11076
11144
  } catch {
11077
11145
  return { ...DEFAULT_STATE };
@@ -11080,7 +11148,7 @@ function loadState() {
11080
11148
  function saveState(state) {
11081
11149
  const statePath = getStatePath();
11082
11150
  const normalized = normalizeState(state);
11083
- writeFileSync5(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
11151
+ writeFileSync6(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
11084
11152
  }
11085
11153
  function resetState() {
11086
11154
  saveState({ ...DEFAULT_STATE });
@@ -11089,7 +11157,7 @@ function resetState() {
11089
11157
  // src/detection/ide-detector.ts
11090
11158
  import { exec as exec2 } from "child_process";
11091
11159
  import { promisify as promisify4 } from "util";
11092
- import { existsSync as existsSync13, statSync as statSync6 } from "fs";
11160
+ import { existsSync as existsSync14, statSync as statSync6 } from "fs";
11093
11161
  import { platform as platform2, homedir as homedir5 } from "os";
11094
11162
  import * as path10 from "path";
11095
11163
  var execAsync2 = promisify4(exec2);
@@ -11114,7 +11182,7 @@ function findCliCommand(command) {
11114
11182
  if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
11115
11183
  const candidate = trimmed.startsWith("~") ? path10.join(homedir5(), trimmed.slice(1)) : trimmed;
11116
11184
  const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
11117
- return existsSync13(resolved) ? resolved : null;
11185
+ return existsSync14(resolved) ? resolved : null;
11118
11186
  }
11119
11187
  const isWin = platform2() === "win32";
11120
11188
  const paths = (process.env.PATH || "").split(isWin ? ";" : ":");
@@ -11124,7 +11192,7 @@ function findCliCommand(command) {
11124
11192
  for (const ext of exes) {
11125
11193
  const fullPath = path10.join(p, trimmed + ext);
11126
11194
  try {
11127
- if (existsSync13(fullPath)) {
11195
+ if (existsSync14(fullPath)) {
11128
11196
  const stat2 = statSync6(fullPath);
11129
11197
  if (stat2.isFile() && (isWin || stat2.mode & 73)) {
11130
11198
  return fullPath;
@@ -11154,9 +11222,9 @@ function checkPathExists(paths) {
11154
11222
  if (normalized.includes("*")) {
11155
11223
  const username = home.split(/[\\/]/).pop() || "";
11156
11224
  const resolved = normalized.replace("*", username);
11157
- if (existsSync13(resolved)) return resolved;
11225
+ if (existsSync14(resolved)) return resolved;
11158
11226
  } else {
11159
- if (existsSync13(normalized)) return normalized;
11227
+ if (existsSync14(normalized)) return normalized;
11160
11228
  }
11161
11229
  }
11162
11230
  return null;
@@ -11170,7 +11238,7 @@ async function detectIDEs(providerLoader) {
11170
11238
  let resolvedCli = cliPath;
11171
11239
  if (!resolvedCli && appPath && os22 === "darwin") {
11172
11240
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
11173
- if (existsSync13(bundledCli)) resolvedCli = bundledCli;
11241
+ if (existsSync14(bundledCli)) resolvedCli = bundledCli;
11174
11242
  }
11175
11243
  if (!resolvedCli && appPath && os22 === "win32") {
11176
11244
  const { dirname: dirname9 } = await import("path");
@@ -11183,7 +11251,7 @@ async function detectIDEs(providerLoader) {
11183
11251
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
11184
11252
  ];
11185
11253
  for (const c of candidates) {
11186
- if (existsSync13(c)) {
11254
+ if (existsSync14(c)) {
11187
11255
  resolvedCli = c;
11188
11256
  break;
11189
11257
  }
@@ -16920,7 +16988,7 @@ var ACP_SESSION_CAPABILITIES = [
16920
16988
  "set_mode",
16921
16989
  "set_thought_level"
16922
16990
  ];
16923
- function buildIdeWorkspaceSession(state, cdpManagers, options) {
16991
+ function buildWorkspaceSession(state, cdpManagers, options) {
16924
16992
  const profile = options.profile || "full";
16925
16993
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
16926
16994
  const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
@@ -16931,7 +16999,10 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
16931
16999
  const git = getGitSummaryForWorkspace(workspace, options);
16932
17000
  const title = activeChat?.title || state.name;
16933
17001
  const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
16934
- const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
17002
+ const registryEntry = state.instanceId ? getCoordinatorForSession(state.instanceId) : void 0;
17003
+ const effectiveMeshId = meshCoordinatorFor || registryEntry?.meshId;
17004
+ const coordinator = effectiveMeshId ? { meshId: effectiveMeshId, role: "coordinator" } : void 0;
17005
+ const meshQueueStats = effectiveMeshId ? getMeshQueueStats(effectiveMeshId) : void 0;
16935
17006
  return {
16936
17007
  id: state.instanceId || state.type,
16937
17008
  parentId: null,
@@ -16955,6 +17026,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
16955
17026
  errorReason: state.errorReason,
16956
17027
  lastUpdated: state.lastUpdated,
16957
17028
  settings: state.settings,
17029
+ ...coordinator && { coordinator },
16958
17030
  ...meshQueueStats && { meshQueueStats }
16959
17031
  };
16960
17032
  }
@@ -16968,7 +17040,10 @@ function buildExtensionAgentSession(parent, ext, options) {
16968
17040
  const workspace = parent.workspace || null;
16969
17041
  const git = getGitSummaryForWorkspace(workspace, options);
16970
17042
  const meshCoordinatorFor = ext.settings?.meshCoordinatorFor;
16971
- const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
17043
+ const registryEntry = ext.instanceId ? getCoordinatorForSession(ext.instanceId) : void 0;
17044
+ const effectiveMeshId = meshCoordinatorFor || registryEntry?.meshId;
17045
+ const coordinator = effectiveMeshId ? { meshId: effectiveMeshId, role: "coordinator" } : void 0;
17046
+ const meshQueueStats = effectiveMeshId ? getMeshQueueStats(effectiveMeshId) : void 0;
16972
17047
  return {
16973
17048
  id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
16974
17049
  parentId: parent.instanceId || parent.type,
@@ -16992,6 +17067,7 @@ function buildExtensionAgentSession(parent, ext, options) {
16992
17067
  errorReason: ext.errorReason,
16993
17068
  lastUpdated: ext.lastUpdated,
16994
17069
  settings: ext.settings,
17070
+ ...coordinator && { coordinator },
16995
17071
  ...meshQueueStats && { meshQueueStats }
16996
17072
  };
16997
17073
  }
@@ -17021,7 +17097,10 @@ function buildCliSession(state, options) {
17021
17097
  const workspace = state.workspace || null;
17022
17098
  const git = getGitSummaryForWorkspace(workspace, options);
17023
17099
  const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
17024
- const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
17100
+ const registryEntry = state.instanceId ? getCoordinatorForSession(state.instanceId) : void 0;
17101
+ const effectiveMeshId = meshCoordinatorFor || registryEntry?.meshId;
17102
+ const coordinator = effectiveMeshId ? { meshId: effectiveMeshId, role: "coordinator" } : void 0;
17103
+ const meshQueueStats = effectiveMeshId ? getMeshQueueStats(effectiveMeshId) : void 0;
17025
17104
  return {
17026
17105
  id: state.instanceId,
17027
17106
  parentId: null,
@@ -17061,6 +17140,7 @@ function buildCliSession(state, options) {
17061
17140
  errorReason: state.errorReason,
17062
17141
  lastUpdated: state.lastUpdated,
17063
17142
  settings: state.settings,
17143
+ ...coordinator && { coordinator },
17064
17144
  ...meshQueueStats && { meshQueueStats }
17065
17145
  };
17066
17146
  }
@@ -17074,7 +17154,10 @@ function buildAcpSession(state, options) {
17074
17154
  const workspace = state.workspace || null;
17075
17155
  const git = getGitSummaryForWorkspace(workspace, options);
17076
17156
  const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
17077
- const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
17157
+ const registryEntry = state.instanceId ? getCoordinatorForSession(state.instanceId) : void 0;
17158
+ const effectiveMeshId = meshCoordinatorFor || registryEntry?.meshId;
17159
+ const coordinator = effectiveMeshId ? { meshId: effectiveMeshId, role: "coordinator" } : void 0;
17160
+ const meshQueueStats = effectiveMeshId ? getMeshQueueStats(effectiveMeshId) : void 0;
17078
17161
  return {
17079
17162
  id: state.instanceId,
17080
17163
  parentId: null,
@@ -17097,6 +17180,7 @@ function buildAcpSession(state, options) {
17097
17180
  errorReason: state.errorReason,
17098
17181
  lastUpdated: state.lastUpdated,
17099
17182
  settings: state.settings,
17183
+ ...coordinator && { coordinator },
17100
17184
  ...meshQueueStats && { meshQueueStats }
17101
17185
  };
17102
17186
  }
@@ -17106,7 +17190,7 @@ function buildSessionEntries(allStates, cdpManagers, options = {}) {
17106
17190
  const cliStates = allStates.filter((s) => s.category === "cli");
17107
17191
  const acpStates = allStates.filter((s) => s.category === "acp");
17108
17192
  for (const state of ideStates) {
17109
- sessions.push(buildIdeWorkspaceSession(state, cdpManagers, options));
17193
+ sessions.push(buildWorkspaceSession(state, cdpManagers, options));
17110
17194
  for (const ext of state.extensions) {
17111
17195
  if (!shouldIncludeExtensionSession(ext)) continue;
17112
17196
  sessions.push(buildExtensionAgentSession(state, ext, options));
@@ -21626,7 +21710,7 @@ init_config();
21626
21710
  import * as os13 from "os";
21627
21711
  import * as path18 from "path";
21628
21712
  import * as crypto4 from "crypto";
21629
- import { existsSync as existsSync17, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
21713
+ import { existsSync as existsSync18, mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
21630
21714
  import { execFileSync } from "child_process";
21631
21715
  import chalk from "chalk";
21632
21716
 
@@ -22434,10 +22518,17 @@ var CliProviderInstance = class {
22434
22518
  return autoApproveActive;
22435
22519
  }
22436
22520
  const modal = adapterStatus.activeModal;
22437
- const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(modal?.buttons, this.provider);
22521
+ const buttons = Array.isArray(modal?.buttons) ? modal.buttons.map((b) => String(b || "").trim()).filter(Boolean) : [];
22522
+ if (!modal || buttons.length === 0) {
22523
+ return autoApproveActive;
22524
+ }
22525
+ const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(buttons, this.provider);
22526
+ if (buttonIndex < 0) {
22527
+ return autoApproveActive;
22528
+ }
22438
22529
  const signature = [
22439
22530
  typeof modal?.message === "string" ? modal.message.trim() : "",
22440
- Array.isArray(modal?.buttons) ? modal.buttons.join("|") : "",
22531
+ buttons.join("|"),
22441
22532
  buttonIndex
22442
22533
  ].join("::");
22443
22534
  if (!this.autoApproveBusy || signature !== this.lastAutoApprovalSignature) {
@@ -24340,7 +24431,7 @@ function commandExists(command) {
24340
24431
  const trimmed = command.trim();
24341
24432
  if (!trimmed) return false;
24342
24433
  if (isExplicitCommand(trimmed)) {
24343
- return existsSync17(expandExecutable(trimmed));
24434
+ return existsSync18(expandExecutable(trimmed));
24344
24435
  }
24345
24436
  try {
24346
24437
  execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -24465,7 +24556,7 @@ function ensureEmptyDelegatedMcpConfig(workspace) {
24465
24556
  mkdirSync10(baseDir, { recursive: true });
24466
24557
  const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
24467
24558
  const filePath = path18.join(baseDir, `${workspaceHash}.json`);
24468
- writeFileSync10(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
24559
+ writeFileSync11(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
24469
24560
  return filePath;
24470
24561
  }
24471
24562
  function buildCoordinatorDelegatedCliLaunchOptions(input) {
@@ -24696,6 +24787,7 @@ var DaemonCliManager = class {
24696
24787
  this.deps.removeAgentTracking(key);
24697
24788
  sessionRegistry?.unregisterByInstanceKey(key);
24698
24789
  instanceManager?.removeInstance(key);
24790
+ unregisterMeshCoordinator(key);
24699
24791
  LOG.info("CLI", `\u{1F9F9} Auto-cleaned ${status.status} CLI: ${cliType}`);
24700
24792
  this.deps.onStatusChange();
24701
24793
  }
@@ -24967,6 +25059,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
24967
25059
  this.deps.removeAgentTracking(key);
24968
25060
  this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
24969
25061
  this.deps.getInstanceManager()?.removeInstance(key);
25062
+ unregisterMeshCoordinator(key);
24970
25063
  LOG.info("CLI", `\u{1F6D1} Agent stopped: ${adapter.cliType} in ${adapter.workingDir}`);
24971
25064
  this.deps.onStatusChange();
24972
25065
  } else {
@@ -24975,6 +25068,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
24975
25068
  this.deps.getSessionRegistry?.()?.unregisterByInstanceKey(key);
24976
25069
  im.removeInstance(key);
24977
25070
  this.deps.removeAgentTracking(key);
25071
+ unregisterMeshCoordinator(key);
24978
25072
  LOG.warn("CLI", `\u{1F9F9} Force-removed orphan entry: ${key}`);
24979
25073
  this.deps.onStatusChange();
24980
25074
  }
@@ -27754,7 +27848,7 @@ import * as yaml3 from "js-yaml";
27754
27848
  // src/commands/mesh-coordinator.ts
27755
27849
  import { createHash as createHash4 } from "crypto";
27756
27850
  import * as os17 from "os";
27757
- import { isAbsolute as isAbsolute11, join as join23, resolve as resolve14 } from "path";
27851
+ import { isAbsolute as isAbsolute11, join as join24, resolve as resolve14 } from "path";
27758
27852
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
27759
27853
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev";
27760
27854
  var HERMES_CLI_TYPE = "hermes-cli";
@@ -27776,7 +27870,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
27776
27870
  reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
27777
27871
  };
27778
27872
  }
27779
- const configPath = join23(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
27873
+ const configPath = join24(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
27780
27874
  if (!configPath.trim()) {
27781
27875
  return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
27782
27876
  }
@@ -27896,14 +27990,14 @@ function resolveHermesCoordinatorHome(meshId, workspace) {
27896
27990
  const key = `${meshId || "mesh"}
27897
27991
  ${resolve14(workspace || os17.tmpdir())}`;
27898
27992
  const hash = createHash4("sha256").update(key).digest("hex").slice(0, 16);
27899
- return join23(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
27993
+ return join24(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
27900
27994
  }
27901
27995
  function resolveMcpConfigPath(configPath, workspace) {
27902
27996
  const trimmed = configPath.trim();
27903
27997
  if (trimmed === "~") return os17.homedir();
27904
- if (trimmed.startsWith("~/")) return join23(os17.homedir(), trimmed.slice(2));
27998
+ if (trimmed.startsWith("~/")) return join24(os17.homedir(), trimmed.slice(2));
27905
27999
  if (isAbsolute11(trimmed)) return trimmed;
27906
- return join23(workspace, trimmed);
28000
+ return join24(workspace, trimmed);
27907
28001
  }
27908
28002
  function resolveAdhdevMcpServerLaunch(options) {
27909
28003
  const command = resolveAdhdevCommand(options.adhdevMcpCommand);
@@ -27938,7 +28032,7 @@ init_mesh_host_ownership();
27938
28032
 
27939
28033
  // src/mesh/preview-freshness.ts
27940
28034
  import { execFileSync as execFileSync2 } from "child_process";
27941
- import { existsSync as existsSync20, readFileSync as readFileSync13 } from "fs";
28035
+ import { existsSync as existsSync21, readFileSync as readFileSync14 } from "fs";
27942
28036
  import { resolve as resolve15 } from "path";
27943
28037
  var PREVIEW_DEPLOY_RECORD = ".adhdev/preview-deploy.json";
27944
28038
  function runGit2(repoRoot, args) {
@@ -27955,9 +28049,9 @@ function runGit2(repoRoot, args) {
27955
28049
  }
27956
28050
  function readRecord3(repoRoot) {
27957
28051
  const path28 = resolve15(repoRoot, PREVIEW_DEPLOY_RECORD);
27958
- if (!existsSync20(path28)) return null;
28052
+ if (!existsSync21(path28)) return null;
27959
28053
  try {
27960
- const parsed = JSON.parse(readFileSync13(path28, "utf8"));
28054
+ const parsed = JSON.parse(readFileSync14(path28, "utf8"));
27961
28055
  return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
27962
28056
  } catch {
27963
28057
  return null;
@@ -33068,11 +33162,15 @@ ${block2}`);
33068
33162
  return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
33069
33163
  }
33070
33164
  LOG.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
33165
+ const cliCmdSessionId = cliCmdLaunch.sessionId || cliCmdLaunch.id;
33166
+ if (cliCmdSessionId) {
33167
+ registerMeshCoordinator({ meshId, sessionId: cliCmdSessionId, workspace, startedAt: Date.now() });
33168
+ }
33071
33169
  try {
33072
33170
  const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
33073
33171
  appendLedgerEntry2(meshId, {
33074
33172
  kind: "coordinator_started",
33075
- sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
33173
+ sessionId: cliCmdSessionId,
33076
33174
  providerType: cliType,
33077
33175
  payload: { workspace }
33078
33176
  });
@@ -33083,7 +33181,7 @@ ${block2}`);
33083
33181
  meshId,
33084
33182
  cliType,
33085
33183
  workspace,
33086
- sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
33184
+ sessionId: cliCmdSessionId,
33087
33185
  mcpRegistered: true
33088
33186
  };
33089
33187
  }
@@ -33113,7 +33211,7 @@ ${block2}`);
33113
33211
  workspace
33114
33212
  };
33115
33213
  }
33116
- const { existsSync: existsSync28, readFileSync: readFileSync21, writeFileSync: writeFileSync16, copyFileSync: copyFileSync4, mkdirSync: mkdirSync18 } = await import("fs");
33214
+ const { existsSync: existsSync29, readFileSync: readFileSync22, writeFileSync: writeFileSync17, copyFileSync: copyFileSync4, mkdirSync: mkdirSync18 } = await import("fs");
33117
33215
  const { dirname: dirname9 } = await import("path");
33118
33216
  const mcpConfigPath = coordinatorSetup.configPath;
33119
33217
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -33156,14 +33254,14 @@ ${block2}`);
33156
33254
  if (hermesManualFallback) return returnManualFallback(message);
33157
33255
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
33158
33256
  }
33159
- const hadExistingMcpConfig = existsSync28(mcpConfigPath);
33257
+ const hadExistingMcpConfig = existsSync29(mcpConfigPath);
33160
33258
  let existingMcpConfig = hermesBaseConfig?.config || {};
33161
33259
  if (hermesBaseConfig) {
33162
33260
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
33163
33261
  }
33164
33262
  if (hadExistingMcpConfig) {
33165
33263
  try {
33166
- const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync21(mcpConfigPath, "utf-8"), configFormat);
33264
+ const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync22(mcpConfigPath, "utf-8"), configFormat);
33167
33265
  const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
33168
33266
  existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
33169
33267
  copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
@@ -33186,7 +33284,7 @@ ${block2}`);
33186
33284
  }
33187
33285
  };
33188
33286
  try {
33189
- writeFileSync16(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
33287
+ writeFileSync17(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
33190
33288
  } catch (error) {
33191
33289
  const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
33192
33290
  LOG.error("MeshCoordinator", message);
@@ -33223,11 +33321,15 @@ ${block2}`);
33223
33321
  return { success: false, error: launchResult?.error || "Failed to launch CLI session" };
33224
33322
  }
33225
33323
  LOG.info("MeshCoordinator", `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
33324
+ const launchSessionId = launchResult.sessionId || launchResult.id;
33325
+ if (launchSessionId) {
33326
+ registerMeshCoordinator({ meshId, sessionId: launchSessionId, workspace, startedAt: Date.now() });
33327
+ }
33226
33328
  try {
33227
33329
  const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
33228
33330
  appendLedgerEntry2(meshId, {
33229
33331
  kind: "coordinator_started",
33230
- sessionId: launchResult.sessionId || launchResult.id,
33332
+ sessionId: launchSessionId,
33231
33333
  providerType: cliType,
33232
33334
  payload: { workspace }
33233
33335
  });
@@ -33238,7 +33340,7 @@ ${block2}`);
33238
33340
  meshId,
33239
33341
  cliType,
33240
33342
  workspace,
33241
- sessionId: launchResult.sessionId || launchResult.id,
33343
+ sessionId: launchSessionId,
33242
33344
  mcpConfigWritten: true
33243
33345
  };
33244
33346
  } catch (e) {
@@ -41443,6 +41545,7 @@ init_config();
41443
41545
  init_mesh_events();
41444
41546
  async function initDaemonComponents(config) {
41445
41547
  installGlobalInterceptor();
41548
+ loadMeshCoordinatorRegistry();
41446
41549
  const appConfig = loadConfig();
41447
41550
  const providerSourceMode = appConfig.providerSourceMode || "normal";
41448
41551
  const disableUpstream = providerSourceMode === "no-upstream";
@@ -41799,7 +41902,9 @@ export {
41799
41902
  getAIExtensions,
41800
41903
  getActiveDirectDispatches,
41801
41904
  getAvailableIdeIds,
41905
+ getCoordinatorForSession,
41802
41906
  getCurrentDaemonLogPath,
41907
+ getDaemonDataDir,
41803
41908
  getDaemonLogDir,
41804
41909
  getDebugRuntimeConfig,
41805
41910
  getGitDiffSummary,
@@ -41851,10 +41956,12 @@ export {
41851
41956
  killIdeProcess,
41852
41957
  launchIDE,
41853
41958
  launchWithCdp,
41959
+ listCoordinatorsForWorkspace,
41854
41960
  listHostedCliRuntimes,
41855
41961
  listMeshes,
41856
41962
  listWorktrees,
41857
41963
  loadConfig,
41964
+ loadMeshCoordinatorRegistry,
41858
41965
  loadMeshRefineConfig,
41859
41966
  loadMeshWorktreeBootstrapConfig,
41860
41967
  loadState,
@@ -41891,6 +41998,7 @@ export {
41891
41998
  readLedgerSlice,
41892
41999
  recordDebugTrace,
41893
42000
  registerExtensionProviders,
42001
+ registerMeshCoordinator,
41894
42002
  removeNode,
41895
42003
  removeWorktree,
41896
42004
  requeueTask,
@@ -41924,6 +42032,7 @@ export {
41924
42032
  summarizeGitStatus,
41925
42033
  syncMeshes,
41926
42034
  triggerMeshQueue,
42035
+ unregisterMeshCoordinator,
41927
42036
  updateConfig,
41928
42037
  updateDirectDispatchStatus,
41929
42038
  updateMesh,