@adhdev/daemon-standalone 0.9.82-rc.3 → 0.9.82-rc.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -23490,6 +23490,36 @@ Follow these recovery rules:
23490
23490
  const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
23491
23491
  return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.json`);
23492
23492
  }
23493
+ function getLockPath(meshId) {
23494
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
23495
+ return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.lock`);
23496
+ }
23497
+ function withQueueLock(meshId, fn) {
23498
+ const lockPath = getLockPath(meshId);
23499
+ let fd = -1;
23500
+ for (let i = 0; i < 10; i++) {
23501
+ try {
23502
+ fd = (0, import_fs4.openSync)(lockPath, "wx");
23503
+ break;
23504
+ } catch {
23505
+ const deadline = Date.now() + 30;
23506
+ while (Date.now() < deadline) {
23507
+ }
23508
+ }
23509
+ }
23510
+ try {
23511
+ return fn();
23512
+ } finally {
23513
+ if (fd !== -1) try {
23514
+ (0, import_fs4.closeSync)(fd);
23515
+ } catch {
23516
+ }
23517
+ try {
23518
+ (0, import_fs4.unlinkSync)(lockPath);
23519
+ } catch {
23520
+ }
23521
+ }
23522
+ }
23493
23523
  function readQueue(meshId) {
23494
23524
  const path28 = getQueuePath(meshId);
23495
23525
  if (!(0, import_fs4.existsSync)(path28)) return [];
@@ -23505,20 +23535,22 @@ Follow these recovery rules:
23505
23535
  (0, import_fs4.writeFileSync)(path28, JSON.stringify(queue, null, 2), "utf-8");
23506
23536
  }
23507
23537
  function enqueueTask(meshId, message, opts) {
23508
- const queue = readQueue(meshId);
23509
- const entry = {
23510
- id: (0, import_crypto5.randomUUID)(),
23511
- meshId,
23512
- message,
23513
- status: "pending",
23514
- targetNodeId: opts?.targetNodeId,
23515
- targetSessionId: opts?.targetSessionId,
23516
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
23517
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
23518
- };
23519
- queue.push(entry);
23520
- writeQueue(meshId, queue);
23521
- return entry;
23538
+ return withQueueLock(meshId, () => {
23539
+ const queue = readQueue(meshId);
23540
+ const entry = {
23541
+ id: (0, import_crypto5.randomUUID)(),
23542
+ meshId,
23543
+ message,
23544
+ status: "pending",
23545
+ targetNodeId: opts?.targetNodeId,
23546
+ targetSessionId: opts?.targetSessionId,
23547
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
23548
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
23549
+ };
23550
+ queue.push(entry);
23551
+ writeQueue(meshId, queue);
23552
+ return entry;
23553
+ });
23522
23554
  }
23523
23555
  function getQueue(meshId, opts) {
23524
23556
  let queue = readQueue(meshId);
@@ -23529,100 +23561,111 @@ Follow these recovery rules:
23529
23561
  return queue;
23530
23562
  }
23531
23563
  function claimNextTask(meshId, nodeId, sessionId) {
23532
- const queue = readQueue(meshId);
23533
- const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
23534
- if (hasActiveAssignment) return null;
23535
- let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
23536
- if (targetIdx === -1) {
23537
- targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
23538
- }
23539
- if (targetIdx === -1) {
23540
- targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
23541
- }
23542
- if (targetIdx === -1) return null;
23543
- const entry = queue[targetIdx];
23544
- entry.status = "assigned";
23545
- entry.assignedNodeId = nodeId;
23546
- entry.assignedSessionId = sessionId;
23547
- entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
23548
- entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
23549
- writeQueue(meshId, queue);
23550
- return entry;
23564
+ return withQueueLock(meshId, () => {
23565
+ const queue = readQueue(meshId);
23566
+ const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
23567
+ if (hasActiveAssignment) return null;
23568
+ let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
23569
+ if (targetIdx === -1) {
23570
+ targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
23571
+ }
23572
+ if (targetIdx === -1) {
23573
+ targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
23574
+ }
23575
+ if (targetIdx === -1) return null;
23576
+ const entry = queue[targetIdx];
23577
+ entry.status = "assigned";
23578
+ entry.assignedNodeId = nodeId;
23579
+ entry.assignedSessionId = sessionId;
23580
+ entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
23581
+ entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
23582
+ writeQueue(meshId, queue);
23583
+ return entry;
23584
+ });
23551
23585
  }
23552
23586
  function updateTaskStatus(meshId, taskId, status) {
23553
- const queue = readQueue(meshId);
23554
- const idx = queue.findIndex((q) => q.id === taskId);
23555
- if (idx === -1) return null;
23556
- queue[idx].status = status;
23557
- queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
23558
- writeQueue(meshId, queue);
23559
- return queue[idx];
23587
+ return withQueueLock(meshId, () => {
23588
+ const queue = readQueue(meshId);
23589
+ const idx = queue.findIndex((q) => q.id === taskId);
23590
+ if (idx === -1) return null;
23591
+ queue[idx].status = status;
23592
+ queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
23593
+ writeQueue(meshId, queue);
23594
+ return queue[idx];
23595
+ });
23560
23596
  }
23561
23597
  function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
23562
- const queue = readQueue(meshId);
23563
- const idx = queue.findIndex((q) => q.id === taskId);
23564
- if (idx === -1) return null;
23565
- const now = (/* @__PURE__ */ new Date()).toISOString();
23566
- queue[idx].autoLaunch = {
23567
- ...autoLaunch,
23568
- updatedAt: now
23569
- };
23570
- queue[idx].updatedAt = now;
23571
- writeQueue(meshId, queue);
23572
- return queue[idx];
23598
+ return withQueueLock(meshId, () => {
23599
+ const queue = readQueue(meshId);
23600
+ const idx = queue.findIndex((q) => q.id === taskId);
23601
+ if (idx === -1) return null;
23602
+ const now = (/* @__PURE__ */ new Date()).toISOString();
23603
+ queue[idx].autoLaunch = { ...autoLaunch, updatedAt: now };
23604
+ queue[idx].updatedAt = now;
23605
+ writeQueue(meshId, queue);
23606
+ return queue[idx];
23607
+ });
23573
23608
  }
23574
23609
  function cancelTask(meshId, taskId, opts) {
23575
- const queue = readQueue(meshId);
23576
- const idx = queue.findIndex((q) => q.id === taskId);
23577
- if (idx === -1) return null;
23578
- const now = (/* @__PURE__ */ new Date()).toISOString();
23579
- queue[idx].status = "cancelled";
23580
- queue[idx].updatedAt = now;
23581
- queue[idx].cancelledAt = now;
23582
- if (opts?.reason) queue[idx].cancelReason = opts.reason;
23583
- writeQueue(meshId, queue);
23584
- return queue[idx];
23610
+ return withQueueLock(meshId, () => {
23611
+ const queue = readQueue(meshId);
23612
+ const idx = queue.findIndex((q) => q.id === taskId);
23613
+ if (idx === -1) return null;
23614
+ const now = (/* @__PURE__ */ new Date()).toISOString();
23615
+ queue[idx].status = "cancelled";
23616
+ queue[idx].updatedAt = now;
23617
+ queue[idx].cancelledAt = now;
23618
+ if (opts?.reason) queue[idx].cancelReason = opts.reason;
23619
+ writeQueue(meshId, queue);
23620
+ return queue[idx];
23621
+ });
23585
23622
  }
23586
23623
  function requeueTask(meshId, taskId, opts) {
23587
- const queue = readQueue(meshId);
23588
- const idx = queue.findIndex((q) => q.id === taskId);
23589
- if (idx === -1) return null;
23590
- const entry = queue[idx];
23591
- const now = (/* @__PURE__ */ new Date()).toISOString();
23592
- entry.status = "pending";
23593
- delete entry.assignedNodeId;
23594
- delete entry.assignedSessionId;
23595
- delete entry.cancelledAt;
23596
- delete entry.cancelReason;
23597
- if (opts?.clearTargetNode) delete entry.targetNodeId;
23598
- if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
23599
- if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
23600
- if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
23601
- entry.updatedAt = now;
23602
- entry.requeuedAt = now;
23603
- entry.requeueCount = (entry.requeueCount || 0) + 1;
23604
- if (opts?.reason) entry.requeueReason = opts.reason;
23605
- writeQueue(meshId, queue);
23606
- return entry;
23607
- }
23608
- function updateSessionTaskStatus(meshId, sessionId, status) {
23609
- const queue = readQueue(meshId);
23610
- let bestIdx = -1;
23611
- let bestTime = 0;
23612
- for (let i = queue.length - 1; i >= 0; i--) {
23613
- if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
23624
+ return withQueueLock(meshId, () => {
23625
+ const queue = readQueue(meshId);
23626
+ const idx = queue.findIndex((q) => q.id === taskId);
23627
+ if (idx === -1) return null;
23628
+ const entry = queue[idx];
23629
+ const now = (/* @__PURE__ */ new Date()).toISOString();
23630
+ entry.status = "pending";
23631
+ delete entry.assignedNodeId;
23632
+ delete entry.assignedSessionId;
23633
+ delete entry.cancelledAt;
23634
+ delete entry.cancelReason;
23635
+ if (opts?.clearTargetNode) delete entry.targetNodeId;
23636
+ if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
23637
+ if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
23638
+ if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
23639
+ entry.updatedAt = now;
23640
+ entry.requeuedAt = now;
23641
+ entry.requeueCount = (entry.requeueCount || 0) + 1;
23642
+ if (opts?.reason) entry.requeueReason = opts.reason;
23643
+ writeQueue(meshId, queue);
23644
+ return entry;
23645
+ });
23646
+ }
23647
+ function updateSessionTaskStatus(meshId, sessionId, status, opts) {
23648
+ return withQueueLock(meshId, () => {
23649
+ const queue = readQueue(meshId);
23650
+ const occurredAtTime = opts?.occurredAt ? new Date(opts.occurredAt).getTime() : Number.NaN;
23651
+ const hasOccurredAt = Number.isFinite(occurredAtTime);
23652
+ let bestIdx = -1;
23653
+ let bestTime = 0;
23654
+ for (let i = queue.length - 1; i >= 0; i--) {
23655
+ if (queue[i].assignedSessionId !== sessionId || queue[i].status !== "assigned") continue;
23614
23656
  const time3 = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
23657
+ if (hasOccurredAt && Number.isFinite(time3) && time3 > occurredAtTime) continue;
23615
23658
  if (time3 > bestTime) {
23616
23659
  bestTime = time3;
23617
23660
  bestIdx = i;
23618
23661
  }
23619
23662
  }
23620
- }
23621
- if (bestIdx === -1) return null;
23622
- queue[bestIdx].status = status;
23623
- queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
23624
- writeQueue(meshId, queue);
23625
- return queue[bestIdx];
23663
+ if (bestIdx === -1) return null;
23664
+ queue[bestIdx].status = status;
23665
+ queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
23666
+ writeQueue(meshId, queue);
23667
+ return queue[bestIdx];
23668
+ });
23626
23669
  }
23627
23670
  function getMeshQueueStats(meshId) {
23628
23671
  const queue = readQueue(meshId);
@@ -24046,18 +24089,75 @@ Follow these recovery rules:
24046
24089
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
24047
24090
  getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
24048
24091
  handleMeshForwardEvent: () => handleMeshForwardEvent,
24092
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
24049
24093
  setupMeshEventForwarding: () => setupMeshEventForwarding,
24050
24094
  triggerMeshQueue: () => triggerMeshQueue,
24051
24095
  tryAssignQueueTask: () => tryAssignQueueTask
24052
24096
  });
24053
- function drainPendingMeshCoordinatorEvents() {
24054
- return pendingMeshCoordinatorEvents.splice(0);
24097
+ function sweepExpiredRemoteIdleSessions() {
24098
+ const now = Date.now();
24099
+ for (const [key, session] of remoteIdleSessions) {
24100
+ if (session.expiresAt <= now) remoteIdleSessions.delete(key);
24101
+ }
24102
+ }
24103
+ function getPendingEventsPath(meshId) {
24104
+ const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
24105
+ return (0, import_path5.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
24106
+ }
24107
+ function queuePendingMeshCoordinatorEvent(event) {
24108
+ try {
24109
+ (0, import_fs6.appendFileSync)(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
24110
+ return true;
24111
+ } catch (e) {
24112
+ LOG2.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
24113
+ return false;
24114
+ }
24115
+ }
24116
+ function drainPendingMeshCoordinatorEvents(meshId) {
24117
+ if (!meshId) return [];
24118
+ const path28 = getPendingEventsPath(meshId);
24119
+ if (!(0, import_fs6.existsSync)(path28)) return [];
24120
+ try {
24121
+ const raw = (0, import_fs6.readFileSync)(path28, "utf-8");
24122
+ try {
24123
+ (0, import_fs6.unlinkSync)(path28);
24124
+ } catch {
24125
+ }
24126
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
24127
+ try {
24128
+ return [JSON.parse(line)];
24129
+ } catch {
24130
+ return [];
24131
+ }
24132
+ });
24133
+ } catch {
24134
+ return [];
24135
+ }
24055
24136
  }
24056
- function getPendingMeshCoordinatorEvents() {
24057
- return pendingMeshCoordinatorEvents.slice();
24137
+ function getPendingMeshCoordinatorEvents(meshId) {
24138
+ if (!meshId) return [];
24139
+ const path28 = getPendingEventsPath(meshId);
24140
+ if (!(0, import_fs6.existsSync)(path28)) return [];
24141
+ try {
24142
+ const raw = (0, import_fs6.readFileSync)(path28, "utf-8");
24143
+ return raw.split("\n").filter(Boolean).flatMap((line) => {
24144
+ try {
24145
+ return [JSON.parse(line)];
24146
+ } catch {
24147
+ return [];
24148
+ }
24149
+ });
24150
+ } catch {
24151
+ return [];
24152
+ }
24058
24153
  }
24059
- function clearPendingMeshCoordinatorEvents() {
24060
- pendingMeshCoordinatorEvents.splice(0);
24154
+ function clearPendingMeshCoordinatorEvents(meshId) {
24155
+ if (!meshId) return;
24156
+ const path28 = getPendingEventsPath(meshId);
24157
+ if ((0, import_fs6.existsSync)(path28)) try {
24158
+ (0, import_fs6.unlinkSync)(path28);
24159
+ } catch {
24160
+ }
24061
24161
  }
24062
24162
  function readNonEmptyString(value) {
24063
24163
  return typeof value === "string" && value.trim() ? value.trim() : "";
@@ -24103,6 +24203,38 @@ Follow these recovery rules:
24103
24203
  if (isIntentionalCleanupStopMetadata(args.metadataEvent)) return true;
24104
24204
  return hasRecentIntentionalCleanupStop(args.meshId, args.sessionId, args.nodeId);
24105
24205
  }
24206
+ function readEventTimestamp(value) {
24207
+ if (typeof value === "number" && Number.isFinite(value)) return value;
24208
+ if (typeof value === "string" && value.trim()) {
24209
+ const numeric = Number(value);
24210
+ if (Number.isFinite(numeric)) return numeric;
24211
+ const parsed = Date.parse(value);
24212
+ if (Number.isFinite(parsed)) return parsed;
24213
+ }
24214
+ return null;
24215
+ }
24216
+ function buildMeshCompletionFingerprint(args) {
24217
+ const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString(args.finalSummary).slice(0, 200);
24218
+ return [
24219
+ args.meshId,
24220
+ args.event,
24221
+ args.sessionId,
24222
+ args.providerType || "",
24223
+ args.providerSessionId || "",
24224
+ timestampPart
24225
+ ].join("::");
24226
+ }
24227
+ function isDuplicateMeshCompletionEvent(args) {
24228
+ const fingerprint = buildMeshCompletionFingerprint(args);
24229
+ if (!fingerprint) return false;
24230
+ const now = Date.now();
24231
+ for (const [key, seenAt] of recentCompletionFingerprints.entries()) {
24232
+ if (now - seenAt > RECENT_COMPLETION_FINGERPRINT_TTL_MS) recentCompletionFingerprints.delete(key);
24233
+ }
24234
+ if (recentCompletionFingerprints.has(fingerprint)) return true;
24235
+ recentCompletionFingerprints.set(fingerprint, now);
24236
+ return false;
24237
+ }
24106
24238
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
24107
24239
  const task = claimNextTask(meshId, nodeId, sessionId);
24108
24240
  if (!task) {
@@ -24121,7 +24253,16 @@ Follow these recovery rules:
24121
24253
  message: task.message
24122
24254
  }).catch((e) => {
24123
24255
  LOG2.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
24124
- updateTaskStatus(meshId, task.id, "failed");
24256
+ updateTaskStatus(meshId, task.id, "pending");
24257
+ try {
24258
+ appendLedgerEntry(meshId, {
24259
+ kind: "dispatch_failed",
24260
+ nodeId,
24261
+ sessionId,
24262
+ payload: { taskId: task.id, error: e?.message, retryable: true }
24263
+ });
24264
+ } catch {
24265
+ }
24125
24266
  });
24126
24267
  return true;
24127
24268
  }
@@ -24455,18 +24596,36 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24455
24596
  LOG2.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
24456
24597
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
24457
24598
  }
24599
+ const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
24600
+ if (args.event === "agent:generating_completed" && eventSessionId) {
24601
+ const duplicateCompletion = isDuplicateMeshCompletionEvent({
24602
+ meshId: args.meshId,
24603
+ event: args.event,
24604
+ sessionId: eventSessionId,
24605
+ providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
24606
+ providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
24607
+ timestamp: eventTimestamp,
24608
+ finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
24609
+ });
24610
+ if (duplicateCompletion) {
24611
+ LOG2.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
24612
+ return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
24613
+ }
24614
+ }
24458
24615
  let completedTaskForLedger = null;
24459
24616
  if (args.event === "agent:generating_completed") {
24460
24617
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
24461
24618
  const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
24462
24619
  const providerType = readNonEmptyString(args.metadataEvent.providerType);
24463
24620
  if (sessionId) {
24464
- const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
24621
+ const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed", {
24622
+ occurredAt: eventTimestamp !== null ? new Date(eventTimestamp).toISOString() : void 0
24623
+ });
24465
24624
  completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
24466
24625
  if (nodeId && providerType) {
24467
- setTimeout(() => {
24626
+ setImmediate(() => {
24468
24627
  tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
24469
- }, 500);
24628
+ });
24470
24629
  }
24471
24630
  }
24472
24631
  } else if (args.event === "agent:ready") {
@@ -24504,13 +24663,17 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24504
24663
  }
24505
24664
  }
24506
24665
  if (sessionId && nodeId && providerType) {
24507
- remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
24508
- setTimeout(() => {
24666
+ sweepExpiredRemoteIdleSessions();
24667
+ remoteIdleSessions.set(`${nodeId}:${sessionId}`, {
24668
+ nodeId,
24669
+ sessionId,
24670
+ providerType,
24671
+ expiresAt: Date.now() + REMOTE_IDLE_SESSION_TTL_MS
24672
+ });
24673
+ setImmediate(() => {
24509
24674
  const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
24510
- if (assigned) {
24511
- remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
24512
- }
24513
- }, 500);
24675
+ if (assigned) remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
24676
+ });
24514
24677
  }
24515
24678
  } else if (args.event === "agent:generating_started") {
24516
24679
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
@@ -24621,17 +24784,18 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24621
24784
  return true;
24622
24785
  });
24623
24786
  if (coordinatorInstances.length === 0) {
24624
- if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
24625
- pendingMeshCoordinatorEvents.push({
24626
- event: args.event,
24627
- meshId: args.meshId,
24628
- nodeLabel: args.nodeLabel,
24629
- metadataEvent: {
24630
- ...args.metadataEvent,
24631
- ...recoveryContext ? { recoveryContext } : {}
24632
- },
24633
- queuedAt: Date.now()
24634
- });
24787
+ if (queuePendingMeshCoordinatorEvent({
24788
+ event: args.event,
24789
+ meshId: args.meshId,
24790
+ nodeLabel: args.nodeLabel,
24791
+ nodeId: args.nodeId || void 0,
24792
+ workspace: readNonEmptyString(args.metadataEvent.workspace),
24793
+ metadataEvent: {
24794
+ ...args.metadataEvent,
24795
+ ...recoveryContext ? { recoveryContext } : {}
24796
+ },
24797
+ queuedAt: Date.now()
24798
+ })) {
24635
24799
  LOG2.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
24636
24800
  }
24637
24801
  return { success: true, forwarded: 0 };
@@ -24670,6 +24834,7 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24670
24834
  providerType: readNonEmptyString(payload.providerType),
24671
24835
  providerSessionId: readNonEmptyString(payload.providerSessionId),
24672
24836
  finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary),
24837
+ ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
24673
24838
  intentional: payload.intentional === true,
24674
24839
  intentionalStop: payload.intentionalStop === true,
24675
24840
  operatorCleanup: payload.operatorCleanup === true,
@@ -24712,27 +24877,31 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24712
24877
  });
24713
24878
  });
24714
24879
  }
24880
+ var import_fs6;
24881
+ var import_path5;
24882
+ var REMOTE_IDLE_SESSION_TTL_MS;
24715
24883
  var remoteIdleSessions;
24716
- var MAX_PENDING_EVENTS;
24717
- var pendingMeshCoordinatorEvents;
24718
24884
  var MESH_COORDINATOR_EVENTS;
24719
24885
  var EVENT_TO_LEDGER_KIND;
24720
24886
  var INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS;
24887
+ var RECENT_COMPLETION_FINGERPRINT_TTL_MS;
24888
+ var recentCompletionFingerprints;
24721
24889
  var autoLaunchInProgress;
24722
24890
  var autoLaunchCooldownUntil;
24723
24891
  var AUTO_LAUNCH_COOLDOWN_MS;
24724
24892
  var init_mesh_events = __esm2({
24725
24893
  "src/mesh/mesh-events.ts"() {
24726
24894
  "use strict";
24895
+ import_fs6 = require("fs");
24896
+ import_path5 = require("path");
24727
24897
  init_config();
24728
24898
  init_mesh_config();
24729
24899
  init_cli_detector();
24730
24900
  init_logger();
24731
24901
  init_mesh_ledger();
24732
24902
  init_mesh_work_queue();
24903
+ REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
24733
24904
  remoteIdleSessions = /* @__PURE__ */ new Map();
24734
- MAX_PENDING_EVENTS = 50;
24735
- pendingMeshCoordinatorEvents = [];
24736
24905
  MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
24737
24906
  "agent:generating_started",
24738
24907
  "agent:generating_completed",
@@ -24748,6 +24917,8 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
24748
24917
  "monitor:long_generating": "task_stalled"
24749
24918
  };
24750
24919
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
24920
+ RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
24921
+ recentCompletionFingerprints = /* @__PURE__ */ new Map();
24751
24922
  autoLaunchInProgress = /* @__PURE__ */ new Set();
24752
24923
  autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
24753
24924
  AUTO_LAUNCH_COOLDOWN_MS = 5e3;
@@ -28013,6 +28184,7 @@ ${lastSnapshot}`;
28013
28184
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate2,
28014
28185
  prepareSessionModalUpdate: () => prepareSessionModalUpdate2,
28015
28186
  probeCdpPort: () => probeCdpPort,
28187
+ queuePendingMeshCoordinatorEvent: () => queuePendingMeshCoordinatorEvent,
28016
28188
  readChatHistory: () => readChatHistory,
28017
28189
  readLedgerEntries: () => readLedgerEntries,
28018
28190
  readLedgerSlice: () => readLedgerSlice,
@@ -28062,8 +28234,14 @@ ${lastSnapshot}`;
28062
28234
  const includeSubmodules = options.includeSubmodules !== false;
28063
28235
  try {
28064
28236
  const repo = await resolveGitRepository(workspace, options);
28065
- const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
28066
- const parsed = parsePorcelainV2Status(statusOutput.stdout);
28237
+ let parsed = await readPorcelainStatus(repo, options);
28238
+ let upstreamProbe = getInitialUpstreamProbe(parsed);
28239
+ if (options.refreshUpstream) {
28240
+ upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
28241
+ if (upstreamProbe.upstreamStatus === "fresh") {
28242
+ parsed = await readPorcelainStatus(repo, options);
28243
+ }
28244
+ }
28067
28245
  const head = await readHead(repo, options);
28068
28246
  const stashCount = await readStashCount(repo, options);
28069
28247
  let submodules;
@@ -28078,6 +28256,9 @@ ${lastSnapshot}`;
28078
28256
  headCommit: head.commit,
28079
28257
  headMessage: head.message,
28080
28258
  upstream: parsed.upstream,
28259
+ upstreamStatus: parsed.upstream ? upstreamProbe.upstreamStatus : "no_upstream",
28260
+ upstreamFetchedAt: upstreamProbe.upstreamFetchedAt,
28261
+ upstreamFetchError: upstreamProbe.upstreamFetchError,
28081
28262
  ahead: parsed.ahead,
28082
28263
  behind: parsed.behind,
28083
28264
  staged: parsed.staged,
@@ -28102,6 +28283,60 @@ ${lastSnapshot}`;
28102
28283
  );
28103
28284
  }
28104
28285
  }
28286
+ async function readPorcelainStatus(repo, options) {
28287
+ const statusOutput = await runGit(repo, ["status", "--porcelain=v2", "--branch"], options);
28288
+ return parsePorcelainV2Status(statusOutput.stdout);
28289
+ }
28290
+ function getInitialUpstreamProbe(parsed) {
28291
+ return {
28292
+ upstreamStatus: parsed.upstream ? "unchecked" : "no_upstream"
28293
+ };
28294
+ }
28295
+ async function refreshTrackedUpstream(repo, parsed, options) {
28296
+ if (!parsed.upstream || !parsed.branch) {
28297
+ return { upstreamStatus: "no_upstream" };
28298
+ }
28299
+ const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
28300
+ if (!remoteName) {
28301
+ return {
28302
+ upstreamStatus: "stale",
28303
+ upstreamFetchError: `Unable to resolve remote for upstream '${parsed.upstream}'`
28304
+ };
28305
+ }
28306
+ try {
28307
+ await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
28308
+ return {
28309
+ upstreamStatus: "fresh",
28310
+ upstreamFetchedAt: Date.now()
28311
+ };
28312
+ } catch (error48) {
28313
+ return {
28314
+ upstreamStatus: "stale",
28315
+ upstreamFetchError: formatGitError(error48)
28316
+ };
28317
+ }
28318
+ }
28319
+ async function readBranchRemote(repo, branch, options) {
28320
+ try {
28321
+ const result = await runGit(repo, ["config", "--get", `branch.${branch}.remote`], options);
28322
+ return result.stdout.trim() || null;
28323
+ } catch {
28324
+ return null;
28325
+ }
28326
+ }
28327
+ function inferRemoteName(upstream) {
28328
+ const [remoteName] = upstream.split("/");
28329
+ return remoteName?.trim() || null;
28330
+ }
28331
+ function formatGitError(error48) {
28332
+ if (error48 instanceof GitCommandError) {
28333
+ return error48.stderr || error48.message;
28334
+ }
28335
+ if (error48 instanceof Error) {
28336
+ return error48.message;
28337
+ }
28338
+ return String(error48);
28339
+ }
28105
28340
  function parsePorcelainV2Status(output) {
28106
28341
  const parsed = {
28107
28342
  branch: null,
@@ -28196,6 +28431,7 @@ ${lastSnapshot}`;
28196
28431
  headCommit: null,
28197
28432
  headMessage: null,
28198
28433
  upstream: null,
28434
+ upstreamStatus: "unavailable",
28199
28435
  ahead: 0,
28200
28436
  behind: 0,
28201
28437
  staged: 0,
@@ -28472,6 +28708,9 @@ ${lastSnapshot}`;
28472
28708
  isGitRepo: status.isGitRepo,
28473
28709
  repoRoot: status.repoRoot,
28474
28710
  branch: status.branch,
28711
+ upstreamStatus: status.upstreamStatus,
28712
+ upstreamFetchedAt: status.upstreamFetchedAt,
28713
+ upstreamFetchError: status.upstreamFetchError,
28475
28714
  dirty: status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0 || conflictCount > 0 || changedFiles > 0,
28476
28715
  changedFiles,
28477
28716
  ahead: status.ahead,
@@ -28810,7 +29049,7 @@ ${lastSnapshot}`;
28810
29049
  });
28811
29050
  function createDefaultGitCommandServices() {
28812
29051
  return {
28813
- getStatus: ({ workspace }) => getGitRepoStatus(workspace),
29052
+ getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
28814
29053
  getDiffSummary: ({ workspace }) => getGitDiffSummary(workspace),
28815
29054
  getDiffFile: ({ workspace, path: filePath }) => getGitFileDiff(workspace, filePath),
28816
29055
  createSnapshot: ({ workspace, reason, sessionId, turnId }) => defaultSnapshotStore.create({
@@ -28896,7 +29135,7 @@ ${lastSnapshot}`;
28896
29135
  switch (command) {
28897
29136
  case "git_status": {
28898
29137
  if (!services.getStatus) return serviceNotImplemented(command);
28899
- const status = await runService(() => services.getStatus({ workspace }));
29138
+ const status = await runService(() => services.getStatus({ workspace, refreshUpstream: optionalBoolean(args?.refreshUpstream) }));
28900
29139
  return "success" in status ? status : { success: true, status };
28901
29140
  }
28902
29141
  case "git_diff_summary": {
@@ -29904,8 +30143,8 @@ ${lastSnapshot}`;
29904
30143
  this.targetDaemonId = context.targetDaemonId;
29905
30144
  }
29906
30145
  };
29907
- var import_fs6 = require("fs");
29908
- var import_path5 = require("path");
30146
+ var import_fs7 = require("fs");
30147
+ var import_path6 = require("path");
29909
30148
  init_config();
29910
30149
  var DEFAULT_STATE = {
29911
30150
  recentActivity: [],
@@ -29919,7 +30158,7 @@ ${lastSnapshot}`;
29919
30158
  return !!value && typeof value === "object" && !Array.isArray(value);
29920
30159
  }
29921
30160
  function getStatePath() {
29922
- return (0, import_path5.join)(getConfigDir(), "state.json");
30161
+ return (0, import_path6.join)(getConfigDir(), "state.json");
29923
30162
  }
29924
30163
  function normalizeState(raw) {
29925
30164
  const parsed = isPlainObject22(raw) ? raw : {};
@@ -29955,11 +30194,11 @@ ${lastSnapshot}`;
29955
30194
  }
29956
30195
  function loadState() {
29957
30196
  const statePath = getStatePath();
29958
- if (!(0, import_fs6.existsSync)(statePath)) {
30197
+ if (!(0, import_fs7.existsSync)(statePath)) {
29959
30198
  return { ...DEFAULT_STATE };
29960
30199
  }
29961
30200
  try {
29962
- const raw = (0, import_fs6.readFileSync)(statePath, "utf-8");
30201
+ const raw = (0, import_fs7.readFileSync)(statePath, "utf-8");
29963
30202
  return normalizeState(JSON.parse(raw));
29964
30203
  } catch {
29965
30204
  return { ...DEFAULT_STATE };
@@ -29968,13 +30207,13 @@ ${lastSnapshot}`;
29968
30207
  function saveState(state) {
29969
30208
  const statePath = getStatePath();
29970
30209
  const normalized = normalizeState(state);
29971
- (0, import_fs6.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
30210
+ (0, import_fs7.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
29972
30211
  }
29973
30212
  function resetState() {
29974
30213
  saveState({ ...DEFAULT_STATE });
29975
30214
  }
29976
30215
  var import_child_process2 = require("child_process");
29977
- var import_fs7 = require("fs");
30216
+ var import_fs8 = require("fs");
29978
30217
  var import_os22 = require("os");
29979
30218
  var path10 = __toESM2(require("path"));
29980
30219
  var BUILTIN_IDE_DEFINITIONS = [];
@@ -29998,7 +30237,7 @@ ${lastSnapshot}`;
29998
30237
  if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
29999
30238
  const candidate = trimmed.startsWith("~") ? path10.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
30000
30239
  const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
30001
- return (0, import_fs7.existsSync)(resolved) ? resolved : null;
30240
+ return (0, import_fs8.existsSync)(resolved) ? resolved : null;
30002
30241
  }
30003
30242
  try {
30004
30243
  const result = (0, import_child_process2.execSync)(
@@ -30029,9 +30268,9 @@ ${lastSnapshot}`;
30029
30268
  if (normalized.includes("*")) {
30030
30269
  const username = home.split(/[\\/]/).pop() || "";
30031
30270
  const resolved = normalized.replace("*", username);
30032
- if ((0, import_fs7.existsSync)(resolved)) return resolved;
30271
+ if ((0, import_fs8.existsSync)(resolved)) return resolved;
30033
30272
  } else {
30034
- if ((0, import_fs7.existsSync)(normalized)) return normalized;
30273
+ if ((0, import_fs8.existsSync)(normalized)) return normalized;
30035
30274
  }
30036
30275
  }
30037
30276
  return null;
@@ -30045,7 +30284,7 @@ ${lastSnapshot}`;
30045
30284
  let resolvedCli = cliPath;
30046
30285
  if (!resolvedCli && appPath && os222 === "darwin") {
30047
30286
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
30048
- if ((0, import_fs7.existsSync)(bundledCli)) resolvedCli = bundledCli;
30287
+ if ((0, import_fs8.existsSync)(bundledCli)) resolvedCli = bundledCli;
30049
30288
  }
30050
30289
  if (!resolvedCli && appPath && os222 === "win32") {
30051
30290
  const { dirname: dirname9 } = await import("path");
@@ -30058,7 +30297,7 @@ ${lastSnapshot}`;
30058
30297
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
30059
30298
  ];
30060
30299
  for (const c of candidates) {
30061
- if ((0, import_fs7.existsSync)(c)) {
30300
+ if ((0, import_fs8.existsSync)(c)) {
30062
30301
  resolvedCli = c;
30063
30302
  break;
30064
30303
  }
@@ -31928,7 +32167,8 @@ ${lastSnapshot}`;
31928
32167
  }
31929
32168
  }
31930
32169
  };
31931
- function extractFinalSummaryFromMessages(messages, maxChars = 500) {
32170
+ var DEFAULT_FINAL_SUMMARY_MAX_CHARS = 4e3;
32171
+ function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
31932
32172
  if (!Array.isArray(messages) || messages.length === 0) return "";
31933
32173
  for (let i = messages.length - 1; i >= 0; i--) {
31934
32174
  const msg = messages[i];
@@ -39122,7 +39362,7 @@ ${effect.notification.body || ""}`.trim();
39122
39362
  var os13 = __toESM2(require("os"));
39123
39363
  var path18 = __toESM2(require("path"));
39124
39364
  var crypto4 = __toESM2(require("crypto"));
39125
- var import_fs8 = require("fs");
39365
+ var import_fs9 = require("fs");
39126
39366
  var import_child_process6 = require("child_process");
39127
39367
  var import_chalk = __toESM2((init_source(), __toCommonJS(source_exports)));
39128
39368
  init_provider_cli_adapter();
@@ -41580,7 +41820,7 @@ ${rawInput}` : rawInput;
41580
41820
  const trimmed = command.trim();
41581
41821
  if (!trimmed) return false;
41582
41822
  if (isExplicitCommand(trimmed)) {
41583
- return (0, import_fs8.existsSync)(expandExecutable(trimmed));
41823
+ return (0, import_fs9.existsSync)(expandExecutable(trimmed));
41584
41824
  }
41585
41825
  try {
41586
41826
  (0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -41609,10 +41849,10 @@ ${rawInput}` : rawInput;
41609
41849
  }
41610
41850
  function ensureEmptyDelegatedMcpConfig(workspace) {
41611
41851
  const baseDir = path18.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
41612
- (0, import_fs8.mkdirSync)(baseDir, { recursive: true });
41852
+ (0, import_fs9.mkdirSync)(baseDir, { recursive: true });
41613
41853
  const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
41614
41854
  const filePath = path18.join(baseDir, `${workspaceHash}.json`);
41615
- (0, import_fs8.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
41855
+ (0, import_fs9.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
41616
41856
  return filePath;
41617
41857
  }
41618
41858
  function buildCoordinatorDelegatedCliLaunchOptions(input) {
@@ -45763,7 +46003,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
45763
46003
  }
45764
46004
  }
45765
46005
  var import_os3 = require("os");
45766
- var import_path6 = require("path");
46006
+ var import_path7 = require("path");
45767
46007
  var fs10 = __toESM2(require("fs"));
45768
46008
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
45769
46009
  var CHANNEL_SERVER_URL = {
@@ -45812,52 +46052,33 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
45812
46052
  }
45813
46053
  return void 0;
45814
46054
  }
45815
- function buildCachedInlineMeshGitStatus(node) {
45816
- const cachedStatus = readObjectRecord(node?.cachedStatus);
45817
- const cachedGit = readObjectRecord(cachedStatus.git);
45818
- if (Object.keys(cachedGit).length) {
45819
- const conflictFiles2 = Array.isArray(cachedGit.conflictFiles) ? cachedGit.conflictFiles.filter((value) => typeof value === "string") : [];
45820
- const conflictCount2 = readNumberValue(cachedGit.conflicts) ?? conflictFiles2.length;
45821
- const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
45822
- const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
45823
- if (isGitRepo2 !== void 0) {
45824
- return {
45825
- workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
45826
- repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
45827
- isGitRepo: isGitRepo2,
45828
- branch: readStringValue(cachedGit.branch) ?? null,
45829
- headCommit: readStringValue(cachedGit.headCommit) ?? null,
45830
- headMessage: readStringValue(cachedGit.headMessage) ?? null,
45831
- upstream: readStringValue(cachedGit.upstream) ?? null,
45832
- ahead: readNumberValue(cachedGit.ahead) ?? 0,
45833
- behind: readNumberValue(cachedGit.behind) ?? 0,
45834
- staged: readNumberValue(cachedGit.staged) ?? 0,
45835
- modified: readNumberValue(cachedGit.modified) ?? 0,
45836
- untracked: readNumberValue(cachedGit.untracked) ?? 0,
45837
- deleted: readNumberValue(cachedGit.deleted) ?? 0,
45838
- renamed: readNumberValue(cachedGit.renamed) ?? 0,
45839
- hasConflicts: hasConflicts2,
45840
- conflictFiles: conflictFiles2,
45841
- stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
45842
- lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now()
45843
- };
45844
- }
45845
- }
45846
- const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
45847
- const gitResult = readObjectRecord(rawGit.result);
45848
- const directStatus = readObjectRecord(rawGit.status);
45849
- const nestedStatus = readObjectRecord(gitResult.status);
45850
- const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
45851
- const probeGit = readObjectRecord(rawProbe.git);
45852
- const probeGitResult = readObjectRecord(probeGit.result);
45853
- const probeDirectStatus = readObjectRecord(probeGit.status);
45854
- const probeNestedStatus = readObjectRecord(probeGitResult.status);
45855
- const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
46055
+ function readGitSubmodules(value) {
46056
+ if (!Array.isArray(value)) return void 0;
46057
+ const submodules = value.map((entry) => {
46058
+ const submodule = readObjectRecord(entry);
46059
+ const path28 = readStringValue(submodule.path);
46060
+ const commit = readStringValue(submodule.commit);
46061
+ const repoPath = readStringValue(submodule.repoPath, submodule.repo_root);
46062
+ if (!path28 || !commit || !repoPath) return null;
46063
+ return {
46064
+ path: path28,
46065
+ commit,
46066
+ repoPath,
46067
+ dirty: readBooleanValue(submodule.dirty) ?? false,
46068
+ outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
46069
+ lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
46070
+ ...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
46071
+ };
46072
+ }).filter((entry) => entry !== null);
46073
+ return submodules.length > 0 ? submodules : void 0;
46074
+ }
46075
+ function normalizeInlineMeshGitStatus(status, node, options) {
45856
46076
  const isGitRepo = readBooleanValue(status.isGitRepo);
45857
46077
  if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
45858
46078
  const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
45859
46079
  const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
45860
46080
  const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
46081
+ const submodules = readGitSubmodules(status.submodules);
45861
46082
  return {
45862
46083
  workspace: readStringValue(status.workspace, node?.workspace) || "",
45863
46084
  repoRoot: readStringValue(status.repoRoot, node?.repoRoot, node?.workspace) || null,
@@ -45876,29 +46097,285 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
45876
46097
  hasConflicts,
45877
46098
  conflictFiles,
45878
46099
  stashCount: readNumberValue(status.stashCount) ?? 0,
45879
- lastCheckedAt: Date.now()
46100
+ lastCheckedAt: options?.lastCheckedAt ?? readNumberValue(status.lastCheckedAt) ?? Date.now(),
46101
+ ...submodules ? { submodules } : {}
45880
46102
  };
45881
46103
  }
45882
- function applyCachedInlineMeshNodeStatus(status, node) {
46104
+ function buildInlineMeshTransitGitStatus(node) {
46105
+ const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
46106
+ const gitResult = readObjectRecord(rawGit.result);
46107
+ const directStatus = readObjectRecord(rawGit.status);
46108
+ const nestedStatus = readObjectRecord(gitResult.status);
46109
+ const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
46110
+ const probeGit = readObjectRecord(rawProbe.git);
46111
+ const probeGitResult = readObjectRecord(probeGit.result);
46112
+ const probeDirectStatus = readObjectRecord(probeGit.status);
46113
+ const probeNestedStatus = readObjectRecord(probeGitResult.status);
46114
+ const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
46115
+ return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
46116
+ }
46117
+ function buildCachedInlineMeshGitStatus(node) {
46118
+ const liveGit = buildInlineMeshTransitGitStatus(node);
46119
+ if (liveGit) return liveGit;
46120
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
46121
+ const cachedGit = readObjectRecord(cachedStatus.git);
46122
+ if (!Object.keys(cachedGit).length) return void 0;
46123
+ return normalizeInlineMeshGitStatus(cachedGit, node);
46124
+ }
46125
+ function shouldDiscardCachedInlineMeshStatus(node) {
45883
46126
  const cachedStatus = readObjectRecord(node?.cachedStatus);
45884
- const git = buildCachedInlineMeshGitStatus(node);
45885
- const error48 = readStringValue(cachedStatus.error, node?.error);
45886
- const health = readStringValue(cachedStatus.health, node?.health);
46127
+ if (!Object.keys(cachedStatus).length) return false;
46128
+ const cachedGit = readObjectRecord(cachedStatus.git);
46129
+ const workspaceError = readStringValue(cachedStatus.error, node?.error);
46130
+ if (workspaceError && /workspace must be an existing directory/i.test(workspaceError)) return true;
46131
+ const isGitRepo = readBooleanValue(cachedGit.isGitRepo);
46132
+ const branch = readStringValue(cachedGit.branch);
46133
+ const headCommit = readStringValue(cachedGit.headCommit);
46134
+ return isGitRepo === false && !branch && !headCommit;
46135
+ }
46136
+ function stripInlineMeshTransientNodeState(node) {
46137
+ if (!node || typeof node !== "object" || Array.isArray(node)) return node;
46138
+ const {
46139
+ cachedStatus,
46140
+ lastGit: _lastGit,
46141
+ last_git: _lastGitLegacy,
46142
+ lastProbe: _lastProbe,
46143
+ last_probe: _lastProbeLegacy,
46144
+ error: _error,
46145
+ health: _health,
46146
+ machineStatus: _machineStatus,
46147
+ lastSeenAt: _lastSeenAt,
46148
+ last_seen_at: _lastSeenAtLegacy,
46149
+ updatedAt: _updatedAt,
46150
+ updated_at: _updatedAtLegacy,
46151
+ activeSession: _activeSession,
46152
+ active_session: _activeSessionLegacy,
46153
+ activeSessionId: _activeSessionId,
46154
+ active_session_id: _activeSessionIdLegacy,
46155
+ sessionId: _sessionId,
46156
+ session_id: _sessionIdLegacy,
46157
+ providerType: _providerType,
46158
+ provider_type: _providerTypeLegacy,
46159
+ providers: _providers,
46160
+ ...rest
46161
+ } = node;
46162
+ if (cachedStatus && !shouldDiscardCachedInlineMeshStatus(node)) {
46163
+ return { ...rest, cachedStatus };
46164
+ }
46165
+ return rest;
46166
+ }
46167
+ function hasInlineMeshTransientNodeState(node) {
46168
+ if (!node || typeof node !== "object" || Array.isArray(node)) return false;
46169
+ return "cachedStatus" in node || "lastGit" in node || "last_git" in node || "lastProbe" in node || "last_probe" in node || "error" in node || "health" in node || "machineStatus" in node || "lastSeenAt" in node || "last_seen_at" in node || "updatedAt" in node || "updated_at" in node || "activeSession" in node || "active_session" in node || "activeSessionId" in node || "active_session_id" in node || "sessionId" in node || "session_id" in node || "providerType" in node || "provider_type" in node || "providers" in node;
46170
+ }
46171
+ function readInlineMeshNodeId(node) {
46172
+ return readStringValue(node?.id, node?.nodeId) || "";
46173
+ }
46174
+ function sanitizeInlineMesh(inlineMesh) {
46175
+ if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
46176
+ if (!Array.isArray(inlineMesh.nodes)) return inlineMesh;
46177
+ let changed = false;
46178
+ const nodes = inlineMesh.nodes.map((node) => {
46179
+ if (!hasInlineMeshTransientNodeState(node)) return node;
46180
+ changed = true;
46181
+ return stripInlineMeshTransientNodeState(node);
46182
+ });
46183
+ if (!changed) return inlineMesh;
46184
+ return {
46185
+ ...inlineMesh,
46186
+ nodes
46187
+ };
46188
+ }
46189
+ function reconcileInlineMeshCache(cached2, incoming) {
46190
+ if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
46191
+ if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
46192
+ const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
46193
+ const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
46194
+ if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
46195
+ const incomingById = /* @__PURE__ */ new Map();
46196
+ for (const node of incomingNodes) {
46197
+ const nodeId = readInlineMeshNodeId(node);
46198
+ if (nodeId) incomingById.set(nodeId, node);
46199
+ }
46200
+ const nodes = cachedNodes.map((cachedNode) => {
46201
+ const nodeId = readInlineMeshNodeId(cachedNode);
46202
+ const incomingNode = nodeId ? incomingById.get(nodeId) : void 0;
46203
+ if (!incomingNode) return cachedNode;
46204
+ if (hasInlineMeshTransientNodeState(incomingNode)) {
46205
+ return { ...cachedNode, ...incomingNode };
46206
+ }
46207
+ return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
46208
+ });
46209
+ return {
46210
+ ...cached2,
46211
+ ...incoming,
46212
+ nodes
46213
+ };
46214
+ }
46215
+ function hasGitWorktreeChanges(git) {
46216
+ if (!git) return false;
46217
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
46218
+ }
46219
+ function getGitSubmoduleDriftState(git) {
46220
+ const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
46221
+ let dirty = false;
46222
+ let outOfSync = false;
46223
+ for (const entry of submodules) {
46224
+ const submodule = readObjectRecord(entry);
46225
+ if (readBooleanValue(submodule.dirty) === true) dirty = true;
46226
+ if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
46227
+ }
46228
+ return { dirty, outOfSync };
46229
+ }
46230
+ function deriveMeshNodeHealthFromGit(git) {
46231
+ if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
46232
+ const branch = readStringValue(git.branch);
46233
+ if (!branch) return "degraded";
46234
+ const submoduleDrift = getGitSubmoduleDriftState(git);
46235
+ if (submoduleDrift.outOfSync) return "degraded";
46236
+ if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
46237
+ return "online";
46238
+ }
46239
+ function readCachedInlineMeshActiveSessions(node) {
46240
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
46241
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
46242
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
46243
+ const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
46244
+ return sessionId ? [sessionId] : [];
46245
+ }
46246
+ function readCachedInlineMeshActiveSessionDetails(node) {
46247
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
46248
+ const activeSession = readObjectRecord(cachedStatus.activeSession);
46249
+ const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
46250
+ const sessionId = readStringValue(
46251
+ fallbackSession.id,
46252
+ fallbackSession.sessionId,
46253
+ fallbackSession.session_id,
46254
+ node?.activeSessionId,
46255
+ node?.active_session_id,
46256
+ node?.sessionId,
46257
+ node?.session_id
46258
+ );
46259
+ if (!sessionId) return [];
46260
+ return [{
46261
+ sessionId,
46262
+ providerType: readStringValue(
46263
+ fallbackSession.providerType,
46264
+ fallbackSession.provider_type,
46265
+ fallbackSession.cliType,
46266
+ fallbackSession.cli_type,
46267
+ fallbackSession.provider,
46268
+ node?.providerType,
46269
+ node?.provider_type
46270
+ ),
46271
+ state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
46272
+ lifecycle: readStringValue(fallbackSession.lifecycle),
46273
+ title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
46274
+ workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
46275
+ lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
46276
+ recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
46277
+ isCached: true
46278
+ }];
46279
+ }
46280
+ function readLiveMeshSessionState(record2) {
46281
+ return readStringValue(
46282
+ record2?.meta?.sessionStatus,
46283
+ record2?.meta?.status,
46284
+ record2?.meta?.providerStatus,
46285
+ record2?.status,
46286
+ record2?.state,
46287
+ record2?.lifecycle
46288
+ );
46289
+ }
46290
+ function toIsoTimestamp(value) {
46291
+ if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
46292
+ const stringValue = readStringValue(value);
46293
+ return stringValue || null;
46294
+ }
46295
+ function summarizeMeshSessionRecord(record2) {
46296
+ return {
46297
+ sessionId: readStringValue(record2?.sessionId) || "unknown",
46298
+ providerType: readStringValue(record2?.providerType),
46299
+ state: readLiveMeshSessionState(record2),
46300
+ lifecycle: readStringValue(record2?.lifecycle),
46301
+ surfaceKind: getSessionHostSurfaceKind(record2),
46302
+ recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
46303
+ workspace: readStringValue(record2?.workspace) ?? null,
46304
+ title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
46305
+ lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
46306
+ isCached: false
46307
+ };
46308
+ }
46309
+ function liveSessionRecordMatchesMeshNode(record2, meshId, nodeId) {
46310
+ const recordNodeId = readStringValue(record2?.meta?.meshNodeId);
46311
+ if (!recordNodeId || recordNodeId !== nodeId) return false;
46312
+ const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
46313
+ return !recordMeshId || recordMeshId === meshId;
46314
+ }
46315
+ function liveSessionRecordMatchesMeshWorkspace(record2, meshId, workspace) {
46316
+ const recordWorkspace = readStringValue(record2?.workspace);
46317
+ if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
46318
+ const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
46319
+ if (recordMeshId) return recordMeshId === meshId;
46320
+ return record2?.meta?.launchedByCoordinator === true || !!readStringValue(record2?.meta?.meshNodeId);
46321
+ }
46322
+ function readLiveMeshNodeWorkspace(args) {
46323
+ const directNodeWorkspace = args.liveSessionRecords.find((record2) => liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId) && readStringValue(record2?.workspace));
46324
+ if (directNodeWorkspace) {
46325
+ return readStringValue(directNodeWorkspace.workspace) || "";
46326
+ }
46327
+ if (args.allowCoordinatorSession) {
46328
+ const coordinatorWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record2?.workspace));
46329
+ if (coordinatorWorkspace) {
46330
+ return readStringValue(coordinatorWorkspace.workspace) || "";
46331
+ }
46332
+ }
46333
+ return "";
46334
+ }
46335
+ function collectLiveMeshSessionRecords(args) {
46336
+ const matches = args.liveSessionRecords.filter((record2) => {
46337
+ const nodeWorkspace = readStringValue(args.node?.workspace);
46338
+ if (liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId)) return true;
46339
+ return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record2, args.meshId, nodeWorkspace);
46340
+ });
46341
+ if (args.allowCoordinatorSession) {
46342
+ for (const record2 of args.liveSessionRecords) {
46343
+ if (readStringValue(record2?.meta?.meshCoordinatorFor) !== args.meshId) continue;
46344
+ const sessionId = readStringValue(record2?.sessionId);
46345
+ if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
46346
+ matches.push(record2);
46347
+ }
46348
+ }
46349
+ return matches;
46350
+ }
46351
+ function applyCachedInlineMeshNodeStatus(status, node, options) {
46352
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
46353
+ const liveGit = buildInlineMeshTransitGitStatus(node);
46354
+ const git = options?.skipGit ? void 0 : liveGit ?? buildCachedInlineMeshGitStatus(node);
46355
+ const error48 = options?.skipError ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
46356
+ const health = options?.skipHealth ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
45887
46357
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
45888
- if (!git && !error48 && !health) return false;
45889
- if (!machineStatus && !git && !error48) return false;
46358
+ const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
46359
+ const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
46360
+ const activeSessions = readCachedInlineMeshActiveSessions(node);
46361
+ const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
46362
+ if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
45890
46363
  if (git) status.git = git;
45891
46364
  if (error48) status.error = error48;
46365
+ if (machineStatus) status.machineStatus = machineStatus;
46366
+ if (lastSeenAt) status.lastSeenAt = lastSeenAt;
46367
+ if (updatedAt) status.updatedAt = updatedAt;
46368
+ if (activeSessions.length > 0) status.activeSessions = activeSessions;
46369
+ if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
45892
46370
  if (health) {
45893
46371
  status.health = health;
45894
46372
  return true;
45895
46373
  }
45896
46374
  if (git) {
45897
- const dirty = Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
45898
- status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
46375
+ status.health = deriveMeshNodeHealthFromGit(git);
45899
46376
  return true;
45900
46377
  }
45901
- return false;
46378
+ return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
45902
46379
  }
45903
46380
  async function resolveProviderTypeFromPriority(args) {
45904
46381
  if (!args.providerPriority.length) {
@@ -45936,7 +46413,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
45936
46413
  }
45937
46414
  function readPackageScripts(workspace) {
45938
46415
  try {
45939
- const packageJsonPath = (0, import_path6.join)(workspace, "package.json");
46416
+ const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
45940
46417
  const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
45941
46418
  return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
45942
46419
  } catch {
@@ -46144,13 +46621,13 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46144
46621
  }
46145
46622
  function resolveHermesUserHome() {
46146
46623
  const explicitHome = process.env.HERMES_HOME?.trim();
46147
- return explicitHome || (0, import_path6.join)((0, import_os3.homedir)(), ".hermes");
46624
+ return explicitHome || (0, import_path7.join)((0, import_os3.homedir)(), ".hermes");
46148
46625
  }
46149
46626
  function loadHermesCoordinatorBaseConfig(targetConfigPath) {
46150
46627
  const sourceHome = resolveHermesUserHome();
46151
- const sourceConfigPath = (0, import_path6.join)(sourceHome, "config.yaml");
46628
+ const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
46152
46629
  if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
46153
- if ((0, import_path6.resolve)(sourceConfigPath) === (0, import_path6.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
46630
+ if ((0, import_path7.resolve)(sourceConfigPath) === (0, import_path7.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
46154
46631
  const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
46155
46632
  const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
46156
46633
  return { config: baseConfig, sourceHome, sourceConfigPath };
@@ -46184,10 +46661,10 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46184
46661
  return sanitized;
46185
46662
  }
46186
46663
  function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
46187
- if ((0, import_path6.resolve)(sourceHome) === (0, import_path6.resolve)(targetHome)) return;
46664
+ if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
46188
46665
  for (const fileName of [".env", "auth.json"]) {
46189
- const sourcePath = (0, import_path6.join)(sourceHome, fileName);
46190
- const targetPath = (0, import_path6.join)(targetHome, fileName);
46666
+ const sourcePath = (0, import_path7.join)(sourceHome, fileName);
46667
+ const targetPath = (0, import_path7.join)(targetHome, fileName);
46191
46668
  if (!fs10.existsSync(sourcePath)) continue;
46192
46669
  try {
46193
46670
  fs10.copyFileSync(sourcePath, targetPath);
@@ -46296,25 +46773,40 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46296
46773
  }
46297
46774
  getCachedInlineMesh(meshId, inlineMesh) {
46298
46775
  if (inlineMesh && typeof inlineMesh === "object") {
46299
- this.inlineMeshCache.set(meshId, inlineMesh);
46300
- return inlineMesh;
46776
+ return this.warmInlineMeshCache(meshId, inlineMesh);
46301
46777
  }
46302
46778
  return this.inlineMeshCache.get(meshId);
46303
46779
  }
46780
+ warmInlineMeshCache(meshId, inlineMesh) {
46781
+ if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
46782
+ const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
46783
+ const cached2 = this.inlineMeshCache.get(meshId);
46784
+ if (cached2) {
46785
+ const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
46786
+ this.inlineMeshCache.set(meshId, merged);
46787
+ return merged;
46788
+ }
46789
+ this.inlineMeshCache.set(meshId, sanitizedInlineMesh);
46790
+ return sanitizedInlineMesh;
46791
+ }
46304
46792
  async getMeshForCommand(meshId, inlineMesh, options) {
46305
46793
  const preferInline = options?.preferInline === true;
46306
46794
  if (preferInline) {
46307
- const cached22 = this.getCachedInlineMesh(meshId, inlineMesh);
46308
- if (cached22) return { mesh: cached22, inline: true };
46795
+ const cached22 = this.getCachedInlineMesh(meshId);
46796
+ if (cached22) return { mesh: cached22, inline: true, source: "inline_cache" };
46797
+ const warmedInline2 = this.warmInlineMeshCache(meshId, inlineMesh);
46798
+ if (warmedInline2) return { mesh: warmedInline2, inline: true, source: "inline_bootstrap" };
46309
46799
  }
46310
46800
  try {
46311
46801
  const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
46312
46802
  const mesh = getMesh3(meshId);
46313
- if (mesh) return { mesh, inline: false };
46803
+ if (mesh) return { mesh, inline: false, source: "local_config" };
46314
46804
  } catch {
46315
46805
  }
46316
- const cached2 = this.getCachedInlineMesh(meshId, inlineMesh);
46317
- return cached2 ? { mesh: cached2, inline: true } : null;
46806
+ const cached2 = this.getCachedInlineMesh(meshId);
46807
+ if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
46808
+ const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
46809
+ return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
46318
46810
  }
46319
46811
  updateInlineMeshNode(meshId, mesh, node) {
46320
46812
  if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
@@ -46379,7 +46871,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46379
46871
  }
46380
46872
  const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
46381
46873
  const normalizePath = (value) => {
46382
- const resolved = (0, import_path6.resolve)(value);
46874
+ const resolved = (0, import_path7.resolve)(value);
46383
46875
  try {
46384
46876
  return fs10.realpathSync(resolved);
46385
46877
  } catch {
@@ -46543,6 +47035,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46543
47035
  const deletedSessionIds = [];
46544
47036
  const skippedSessionIds = [];
46545
47037
  const skippedLiveSessionIds = [];
47038
+ const skippedCoordinatorSessionIds = [];
46546
47039
  const deleteUnsupportedSessionIds = [];
46547
47040
  const recordsRemainSessionIds = [];
46548
47041
  const errors = [];
@@ -46575,6 +47068,12 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46575
47068
  const completed = this.isCompletedHostedSession(record2);
46576
47069
  const surfaceKind = getSessionHostSurfaceKind(record2);
46577
47070
  const liveRuntime = surfaceKind === "live_runtime";
47071
+ const coordinatorSession = readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId;
47072
+ if (!hasExplicitSessionIds && coordinatorSession) {
47073
+ skippedSessionIds.push(sessionId);
47074
+ skippedCoordinatorSessionIds.push(sessionId);
47075
+ continue;
47076
+ }
46578
47077
  if (!hasExplicitSessionIds && liveRuntime) {
46579
47078
  skippedSessionIds.push(sessionId);
46580
47079
  skippedLiveSessionIds.push(sessionId);
@@ -46640,6 +47139,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46640
47139
  deletedSessionIds,
46641
47140
  skippedSessionIds,
46642
47141
  skippedLiveSessionIds,
47142
+ skippedCoordinatorSessionIds,
46643
47143
  ...deleteUnsupported ? {
46644
47144
  deleteUnsupported: true,
46645
47145
  effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
@@ -46772,7 +47272,8 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
46772
47272
  return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
46773
47273
  }
46774
47274
  case "get_pending_mesh_events": {
46775
- const events = drainPendingMeshCoordinatorEvents();
47275
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
47276
+ const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
46776
47277
  return { success: true, events };
46777
47278
  }
46778
47279
  case "launch_cli":
@@ -47301,14 +47802,8 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
47301
47802
  case "get_mesh": {
47302
47803
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
47303
47804
  if (!meshId) return { success: false, error: "meshId required" };
47304
- try {
47305
- const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
47306
- const mesh = getMesh3(meshId);
47307
- if (mesh) return { success: true, mesh };
47308
- } catch {
47309
- }
47310
- const cached2 = this.inlineMeshCache.get(meshId);
47311
- if (cached2) return { success: true, mesh: cached2 };
47805
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
47806
+ if (meshRecord?.mesh) return { success: true, mesh: meshRecord.mesh };
47312
47807
  return { success: false, error: "Mesh not found" };
47313
47808
  }
47314
47809
  case "create_mesh": {
@@ -47830,7 +48325,14 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
47830
48325
  cliType
47831
48326
  };
47832
48327
  }
47833
- const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
48328
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
48329
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
48330
+ const workspace = readLiveMeshNodeWorkspace({
48331
+ meshId,
48332
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
48333
+ liveSessionRecords: liveMeshSessions,
48334
+ allowCoordinatorSession: true
48335
+ }) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
47834
48336
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
47835
48337
  if (!cliType) {
47836
48338
  const resolved = await resolveProviderTypeFromPriority({
@@ -47992,7 +48494,7 @@ ${block}`);
47992
48494
  workspace
47993
48495
  };
47994
48496
  }
47995
- const { existsSync: existsSync25, readFileSync: readFileSync17, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
48497
+ const { existsSync: existsSync26, readFileSync: readFileSync18, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
47996
48498
  const { dirname: dirname9 } = await import("path");
47997
48499
  const mcpConfigPath = coordinatorSetup.configPath;
47998
48500
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -48035,14 +48537,14 @@ ${block}`);
48035
48537
  if (hermesManualFallback) return returnManualFallback(message);
48036
48538
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
48037
48539
  }
48038
- const hadExistingMcpConfig = existsSync25(mcpConfigPath);
48540
+ const hadExistingMcpConfig = existsSync26(mcpConfigPath);
48039
48541
  let existingMcpConfig = hermesBaseConfig?.config || {};
48040
48542
  if (hermesBaseConfig) {
48041
48543
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
48042
48544
  }
48043
48545
  if (hadExistingMcpConfig) {
48044
48546
  try {
48045
- const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
48547
+ const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync18(mcpConfigPath, "utf-8"), configFormat);
48046
48548
  const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
48047
48549
  existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
48048
48550
  copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
@@ -48138,92 +48640,157 @@ ${block}`);
48138
48640
  const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
48139
48641
  const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
48140
48642
  const ledgerSummary = getLedgerSummary2(meshId);
48643
+ const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
48644
+ const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
48645
+ const localMachineId = loadConfig2().machineId || "";
48646
+ const selectedCoordinatorNodeId = readStringValue(
48647
+ mesh.coordinator?.preferredNodeId,
48648
+ mesh.nodes?.[0]?.id,
48649
+ mesh.nodes?.[0]?.nodeId
48650
+ );
48651
+ const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
48652
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
48141
48653
  const nodeStatuses = [];
48142
- for (const node of mesh.nodes || []) {
48654
+ for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
48655
+ const nodeId = String(node.id || node.nodeId || "");
48656
+ const daemonId = readStringValue(node.daemonId);
48657
+ const providerPriority = readProviderPriorityFromPolicy(node.policy);
48658
+ const isSelfNode = Boolean(
48659
+ nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
48660
+ ) || Boolean(
48661
+ daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
48662
+ ) || Boolean(meshRecord?.inline && nodeIndex === 0);
48143
48663
  const status = {
48144
- nodeId: node.id || node.nodeId,
48664
+ nodeId,
48145
48665
  machineLabel: node.machineLabel || node.id || node.nodeId,
48146
48666
  workspace: node.workspace,
48147
48667
  repoRoot: node.repoRoot,
48148
48668
  isLocalWorktree: node.isLocalWorktree,
48149
48669
  worktreeBranch: node.worktreeBranch,
48150
- daemonId: node.daemonId,
48670
+ daemonId,
48151
48671
  machineId: node.machineId,
48672
+ machineStatus: node.machineStatus,
48152
48673
  health: "unknown",
48153
48674
  providers: node.providers || [],
48154
- activeSessions: []
48675
+ providerPriority,
48676
+ activeSessions: [],
48677
+ activeSessionDetails: [],
48678
+ launchReady: false
48155
48679
  };
48156
- if (node.workspace && typeof node.workspace === "string") {
48157
- if (!fs10.existsSync(node.workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
48158
- nodeStatuses.push(status);
48159
- continue;
48680
+ if (isSelfNode) {
48681
+ status.connection = {
48682
+ perspective: "selected_coordinator",
48683
+ source: "mesh_peer_status",
48684
+ state: "self",
48685
+ transport: "local",
48686
+ reported: true,
48687
+ reason: "Selected coordinator daemon",
48688
+ lastStateChangeAt: refreshedAt
48689
+ };
48690
+ } else if (daemonId) {
48691
+ const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
48692
+ status.connection = connection ?? {
48693
+ perspective: "selected_coordinator",
48694
+ source: "not_reported",
48695
+ state: "unknown",
48696
+ transport: "unknown",
48697
+ reported: false,
48698
+ reason: "No live mesh peer telemetry reported by the selected coordinator yet."
48699
+ };
48700
+ } else {
48701
+ status.connection = {
48702
+ perspective: "selected_coordinator",
48703
+ source: "not_reported",
48704
+ state: "unknown",
48705
+ transport: "unknown",
48706
+ reported: false,
48707
+ reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
48708
+ };
48709
+ }
48710
+ const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
48711
+ meshId,
48712
+ node,
48713
+ nodeId,
48714
+ liveSessionRecords: liveMeshSessions,
48715
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
48716
+ });
48717
+ const workspace = readLiveMeshNodeWorkspace({
48718
+ meshId,
48719
+ nodeId,
48720
+ liveSessionRecords: matchedLiveSessionRecords,
48721
+ allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
48722
+ }) || (typeof node.workspace === "string" ? node.workspace : "");
48723
+ status.workspace = workspace || node.workspace;
48724
+ if (matchedLiveSessionRecords.length > 0) {
48725
+ const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
48726
+ const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
48727
+ status.activeSessions = sessionIds;
48728
+ status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
48729
+ if (providerTypes.length > 0) {
48730
+ status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
48160
48731
  }
48161
- try {
48162
- const { execFile: execFile3 } = await import("child_process");
48163
- const { promisify: promisify3 } = await import("util");
48164
- const execFileAsync3 = promisify3(execFile3);
48165
- const runGit2 = async (args2) => {
48166
- const result = await execFileAsync3("git", ["-C", node.workspace, ...args2], {
48167
- encoding: "utf8",
48168
- timeout: 1e4
48169
- });
48170
- return result.stdout.trim();
48171
- };
48172
- const branch = await runGit2(["branch", "--show-current"]).catch(() => "");
48173
- const porc = await runGit2(["status", "--porcelain"]).catch(() => "");
48174
- const headCommit = await runGit2(["rev-parse", "--short", "HEAD"]).catch(() => null);
48175
- const headMessage = await runGit2(["log", "-1", "--format=%s"]).catch(() => null);
48176
- const upstream = await runGit2(["rev-parse", "--abbrev-ref", "@{upstream}"]).catch(() => null);
48177
- const aheadBehind = await runGit2(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]).catch(() => "");
48178
- const stashCount = await runGit2(["stash", "list"]).catch(() => "");
48179
- let ahead = 0, behind = 0;
48180
- if (aheadBehind) {
48181
- const parts = aheadBehind.split(/\s+/);
48182
- if (parts.length >= 2) {
48183
- behind = parseInt(parts[0], 10) || 0;
48184
- ahead = parseInt(parts[1], 10) || 0;
48732
+ }
48733
+ if (workspace) {
48734
+ if (!fs10.existsSync(workspace)) {
48735
+ let remoteProbeApplied = false;
48736
+ if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
48737
+ try {
48738
+ const remoteResult = await Promise.race([
48739
+ this.deps.dispatchMeshCommand(daemonId, "git_status", { workspace }),
48740
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 8e3))
48741
+ ]);
48742
+ const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
48743
+ if (remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean") {
48744
+ status.git = remoteGit;
48745
+ status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
48746
+ remoteProbeApplied = true;
48747
+ }
48748
+ } catch {
48185
48749
  }
48186
48750
  }
48187
- const dirty = porc.length > 0;
48188
- const lines = porc ? porc.split("\n").filter(Boolean) : [];
48189
- let staged = 0, modified = 0, untracked = 0, deleted = 0, renamed = 0;
48190
- for (const line of lines) {
48191
- const xy = line.slice(0, 2);
48192
- if (xy[0] !== " " && xy[0] !== "?") staged++;
48193
- if (xy[1] === "M") modified++;
48194
- if (xy[1] === "D") deleted++;
48195
- if (xy[0] === "R" || xy[1] === "R") renamed++;
48196
- if (xy === "??") untracked++;
48751
+ if (!remoteProbeApplied) {
48752
+ const connectionState = readStringValue(status.connection?.state);
48753
+ const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
48754
+ const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
48755
+ if (pendingPeerGitProbe) {
48756
+ status.gitProbePending = true;
48757
+ status.health = "unknown";
48758
+ }
48759
+ if (applyCachedInlineMeshNodeStatus(
48760
+ status,
48761
+ node,
48762
+ pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
48763
+ )) {
48764
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
48765
+ nodeStatuses.push(status);
48766
+ continue;
48767
+ }
48768
+ if (meshRecord?.source === "inline_cache" && !isSelfNode) {
48769
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
48770
+ nodeStatuses.push(status);
48771
+ continue;
48772
+ }
48197
48773
  }
48198
- status.git = {
48199
- workspace: node.workspace,
48200
- repoRoot: node.workspace,
48201
- isGitRepo: true,
48202
- branch: branch || null,
48203
- headCommit,
48204
- headMessage,
48205
- upstream,
48206
- ahead,
48207
- behind,
48208
- staged,
48209
- modified,
48210
- untracked,
48211
- deleted,
48212
- renamed,
48213
- hasConflicts: false,
48214
- conflictFiles: [],
48215
- stashCount: stashCount ? stashCount.split("\n").filter(Boolean).length : 0,
48216
- lastCheckedAt: Date.now()
48217
- };
48218
- status.health = branch ? dirty ? "dirty" : "online" : "degraded";
48219
- } catch {
48220
- if (!applyCachedInlineMeshNodeStatus(status, node)) {
48221
- status.health = "degraded";
48774
+ } else {
48775
+ try {
48776
+ const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
48777
+ status.git = gitStatus;
48778
+ if (gitStatus.isGitRepo) {
48779
+ status.health = deriveMeshNodeHealthFromGit(gitStatus);
48780
+ } else {
48781
+ status.health = "degraded";
48782
+ if (gitStatus.error && !status.error) status.error = gitStatus.error;
48783
+ }
48784
+ } catch {
48785
+ if (!applyCachedInlineMeshNodeStatus(status, node)) {
48786
+ status.health = "degraded";
48787
+ }
48222
48788
  }
48223
48789
  }
48224
48790
  } else {
48225
48791
  applyCachedInlineMeshNodeStatus(status, node);
48226
48792
  }
48793
+ status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
48227
48794
  nodeStatuses.push(status);
48228
48795
  }
48229
48796
  return {
@@ -48232,6 +48799,12 @@ ${block}`);
48232
48799
  meshName: mesh.name,
48233
48800
  repoIdentity: mesh.repoIdentity,
48234
48801
  defaultBranch: mesh.defaultBranch,
48802
+ refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
48803
+ sourceOfTruth: {
48804
+ membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
48805
+ coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
48806
+ historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
48807
+ },
48235
48808
  nodes: nodeStatuses,
48236
48809
  queue: { tasks: queue, summary: queueSummary },
48237
48810
  ledger: { entries: ledgerEntries, summary: ledgerSummary }
@@ -56107,6 +56680,7 @@ data: ${JSON.stringify(msg.data)}
56107
56680
  sessionHostControl: config2.sessionHostControl,
56108
56681
  statusInstanceId: config2.statusInstanceId,
56109
56682
  statusVersion: config2.statusVersion,
56683
+ getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
56110
56684
  getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG2.forComponent(`CDP:${ideType}`).asLogFn())
56111
56685
  });
56112
56686
  poller = new AgentStreamPoller({