@adhdev/daemon-standalone 0.9.82-rc.4 → 0.9.82-rc.40
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 +1366 -312
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/index-BNKDsz6G.css +1 -0
- package/public/assets/index-BVxQhhk5.js +98 -0
- package/public/assets/{terminal-DCVDkSIp.js → terminal-D46M5EWH.js} +4 -4
- package/public/assets/{vendor-piMzuE8Y.js → vendor-CgiI0UIA.js} +29 -29
- package/public/index.html +3 -3
- package/vendor/mcp-server/index.js +331 -32
- package/vendor/mcp-server/index.js.map +1 -1
- package/public/assets/index-BLzTtSTm.js +0 -98
- package/public/assets/index-CMNWyMpB.css +0 -1
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
|
-
|
|
23509
|
-
|
|
23510
|
-
|
|
23511
|
-
|
|
23512
|
-
|
|
23513
|
-
|
|
23514
|
-
|
|
23515
|
-
|
|
23516
|
-
|
|
23517
|
-
|
|
23518
|
-
|
|
23519
|
-
|
|
23520
|
-
|
|
23521
|
-
|
|
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
|
-
|
|
23533
|
-
|
|
23534
|
-
|
|
23535
|
-
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
|
|
23542
|
-
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
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
|
-
|
|
23554
|
-
|
|
23555
|
-
|
|
23556
|
-
|
|
23557
|
-
|
|
23558
|
-
|
|
23559
|
-
|
|
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
|
-
|
|
23563
|
-
|
|
23564
|
-
|
|
23565
|
-
|
|
23566
|
-
|
|
23567
|
-
...autoLaunch,
|
|
23568
|
-
updatedAt
|
|
23569
|
-
|
|
23570
|
-
|
|
23571
|
-
|
|
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
|
-
|
|
23576
|
-
|
|
23577
|
-
|
|
23578
|
-
|
|
23579
|
-
|
|
23580
|
-
|
|
23581
|
-
|
|
23582
|
-
|
|
23583
|
-
|
|
23584
|
-
|
|
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
|
-
|
|
23588
|
-
|
|
23589
|
-
|
|
23590
|
-
|
|
23591
|
-
|
|
23592
|
-
|
|
23593
|
-
|
|
23594
|
-
|
|
23595
|
-
|
|
23596
|
-
|
|
23597
|
-
|
|
23598
|
-
|
|
23599
|
-
|
|
23600
|
-
|
|
23601
|
-
|
|
23602
|
-
|
|
23603
|
-
|
|
23604
|
-
|
|
23605
|
-
|
|
23606
|
-
|
|
23607
|
-
|
|
23608
|
-
|
|
23609
|
-
|
|
23610
|
-
|
|
23611
|
-
|
|
23612
|
-
|
|
23613
|
-
|
|
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
|
-
|
|
23622
|
-
|
|
23623
|
-
|
|
23624
|
-
|
|
23625
|
-
|
|
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
|
|
24054
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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, "
|
|
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
|
-
|
|
24626
|
+
setImmediate(() => {
|
|
24468
24627
|
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
24469
|
-
}
|
|
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
|
-
|
|
24508
|
-
|
|
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
|
-
|
|
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 (
|
|
24625
|
-
|
|
24626
|
-
|
|
24627
|
-
|
|
24628
|
-
|
|
24629
|
-
|
|
24630
|
-
|
|
24631
|
-
|
|
24632
|
-
}
|
|
24633
|
-
|
|
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
|
-
|
|
28066
|
-
|
|
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
|
|
29908
|
-
var
|
|
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,
|
|
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,
|
|
30197
|
+
if (!(0, import_fs7.existsSync)(statePath)) {
|
|
29959
30198
|
return { ...DEFAULT_STATE };
|
|
29960
30199
|
}
|
|
29961
30200
|
try {
|
|
29962
|
-
const raw = (0,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
30271
|
+
if ((0, import_fs8.existsSync)(resolved)) return resolved;
|
|
30033
30272
|
} else {
|
|
30034
|
-
if ((0,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,55 +46052,45 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
45812
46052
|
}
|
|
45813
46053
|
return void 0;
|
|
45814
46054
|
}
|
|
45815
|
-
function
|
|
45816
|
-
const
|
|
45817
|
-
const
|
|
45818
|
-
if (
|
|
45819
|
-
|
|
45820
|
-
|
|
45821
|
-
|
|
45822
|
-
|
|
45823
|
-
|
|
45824
|
-
|
|
45825
|
-
|
|
45826
|
-
|
|
45827
|
-
|
|
45828
|
-
|
|
45829
|
-
|
|
45830
|
-
|
|
45831
|
-
|
|
45832
|
-
|
|
45833
|
-
|
|
45834
|
-
|
|
45835
|
-
|
|
45836
|
-
|
|
45837
|
-
|
|
45838
|
-
|
|
45839
|
-
|
|
45840
|
-
|
|
45841
|
-
|
|
45842
|
-
|
|
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 joinRepoPath(root, relativePath) {
|
|
46056
|
+
const normalizedRoot = typeof root === "string" ? root.trim().replace(/[\\/]+$/, "") : "";
|
|
46057
|
+
const normalizedPath = typeof relativePath === "string" ? relativePath.trim() : "";
|
|
46058
|
+
if (!normalizedPath) return void 0;
|
|
46059
|
+
if (/^(?:[A-Za-z]:[\\/]|\/)/.test(normalizedPath)) return normalizedPath;
|
|
46060
|
+
if (!normalizedRoot) return void 0;
|
|
46061
|
+
return `${normalizedRoot}/${normalizedPath.replace(/^[\\/]+/, "")}`;
|
|
46062
|
+
}
|
|
46063
|
+
function readGitSubmodules(value, parentRepoRoot) {
|
|
46064
|
+
if (!Array.isArray(value)) return void 0;
|
|
46065
|
+
const submodules = value.map((entry) => {
|
|
46066
|
+
const submodule = readObjectRecord(entry);
|
|
46067
|
+
const path28 = readStringValue(submodule.path);
|
|
46068
|
+
const commit = readStringValue(submodule.commit);
|
|
46069
|
+
const repoPath = readStringValue(submodule.repoPath, submodule.repo_root) ?? joinRepoPath(parentRepoRoot, path28);
|
|
46070
|
+
if (!path28 || !commit || !repoPath) return null;
|
|
46071
|
+
return {
|
|
46072
|
+
path: path28,
|
|
46073
|
+
commit,
|
|
46074
|
+
repoPath,
|
|
46075
|
+
dirty: readBooleanValue(submodule.dirty) ?? false,
|
|
46076
|
+
outOfSync: readBooleanValue(submodule.outOfSync, submodule.out_of_sync) ?? false,
|
|
46077
|
+
lastCheckedAt: readNumberValue(submodule.lastCheckedAt, submodule.last_checked_at) ?? Date.now(),
|
|
46078
|
+
...readStringValue(submodule.error) ? { error: readStringValue(submodule.error) } : {}
|
|
46079
|
+
};
|
|
46080
|
+
}).filter((entry) => entry !== null);
|
|
46081
|
+
return submodules.length > 0 ? submodules : void 0;
|
|
46082
|
+
}
|
|
46083
|
+
function normalizeInlineMeshGitStatus(status, node, options) {
|
|
45856
46084
|
const isGitRepo = readBooleanValue(status.isGitRepo);
|
|
45857
46085
|
if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
|
|
45858
46086
|
const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
|
|
45859
46087
|
const conflictCount = readNumberValue(status.conflicts) ?? conflictFiles.length;
|
|
45860
46088
|
const hasConflicts = readBooleanValue(status.hasConflicts) ?? conflictCount > 0;
|
|
46089
|
+
const repoRoot = readStringValue(status.repoRoot, status.repo_root, node?.repoRoot, node?.repo_root, status.workspace, node?.workspace) || void 0;
|
|
46090
|
+
const submodules = readGitSubmodules(status.submodules, repoRoot);
|
|
45861
46091
|
return {
|
|
45862
46092
|
workspace: readStringValue(status.workspace, node?.workspace) || "",
|
|
45863
|
-
repoRoot:
|
|
46093
|
+
repoRoot: repoRoot ?? null,
|
|
45864
46094
|
isGitRepo,
|
|
45865
46095
|
branch: readStringValue(status.branch) ?? null,
|
|
45866
46096
|
headCommit: readStringValue(status.headCommit) ?? null,
|
|
@@ -45876,29 +46106,412 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
45876
46106
|
hasConflicts,
|
|
45877
46107
|
conflictFiles,
|
|
45878
46108
|
stashCount: readNumberValue(status.stashCount) ?? 0,
|
|
45879
|
-
lastCheckedAt: Date.now()
|
|
46109
|
+
lastCheckedAt: options?.lastCheckedAt ?? readNumberValue(status.lastCheckedAt) ?? Date.now(),
|
|
46110
|
+
...submodules ? { submodules } : {}
|
|
46111
|
+
};
|
|
46112
|
+
}
|
|
46113
|
+
function buildInlineMeshTransitGitStatus(node) {
|
|
46114
|
+
const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
|
|
46115
|
+
const gitResult = readObjectRecord(rawGit.result);
|
|
46116
|
+
const directStatus = readObjectRecord(rawGit.status);
|
|
46117
|
+
const nestedStatus = readObjectRecord(gitResult.status);
|
|
46118
|
+
const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
|
|
46119
|
+
const probeGit = readObjectRecord(rawProbe.git);
|
|
46120
|
+
const probeGitResult = readObjectRecord(probeGit.result);
|
|
46121
|
+
const probeDirectStatus = readObjectRecord(probeGit.status);
|
|
46122
|
+
const probeNestedStatus = readObjectRecord(probeGitResult.status);
|
|
46123
|
+
const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
|
|
46124
|
+
return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
|
|
46125
|
+
}
|
|
46126
|
+
function recordInlineMeshDirectGitTruth(node, git, source) {
|
|
46127
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return;
|
|
46128
|
+
const checkedAt = readNumberValue(git.lastCheckedAt) ?? Date.now();
|
|
46129
|
+
const updatedAt = new Date(checkedAt).toISOString();
|
|
46130
|
+
const nextGit = {
|
|
46131
|
+
...git,
|
|
46132
|
+
lastCheckedAt: checkedAt
|
|
46133
|
+
};
|
|
46134
|
+
node.lastGit = {
|
|
46135
|
+
source,
|
|
46136
|
+
checkedAt,
|
|
46137
|
+
status: nextGit
|
|
46138
|
+
};
|
|
46139
|
+
node.last_git = node.lastGit;
|
|
46140
|
+
node.machineStatus = "online";
|
|
46141
|
+
node.updatedAt = updatedAt;
|
|
46142
|
+
node.lastSeenAt = updatedAt;
|
|
46143
|
+
const repoRoot = readStringValue(nextGit.repoRoot);
|
|
46144
|
+
if (repoRoot && !readStringValue(node.repoRoot)) node.repoRoot = repoRoot;
|
|
46145
|
+
}
|
|
46146
|
+
function buildCachedInlineMeshGitStatus(node) {
|
|
46147
|
+
const liveGit = buildInlineMeshTransitGitStatus(node);
|
|
46148
|
+
if (liveGit) return liveGit;
|
|
46149
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46150
|
+
const cachedGit = readObjectRecord(cachedStatus.git);
|
|
46151
|
+
if (!Object.keys(cachedGit).length) return void 0;
|
|
46152
|
+
return normalizeInlineMeshGitStatus(cachedGit, node);
|
|
46153
|
+
}
|
|
46154
|
+
function shouldDiscardCachedInlineMeshStatus(node) {
|
|
46155
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46156
|
+
if (!Object.keys(cachedStatus).length) return false;
|
|
46157
|
+
const cachedGit = readObjectRecord(cachedStatus.git);
|
|
46158
|
+
const workspaceError = readStringValue(cachedStatus.error, node?.error);
|
|
46159
|
+
if (workspaceError && /workspace must be an existing directory/i.test(workspaceError)) return true;
|
|
46160
|
+
const isGitRepo = readBooleanValue(cachedGit.isGitRepo);
|
|
46161
|
+
const branch = readStringValue(cachedGit.branch);
|
|
46162
|
+
const headCommit = readStringValue(cachedGit.headCommit);
|
|
46163
|
+
return isGitRepo === false && !branch && !headCommit;
|
|
46164
|
+
}
|
|
46165
|
+
function stripInlineMeshTransientNodeState(node) {
|
|
46166
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return node;
|
|
46167
|
+
const {
|
|
46168
|
+
cachedStatus,
|
|
46169
|
+
lastGit: _lastGit,
|
|
46170
|
+
last_git: _lastGitLegacy,
|
|
46171
|
+
lastProbe: _lastProbe,
|
|
46172
|
+
last_probe: _lastProbeLegacy,
|
|
46173
|
+
error: _error,
|
|
46174
|
+
health: _health,
|
|
46175
|
+
machineStatus: _machineStatus,
|
|
46176
|
+
lastSeenAt: _lastSeenAt,
|
|
46177
|
+
last_seen_at: _lastSeenAtLegacy,
|
|
46178
|
+
updatedAt: _updatedAt,
|
|
46179
|
+
updated_at: _updatedAtLegacy,
|
|
46180
|
+
activeSession: _activeSession,
|
|
46181
|
+
active_session: _activeSessionLegacy,
|
|
46182
|
+
activeSessionId: _activeSessionId,
|
|
46183
|
+
active_session_id: _activeSessionIdLegacy,
|
|
46184
|
+
sessionId: _sessionId,
|
|
46185
|
+
session_id: _sessionIdLegacy,
|
|
46186
|
+
providerType: _providerType,
|
|
46187
|
+
provider_type: _providerTypeLegacy,
|
|
46188
|
+
...rest
|
|
46189
|
+
} = node;
|
|
46190
|
+
if (cachedStatus && !shouldDiscardCachedInlineMeshStatus(node)) {
|
|
46191
|
+
return { ...rest, cachedStatus };
|
|
46192
|
+
}
|
|
46193
|
+
return rest;
|
|
46194
|
+
}
|
|
46195
|
+
function hasInlineMeshTransientNodeState(node) {
|
|
46196
|
+
if (!node || typeof node !== "object" || Array.isArray(node)) return false;
|
|
46197
|
+
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;
|
|
46198
|
+
}
|
|
46199
|
+
function inlineMeshCarriesTransientNodeTruth(inlineMesh) {
|
|
46200
|
+
if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return false;
|
|
46201
|
+
if (!Array.isArray(inlineMesh.nodes) || inlineMesh.nodes.length === 0) return false;
|
|
46202
|
+
return inlineMesh.nodes.some((node) => hasInlineMeshTransientNodeState(node));
|
|
46203
|
+
}
|
|
46204
|
+
function readInlineMeshNodeId(node) {
|
|
46205
|
+
return readStringValue(node?.id, node?.nodeId) || "";
|
|
46206
|
+
}
|
|
46207
|
+
function sanitizeInlineMesh(inlineMesh) {
|
|
46208
|
+
if (!inlineMesh || typeof inlineMesh !== "object" || Array.isArray(inlineMesh)) return inlineMesh;
|
|
46209
|
+
if (!Array.isArray(inlineMesh.nodes)) return inlineMesh;
|
|
46210
|
+
let changed = false;
|
|
46211
|
+
const nodes = inlineMesh.nodes.map((node) => {
|
|
46212
|
+
if (!hasInlineMeshTransientNodeState(node)) return node;
|
|
46213
|
+
changed = true;
|
|
46214
|
+
return stripInlineMeshTransientNodeState(node);
|
|
46215
|
+
});
|
|
46216
|
+
if (!changed) return inlineMesh;
|
|
46217
|
+
return {
|
|
46218
|
+
...inlineMesh,
|
|
46219
|
+
nodes
|
|
46220
|
+
};
|
|
46221
|
+
}
|
|
46222
|
+
function reconcileInlineMeshCache(cached2, incoming) {
|
|
46223
|
+
if (!cached2 || typeof cached2 !== "object" || Array.isArray(cached2)) return incoming;
|
|
46224
|
+
if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached2;
|
|
46225
|
+
const cachedNodes = Array.isArray(cached2.nodes) ? cached2.nodes : [];
|
|
46226
|
+
const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
|
|
46227
|
+
if (!cachedNodes.length || !incomingNodes.length) return { ...cached2, ...incoming };
|
|
46228
|
+
const incomingById = /* @__PURE__ */ new Map();
|
|
46229
|
+
for (const node of incomingNodes) {
|
|
46230
|
+
const nodeId = readInlineMeshNodeId(node);
|
|
46231
|
+
if (nodeId) incomingById.set(nodeId, node);
|
|
46232
|
+
}
|
|
46233
|
+
const nodes = cachedNodes.map((cachedNode) => {
|
|
46234
|
+
const nodeId = readInlineMeshNodeId(cachedNode);
|
|
46235
|
+
const incomingNode = nodeId ? incomingById.get(nodeId) : void 0;
|
|
46236
|
+
if (!incomingNode) return cachedNode;
|
|
46237
|
+
if (hasInlineMeshTransientNodeState(incomingNode)) {
|
|
46238
|
+
return { ...cachedNode, ...incomingNode };
|
|
46239
|
+
}
|
|
46240
|
+
return { ...stripInlineMeshTransientNodeState(cachedNode), ...incomingNode };
|
|
46241
|
+
});
|
|
46242
|
+
return {
|
|
46243
|
+
...cached2,
|
|
46244
|
+
...incoming,
|
|
46245
|
+
nodes
|
|
46246
|
+
};
|
|
46247
|
+
}
|
|
46248
|
+
function hasGitWorktreeChanges(git) {
|
|
46249
|
+
if (!git) return false;
|
|
46250
|
+
return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
|
|
46251
|
+
}
|
|
46252
|
+
function getGitSubmoduleDriftState(git) {
|
|
46253
|
+
const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
|
|
46254
|
+
let dirty = false;
|
|
46255
|
+
let outOfSync = false;
|
|
46256
|
+
for (const entry of submodules) {
|
|
46257
|
+
const submodule = readObjectRecord(entry);
|
|
46258
|
+
if (readBooleanValue(submodule.dirty) === true) dirty = true;
|
|
46259
|
+
if (readBooleanValue(submodule.outOfSync) === true || !!readStringValue(submodule.error)) outOfSync = true;
|
|
46260
|
+
}
|
|
46261
|
+
return { dirty, outOfSync };
|
|
46262
|
+
}
|
|
46263
|
+
function deriveMeshNodeHealthFromGit(git) {
|
|
46264
|
+
if (!git || readBooleanValue(git.isGitRepo) === false) return "degraded";
|
|
46265
|
+
const branch = readStringValue(git.branch);
|
|
46266
|
+
if (!branch) return "degraded";
|
|
46267
|
+
const submoduleDrift = getGitSubmoduleDriftState(git);
|
|
46268
|
+
if (submoduleDrift.outOfSync) return "degraded";
|
|
46269
|
+
if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
|
|
46270
|
+
return "online";
|
|
46271
|
+
}
|
|
46272
|
+
function readCachedInlineMeshActiveSessions(node) {
|
|
46273
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46274
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46275
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46276
|
+
const sessionId = readStringValue(fallbackSession.id, fallbackSession.sessionId, fallbackSession.session_id, node?.activeSessionId, node?.active_session_id, node?.sessionId, node?.session_id);
|
|
46277
|
+
return sessionId ? [sessionId] : [];
|
|
46278
|
+
}
|
|
46279
|
+
function readCachedInlineMeshActiveSessionDetails(node) {
|
|
46280
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46281
|
+
const activeSession = readObjectRecord(cachedStatus.activeSession);
|
|
46282
|
+
const fallbackSession = Object.keys(activeSession).length ? activeSession : readObjectRecord(node?.activeSession ?? node?.active_session);
|
|
46283
|
+
const sessionId = readStringValue(
|
|
46284
|
+
fallbackSession.id,
|
|
46285
|
+
fallbackSession.sessionId,
|
|
46286
|
+
fallbackSession.session_id,
|
|
46287
|
+
node?.activeSessionId,
|
|
46288
|
+
node?.active_session_id,
|
|
46289
|
+
node?.sessionId,
|
|
46290
|
+
node?.session_id
|
|
46291
|
+
);
|
|
46292
|
+
if (!sessionId) return [];
|
|
46293
|
+
return [{
|
|
46294
|
+
sessionId,
|
|
46295
|
+
providerType: readStringValue(
|
|
46296
|
+
fallbackSession.providerType,
|
|
46297
|
+
fallbackSession.provider_type,
|
|
46298
|
+
fallbackSession.cliType,
|
|
46299
|
+
fallbackSession.cli_type,
|
|
46300
|
+
fallbackSession.provider,
|
|
46301
|
+
node?.providerType,
|
|
46302
|
+
node?.provider_type
|
|
46303
|
+
),
|
|
46304
|
+
state: readStringValue(fallbackSession.status, fallbackSession.state, fallbackSession.lifecycle),
|
|
46305
|
+
lifecycle: readStringValue(fallbackSession.lifecycle),
|
|
46306
|
+
title: readStringValue(fallbackSession.title, fallbackSession.displayName, fallbackSession.display_name) ?? null,
|
|
46307
|
+
workspace: readStringValue(fallbackSession.workspace, node?.workspace) ?? null,
|
|
46308
|
+
lastActivityAt: readStringValue(fallbackSession.lastActivityAt, fallbackSession.last_activity_at) ?? null,
|
|
46309
|
+
recoveryState: readStringValue(fallbackSession.recoveryState, fallbackSession.recovery_state) ?? null,
|
|
46310
|
+
isCached: true
|
|
46311
|
+
}];
|
|
46312
|
+
}
|
|
46313
|
+
function readLiveMeshSessionState(record2) {
|
|
46314
|
+
return readStringValue(
|
|
46315
|
+
record2?.meta?.sessionStatus,
|
|
46316
|
+
record2?.meta?.status,
|
|
46317
|
+
record2?.meta?.providerStatus,
|
|
46318
|
+
record2?.status,
|
|
46319
|
+
record2?.state,
|
|
46320
|
+
record2?.lifecycle
|
|
46321
|
+
);
|
|
46322
|
+
}
|
|
46323
|
+
function toIsoTimestamp(value) {
|
|
46324
|
+
if (typeof value === "number" && Number.isFinite(value)) return new Date(value).toISOString();
|
|
46325
|
+
const stringValue = readStringValue(value);
|
|
46326
|
+
return stringValue || null;
|
|
46327
|
+
}
|
|
46328
|
+
function synthesizeMeshNodeFreshnessFromConnection(status) {
|
|
46329
|
+
const connection = readObjectRecord(status.connection);
|
|
46330
|
+
const connectionFreshAt = toIsoTimestamp(connection.lastCommandAt ?? connection.lastConnectedAt ?? connection.lastStateChangeAt);
|
|
46331
|
+
const git = readObjectRecord(status.git);
|
|
46332
|
+
const gitCheckedAt = toIsoTimestamp(git.lastCheckedAt);
|
|
46333
|
+
if (!status.lastSeenAt && connectionFreshAt) status.lastSeenAt = connectionFreshAt;
|
|
46334
|
+
if (!status.updatedAt && (gitCheckedAt || connectionFreshAt)) {
|
|
46335
|
+
status.updatedAt = gitCheckedAt ?? connectionFreshAt;
|
|
46336
|
+
}
|
|
46337
|
+
}
|
|
46338
|
+
function finalizeMeshNodeStatus(args) {
|
|
46339
|
+
const { status, node, daemonId, isSelfNode } = args;
|
|
46340
|
+
if (!readStringValue(status.machineStatus)) {
|
|
46341
|
+
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
46342
|
+
const machineStatus = readStringValue(cachedStatus.machineStatus, cachedStatus.machine_status, node?.machineStatus);
|
|
46343
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
46344
|
+
}
|
|
46345
|
+
synthesizeMeshNodeFreshnessFromConnection(status);
|
|
46346
|
+
const connectionState = readStringValue(readObjectRecord(status.connection).state);
|
|
46347
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || connectionState === "connected" || isSelfNode);
|
|
46348
|
+
}
|
|
46349
|
+
async function probeRemoteMeshGitStatus(args) {
|
|
46350
|
+
if (!args.dispatchMeshCommand) return null;
|
|
46351
|
+
const remoteResult = await Promise.race([
|
|
46352
|
+
args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace }),
|
|
46353
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), args.timeoutMs))
|
|
46354
|
+
]);
|
|
46355
|
+
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
46356
|
+
return remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean" ? remoteGit : null;
|
|
46357
|
+
}
|
|
46358
|
+
async function hydrateInlineMeshDirectTruth(args) {
|
|
46359
|
+
const nodes = Array.isArray(args.mesh?.nodes) ? args.mesh.nodes : [];
|
|
46360
|
+
if (!nodes.length) {
|
|
46361
|
+
return {
|
|
46362
|
+
directEvidenceCount: 0,
|
|
46363
|
+
localConfirmedCount: 0,
|
|
46364
|
+
peerAttemptedCount: 0,
|
|
46365
|
+
peerConfirmedCount: 0,
|
|
46366
|
+
unavailableNodeIds: []
|
|
46367
|
+
};
|
|
46368
|
+
}
|
|
46369
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
46370
|
+
args.mesh?.coordinator?.preferredNodeId,
|
|
46371
|
+
nodes[0]?.id,
|
|
46372
|
+
nodes[0]?.nodeId
|
|
46373
|
+
);
|
|
46374
|
+
let localConfirmedCount = 0;
|
|
46375
|
+
let peerAttemptedCount = 0;
|
|
46376
|
+
let peerConfirmedCount = 0;
|
|
46377
|
+
const unavailableNodeIds = [];
|
|
46378
|
+
for (const [nodeIndex, node] of nodes.entries()) {
|
|
46379
|
+
const nodeId = readStringValue(node?.id, node?.nodeId) || `node_${nodeIndex}`;
|
|
46380
|
+
const workspace = readStringValue(node?.workspace);
|
|
46381
|
+
const daemonId = readStringValue(node?.daemonId);
|
|
46382
|
+
const isSelfNode = Boolean(
|
|
46383
|
+
nodeId && selectedCoordinatorNodeId && nodeId === selectedCoordinatorNodeId
|
|
46384
|
+
) || Boolean(
|
|
46385
|
+
daemonId && (daemonId === args.localMachineId || daemonId === args.statusInstanceId)
|
|
46386
|
+
) || Boolean(args.meshSource !== "local_config" && nodeIndex === 0);
|
|
46387
|
+
if (!workspace) {
|
|
46388
|
+
if (!isSelfNode && daemonId) unavailableNodeIds.push(nodeId);
|
|
46389
|
+
continue;
|
|
46390
|
+
}
|
|
46391
|
+
if (isSelfNode && fs10.existsSync(workspace)) {
|
|
46392
|
+
try {
|
|
46393
|
+
const localGit = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
46394
|
+
if (localGit?.isGitRepo) {
|
|
46395
|
+
recordInlineMeshDirectGitTruth(node, localGit, "selected_coordinator_local_git");
|
|
46396
|
+
localConfirmedCount += 1;
|
|
46397
|
+
continue;
|
|
46398
|
+
}
|
|
46399
|
+
} catch {
|
|
46400
|
+
}
|
|
46401
|
+
}
|
|
46402
|
+
if (!daemonId || !args.dispatchMeshCommand) {
|
|
46403
|
+
if (!isSelfNode) unavailableNodeIds.push(nodeId);
|
|
46404
|
+
continue;
|
|
46405
|
+
}
|
|
46406
|
+
peerAttemptedCount += 1;
|
|
46407
|
+
try {
|
|
46408
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
46409
|
+
dispatchMeshCommand: args.dispatchMeshCommand,
|
|
46410
|
+
daemonId,
|
|
46411
|
+
workspace,
|
|
46412
|
+
timeoutMs: 8e3
|
|
46413
|
+
});
|
|
46414
|
+
if (remoteGit) {
|
|
46415
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
46416
|
+
peerConfirmedCount += 1;
|
|
46417
|
+
continue;
|
|
46418
|
+
}
|
|
46419
|
+
} catch {
|
|
46420
|
+
}
|
|
46421
|
+
unavailableNodeIds.push(nodeId);
|
|
46422
|
+
}
|
|
46423
|
+
return {
|
|
46424
|
+
directEvidenceCount: localConfirmedCount + peerConfirmedCount,
|
|
46425
|
+
localConfirmedCount,
|
|
46426
|
+
peerAttemptedCount,
|
|
46427
|
+
peerConfirmedCount,
|
|
46428
|
+
unavailableNodeIds
|
|
45880
46429
|
};
|
|
45881
46430
|
}
|
|
45882
|
-
function
|
|
46431
|
+
function summarizeMeshSessionRecord(record2) {
|
|
46432
|
+
return {
|
|
46433
|
+
sessionId: readStringValue(record2?.sessionId) || "unknown",
|
|
46434
|
+
providerType: readStringValue(record2?.providerType),
|
|
46435
|
+
state: readLiveMeshSessionState(record2),
|
|
46436
|
+
lifecycle: readStringValue(record2?.lifecycle),
|
|
46437
|
+
surfaceKind: getSessionHostSurfaceKind(record2),
|
|
46438
|
+
recoveryState: readStringValue(record2?.meta?.runtimeRecoveryState) ?? null,
|
|
46439
|
+
workspace: readStringValue(record2?.workspace) ?? null,
|
|
46440
|
+
title: readStringValue(record2?.displayName, record2?.workspaceLabel) ?? null,
|
|
46441
|
+
lastActivityAt: toIsoTimestamp(record2?.updatedAt ?? record2?.lastActivityAt ?? record2?.last_activity_at),
|
|
46442
|
+
isCached: false
|
|
46443
|
+
};
|
|
46444
|
+
}
|
|
46445
|
+
function liveSessionRecordMatchesMeshNode(record2, meshId, nodeId) {
|
|
46446
|
+
const recordNodeId = readStringValue(record2?.meta?.meshNodeId);
|
|
46447
|
+
if (!recordNodeId || recordNodeId !== nodeId) return false;
|
|
46448
|
+
const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
|
|
46449
|
+
return !recordMeshId || recordMeshId === meshId;
|
|
46450
|
+
}
|
|
46451
|
+
function liveSessionRecordMatchesMeshWorkspace(record2, meshId, workspace) {
|
|
46452
|
+
const recordWorkspace = readStringValue(record2?.workspace);
|
|
46453
|
+
if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
|
|
46454
|
+
const recordMeshId = readStringValue(record2?.meta?.meshNodeFor);
|
|
46455
|
+
if (recordMeshId) return recordMeshId === meshId;
|
|
46456
|
+
return record2?.meta?.launchedByCoordinator === true || !!readStringValue(record2?.meta?.meshNodeId);
|
|
46457
|
+
}
|
|
46458
|
+
function readLiveMeshNodeWorkspace(args) {
|
|
46459
|
+
const directNodeWorkspace = args.liveSessionRecords.find((record2) => liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId) && readStringValue(record2?.workspace));
|
|
46460
|
+
if (directNodeWorkspace) {
|
|
46461
|
+
return readStringValue(directNodeWorkspace.workspace) || "";
|
|
46462
|
+
}
|
|
46463
|
+
if (args.allowCoordinatorSession) {
|
|
46464
|
+
const coordinatorWorkspace = args.liveSessionRecords.find((record2) => readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId && readStringValue(record2?.workspace));
|
|
46465
|
+
if (coordinatorWorkspace) {
|
|
46466
|
+
return readStringValue(coordinatorWorkspace.workspace) || "";
|
|
46467
|
+
}
|
|
46468
|
+
}
|
|
46469
|
+
return "";
|
|
46470
|
+
}
|
|
46471
|
+
function collectLiveMeshSessionRecords(args) {
|
|
46472
|
+
const matches = args.liveSessionRecords.filter((record2) => {
|
|
46473
|
+
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
46474
|
+
if (liveSessionRecordMatchesMeshNode(record2, args.meshId, args.nodeId)) return true;
|
|
46475
|
+
return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record2, args.meshId, nodeWorkspace);
|
|
46476
|
+
});
|
|
46477
|
+
if (args.allowCoordinatorSession) {
|
|
46478
|
+
for (const record2 of args.liveSessionRecords) {
|
|
46479
|
+
if (readStringValue(record2?.meta?.meshCoordinatorFor) !== args.meshId) continue;
|
|
46480
|
+
const sessionId = readStringValue(record2?.sessionId);
|
|
46481
|
+
if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
|
|
46482
|
+
matches.push(record2);
|
|
46483
|
+
}
|
|
46484
|
+
}
|
|
46485
|
+
return matches;
|
|
46486
|
+
}
|
|
46487
|
+
function applyCachedInlineMeshNodeStatus(status, node, options) {
|
|
45883
46488
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
45884
|
-
const
|
|
45885
|
-
const
|
|
45886
|
-
const
|
|
46489
|
+
const liveGit = buildInlineMeshTransitGitStatus(node);
|
|
46490
|
+
const git = options?.skipGit ? void 0 : liveGit ?? buildCachedInlineMeshGitStatus(node);
|
|
46491
|
+
const error48 = options?.skipError ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
|
|
46492
|
+
const health = options?.skipHealth ? void 0 : liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
|
|
45887
46493
|
const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
|
|
45888
|
-
|
|
45889
|
-
|
|
46494
|
+
const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
|
|
46495
|
+
const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);
|
|
46496
|
+
const activeSessions = readCachedInlineMeshActiveSessions(node);
|
|
46497
|
+
const activeSessionDetails = readCachedInlineMeshActiveSessionDetails(node);
|
|
46498
|
+
if (!git && !error48 && !health && !machineStatus && !lastSeenAt && !updatedAt && activeSessions.length === 0) return false;
|
|
45890
46499
|
if (git) status.git = git;
|
|
45891
46500
|
if (error48) status.error = error48;
|
|
46501
|
+
if (machineStatus) status.machineStatus = machineStatus;
|
|
46502
|
+
if (lastSeenAt) status.lastSeenAt = lastSeenAt;
|
|
46503
|
+
if (updatedAt) status.updatedAt = updatedAt;
|
|
46504
|
+
if (activeSessions.length > 0) status.activeSessions = activeSessions;
|
|
46505
|
+
if (activeSessionDetails.length > 0) status.activeSessionDetails = activeSessionDetails;
|
|
45892
46506
|
if (health) {
|
|
45893
46507
|
status.health = health;
|
|
45894
46508
|
return true;
|
|
45895
46509
|
}
|
|
45896
46510
|
if (git) {
|
|
45897
|
-
|
|
45898
|
-
status.health = git.isGitRepo === false ? "degraded" : dirty ? "dirty" : "online";
|
|
46511
|
+
status.health = deriveMeshNodeHealthFromGit(git);
|
|
45899
46512
|
return true;
|
|
45900
46513
|
}
|
|
45901
|
-
return
|
|
46514
|
+
return activeSessions.length > 0 || !!machineStatus || !!lastSeenAt || !!updatedAt;
|
|
45902
46515
|
}
|
|
45903
46516
|
async function resolveProviderTypeFromPriority(args) {
|
|
45904
46517
|
if (!args.providerPriority.length) {
|
|
@@ -45928,15 +46541,92 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
45928
46541
|
var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
|
|
45929
46542
|
var REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
|
|
45930
46543
|
var REFINE_VALIDATION_MAX_COMMANDS = 4;
|
|
46544
|
+
var REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
|
|
45931
46545
|
function truncateValidationOutput(value) {
|
|
45932
46546
|
const text = typeof value === "string" ? value : value == null ? "" : String(value);
|
|
45933
46547
|
if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
|
|
45934
46548
|
return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
|
|
45935
46549
|
[truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
|
|
45936
46550
|
}
|
|
46551
|
+
function recordMeshRefineStage(stages, stage, status, startedAt, details) {
|
|
46552
|
+
stages.push({
|
|
46553
|
+
stage,
|
|
46554
|
+
status,
|
|
46555
|
+
durationMs: Date.now() - startedAt,
|
|
46556
|
+
...details || {}
|
|
46557
|
+
});
|
|
46558
|
+
}
|
|
46559
|
+
async function computeGitPatchId(cwd, fromRef, toRef) {
|
|
46560
|
+
const { execFileSync: execFileSync4 } = await import("child_process");
|
|
46561
|
+
const diff = execFileSync4("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
|
|
46562
|
+
cwd,
|
|
46563
|
+
encoding: "utf8",
|
|
46564
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
46565
|
+
});
|
|
46566
|
+
if (!diff.trim()) return "";
|
|
46567
|
+
const patchId = execFileSync4("git", ["patch-id", "--stable"], {
|
|
46568
|
+
cwd,
|
|
46569
|
+
input: diff,
|
|
46570
|
+
encoding: "utf8",
|
|
46571
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
46572
|
+
}).trim();
|
|
46573
|
+
return patchId.split(/\s+/)[0] || "";
|
|
46574
|
+
}
|
|
46575
|
+
async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
|
|
46576
|
+
const startedAt = Date.now();
|
|
46577
|
+
try {
|
|
46578
|
+
const { execFileSync: execFileSync4 } = await import("child_process");
|
|
46579
|
+
const git = (args) => execFileSync4("git", args, {
|
|
46580
|
+
cwd: repoRoot,
|
|
46581
|
+
encoding: "utf8",
|
|
46582
|
+
maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
|
|
46583
|
+
});
|
|
46584
|
+
const mergeBase = git(["merge-base", baseHead, branchHead]).trim();
|
|
46585
|
+
const mergeTreeStdout = git(["merge-tree", "--write-tree", baseHead, branchHead]);
|
|
46586
|
+
const mergedTree = mergeTreeStdout.trim().split(/\s+/)[0] || "";
|
|
46587
|
+
if (!mergeBase || !mergedTree) {
|
|
46588
|
+
return {
|
|
46589
|
+
status: "failed",
|
|
46590
|
+
equivalent: false,
|
|
46591
|
+
baseHead,
|
|
46592
|
+
branchHead,
|
|
46593
|
+
mergeBase: mergeBase || void 0,
|
|
46594
|
+
mergedTree: mergedTree || void 0,
|
|
46595
|
+
durationMs: Date.now() - startedAt,
|
|
46596
|
+
error: "patch equivalence preflight could not resolve merge-base or synthetic merge tree",
|
|
46597
|
+
stdout: truncateValidationOutput(mergeTreeStdout)
|
|
46598
|
+
};
|
|
46599
|
+
}
|
|
46600
|
+
const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
|
|
46601
|
+
const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree);
|
|
46602
|
+
const equivalent = expectedPatchId === actualPatchId;
|
|
46603
|
+
return {
|
|
46604
|
+
status: equivalent ? "passed" : "failed",
|
|
46605
|
+
equivalent,
|
|
46606
|
+
baseHead,
|
|
46607
|
+
branchHead,
|
|
46608
|
+
mergeBase,
|
|
46609
|
+
mergedTree,
|
|
46610
|
+
expectedPatchId,
|
|
46611
|
+
actualPatchId,
|
|
46612
|
+
durationMs: Date.now() - startedAt
|
|
46613
|
+
};
|
|
46614
|
+
} catch (e) {
|
|
46615
|
+
return {
|
|
46616
|
+
status: "failed",
|
|
46617
|
+
equivalent: false,
|
|
46618
|
+
baseHead,
|
|
46619
|
+
branchHead,
|
|
46620
|
+
durationMs: Date.now() - startedAt,
|
|
46621
|
+
error: e?.message || String(e),
|
|
46622
|
+
stdout: truncateValidationOutput(e?.stdout),
|
|
46623
|
+
stderr: truncateValidationOutput(e?.stderr)
|
|
46624
|
+
};
|
|
46625
|
+
}
|
|
46626
|
+
}
|
|
45937
46627
|
function readPackageScripts(workspace) {
|
|
45938
46628
|
try {
|
|
45939
|
-
const packageJsonPath = (0,
|
|
46629
|
+
const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
|
|
45940
46630
|
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
45941
46631
|
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
45942
46632
|
} catch {
|
|
@@ -46144,13 +46834,13 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46144
46834
|
}
|
|
46145
46835
|
function resolveHermesUserHome() {
|
|
46146
46836
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
46147
|
-
return explicitHome || (0,
|
|
46837
|
+
return explicitHome || (0, import_path7.join)((0, import_os3.homedir)(), ".hermes");
|
|
46148
46838
|
}
|
|
46149
46839
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
46150
46840
|
const sourceHome = resolveHermesUserHome();
|
|
46151
|
-
const sourceConfigPath = (0,
|
|
46841
|
+
const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
|
|
46152
46842
|
if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
46153
|
-
if ((0,
|
|
46843
|
+
if ((0, import_path7.resolve)(sourceConfigPath) === (0, import_path7.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
46154
46844
|
const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
46155
46845
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
46156
46846
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
@@ -46184,10 +46874,10 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46184
46874
|
return sanitized;
|
|
46185
46875
|
}
|
|
46186
46876
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
46187
|
-
if ((0,
|
|
46877
|
+
if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
|
|
46188
46878
|
for (const fileName of [".env", "auth.json"]) {
|
|
46189
|
-
const sourcePath = (0,
|
|
46190
|
-
const targetPath = (0,
|
|
46879
|
+
const sourcePath = (0, import_path7.join)(sourceHome, fileName);
|
|
46880
|
+
const targetPath = (0, import_path7.join)(targetHome, fileName);
|
|
46191
46881
|
if (!fs10.existsSync(sourcePath)) continue;
|
|
46192
46882
|
try {
|
|
46193
46883
|
fs10.copyFileSync(sourcePath, targetPath);
|
|
@@ -46291,30 +46981,97 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46291
46981
|
* Allows the MCP server to query mesh data via get_mesh even when
|
|
46292
46982
|
* the mesh doesn't exist in the local meshes.json file. */
|
|
46293
46983
|
inlineMeshCache = /* @__PURE__ */ new Map();
|
|
46984
|
+
/** Coordinator-owned whole-mesh aggregate status snapshots. Browser callers read this by default. */
|
|
46985
|
+
aggregateMeshStatusCache = /* @__PURE__ */ new Map();
|
|
46294
46986
|
constructor(deps) {
|
|
46295
46987
|
this.deps = deps;
|
|
46296
46988
|
}
|
|
46989
|
+
cloneJsonValue(value) {
|
|
46990
|
+
if (typeof structuredClone === "function") return structuredClone(value);
|
|
46991
|
+
return JSON.parse(JSON.stringify(value));
|
|
46992
|
+
}
|
|
46993
|
+
getCachedAggregateMeshStatus(meshId) {
|
|
46994
|
+
const cached2 = this.aggregateMeshStatusCache.get(meshId);
|
|
46995
|
+
if (!cached2?.snapshot || cached2.snapshot.success !== true || !Array.isArray(cached2.snapshot.nodes)) return null;
|
|
46996
|
+
const snapshot = this.cloneJsonValue(cached2.snapshot);
|
|
46997
|
+
const ageMs = Math.max(0, Date.now() - cached2.builtAt);
|
|
46998
|
+
const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
|
|
46999
|
+
snapshot.sourceOfTruth = {
|
|
47000
|
+
...sourceOfTruth,
|
|
47001
|
+
aggregateSnapshot: {
|
|
47002
|
+
...sourceOfTruth.aggregateSnapshot && typeof sourceOfTruth.aggregateSnapshot === "object" ? sourceOfTruth.aggregateSnapshot : {},
|
|
47003
|
+
owner: "coordinator_daemon_memory",
|
|
47004
|
+
cached: true,
|
|
47005
|
+
source: "memory",
|
|
47006
|
+
refreshReason: "memory_cache_hit",
|
|
47007
|
+
ageMs,
|
|
47008
|
+
cachedAt: new Date(cached2.builtAt).toISOString(),
|
|
47009
|
+
returnedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
47010
|
+
}
|
|
47011
|
+
};
|
|
47012
|
+
return snapshot;
|
|
47013
|
+
}
|
|
47014
|
+
rememberAggregateMeshStatus(meshId, snapshot, refreshReason) {
|
|
47015
|
+
if (!snapshot || typeof snapshot !== "object" || snapshot.success !== true || !Array.isArray(snapshot.nodes)) return snapshot;
|
|
47016
|
+
const builtAt = Date.now();
|
|
47017
|
+
const next = this.cloneJsonValue(snapshot);
|
|
47018
|
+
const sourceOfTruth = next.sourceOfTruth && typeof next.sourceOfTruth === "object" ? next.sourceOfTruth : {};
|
|
47019
|
+
next.sourceOfTruth = {
|
|
47020
|
+
...sourceOfTruth,
|
|
47021
|
+
aggregateSnapshot: {
|
|
47022
|
+
owner: "coordinator_daemon_memory",
|
|
47023
|
+
cached: false,
|
|
47024
|
+
source: "live_refresh",
|
|
47025
|
+
refreshReason,
|
|
47026
|
+
ageMs: 0,
|
|
47027
|
+
cachedAt: new Date(builtAt).toISOString(),
|
|
47028
|
+
returnedAt: new Date(builtAt).toISOString()
|
|
47029
|
+
}
|
|
47030
|
+
};
|
|
47031
|
+
this.aggregateMeshStatusCache.set(meshId, { builtAt, snapshot: this.cloneJsonValue(next) });
|
|
47032
|
+
return next;
|
|
47033
|
+
}
|
|
46297
47034
|
getCachedInlineMesh(meshId, inlineMesh) {
|
|
46298
47035
|
if (inlineMesh && typeof inlineMesh === "object") {
|
|
46299
|
-
this.
|
|
46300
|
-
return inlineMesh;
|
|
47036
|
+
return this.warmInlineMeshCache(meshId, inlineMesh);
|
|
46301
47037
|
}
|
|
46302
47038
|
return this.inlineMeshCache.get(meshId);
|
|
46303
47039
|
}
|
|
47040
|
+
warmInlineMeshCache(meshId, inlineMesh) {
|
|
47041
|
+
if (!inlineMesh || typeof inlineMesh !== "object") return void 0;
|
|
47042
|
+
const sanitizedInlineMesh = sanitizeInlineMesh(inlineMesh);
|
|
47043
|
+
const cached2 = this.inlineMeshCache.get(meshId);
|
|
47044
|
+
if (cached2) {
|
|
47045
|
+
const merged = reconcileInlineMeshCache(cached2, sanitizedInlineMesh);
|
|
47046
|
+
this.inlineMeshCache.set(meshId, merged);
|
|
47047
|
+
return merged;
|
|
47048
|
+
}
|
|
47049
|
+
this.inlineMeshCache.set(meshId, sanitizedInlineMesh);
|
|
47050
|
+
return sanitizedInlineMesh;
|
|
47051
|
+
}
|
|
46304
47052
|
async getMeshForCommand(meshId, inlineMesh, options) {
|
|
46305
47053
|
const preferInline = options?.preferInline === true;
|
|
46306
47054
|
if (preferInline) {
|
|
46307
|
-
const cached22 = this.getCachedInlineMesh(meshId
|
|
46308
|
-
if (cached22) return { mesh: cached22, inline: true };
|
|
47055
|
+
const cached22 = this.getCachedInlineMesh(meshId);
|
|
47056
|
+
if (cached22) return { mesh: cached22, inline: true, source: "inline_cache" };
|
|
47057
|
+
if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
|
|
47058
|
+
this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47059
|
+
return { mesh: inlineMesh, inline: true, source: "inline_bootstrap" };
|
|
47060
|
+
}
|
|
46309
47061
|
}
|
|
46310
47062
|
try {
|
|
46311
47063
|
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
46312
47064
|
const mesh = getMesh3(meshId);
|
|
46313
|
-
if (mesh) return { mesh, inline: false };
|
|
47065
|
+
if (mesh) return { mesh, inline: false, source: "local_config" };
|
|
46314
47066
|
} catch {
|
|
46315
47067
|
}
|
|
46316
|
-
const cached2 = this.getCachedInlineMesh(meshId
|
|
46317
|
-
|
|
47068
|
+
const cached2 = this.getCachedInlineMesh(meshId);
|
|
47069
|
+
if (cached2) return { mesh: cached2, inline: true, source: "inline_cache" };
|
|
47070
|
+
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
47071
|
+
return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
|
|
47072
|
+
}
|
|
47073
|
+
invalidateAggregateMeshStatus(meshId) {
|
|
47074
|
+
this.aggregateMeshStatusCache.delete(meshId);
|
|
46318
47075
|
}
|
|
46319
47076
|
updateInlineMeshNode(meshId, mesh, node) {
|
|
46320
47077
|
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
@@ -46323,6 +47080,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46323
47080
|
else mesh.nodes.push(node);
|
|
46324
47081
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
46325
47082
|
this.inlineMeshCache.set(meshId, mesh);
|
|
47083
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
46326
47084
|
}
|
|
46327
47085
|
removeInlineMeshNode(meshId, mesh, nodeId) {
|
|
46328
47086
|
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
@@ -46331,6 +47089,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46331
47089
|
mesh.nodes.splice(idx, 1);
|
|
46332
47090
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
46333
47091
|
this.inlineMeshCache.set(meshId, mesh);
|
|
47092
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
46334
47093
|
return true;
|
|
46335
47094
|
}
|
|
46336
47095
|
normalizeMeshSessionCleanupMode(value) {
|
|
@@ -46379,7 +47138,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46379
47138
|
}
|
|
46380
47139
|
const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
46381
47140
|
const normalizePath = (value) => {
|
|
46382
|
-
const resolved = (0,
|
|
47141
|
+
const resolved = (0, import_path7.resolve)(value);
|
|
46383
47142
|
try {
|
|
46384
47143
|
return fs10.realpathSync(resolved);
|
|
46385
47144
|
} catch {
|
|
@@ -46543,6 +47302,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46543
47302
|
const deletedSessionIds = [];
|
|
46544
47303
|
const skippedSessionIds = [];
|
|
46545
47304
|
const skippedLiveSessionIds = [];
|
|
47305
|
+
const skippedCoordinatorSessionIds = [];
|
|
46546
47306
|
const deleteUnsupportedSessionIds = [];
|
|
46547
47307
|
const recordsRemainSessionIds = [];
|
|
46548
47308
|
const errors = [];
|
|
@@ -46575,6 +47335,12 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46575
47335
|
const completed = this.isCompletedHostedSession(record2);
|
|
46576
47336
|
const surfaceKind = getSessionHostSurfaceKind(record2);
|
|
46577
47337
|
const liveRuntime = surfaceKind === "live_runtime";
|
|
47338
|
+
const coordinatorSession = readStringValue(record2?.meta?.meshCoordinatorFor) === args.meshId;
|
|
47339
|
+
if (!hasExplicitSessionIds && coordinatorSession) {
|
|
47340
|
+
skippedSessionIds.push(sessionId);
|
|
47341
|
+
skippedCoordinatorSessionIds.push(sessionId);
|
|
47342
|
+
continue;
|
|
47343
|
+
}
|
|
46578
47344
|
if (!hasExplicitSessionIds && liveRuntime) {
|
|
46579
47345
|
skippedSessionIds.push(sessionId);
|
|
46580
47346
|
skippedLiveSessionIds.push(sessionId);
|
|
@@ -46640,6 +47406,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46640
47406
|
deletedSessionIds,
|
|
46641
47407
|
skippedSessionIds,
|
|
46642
47408
|
skippedLiveSessionIds,
|
|
47409
|
+
skippedCoordinatorSessionIds,
|
|
46643
47410
|
...deleteUnsupported ? {
|
|
46644
47411
|
deleteUnsupported: true,
|
|
46645
47412
|
effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
|
|
@@ -46772,7 +47539,8 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
46772
47539
|
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
|
|
46773
47540
|
}
|
|
46774
47541
|
case "get_pending_mesh_events": {
|
|
46775
|
-
const
|
|
47542
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47543
|
+
const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
|
|
46776
47544
|
return { success: true, events };
|
|
46777
47545
|
}
|
|
46778
47546
|
case "launch_cli":
|
|
@@ -47301,15 +48069,39 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47301
48069
|
case "get_mesh": {
|
|
47302
48070
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47303
48071
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
47304
|
-
|
|
47305
|
-
|
|
47306
|
-
|
|
47307
|
-
|
|
47308
|
-
|
|
48072
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48073
|
+
if (!meshRecord?.mesh) return { success: false, error: "Mesh not found" };
|
|
48074
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
48075
|
+
const directTruth = await hydrateInlineMeshDirectTruth({
|
|
48076
|
+
mesh: meshRecord.mesh,
|
|
48077
|
+
meshSource: meshRecord.source,
|
|
48078
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
48079
|
+
statusInstanceId: this.deps.statusInstanceId,
|
|
48080
|
+
localMachineId: loadConfig2().machineId || ""
|
|
48081
|
+
});
|
|
48082
|
+
const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
|
|
48083
|
+
const sourceOfTruth = {
|
|
48084
|
+
membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
48085
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
48086
|
+
directPeerTruth: {
|
|
48087
|
+
required: requireDirectPeerTruth,
|
|
48088
|
+
satisfied: directTruthSatisfied,
|
|
48089
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
48090
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
48091
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
48092
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
48093
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
48094
|
+
}
|
|
48095
|
+
};
|
|
48096
|
+
if (requireDirectPeerTruth && !directTruthSatisfied) {
|
|
48097
|
+
return {
|
|
48098
|
+
success: false,
|
|
48099
|
+
code: "mesh_direct_peer_truth_unavailable",
|
|
48100
|
+
error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct get_mesh probes succeed.",
|
|
48101
|
+
sourceOfTruth
|
|
48102
|
+
};
|
|
47309
48103
|
}
|
|
47310
|
-
|
|
47311
|
-
if (cached2) return { success: true, mesh: cached2 };
|
|
47312
|
-
return { success: false, error: "Mesh not found" };
|
|
48104
|
+
return { success: true, mesh: meshRecord.mesh, sourceOfTruth };
|
|
47313
48105
|
}
|
|
47314
48106
|
case "create_mesh": {
|
|
47315
48107
|
const name = typeof args?.name === "string" ? args.name.trim() : "";
|
|
@@ -47339,6 +48131,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47339
48131
|
const mesh = updateMesh2(meshId, patch);
|
|
47340
48132
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
47341
48133
|
this.inlineMeshCache.set(meshId, mesh);
|
|
48134
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
47342
48135
|
return { success: true, mesh };
|
|
47343
48136
|
} catch (e) {
|
|
47344
48137
|
return { success: false, error: e.message };
|
|
@@ -47528,26 +48321,41 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47528
48321
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
47529
48322
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
47530
48323
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
48324
|
+
const refineStages = [];
|
|
47531
48325
|
try {
|
|
47532
48326
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
47533
48327
|
const mesh = meshRecord?.mesh;
|
|
47534
48328
|
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
47535
|
-
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh
|
|
48329
|
+
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
|
|
47536
48330
|
if (!node.isLocalWorktree || !node.workspace) {
|
|
47537
|
-
return { success: false, error: `Refinery requires a local worktree node
|
|
48331
|
+
return { success: false, error: `Refinery requires a local worktree node`, refineStages };
|
|
47538
48332
|
}
|
|
47539
48333
|
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
47540
48334
|
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
47541
|
-
if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
|
|
48335
|
+
if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
|
|
47542
48336
|
const { execFile: execFile3 } = await import("child_process");
|
|
47543
48337
|
const { promisify: promisify3 } = await import("util");
|
|
47544
48338
|
const execFileAsync3 = promisify3(execFile3);
|
|
48339
|
+
const resolveStarted = Date.now();
|
|
47545
48340
|
const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
|
|
47546
48341
|
const branch = branchStdout.trim();
|
|
47547
|
-
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
48342
|
+
if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
|
|
47548
48343
|
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
47549
48344
|
const baseBranch = baseBranchStdout.trim();
|
|
48345
|
+
const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
|
|
48346
|
+
const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
|
|
48347
|
+
const baseHead = baseHeadStdout.trim();
|
|
48348
|
+
const branchHead = branchHeadStdout.trim();
|
|
48349
|
+
recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
|
|
48350
|
+
const validationStarted = Date.now();
|
|
47550
48351
|
const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
|
|
48352
|
+
recordMeshRefineStage(
|
|
48353
|
+
refineStages,
|
|
48354
|
+
"validation",
|
|
48355
|
+
validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
|
|
48356
|
+
validationStarted,
|
|
48357
|
+
{ validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
|
|
48358
|
+
);
|
|
47551
48359
|
if (validationSummary.status === "failed") {
|
|
47552
48360
|
return {
|
|
47553
48361
|
success: false,
|
|
@@ -47557,6 +48365,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47557
48365
|
branch,
|
|
47558
48366
|
into: baseBranch,
|
|
47559
48367
|
validationSummary,
|
|
48368
|
+
refineStages,
|
|
47560
48369
|
finalBranchConvergenceState: {
|
|
47561
48370
|
branch,
|
|
47562
48371
|
baseBranch,
|
|
@@ -47576,6 +48385,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47576
48385
|
branch,
|
|
47577
48386
|
into: baseBranch,
|
|
47578
48387
|
validationSummary,
|
|
48388
|
+
refineStages,
|
|
47579
48389
|
finalBranchConvergenceState: {
|
|
47580
48390
|
branch,
|
|
47581
48391
|
baseBranch,
|
|
@@ -47586,37 +48396,121 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47586
48396
|
}
|
|
47587
48397
|
};
|
|
47588
48398
|
}
|
|
48399
|
+
const patchEquivalenceStarted = Date.now();
|
|
48400
|
+
const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
|
|
48401
|
+
recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
|
|
48402
|
+
equivalent: patchEquivalence.equivalent,
|
|
48403
|
+
expectedPatchId: patchEquivalence.expectedPatchId,
|
|
48404
|
+
actualPatchId: patchEquivalence.actualPatchId,
|
|
48405
|
+
error: patchEquivalence.error
|
|
48406
|
+
});
|
|
48407
|
+
if (!patchEquivalence.equivalent) {
|
|
48408
|
+
return {
|
|
48409
|
+
success: false,
|
|
48410
|
+
code: "patch_equivalence_failed",
|
|
48411
|
+
convergenceStatus: "blocked_review",
|
|
48412
|
+
error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
|
|
48413
|
+
branch,
|
|
48414
|
+
into: baseBranch,
|
|
48415
|
+
validationSummary,
|
|
48416
|
+
patchEquivalence,
|
|
48417
|
+
refineStages,
|
|
48418
|
+
finalBranchConvergenceState: {
|
|
48419
|
+
branch,
|
|
48420
|
+
baseBranch,
|
|
48421
|
+
merged: false,
|
|
48422
|
+
removed: false,
|
|
48423
|
+
validation: "passed",
|
|
48424
|
+
patchEquivalence: "failed",
|
|
48425
|
+
status: "blocked_review"
|
|
48426
|
+
}
|
|
48427
|
+
};
|
|
48428
|
+
}
|
|
48429
|
+
let mergeResult;
|
|
48430
|
+
const mergeStarted = Date.now();
|
|
47589
48431
|
try {
|
|
47590
|
-
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
48432
|
+
const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
48433
|
+
mergeResult = {
|
|
48434
|
+
stdout: truncateValidationOutput(result.stdout),
|
|
48435
|
+
stderr: truncateValidationOutput(result.stderr),
|
|
48436
|
+
durationMs: Date.now() - mergeStarted
|
|
48437
|
+
};
|
|
48438
|
+
recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
|
|
47591
48439
|
} catch (e) {
|
|
48440
|
+
recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
|
|
48441
|
+
error: e?.message || String(e),
|
|
48442
|
+
stdout: truncateValidationOutput(e?.stdout),
|
|
48443
|
+
stderr: truncateValidationOutput(e?.stderr)
|
|
48444
|
+
});
|
|
47592
48445
|
return {
|
|
47593
48446
|
success: false,
|
|
47594
48447
|
error: `Merge failed (conflicts?): ${e.message}`,
|
|
47595
48448
|
validationSummary,
|
|
48449
|
+
patchEquivalence,
|
|
48450
|
+
refineStages,
|
|
47596
48451
|
finalBranchConvergenceState: {
|
|
47597
48452
|
branch,
|
|
47598
48453
|
baseBranch,
|
|
47599
48454
|
merged: false,
|
|
47600
48455
|
removed: false,
|
|
47601
48456
|
validation: "passed",
|
|
48457
|
+
patchEquivalence: "passed",
|
|
47602
48458
|
status: "not_mergeable"
|
|
47603
48459
|
}
|
|
47604
48460
|
};
|
|
47605
48461
|
}
|
|
48462
|
+
const cleanupStarted = Date.now();
|
|
47606
48463
|
const removeResult = await this.execute("remove_mesh_node", {
|
|
47607
48464
|
meshId,
|
|
47608
48465
|
nodeId,
|
|
47609
|
-
sessionCleanupMode: "
|
|
48466
|
+
sessionCleanupMode: "preserve",
|
|
47610
48467
|
inlineMesh: args?.inlineMesh
|
|
47611
48468
|
});
|
|
48469
|
+
recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
|
|
48470
|
+
removed: removeResult?.removed,
|
|
48471
|
+
code: removeResult?.code,
|
|
48472
|
+
error: removeResult?.error
|
|
48473
|
+
});
|
|
48474
|
+
let ledgerError;
|
|
48475
|
+
const ledgerStarted = Date.now();
|
|
47612
48476
|
try {
|
|
47613
48477
|
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
47614
48478
|
appendLedgerEntry2(meshId, {
|
|
47615
48479
|
kind: "node_removed",
|
|
47616
48480
|
nodeId,
|
|
47617
|
-
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
|
|
48481
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
|
|
47618
48482
|
});
|
|
47619
|
-
|
|
48483
|
+
recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
|
|
48484
|
+
} catch (e) {
|
|
48485
|
+
ledgerError = e?.message || String(e);
|
|
48486
|
+
recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
|
|
48487
|
+
}
|
|
48488
|
+
const finalBranchConvergenceState = {
|
|
48489
|
+
branch: baseBranch,
|
|
48490
|
+
mergedBranch: branch,
|
|
48491
|
+
baseBranch,
|
|
48492
|
+
merged: true,
|
|
48493
|
+
removed: removeResult?.success !== false,
|
|
48494
|
+
validation: "passed",
|
|
48495
|
+
patchEquivalence: "passed",
|
|
48496
|
+
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
48497
|
+
};
|
|
48498
|
+
if (removeResult?.success === false) {
|
|
48499
|
+
return {
|
|
48500
|
+
success: false,
|
|
48501
|
+
code: "cleanup_failed",
|
|
48502
|
+
error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
|
|
48503
|
+
merged: true,
|
|
48504
|
+
branch,
|
|
48505
|
+
into: baseBranch,
|
|
48506
|
+
removeResult,
|
|
48507
|
+
validationSummary,
|
|
48508
|
+
patchEquivalence,
|
|
48509
|
+
mergeResult,
|
|
48510
|
+
refineStages,
|
|
48511
|
+
...ledgerError ? { ledgerError } : {},
|
|
48512
|
+
finalBranchConvergenceState
|
|
48513
|
+
};
|
|
47620
48514
|
}
|
|
47621
48515
|
return {
|
|
47622
48516
|
success: true,
|
|
@@ -47625,18 +48519,14 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47625
48519
|
into: baseBranch,
|
|
47626
48520
|
removeResult,
|
|
47627
48521
|
validationSummary,
|
|
47628
|
-
|
|
47629
|
-
|
|
47630
|
-
|
|
47631
|
-
|
|
47632
|
-
|
|
47633
|
-
removed: removeResult?.success !== false,
|
|
47634
|
-
validation: "passed",
|
|
47635
|
-
status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
|
|
47636
|
-
}
|
|
48522
|
+
patchEquivalence,
|
|
48523
|
+
mergeResult,
|
|
48524
|
+
refineStages,
|
|
48525
|
+
...ledgerError ? { ledgerError } : {},
|
|
48526
|
+
finalBranchConvergenceState
|
|
47637
48527
|
};
|
|
47638
48528
|
} catch (e) {
|
|
47639
|
-
return { success: false, error: e.message };
|
|
48529
|
+
return { success: false, error: e.message, refineStages };
|
|
47640
48530
|
}
|
|
47641
48531
|
}
|
|
47642
48532
|
case "remove_mesh_node": {
|
|
@@ -47677,6 +48567,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47677
48567
|
} else {
|
|
47678
48568
|
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
47679
48569
|
removed = removeNode3(meshId, nodeId);
|
|
48570
|
+
if (removed) this.invalidateAggregateMeshStatus(meshId);
|
|
47680
48571
|
}
|
|
47681
48572
|
if (removed) {
|
|
47682
48573
|
try {
|
|
@@ -47755,6 +48646,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47755
48646
|
policy: { ...sourceNode.policy || {} }
|
|
47756
48647
|
});
|
|
47757
48648
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
48649
|
+
this.invalidateAggregateMeshStatus(meshId);
|
|
47758
48650
|
}
|
|
47759
48651
|
const initSubmodules = sourceNode.policy?.initSubmodulesOnClone !== false;
|
|
47760
48652
|
if (initSubmodules) {
|
|
@@ -47830,7 +48722,14 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
47830
48722
|
cliType
|
|
47831
48723
|
};
|
|
47832
48724
|
}
|
|
47833
|
-
const
|
|
48725
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
48726
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
48727
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
48728
|
+
meshId,
|
|
48729
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ""),
|
|
48730
|
+
liveSessionRecords: liveMeshSessions,
|
|
48731
|
+
allowCoordinatorSession: true
|
|
48732
|
+
}) || (typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "");
|
|
47834
48733
|
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
47835
48734
|
if (!cliType) {
|
|
47836
48735
|
const resolved = await resolveProviderTypeFromPriority({
|
|
@@ -47992,7 +48891,7 @@ ${block}`);
|
|
|
47992
48891
|
workspace
|
|
47993
48892
|
};
|
|
47994
48893
|
}
|
|
47995
|
-
const { existsSync:
|
|
48894
|
+
const { existsSync: existsSync26, readFileSync: readFileSync18, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
|
|
47996
48895
|
const { dirname: dirname9 } = await import("path");
|
|
47997
48896
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
47998
48897
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -48035,14 +48934,14 @@ ${block}`);
|
|
|
48035
48934
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
48036
48935
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
48037
48936
|
}
|
|
48038
|
-
const hadExistingMcpConfig =
|
|
48937
|
+
const hadExistingMcpConfig = existsSync26(mcpConfigPath);
|
|
48039
48938
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
48040
48939
|
if (hermesBaseConfig) {
|
|
48041
48940
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
|
|
48042
48941
|
}
|
|
48043
48942
|
if (hadExistingMcpConfig) {
|
|
48044
48943
|
try {
|
|
48045
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
48944
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync18(mcpConfigPath, "utf-8"), configFormat);
|
|
48046
48945
|
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
48047
48946
|
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
48048
48947
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
@@ -48132,110 +49031,264 @@ ${block}`);
|
|
|
48132
49031
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh, { preferInline: true });
|
|
48133
49032
|
const mesh = meshRecord?.mesh;
|
|
48134
49033
|
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
49034
|
+
const refreshRequested = args?.refresh === true || args?.forceRefresh === true;
|
|
49035
|
+
if (!refreshRequested) {
|
|
49036
|
+
const cachedStatus = this.getCachedAggregateMeshStatus(meshId);
|
|
49037
|
+
if (cachedStatus) return cachedStatus;
|
|
49038
|
+
}
|
|
49039
|
+
const refreshReason = refreshRequested ? "explicit_refresh" : "cold_cache_miss";
|
|
48135
49040
|
const { getMeshQueueStats: getMeshQueueStats2, getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
48136
49041
|
const queue = getQueue2(meshId);
|
|
48137
49042
|
const queueSummary = getMeshQueueStats2(meshId);
|
|
48138
49043
|
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
48139
49044
|
const ledgerEntries = readLedgerEntries2(meshId, { tail: 20 });
|
|
48140
49045
|
const ledgerSummary = getLedgerSummary2(meshId);
|
|
49046
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
|
|
49047
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
49048
|
+
const localMachineId = loadConfig2().machineId || "";
|
|
49049
|
+
const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
|
|
49050
|
+
const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
|
|
49051
|
+
mesh,
|
|
49052
|
+
meshSource: meshRecord.source,
|
|
49053
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49054
|
+
statusInstanceId: this.deps.statusInstanceId,
|
|
49055
|
+
localMachineId
|
|
49056
|
+
}) : {
|
|
49057
|
+
directEvidenceCount: 0,
|
|
49058
|
+
localConfirmedCount: 0,
|
|
49059
|
+
peerAttemptedCount: 0,
|
|
49060
|
+
peerConfirmedCount: 0,
|
|
49061
|
+
unavailableNodeIds: []
|
|
49062
|
+
};
|
|
49063
|
+
const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
|
|
49064
|
+
if (requireDirectPeerTruth && !directTruthSatisfied) {
|
|
49065
|
+
return {
|
|
49066
|
+
success: false,
|
|
49067
|
+
code: "mesh_direct_peer_truth_unavailable",
|
|
49068
|
+
error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
|
|
49069
|
+
sourceOfTruth: {
|
|
49070
|
+
membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
49071
|
+
coordinatorOwnsLiveTruth: false,
|
|
49072
|
+
currentStatus: "direct_peer_truth_unavailable",
|
|
49073
|
+
directPeerTruth: {
|
|
49074
|
+
required: true,
|
|
49075
|
+
satisfied: false,
|
|
49076
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
49077
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
49078
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
49079
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
49080
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
49081
|
+
}
|
|
49082
|
+
}
|
|
49083
|
+
};
|
|
49084
|
+
}
|
|
49085
|
+
const directTruthUnavailableNodeIds = new Set(directTruth.unavailableNodeIds);
|
|
49086
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
49087
|
+
mesh.coordinator?.preferredNodeId,
|
|
49088
|
+
mesh.nodes?.[0]?.id,
|
|
49089
|
+
mesh.nodes?.[0]?.nodeId
|
|
49090
|
+
);
|
|
49091
|
+
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes) ? selectedCoordinatorNodeId : void 0;
|
|
49092
|
+
const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
48141
49093
|
const nodeStatuses = [];
|
|
48142
|
-
for (const node of mesh.nodes || []) {
|
|
49094
|
+
for (const [nodeIndex, node] of (mesh.nodes || []).entries()) {
|
|
49095
|
+
const nodeId = String(node.id || node.nodeId || "");
|
|
49096
|
+
const daemonId = readStringValue(node.daemonId);
|
|
49097
|
+
const providerPriority = readProviderPriorityFromPolicy(node.policy);
|
|
49098
|
+
const isSelfNode = Boolean(
|
|
49099
|
+
nodeId && inlineCoordinatorNodeId && nodeId === inlineCoordinatorNodeId
|
|
49100
|
+
) || Boolean(
|
|
49101
|
+
daemonId && (daemonId === localMachineId || daemonId === this.deps.statusInstanceId)
|
|
49102
|
+
) || Boolean(meshRecord?.inline && nodeIndex === 0);
|
|
48143
49103
|
const status = {
|
|
48144
|
-
nodeId
|
|
49104
|
+
nodeId,
|
|
48145
49105
|
machineLabel: node.machineLabel || node.id || node.nodeId,
|
|
48146
49106
|
workspace: node.workspace,
|
|
48147
49107
|
repoRoot: node.repoRoot,
|
|
48148
49108
|
isLocalWorktree: node.isLocalWorktree,
|
|
48149
49109
|
worktreeBranch: node.worktreeBranch,
|
|
48150
|
-
daemonId
|
|
49110
|
+
daemonId,
|
|
48151
49111
|
machineId: node.machineId,
|
|
49112
|
+
machineStatus: node.machineStatus,
|
|
48152
49113
|
health: "unknown",
|
|
48153
49114
|
providers: node.providers || [],
|
|
48154
|
-
|
|
49115
|
+
providerPriority,
|
|
49116
|
+
activeSessions: [],
|
|
49117
|
+
activeSessionDetails: [],
|
|
49118
|
+
launchReady: false
|
|
48155
49119
|
};
|
|
48156
|
-
if (
|
|
48157
|
-
|
|
48158
|
-
|
|
48159
|
-
|
|
49120
|
+
if (isSelfNode) {
|
|
49121
|
+
status.connection = {
|
|
49122
|
+
perspective: "selected_coordinator",
|
|
49123
|
+
source: "mesh_peer_status",
|
|
49124
|
+
state: "self",
|
|
49125
|
+
transport: "local",
|
|
49126
|
+
reported: true,
|
|
49127
|
+
reason: "Selected coordinator daemon",
|
|
49128
|
+
lastStateChangeAt: refreshedAt
|
|
49129
|
+
};
|
|
49130
|
+
} else if (daemonId) {
|
|
49131
|
+
const connection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
49132
|
+
status.connection = connection ?? {
|
|
49133
|
+
perspective: "selected_coordinator",
|
|
49134
|
+
source: "not_reported",
|
|
49135
|
+
state: "unknown",
|
|
49136
|
+
transport: "unknown",
|
|
49137
|
+
reported: false,
|
|
49138
|
+
reason: "No live mesh peer telemetry reported by the selected coordinator yet."
|
|
49139
|
+
};
|
|
49140
|
+
} else {
|
|
49141
|
+
status.connection = {
|
|
49142
|
+
perspective: "selected_coordinator",
|
|
49143
|
+
source: "not_reported",
|
|
49144
|
+
state: "unknown",
|
|
49145
|
+
transport: "unknown",
|
|
49146
|
+
reported: false,
|
|
49147
|
+
reason: "Node has no daemon id, so mesh transport cannot be reported from the selected coordinator."
|
|
49148
|
+
};
|
|
49149
|
+
}
|
|
49150
|
+
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
49151
|
+
meshId,
|
|
49152
|
+
node,
|
|
49153
|
+
nodeId,
|
|
49154
|
+
liveSessionRecords: liveMeshSessions,
|
|
49155
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49156
|
+
});
|
|
49157
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
49158
|
+
meshId,
|
|
49159
|
+
nodeId,
|
|
49160
|
+
liveSessionRecords: matchedLiveSessionRecords,
|
|
49161
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId
|
|
49162
|
+
}) || (typeof node.workspace === "string" ? node.workspace : "");
|
|
49163
|
+
status.workspace = workspace || node.workspace;
|
|
49164
|
+
if (matchedLiveSessionRecords.length > 0) {
|
|
49165
|
+
const sessionIds = matchedLiveSessionRecords.map((record2) => typeof record2?.sessionId === "string" ? record2.sessionId : "").filter(Boolean);
|
|
49166
|
+
const providerTypes = matchedLiveSessionRecords.map((record2) => readStringValue(record2?.providerType)).filter(Boolean);
|
|
49167
|
+
status.activeSessions = sessionIds;
|
|
49168
|
+
status.activeSessionDetails = matchedLiveSessionRecords.map(summarizeMeshSessionRecord);
|
|
49169
|
+
if (providerTypes.length > 0) {
|
|
49170
|
+
status.providers = Array.from(/* @__PURE__ */ new Set([...Array.isArray(status.providers) ? status.providers : [], ...providerTypes]));
|
|
48160
49171
|
}
|
|
48161
|
-
|
|
48162
|
-
|
|
48163
|
-
|
|
48164
|
-
const
|
|
48165
|
-
|
|
48166
|
-
|
|
48167
|
-
|
|
48168
|
-
|
|
48169
|
-
|
|
48170
|
-
|
|
48171
|
-
|
|
48172
|
-
|
|
48173
|
-
|
|
48174
|
-
|
|
48175
|
-
|
|
48176
|
-
|
|
48177
|
-
|
|
48178
|
-
|
|
48179
|
-
|
|
48180
|
-
|
|
48181
|
-
|
|
48182
|
-
|
|
48183
|
-
|
|
48184
|
-
|
|
49172
|
+
}
|
|
49173
|
+
if (workspace) {
|
|
49174
|
+
if (!fs10.existsSync(workspace)) {
|
|
49175
|
+
const inlineTransitGit = buildInlineMeshTransitGitStatus(node);
|
|
49176
|
+
let remoteProbeApplied = false;
|
|
49177
|
+
if (inlineTransitGit) {
|
|
49178
|
+
status.git = inlineTransitGit;
|
|
49179
|
+
status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
|
|
49180
|
+
remoteProbeApplied = true;
|
|
49181
|
+
} else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
|
|
49182
|
+
try {
|
|
49183
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
49184
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49185
|
+
daemonId,
|
|
49186
|
+
workspace,
|
|
49187
|
+
timeoutMs: 8e3
|
|
49188
|
+
});
|
|
49189
|
+
if (remoteGit) {
|
|
49190
|
+
status.git = remoteGit;
|
|
49191
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
49192
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
49193
|
+
remoteProbeApplied = true;
|
|
49194
|
+
}
|
|
49195
|
+
} catch {
|
|
49196
|
+
const refreshedConnection = this.deps.getMeshPeerConnectionStatus?.(daemonId);
|
|
49197
|
+
const refreshedConnectionState = readStringValue(refreshedConnection?.state);
|
|
49198
|
+
if (refreshedConnection && refreshedConnectionState === "connected") {
|
|
49199
|
+
status.connection = refreshedConnection;
|
|
49200
|
+
try {
|
|
49201
|
+
const remoteGit = await probeRemoteMeshGitStatus({
|
|
49202
|
+
dispatchMeshCommand: this.deps.dispatchMeshCommand,
|
|
49203
|
+
daemonId,
|
|
49204
|
+
workspace,
|
|
49205
|
+
timeoutMs: 12e3
|
|
49206
|
+
});
|
|
49207
|
+
if (remoteGit) {
|
|
49208
|
+
status.git = remoteGit;
|
|
49209
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
49210
|
+
recordInlineMeshDirectGitTruth(node, remoteGit, "selected_coordinator_mesh_p2p_git");
|
|
49211
|
+
remoteProbeApplied = true;
|
|
49212
|
+
}
|
|
49213
|
+
} catch {
|
|
49214
|
+
}
|
|
49215
|
+
}
|
|
48185
49216
|
}
|
|
48186
49217
|
}
|
|
48187
|
-
|
|
48188
|
-
|
|
48189
|
-
|
|
48190
|
-
|
|
48191
|
-
|
|
48192
|
-
|
|
48193
|
-
|
|
48194
|
-
if (
|
|
48195
|
-
|
|
48196
|
-
|
|
49218
|
+
if (!remoteProbeApplied) {
|
|
49219
|
+
const connectionState = readStringValue(status.connection?.state);
|
|
49220
|
+
const pendingPeerGitProbe = !inlineTransitGit && !isSelfNode && !!daemonId && (readStringValue(status.machineStatus) === "online" || readStringValue(status.health) === "online" || connectionState === "connecting" || connectionState === "connected" || connectionState === "unknown");
|
|
49221
|
+
if (pendingPeerGitProbe) {
|
|
49222
|
+
status.gitProbePending = true;
|
|
49223
|
+
status.health = "unknown";
|
|
49224
|
+
}
|
|
49225
|
+
if (applyCachedInlineMeshNodeStatus(
|
|
49226
|
+
status,
|
|
49227
|
+
node,
|
|
49228
|
+
pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
|
|
49229
|
+
)) {
|
|
49230
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
49231
|
+
nodeStatuses.push(status);
|
|
49232
|
+
continue;
|
|
49233
|
+
}
|
|
49234
|
+
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
49235
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
49236
|
+
nodeStatuses.push(status);
|
|
49237
|
+
continue;
|
|
49238
|
+
}
|
|
48197
49239
|
}
|
|
48198
|
-
|
|
48199
|
-
|
|
48200
|
-
|
|
48201
|
-
|
|
48202
|
-
|
|
48203
|
-
|
|
48204
|
-
|
|
48205
|
-
|
|
48206
|
-
|
|
48207
|
-
|
|
48208
|
-
|
|
48209
|
-
|
|
48210
|
-
|
|
48211
|
-
|
|
48212
|
-
|
|
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";
|
|
49240
|
+
} else {
|
|
49241
|
+
try {
|
|
49242
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
49243
|
+
status.git = gitStatus;
|
|
49244
|
+
recordInlineMeshDirectGitTruth(node, gitStatus, "selected_coordinator_local_git");
|
|
49245
|
+
if (gitStatus.isGitRepo) {
|
|
49246
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
49247
|
+
} else {
|
|
49248
|
+
status.health = "degraded";
|
|
49249
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
49250
|
+
}
|
|
49251
|
+
} catch {
|
|
49252
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
49253
|
+
status.health = "degraded";
|
|
49254
|
+
}
|
|
48222
49255
|
}
|
|
48223
49256
|
}
|
|
48224
49257
|
} else {
|
|
48225
49258
|
applyCachedInlineMeshNodeStatus(status, node);
|
|
48226
49259
|
}
|
|
49260
|
+
finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
|
|
48227
49261
|
nodeStatuses.push(status);
|
|
48228
49262
|
}
|
|
48229
|
-
|
|
49263
|
+
const statusResult = {
|
|
48230
49264
|
success: true,
|
|
48231
49265
|
meshId: mesh.id,
|
|
48232
49266
|
meshName: mesh.name,
|
|
48233
49267
|
repoIdentity: mesh.repoIdentity,
|
|
48234
49268
|
defaultBranch: mesh.defaultBranch,
|
|
49269
|
+
refreshedAt,
|
|
49270
|
+
sourceOfTruth: {
|
|
49271
|
+
membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
|
|
49272
|
+
coordinatorOwnsLiveTruth: directTruthSatisfied,
|
|
49273
|
+
...requireDirectPeerTruth ? {
|
|
49274
|
+
currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
|
|
49275
|
+
directPeerTruth: {
|
|
49276
|
+
required: true,
|
|
49277
|
+
satisfied: directTruthSatisfied,
|
|
49278
|
+
directEvidenceCount: directTruth.directEvidenceCount,
|
|
49279
|
+
localConfirmedCount: directTruth.localConfirmedCount,
|
|
49280
|
+
peerAttemptedCount: directTruth.peerAttemptedCount,
|
|
49281
|
+
peerConfirmedCount: directTruth.peerConfirmedCount,
|
|
49282
|
+
unavailableNodeIds: directTruth.unavailableNodeIds
|
|
49283
|
+
}
|
|
49284
|
+
} : {},
|
|
49285
|
+
historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
|
|
49286
|
+
},
|
|
48235
49287
|
nodes: nodeStatuses,
|
|
48236
49288
|
queue: { tasks: queue, summary: queueSummary },
|
|
48237
49289
|
ledger: { entries: ledgerEntries, summary: ledgerSummary }
|
|
48238
49290
|
};
|
|
49291
|
+
return this.rememberAggregateMeshStatus(meshId, statusResult, refreshReason);
|
|
48239
49292
|
} catch (e) {
|
|
48240
49293
|
return { success: false, error: e.message };
|
|
48241
49294
|
}
|
|
@@ -56107,6 +57160,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
56107
57160
|
sessionHostControl: config2.sessionHostControl,
|
|
56108
57161
|
statusInstanceId: config2.statusInstanceId,
|
|
56109
57162
|
statusVersion: config2.statusVersion,
|
|
57163
|
+
getMeshPeerConnectionStatus: config2.getMeshPeerConnectionStatus,
|
|
56110
57164
|
getCdpLogFn: config2.getCdpLogFn || ((ideType) => LOG2.forComponent(`CDP:${ideType}`).asLogFn())
|
|
56111
57165
|
});
|
|
56112
57166
|
poller = new AgentStreamPoller({
|