@adhdev/daemon-core 0.9.82-rc.274 → 0.9.82-rc.276

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.
@@ -85,6 +85,7 @@ export interface DaemonComponents {
85
85
  meshReconcileLoop?: {
86
86
  stop(): void;
87
87
  };
88
+ statusInstanceId?: string;
88
89
  }
89
90
  export interface DaemonDevSupportOptions {
90
91
  components: DaemonComponents;
package/dist/index.js CHANGED
@@ -275,10 +275,10 @@ function readInjected(value) {
275
275
  }
276
276
  function getDaemonBuildInfo() {
277
277
  if (cached) return cached;
278
- const commit = readInjected(true ? "89d1ac61612c1dfe7fac53be61ec5dbfa67d00b2" : void 0) ?? "unknown";
279
- const commitShort = readInjected(true ? "89d1ac61" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
- const version = readInjected(true ? "0.9.82-rc.274" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
- const builtAt = readInjected(true ? "2026-06-15T07:04:52.710Z" : void 0);
278
+ const commit = readInjected(true ? "746fc68e4c297b988b76207bb8c63ab6062a38e1" : void 0) ?? "unknown";
279
+ const commitShort = readInjected(true ? "746fc68e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
+ const version = readInjected(true ? "0.9.82-rc.276" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
+ const builtAt = readInjected(true ? "2026-06-15T09:29:09.895Z" : void 0);
282
282
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
283
283
  return cached;
284
284
  }
@@ -4264,12 +4264,34 @@ var init_mesh_runtime_store = __esm({
4264
4264
  this.maybeCheckpointWal();
4265
4265
  return result.changes > 0;
4266
4266
  }
4267
- drainPendingEvents(meshId, coordinatorDaemonId) {
4267
+ /**
4268
+ * Drain undrained pending events for a mesh, atomically marking them drained.
4269
+ * When `opts.onlyEvents` is supplied, ONLY rows whose `event` is in that set are
4270
+ * drained — the rest stay queued (drained=0) for a later drain. This is how the
4271
+ * reconcile loop force-drains terminal/force-inject events into a *generating*
4272
+ * coordinator while leaving non-force progress events for the coordinator's next
4273
+ * idle transition. Filtering happens inside the same transaction as the
4274
+ * drained=1 marking, so force-drain + a concurrent full drain can never both
4275
+ * consume the same row.
4276
+ */
4277
+ drainPendingEvents(meshId, coordinatorDaemonId, opts) {
4268
4278
  return this.transaction(() => {
4269
- const whereClause = coordinatorDaemonId ? `WHERE mesh_id = ? AND drained = 0 AND (coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)` : `WHERE mesh_id = ? AND drained = 0`;
4270
- const params = coordinatorDaemonId ? [meshId, coordinatorDaemonId] : [meshId];
4279
+ const onlyEvents = opts?.onlyEvents;
4280
+ if (onlyEvents && onlyEvents.size === 0) return [];
4281
+ const eventList = onlyEvents ? [...onlyEvents] : [];
4282
+ const daemonIds = (Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId ? [coordinatorDaemonId] : []).filter((id) => typeof id === "string" && id.length > 0);
4283
+ const clauses = ["mesh_id = ?", "drained = 0"];
4284
+ const params = [meshId];
4285
+ if (daemonIds.length > 0) {
4286
+ clauses.push(`(coordinator_daemon_id IS NULL OR coordinator_daemon_id IN (${daemonIds.map(() => "?").join(",")}))`);
4287
+ params.push(...daemonIds);
4288
+ }
4289
+ if (eventList.length > 0) {
4290
+ clauses.push(`event IN (${eventList.map(() => "?").join(",")})`);
4291
+ params.push(...eventList);
4292
+ }
4271
4293
  const rows = this.db.prepare(
4272
- `SELECT id, event, payload FROM mesh_pending_events ${whereClause} ORDER BY queued_at ASC LIMIT 100`
4294
+ `SELECT id, event, payload FROM mesh_pending_events WHERE ${clauses.join(" AND ")} ORDER BY queued_at ASC LIMIT 100`
4273
4295
  ).all(...params);
4274
4296
  if (rows.length === 0) return [];
4275
4297
  const ids = rows.map((r) => r.id);
@@ -4292,8 +4314,9 @@ var init_mesh_runtime_store = __esm({
4292
4314
  }
4293
4315
  /** Non-destructive peek — returns undrained events without marking them drained. */
4294
4316
  peekPendingEvents(meshId, coordinatorDaemonId) {
4295
- const whereClause = coordinatorDaemonId ? `WHERE mesh_id = ? AND drained = 0 AND (coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)` : `WHERE mesh_id = ? AND drained = 0`;
4296
- const params = coordinatorDaemonId ? [meshId, coordinatorDaemonId] : [meshId];
4317
+ const daemonIds = (Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId ? [coordinatorDaemonId] : []).filter((id) => typeof id === "string" && id.length > 0);
4318
+ const whereClause = daemonIds.length > 0 ? `WHERE mesh_id = ? AND drained = 0 AND (coordinator_daemon_id IS NULL OR coordinator_daemon_id IN (${daemonIds.map(() => "?").join(",")}))` : `WHERE mesh_id = ? AND drained = 0`;
4319
+ const params = daemonIds.length > 0 ? [meshId, ...daemonIds] : [meshId];
4297
4320
  const rows = this.db.prepare(
4298
4321
  `SELECT id, event, payload FROM mesh_pending_events ${whereClause} ORDER BY queued_at ASC LIMIT 100`
4299
4322
  ).all(...params);
@@ -6333,6 +6356,19 @@ var init_mesh_events_utils = __esm({
6333
6356
  });
6334
6357
 
6335
6358
  // src/mesh/mesh-events-pending.ts
6359
+ function normalizeCoordinatorDaemonIds(coordinatorDaemonId) {
6360
+ const raw = Array.isArray(coordinatorDaemonId) ? coordinatorDaemonId : coordinatorDaemonId != null ? [coordinatorDaemonId] : [];
6361
+ const seen = /* @__PURE__ */ new Set();
6362
+ const out = [];
6363
+ for (const id of raw) {
6364
+ if (typeof id !== "string") continue;
6365
+ const trimmed = id.trim();
6366
+ if (!trimmed || seen.has(trimmed)) continue;
6367
+ seen.add(trimmed);
6368
+ out.push(trimmed);
6369
+ }
6370
+ return out;
6371
+ }
6336
6372
  function readRefineJobId2(event) {
6337
6373
  const metadata = readRecord3(event.metadataEvent) || event;
6338
6374
  const result = readRecord3(metadata.result);
@@ -6387,7 +6423,9 @@ function getPendingEventsPath(meshId, coordinatorDaemonId) {
6387
6423
  }
6388
6424
  function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
6389
6425
  if (!meshId) return [];
6390
- const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
6426
+ const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
6427
+ const primaryDaemonId = daemonIds[0];
6428
+ const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
6391
6429
  const events = [];
6392
6430
  for (const path39 of paths) {
6393
6431
  if (!(0, import_fs8.existsSync)(path39)) continue;
@@ -6400,7 +6438,7 @@ function readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId) {
6400
6438
  return [];
6401
6439
  }
6402
6440
  });
6403
- const filtered = coordinatorDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId) : parsed;
6441
+ const filtered = primaryDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || daemonIds.includes(e.targetCoordinatorDaemonId)) : parsed;
6404
6442
  events.push(...filtered);
6405
6443
  } catch {
6406
6444
  }
@@ -6529,8 +6567,59 @@ function atomicDrainFile(path39) {
6529
6567
  return null;
6530
6568
  }
6531
6569
  }
6532
- function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6570
+ function selectiveDrainFile(path39, predicate) {
6571
+ const tmpPath = `${path39}.draining`;
6572
+ try {
6573
+ (0, import_fs8.renameSync)(path39, tmpPath);
6574
+ } catch {
6575
+ return [];
6576
+ }
6577
+ let content;
6578
+ try {
6579
+ content = (0, import_fs8.readFileSync)(tmpPath, "utf-8");
6580
+ } catch {
6581
+ try {
6582
+ (0, import_fs8.unlinkSync)(tmpPath);
6583
+ } catch {
6584
+ }
6585
+ return [];
6586
+ }
6587
+ const consumed = [];
6588
+ const keptLines = [];
6589
+ for (const line of content.split("\n")) {
6590
+ if (!line) continue;
6591
+ let parsed;
6592
+ try {
6593
+ parsed = JSON.parse(line);
6594
+ } catch {
6595
+ parsed = void 0;
6596
+ }
6597
+ if (parsed && predicate(parsed)) {
6598
+ consumed.push(parsed);
6599
+ } else {
6600
+ keptLines.push(line);
6601
+ }
6602
+ }
6603
+ try {
6604
+ if (keptLines.length > 0) {
6605
+ (0, import_fs8.writeFileSync)(path39, keptLines.join("\n") + "\n", "utf-8");
6606
+ }
6607
+ (0, import_fs8.unlinkSync)(tmpPath);
6608
+ } catch {
6609
+ try {
6610
+ if ((0, import_fs8.existsSync)(tmpPath) && !(0, import_fs8.existsSync)(path39)) (0, import_fs8.renameSync)(tmpPath, path39);
6611
+ } catch {
6612
+ }
6613
+ return [];
6614
+ }
6615
+ return consumed;
6616
+ }
6617
+ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
6533
6618
  if (!meshId) return [];
6619
+ const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
6620
+ const primaryDaemonId = daemonIds[0];
6621
+ const onlyEvents = opts?.onlyEvents;
6622
+ const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
6534
6623
  const merged = [];
6535
6624
  const seenFingerprints = /* @__PURE__ */ new Set();
6536
6625
  const pushUnique = (event) => {
@@ -6544,15 +6633,23 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6544
6633
  try {
6545
6634
  const store = MeshRuntimeStore.getInstance();
6546
6635
  if (store.pendingEventCount(meshId) > 0) {
6547
- for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId)) {
6636
+ for (const row of store.drainPendingEvents(meshId, daemonIds.length > 0 ? daemonIds : void 0, onlyEvents ? { onlyEvents } : void 0)) {
6548
6637
  const event = row.payload;
6549
6638
  if (event) pushUnique(event);
6550
6639
  }
6551
6640
  }
6552
6641
  } catch {
6553
6642
  }
6554
- const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
6643
+ const paths = primaryDaemonId ? [getPendingEventsPath(meshId, primaryDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
6555
6644
  for (const path39 of paths) {
6645
+ const isSharedFile = !!primaryDaemonId && path39 === getPendingEventsPath(meshId);
6646
+ const targets = (e) => !isSharedFile || !e.targetCoordinatorDaemonId || daemonIds.includes(e.targetCoordinatorDaemonId);
6647
+ if (onlyEvents) {
6648
+ for (const event of selectiveDrainFile(path39, (e) => targets(e) && matchesFilter(e.event))) {
6649
+ pushUnique(event);
6650
+ }
6651
+ continue;
6652
+ }
6556
6653
  const content = atomicDrainFile(path39);
6557
6654
  if (!content) continue;
6558
6655
  const parsed = content.split("\n").filter(Boolean).flatMap((line) => {
@@ -6562,7 +6659,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6562
6659
  return [];
6563
6660
  }
6564
6661
  });
6565
- const filtered = coordinatorDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId) : parsed;
6662
+ const filtered = isSharedFile ? parsed.filter(targets) : parsed;
6566
6663
  for (const event of filtered) pushUnique(event);
6567
6664
  }
6568
6665
  if (merged.length === 0) return [];
@@ -6570,6 +6667,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6570
6667
  }
6571
6668
  function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6572
6669
  if (!meshId) return [];
6670
+ const daemonIds = normalizeCoordinatorDaemonIds(coordinatorDaemonId);
6573
6671
  const merged = [];
6574
6672
  const seenFingerprints = /* @__PURE__ */ new Set();
6575
6673
  const pushUnique = (event) => {
@@ -6583,14 +6681,14 @@ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6583
6681
  try {
6584
6682
  const store = MeshRuntimeStore.getInstance();
6585
6683
  if (store.pendingEventCount(meshId) > 0) {
6586
- for (const row of store.peekPendingEvents(meshId, coordinatorDaemonId)) {
6684
+ for (const row of store.peekPendingEvents(meshId, daemonIds.length > 0 ? daemonIds : void 0)) {
6587
6685
  const event = row.payload;
6588
6686
  if (event) pushUnique(event);
6589
6687
  }
6590
6688
  }
6591
6689
  } catch {
6592
6690
  }
6593
- for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId)) {
6691
+ for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId, daemonIds)) {
6594
6692
  pushUnique(event);
6595
6693
  }
6596
6694
  return reconcilePendingMeshCoordinatorEvents(meshId, merged);
@@ -7292,6 +7390,14 @@ var init_mesh_routing = __esm({
7292
7390
  });
7293
7391
 
7294
7392
  // src/mesh/mesh-events-coordinator.ts
7393
+ function resolveCoordinatorDrainDaemonIds(components) {
7394
+ const ids = /* @__PURE__ */ new Set();
7395
+ const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
7396
+ if (statusInstanceId) ids.add(statusInstanceId);
7397
+ const machineId = readNonEmptyString2(loadConfig().machineId);
7398
+ if (machineId) ids.add(machineId);
7399
+ return [...ids];
7400
+ }
7295
7401
  function getCachedMeshByWorkspace(workspace) {
7296
7402
  const now = Date.now();
7297
7403
  const cached2 = meshByWorkspaceCache.get(workspace);
@@ -8416,8 +8522,8 @@ function setupMeshEventForwarding(components) {
8416
8522
  const status = readNonEmptyString2(flushState.status).toLowerCase();
8417
8523
  if (status === "idle") {
8418
8524
  try {
8419
- const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
8420
- const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId, localDaemonId);
8525
+ const drainDaemonIds = resolveCoordinatorDrainDaemonIds(components);
8526
+ const pendingEvents = drainPendingMeshCoordinatorEvents(coordinatorMeshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
8421
8527
  if (pendingEvents.length > 0) {
8422
8528
  LOG.info("MeshEvents", `Auto-flushing ${pendingEvents.length} pending coordinator event(s) for mesh ${coordinatorMeshId} on coordinator idle`);
8423
8529
  for (const pending of pendingEvents) {
@@ -8533,6 +8639,14 @@ function resolveReconcileIntervalMs() {
8533
8639
  }
8534
8640
  return DEFAULT_RECONCILE_INTERVAL_MS;
8535
8641
  }
8642
+ function resolveCoordinatorDaemonIds(components) {
8643
+ const ids = /* @__PURE__ */ new Set();
8644
+ const statusInstanceId = readNonEmptyString2(components.statusInstanceId);
8645
+ if (statusInstanceId) ids.add(statusInstanceId);
8646
+ const machineId = readNonEmptyString2(loadConfig().machineId);
8647
+ if (machineId) ids.add(machineId);
8648
+ return [...ids];
8649
+ }
8536
8650
  function findLiveCoordinators(components) {
8537
8651
  const out = [];
8538
8652
  for (const inst of components.instanceManager.getByCategory("cli")) {
@@ -8565,6 +8679,7 @@ async function runMeshReconcileTick(components) {
8565
8679
  else byMesh.set(c.meshId, [c]);
8566
8680
  }
8567
8681
  const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
8682
+ const drainDaemonIds = resolveCoordinatorDaemonIds(components);
8568
8683
  const dispatchMeshCommand = components.dispatchMeshCommand;
8569
8684
  const store = (() => {
8570
8685
  try {
@@ -8582,7 +8697,9 @@ async function runMeshReconcileTick(components) {
8582
8697
  }
8583
8698
  }
8584
8699
  const idleCoordinators = meshCoordinators.filter((c) => c.idle);
8585
- if (idleCoordinators.length === 0) continue;
8700
+ const generatingCoordinators = meshCoordinators.filter((c) => !c.idle);
8701
+ const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
8702
+ const forceOnly = idleCoordinators.length === 0;
8586
8703
  if (store) {
8587
8704
  try {
8588
8705
  if (store.pendingEventCount(meshId) === 0) continue;
@@ -8591,15 +8708,20 @@ async function runMeshReconcileTick(components) {
8591
8708
  }
8592
8709
  let pendingEvents = [];
8593
8710
  try {
8594
- pendingEvents = drainPendingMeshCoordinatorEvents(meshId, localDaemonId);
8711
+ pendingEvents = drainPendingMeshCoordinatorEvents(
8712
+ meshId,
8713
+ drainDaemonIds.length > 0 ? drainDaemonIds : localDaemonId,
8714
+ forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
8715
+ );
8595
8716
  } catch (e) {
8596
8717
  LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
8597
8718
  continue;
8598
8719
  }
8599
8720
  if (pendingEvents.length === 0) continue;
8600
- LOG.info("MeshReconcile", `Reconcile inject: ${pendingEvents.length} pending event(s) \u2192 ${idleCoordinators.length} idle coordinator(s) for mesh ${meshId}`);
8721
+ const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
8722
+ LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
8601
8723
  for (const pending of pendingEvents) {
8602
- for (const c of idleCoordinators) {
8724
+ for (const c of targetCoordinators) {
8603
8725
  injectPendingIntoCoordinator(c.instance, pending);
8604
8726
  }
8605
8727
  }
@@ -55697,7 +55819,8 @@ async function initDaemonComponents(config) {
55697
55819
  detectedIdes: detectedIdesRef,
55698
55820
  refreshProviderAvailability,
55699
55821
  dispatchMeshCommand: config.dispatchMeshCommand,
55700
- onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded
55822
+ onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded,
55823
+ statusInstanceId: config.statusInstanceId
55701
55824
  };
55702
55825
  setupMeshEventForwarding(components);
55703
55826
  components.meshReconcileLoop = setupMeshReconcileLoop(components);