@adhdev/daemon-core 0.9.82-rc.273 → 0.9.82-rc.275

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.
@@ -82,6 +82,9 @@ export interface DaemonComponents {
82
82
  refreshProviderAvailability: (providerType?: string) => Promise<void>;
83
83
  dispatchMeshCommand?: (daemonId: string, command: string, args: Record<string, unknown>) => Promise<any>;
84
84
  onMeshCoordinatorEventForwarded?: (payload: Record<string, unknown>) => void;
85
+ meshReconcileLoop?: {
86
+ stop(): void;
87
+ };
85
88
  }
86
89
  export interface DaemonDevSupportOptions {
87
90
  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 ? "e4a64afbd050fa5167c383b1fc6f9df5f8e48ba2" : void 0) ?? "unknown";
279
- const commitShort = readInjected(true ? "e4a64afb" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
- const version = readInjected(true ? "0.9.82-rc.273" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
- const builtAt = readInjected(true ? "2026-06-15T05:37:07.054Z" : void 0);
278
+ const commit = readInjected(true ? "080b607ef221e44126942d9d52eaf547b4e92550" : void 0) ?? "unknown";
279
+ const commitShort = readInjected(true ? "080b607e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
280
+ const version = readInjected(true ? "0.9.82-rc.275" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
281
+ const builtAt = readInjected(true ? "2026-06-15T08:24:26.468Z" : void 0);
282
282
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
283
283
  return cached;
284
284
  }
@@ -4264,12 +4264,33 @@ 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 clauses = ["mesh_id = ?", "drained = 0"];
4283
+ const params = [meshId];
4284
+ if (coordinatorDaemonId) {
4285
+ clauses.push("(coordinator_daemon_id IS NULL OR coordinator_daemon_id = ?)");
4286
+ params.push(coordinatorDaemonId);
4287
+ }
4288
+ if (eventList.length > 0) {
4289
+ clauses.push(`event IN (${eventList.map(() => "?").join(",")})`);
4290
+ params.push(...eventList);
4291
+ }
4271
4292
  const rows = this.db.prepare(
4272
- `SELECT id, event, payload FROM mesh_pending_events ${whereClause} ORDER BY queued_at ASC LIMIT 100`
4293
+ `SELECT id, event, payload FROM mesh_pending_events WHERE ${clauses.join(" AND ")} ORDER BY queued_at ASC LIMIT 100`
4273
4294
  ).all(...params);
4274
4295
  if (rows.length === 0) return [];
4275
4296
  const ids = rows.map((r) => r.id);
@@ -6168,16 +6189,6 @@ function readNonEmptyString2(value) {
6168
6189
  function readRecord3(value) {
6169
6190
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
6170
6191
  }
6171
- function canonicalDaemonId(value) {
6172
- const id = readNonEmptyString2(value);
6173
- if (!id) return "";
6174
- return id.replace(/^(?:daemon|standalone)_/, "");
6175
- }
6176
- function sameDaemonId(a, b) {
6177
- const ca = canonicalDaemonId(a);
6178
- const cb = canonicalDaemonId(b);
6179
- return ca !== "" && ca === cb;
6180
- }
6181
6192
  function buildMeshWorkerRelayStamp(currentSettings, meshContext) {
6182
6193
  if (!meshContext) return void 0;
6183
6194
  const settings = currentSettings && typeof currentSettings === "object" ? currentSettings : {};
@@ -6378,29 +6389,6 @@ function buildPendingEventFingerprint(event) {
6378
6389
  timestamp || ""
6379
6390
  ].join("::");
6380
6391
  }
6381
- function markMeshCoordinatorEventDirectDelivered(coordinatorDaemonId, event) {
6382
- const canonical = canonicalDaemonId(coordinatorDaemonId);
6383
- if (!canonical) return;
6384
- const fingerprint = buildPendingEventFingerprint(event);
6385
- if (!fingerprint.trim()) return;
6386
- try {
6387
- const store = MeshRuntimeStore.getInstance();
6388
- store.recordDirectDelivered(canonical, fingerprint, DIRECT_DELIVERED_TTL_MS);
6389
- store.sweepExpiredDirectDelivered();
6390
- } catch {
6391
- }
6392
- }
6393
- function wasDirectDeliveredToCoordinator(coordinatorDaemonId, event) {
6394
- const canonical = canonicalDaemonId(coordinatorDaemonId);
6395
- if (!canonical) return false;
6396
- const fingerprint = buildPendingEventFingerprint(event);
6397
- if (!fingerprint.trim()) return false;
6398
- try {
6399
- return MeshRuntimeStore.getInstance().wasDirectDelivered(canonical, fingerprint);
6400
- } catch {
6401
- return false;
6402
- }
6403
- }
6404
6392
  function hasPendingCoordinatorEventDuplicate(event) {
6405
6393
  const fingerprint = buildPendingEventFingerprint(event);
6406
6394
  if (!fingerprint.trim()) return false;
@@ -6562,8 +6550,57 @@ function atomicDrainFile(path39) {
6562
6550
  return null;
6563
6551
  }
6564
6552
  }
6565
- function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6553
+ function selectiveDrainFile(path39, predicate) {
6554
+ const tmpPath = `${path39}.draining`;
6555
+ try {
6556
+ (0, import_fs8.renameSync)(path39, tmpPath);
6557
+ } catch {
6558
+ return [];
6559
+ }
6560
+ let content;
6561
+ try {
6562
+ content = (0, import_fs8.readFileSync)(tmpPath, "utf-8");
6563
+ } catch {
6564
+ try {
6565
+ (0, import_fs8.unlinkSync)(tmpPath);
6566
+ } catch {
6567
+ }
6568
+ return [];
6569
+ }
6570
+ const consumed = [];
6571
+ const keptLines = [];
6572
+ for (const line of content.split("\n")) {
6573
+ if (!line) continue;
6574
+ let parsed;
6575
+ try {
6576
+ parsed = JSON.parse(line);
6577
+ } catch {
6578
+ parsed = void 0;
6579
+ }
6580
+ if (parsed && predicate(parsed)) {
6581
+ consumed.push(parsed);
6582
+ } else {
6583
+ keptLines.push(line);
6584
+ }
6585
+ }
6586
+ try {
6587
+ if (keptLines.length > 0) {
6588
+ (0, import_fs8.writeFileSync)(path39, keptLines.join("\n") + "\n", "utf-8");
6589
+ }
6590
+ (0, import_fs8.unlinkSync)(tmpPath);
6591
+ } catch {
6592
+ try {
6593
+ if ((0, import_fs8.existsSync)(tmpPath) && !(0, import_fs8.existsSync)(path39)) (0, import_fs8.renameSync)(tmpPath, path39);
6594
+ } catch {
6595
+ }
6596
+ return [];
6597
+ }
6598
+ return consumed;
6599
+ }
6600
+ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId, opts) {
6566
6601
  if (!meshId) return [];
6602
+ const onlyEvents = opts?.onlyEvents;
6603
+ const matchesFilter = (eventName) => !onlyEvents || onlyEvents.has(eventName);
6567
6604
  const merged = [];
6568
6605
  const seenFingerprints = /* @__PURE__ */ new Set();
6569
6606
  const pushUnique = (event) => {
@@ -6577,7 +6614,7 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6577
6614
  try {
6578
6615
  const store = MeshRuntimeStore.getInstance();
6579
6616
  if (store.pendingEventCount(meshId) > 0) {
6580
- for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId)) {
6617
+ for (const row of store.drainPendingEvents(meshId, coordinatorDaemonId, onlyEvents ? { onlyEvents } : void 0)) {
6581
6618
  const event = row.payload;
6582
6619
  if (event) pushUnique(event);
6583
6620
  }
@@ -6586,6 +6623,14 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6586
6623
  }
6587
6624
  const paths = coordinatorDaemonId ? [getPendingEventsPath(meshId, coordinatorDaemonId), getPendingEventsPath(meshId)] : [getPendingEventsPath(meshId)];
6588
6625
  for (const path39 of paths) {
6626
+ const isSharedFile = coordinatorDaemonId && path39 === getPendingEventsPath(meshId);
6627
+ const targets = (e) => !isSharedFile || !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId;
6628
+ if (onlyEvents) {
6629
+ for (const event of selectiveDrainFile(path39, (e) => targets(e) && matchesFilter(e.event))) {
6630
+ pushUnique(event);
6631
+ }
6632
+ continue;
6633
+ }
6589
6634
  const content = atomicDrainFile(path39);
6590
6635
  if (!content) continue;
6591
6636
  const parsed = content.split("\n").filter(Boolean).flatMap((line) => {
@@ -6595,13 +6640,11 @@ function drainPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6595
6640
  return [];
6596
6641
  }
6597
6642
  });
6598
- const filtered = coordinatorDaemonId && path39 === getPendingEventsPath(meshId) ? parsed.filter((e) => !e.targetCoordinatorDaemonId || e.targetCoordinatorDaemonId === coordinatorDaemonId) : parsed;
6643
+ const filtered = isSharedFile ? parsed.filter(targets) : parsed;
6599
6644
  for (const event of filtered) pushUnique(event);
6600
6645
  }
6601
6646
  if (merged.length === 0) return [];
6602
- const deliverable = coordinatorDaemonId ? merged.filter((event) => !wasDirectDeliveredToCoordinator(coordinatorDaemonId, event)) : merged;
6603
- if (deliverable.length === 0) return [];
6604
- return reconcilePendingMeshCoordinatorEvents(meshId, deliverable);
6647
+ return reconcilePendingMeshCoordinatorEvents(meshId, merged);
6605
6648
  }
6606
6649
  function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6607
6650
  if (!meshId) return [];
@@ -6628,8 +6671,7 @@ function getPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6628
6671
  for (const event of readPendingMeshCoordinatorEventsFromDisk(meshId, coordinatorDaemonId)) {
6629
6672
  pushUnique(event);
6630
6673
  }
6631
- const deliverable = coordinatorDaemonId ? merged.filter((event) => !wasDirectDeliveredToCoordinator(coordinatorDaemonId, event)) : merged;
6632
- return reconcilePendingMeshCoordinatorEvents(meshId, deliverable);
6674
+ return reconcilePendingMeshCoordinatorEvents(meshId, merged);
6633
6675
  }
6634
6676
  function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6635
6677
  if (!meshId) return;
@@ -6645,7 +6687,7 @@ function clearPendingMeshCoordinatorEvents(meshId, coordinatorDaemonId) {
6645
6687
  }
6646
6688
  }
6647
6689
  }
6648
- var import_fs8, import_path8, import_crypto7, REFINE_TERMINAL_EVENTS, DIRECT_DELIVERED_TTL_MS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
6690
+ var import_fs8, import_path8, import_crypto7, REFINE_TERMINAL_EVENTS, MAX_PENDING_EVENTS_BYTES, MAX_PENDING_EVENTS_KEEP;
6649
6691
  var init_mesh_events_pending = __esm({
6650
6692
  "src/mesh/mesh-events-pending.ts"() {
6651
6693
  "use strict";
@@ -6657,7 +6699,6 @@ var init_mesh_events_pending = __esm({
6657
6699
  init_mesh_runtime_store();
6658
6700
  init_mesh_events_utils();
6659
6701
  REFINE_TERMINAL_EVENTS = /* @__PURE__ */ new Set(["refine:completed", "refine:failed"]);
6660
- DIRECT_DELIVERED_TTL_MS = 10 * 60 * 1e3;
6661
6702
  MAX_PENDING_EVENTS_BYTES = 100 * 1024;
6662
6703
  MAX_PENDING_EVENTS_KEEP = 50;
6663
6704
  }
@@ -8019,7 +8060,6 @@ function injectMeshSystemMessage(components, args) {
8019
8060
  const workerCoordinatorDaemonId = readNonEmptyString2(
8020
8061
  sourceSession?.getState()?.settings?.meshCoordinatorDaemonId
8021
8062
  );
8022
- const localDaemonId = readNonEmptyString2(loadConfig().machineId);
8023
8063
  if (components.onMeshCoordinatorEventForwarded) {
8024
8064
  try {
8025
8065
  components.onMeshCoordinatorEventForwarded({
@@ -8374,60 +8414,6 @@ function injectMeshSystemMessage(components, args) {
8374
8414
  recoveryContext
8375
8415
  });
8376
8416
  if (!messageText) return { success: false, error: "unsupported mesh event" };
8377
- const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
8378
- const instState = inst.getState();
8379
- if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
8380
- if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
8381
- if (workerCoordinatorDaemonId && localDaemonId && !sameDaemonId(workerCoordinatorDaemonId, localDaemonId)) return false;
8382
- return true;
8383
- });
8384
- if (coordinatorInstances.length === 0) {
8385
- const remoteCoordinatorDaemonId = workerCoordinatorDaemonId && localDaemonId && !sameDaemonId(workerCoordinatorDaemonId, localDaemonId) ? workerCoordinatorDaemonId : "";
8386
- if (remoteCoordinatorDaemonId && components.dispatchMeshCommand) {
8387
- const forwardPayload = {
8388
- event: args.event,
8389
- meshId: args.meshId,
8390
- nodeId: args.nodeId || void 0,
8391
- workspace: readNonEmptyString2(args.metadataEvent.workspace),
8392
- ...args.metadataEvent,
8393
- ...recoveryContext ? { recoveryContext } : {}
8394
- };
8395
- components.dispatchMeshCommand(remoteCoordinatorDaemonId, "mesh_forward_event", forwardPayload).then(() => {
8396
- LOG.info("MeshEvents", `Forwarded ${args.event} for mesh ${args.meshId} to remote coordinator daemon ${remoteCoordinatorDaemonId.slice(0, 12)}\u2026`);
8397
- }).catch((error) => {
8398
- LOG.warn("MeshEvents", `Remote forward of ${args.event} failed (${error?.message || error}); queuing for backfill`);
8399
- queuePendingMeshCoordinatorEvent({
8400
- event: args.event,
8401
- meshId: args.meshId,
8402
- nodeLabel: args.nodeLabel,
8403
- nodeId: args.nodeId || void 0,
8404
- workspace: readNonEmptyString2(args.metadataEvent.workspace),
8405
- metadataEvent: { ...args.metadataEvent, ...recoveryContext ? { recoveryContext } : {} },
8406
- coordinatorMessage: messageText,
8407
- queuedAt: Date.now(),
8408
- targetCoordinatorDaemonId: remoteCoordinatorDaemonId
8409
- });
8410
- });
8411
- return { success: true, forwarded: 0, remoteForwarded: true };
8412
- }
8413
- if (queuePendingMeshCoordinatorEvent({
8414
- event: args.event,
8415
- meshId: args.meshId,
8416
- nodeLabel: args.nodeLabel,
8417
- nodeId: args.nodeId || void 0,
8418
- workspace: readNonEmptyString2(args.metadataEvent.workspace),
8419
- metadataEvent: {
8420
- ...args.metadataEvent,
8421
- ...recoveryContext ? { recoveryContext } : {}
8422
- },
8423
- coordinatorMessage: messageText,
8424
- queuedAt: Date.now(),
8425
- ...workerCoordinatorDaemonId ? { targetCoordinatorDaemonId: workerCoordinatorDaemonId } : {}
8426
- })) {
8427
- LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""})`);
8428
- }
8429
- return { success: true, forwarded: 0 };
8430
- }
8431
8417
  const pendingEvent = {
8432
8418
  event: args.event,
8433
8419
  meshId: args.meshId,
@@ -8443,21 +8429,9 @@ function injectMeshSystemMessage(components, args) {
8443
8429
  ...workerCoordinatorDaemonId ? { targetCoordinatorDaemonId: workerCoordinatorDaemonId } : {}
8444
8430
  };
8445
8431
  if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
8446
- LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
8447
- }
8448
- if (localDaemonId) {
8449
- markMeshCoordinatorEventDirectDelivered(localDaemonId, pendingEvent);
8450
- }
8451
- const forceInject = shouldForceInjectMeshEvent(args.event);
8452
- for (const coord of coordinatorInstances) {
8453
- const coordState = coord.getState();
8454
- LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}${forceInject ? " (force)" : ""}`);
8455
- coord.onEvent("send_message", {
8456
- input: { text: messageText, textFallback: messageText },
8457
- ...forceInject ? { force: true } : {}
8458
- });
8432
+ LOG.info("MeshEvents", `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ""})`);
8459
8433
  }
8460
- return { success: true, forwarded: coordinatorInstances.length };
8434
+ return { success: true, forwarded: 0 };
8461
8435
  }
8462
8436
  function handleMeshForwardEvent(components, payload) {
8463
8437
  const eventName = readNonEmptyString2(payload.event);
@@ -8628,6 +8602,176 @@ var init_mesh_events_coordinator = __esm({
8628
8602
  }
8629
8603
  });
8630
8604
 
8605
+ // src/mesh/mesh-reconcile-loop.ts
8606
+ function resolveReconcileIntervalMs() {
8607
+ const raw = readNonEmptyString2(process.env.MESH_RECONCILE_INTERVAL_MS);
8608
+ if (raw) {
8609
+ const parsed = Number.parseInt(raw, 10);
8610
+ if (Number.isFinite(parsed) && parsed >= 1e3 && parsed <= 6e4) return parsed;
8611
+ }
8612
+ return DEFAULT_RECONCILE_INTERVAL_MS;
8613
+ }
8614
+ function findLiveCoordinators(components) {
8615
+ const out = [];
8616
+ for (const inst of components.instanceManager.getByCategory("cli")) {
8617
+ const state = inst.getState();
8618
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
8619
+ const meshId = readNonEmptyString2(settings.meshCoordinatorFor);
8620
+ if (!meshId) continue;
8621
+ const status = readNonEmptyString2(state.status).toLowerCase();
8622
+ out.push({ meshId, instance: inst, idle: status === "idle" });
8623
+ }
8624
+ return out;
8625
+ }
8626
+ function injectPendingIntoCoordinator(coordinator, pending) {
8627
+ if (!coordinator || !pending.coordinatorMessage) return;
8628
+ const force = shouldForceInjectMeshEvent(pending.event);
8629
+ coordinator.onEvent("send_message", {
8630
+ input: { text: pending.coordinatorMessage, textFallback: pending.coordinatorMessage },
8631
+ ...force ? { force: true } : {}
8632
+ });
8633
+ }
8634
+ async function runMeshReconcileTick(components) {
8635
+ const coordinators = findLiveCoordinators(components);
8636
+ if (coordinators.length === 0) {
8637
+ return;
8638
+ }
8639
+ const byMesh = /* @__PURE__ */ new Map();
8640
+ for (const c of coordinators) {
8641
+ const list = byMesh.get(c.meshId);
8642
+ if (list) list.push(c);
8643
+ else byMesh.set(c.meshId, [c]);
8644
+ }
8645
+ const localDaemonId = readNonEmptyString2(loadConfig().machineId) || void 0;
8646
+ const dispatchMeshCommand = components.dispatchMeshCommand;
8647
+ const store = (() => {
8648
+ try {
8649
+ return MeshRuntimeStore.getInstance();
8650
+ } catch {
8651
+ return void 0;
8652
+ }
8653
+ })();
8654
+ for (const [meshId, meshCoordinators] of byMesh) {
8655
+ if (dispatchMeshCommand) {
8656
+ try {
8657
+ await pullRemoteNodeQueues(components, meshId, localDaemonId);
8658
+ } catch (e) {
8659
+ LOG.warn("MeshReconcile", `Remote node pull failed for mesh ${meshId}: ${e?.message || e}`);
8660
+ }
8661
+ }
8662
+ const idleCoordinators = meshCoordinators.filter((c) => c.idle);
8663
+ const generatingCoordinators = meshCoordinators.filter((c) => !c.idle);
8664
+ const targetCoordinators = idleCoordinators.length > 0 ? idleCoordinators : generatingCoordinators;
8665
+ const forceOnly = idleCoordinators.length === 0;
8666
+ if (store) {
8667
+ try {
8668
+ if (store.pendingEventCount(meshId) === 0) continue;
8669
+ } catch {
8670
+ }
8671
+ }
8672
+ let pendingEvents = [];
8673
+ try {
8674
+ pendingEvents = drainPendingMeshCoordinatorEvents(
8675
+ meshId,
8676
+ localDaemonId,
8677
+ forceOnly ? { onlyEvents: MESH_FORCE_INJECT_EVENTS } : void 0
8678
+ );
8679
+ } catch (e) {
8680
+ LOG.warn("MeshReconcile", `Drain failed for mesh ${meshId}: ${e?.message || e}`);
8681
+ continue;
8682
+ }
8683
+ if (pendingEvents.length === 0) continue;
8684
+ const mode = forceOnly ? "force-drain \u2192 generating" : "inject \u2192 idle";
8685
+ LOG.info("MeshReconcile", `Reconcile ${mode}: ${pendingEvents.length} pending event(s) \u2192 ${targetCoordinators.length} coordinator(s) for mesh ${meshId}`);
8686
+ for (const pending of pendingEvents) {
8687
+ for (const c of targetCoordinators) {
8688
+ injectPendingIntoCoordinator(c.instance, pending);
8689
+ }
8690
+ }
8691
+ }
8692
+ }
8693
+ async function pullRemoteNodeQueues(components, meshId, localDaemonId) {
8694
+ const dispatchMeshCommand = components.dispatchMeshCommand;
8695
+ if (!dispatchMeshCommand) return;
8696
+ const mesh = listMeshes().find((m) => m.id === meshId);
8697
+ if (!mesh) return;
8698
+ const pendingEventArgs = {
8699
+ meshId,
8700
+ ...localDaemonId ? { coordinatorDaemonId: localDaemonId } : {}
8701
+ };
8702
+ for (const node of mesh.nodes) {
8703
+ const nodeDaemonId = readNonEmptyString2(node.daemonId);
8704
+ if (!nodeDaemonId) continue;
8705
+ if (localDaemonId && nodeDaemonId === localDaemonId) continue;
8706
+ let events;
8707
+ try {
8708
+ events = await dispatchMeshCommand(nodeDaemonId, "get_pending_mesh_events", pendingEventArgs);
8709
+ } catch {
8710
+ continue;
8711
+ }
8712
+ const list = extractPendingEvents(events).filter((e) => readNonEmptyString2(e?.meshId) === meshId);
8713
+ for (const event of list) {
8714
+ const payload = buildForwardPayloadFromPending(event);
8715
+ if (!payload.event || !payload.meshId) continue;
8716
+ try {
8717
+ handleMeshForwardEvent(components, payload);
8718
+ } catch {
8719
+ }
8720
+ }
8721
+ }
8722
+ }
8723
+ function extractPendingEvents(raw) {
8724
+ if (Array.isArray(raw)) return raw;
8725
+ if (raw && typeof raw === "object") {
8726
+ const events = raw.events;
8727
+ if (Array.isArray(events)) return events;
8728
+ }
8729
+ return [];
8730
+ }
8731
+ function buildForwardPayloadFromPending(event) {
8732
+ const metadata = event?.metadataEvent && typeof event.metadataEvent === "object" ? event.metadataEvent : {};
8733
+ return {
8734
+ event: readNonEmptyString2(event?.event),
8735
+ meshId: readNonEmptyString2(event?.meshId),
8736
+ nodeId: readNonEmptyString2(event?.nodeId) || readNonEmptyString2(metadata.meshNodeId),
8737
+ workspace: readNonEmptyString2(event?.workspace) || readNonEmptyString2(metadata.workspace),
8738
+ ...metadata
8739
+ };
8740
+ }
8741
+ function setupMeshReconcileLoop(components) {
8742
+ const intervalMs = resolveReconcileIntervalMs();
8743
+ let running = false;
8744
+ const timer = setInterval(() => {
8745
+ if (running) return;
8746
+ running = true;
8747
+ void runMeshReconcileTick(components).catch((e) => LOG.warn("MeshReconcile", `Reconcile tick error: ${e?.message || e}`)).finally(() => {
8748
+ running = false;
8749
+ });
8750
+ }, intervalMs);
8751
+ if (typeof timer.unref === "function") timer.unref();
8752
+ LOG.info("MeshReconcile", `Mesh reconcile loop started (interval ${intervalMs}ms)`);
8753
+ return {
8754
+ stop() {
8755
+ clearInterval(timer);
8756
+ LOG.info("MeshReconcile", "Mesh reconcile loop stopped");
8757
+ }
8758
+ };
8759
+ }
8760
+ var DEFAULT_RECONCILE_INTERVAL_MS;
8761
+ var init_mesh_reconcile_loop = __esm({
8762
+ "src/mesh/mesh-reconcile-loop.ts"() {
8763
+ "use strict";
8764
+ init_config();
8765
+ init_mesh_config();
8766
+ init_logger();
8767
+ init_mesh_events_pending();
8768
+ init_mesh_runtime_store();
8769
+ init_mesh_events_coordinator();
8770
+ init_mesh_events_utils();
8771
+ DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
8772
+ }
8773
+ });
8774
+
8631
8775
  // src/mesh/mesh-events.ts
8632
8776
  var mesh_events_exports = {};
8633
8777
  __export(mesh_events_exports, {
@@ -8638,10 +8782,11 @@ __export(mesh_events_exports, {
8638
8782
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
8639
8783
  handleMeshForwardEvent: () => handleMeshForwardEvent,
8640
8784
  isMeshCoordinatorEvent: () => isMeshCoordinatorEvent,
8641
- markMeshCoordinatorEventDirectDelivered: () => markMeshCoordinatorEventDirectDelivered,
8642
8785
  queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
8643
8786
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
8787
+ runMeshReconcileTick: () => runMeshReconcileTick,
8644
8788
  setupMeshEventForwarding: () => setupMeshEventForwarding,
8789
+ setupMeshReconcileLoop: () => setupMeshReconcileLoop,
8645
8790
  triggerMeshQueue: () => triggerMeshQueue,
8646
8791
  tryAssignQueueTask: () => tryAssignQueueTask
8647
8792
  });
@@ -8650,6 +8795,7 @@ var init_mesh_events = __esm({
8650
8795
  "use strict";
8651
8796
  init_mesh_events_pending();
8652
8797
  init_mesh_events_stale();
8798
+ init_mesh_reconcile_loop();
8653
8799
  init_mesh_events_coordinator();
8654
8800
  }
8655
8801
  });
@@ -55437,6 +55583,7 @@ var SessionRegistry = class {
55437
55583
  init_logger();
55438
55584
  init_config();
55439
55585
  init_mesh_events();
55586
+ init_mesh_reconcile_loop();
55440
55587
 
55441
55588
  // src/boot/process-hardening.ts
55442
55589
  var _hardened = false;
@@ -55638,6 +55785,7 @@ async function initDaemonComponents(config) {
55638
55785
  onMeshCoordinatorEventForwarded: config.onMeshCoordinatorEventForwarded
55639
55786
  };
55640
55787
  setupMeshEventForwarding(components);
55788
+ components.meshReconcileLoop = setupMeshReconcileLoop(components);
55641
55789
  setImmediate(() => void router.resumePendingRefineJobsOnStartup());
55642
55790
  return components;
55643
55791
  }
@@ -55663,10 +55811,15 @@ async function shutdownDaemonComponents(components) {
55663
55811
  agentStreamManager,
55664
55812
  cliManager,
55665
55813
  instanceManager,
55666
- cdpManagers
55814
+ cdpManagers,
55815
+ meshReconcileLoop
55667
55816
  } = components;
55668
55817
  poller.stop();
55669
55818
  cdpInitializer.stop();
55819
+ try {
55820
+ meshReconcileLoop?.stop();
55821
+ } catch {
55822
+ }
55670
55823
  try {
55671
55824
  if (agentStreamManager) {
55672
55825
  await agentStreamManager.dispose(cdpManagers);