@adhdev/daemon-standalone 0.9.77-rc.4 → 0.9.77-rc.41
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 +1157 -9887
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
- package/public/assets/{index-6WEc6L46.js → index-BWLH33S7.js} +27 -27
- package/public/assets/index-BdY6qPu0.css +1 -0
- package/public/assets/{terminal-BeBmUW3m.js → terminal-B-dmfv31.js} +11 -11
- package/public/index.html +2 -2
- package/vendor/mcp-server/index.js +979 -77
- package/vendor/mcp-server/index.js.map +1 -1
- package/public/assets/index-DftJ2WZr.css +0 -1
|
@@ -25120,6 +25120,7 @@ __export(dist_exports, {
|
|
|
25120
25120
|
buildThoughtChatMessage: () => buildThoughtChatMessage,
|
|
25121
25121
|
buildToolChatMessage: () => buildToolChatMessage,
|
|
25122
25122
|
buildUserChatMessage: () => buildUserChatMessage,
|
|
25123
|
+
cancelTask: () => cancelTask,
|
|
25123
25124
|
claimNextTask: () => claimNextTask,
|
|
25124
25125
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
25125
25126
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
|
|
@@ -25163,6 +25164,7 @@ __export(dist_exports, {
|
|
|
25163
25164
|
getLogLevel: () => getLogLevel,
|
|
25164
25165
|
getMesh: () => getMesh,
|
|
25165
25166
|
getMeshByRepo: () => getMeshByRepo,
|
|
25167
|
+
getMeshQueueStats: () => getMeshQueueStats,
|
|
25166
25168
|
getNpmExecOptions: () => getNpmExecOptions,
|
|
25167
25169
|
getQueue: () => getQueue,
|
|
25168
25170
|
getRecentActivity: () => getRecentActivity,
|
|
@@ -25231,6 +25233,7 @@ __export(dist_exports, {
|
|
|
25231
25233
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
25232
25234
|
removeNode: () => removeNode,
|
|
25233
25235
|
removeWorktree: () => removeWorktree,
|
|
25236
|
+
requeueTask: () => requeueTask,
|
|
25234
25237
|
resetConfig: () => resetConfig,
|
|
25235
25238
|
resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
|
|
25236
25239
|
resetState: () => resetState,
|
|
@@ -26029,6 +26032,7 @@ function enqueueTask(meshId, message, opts) {
|
|
|
26029
26032
|
message,
|
|
26030
26033
|
status: "pending",
|
|
26031
26034
|
targetNodeId: opts?.targetNodeId,
|
|
26035
|
+
targetSessionId: opts?.targetSessionId,
|
|
26032
26036
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26033
26037
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26034
26038
|
};
|
|
@@ -26046,9 +26050,14 @@ function getQueue(meshId, opts) {
|
|
|
26046
26050
|
}
|
|
26047
26051
|
function claimNextTask(meshId, nodeId, sessionId) {
|
|
26048
26052
|
const queue = readQueue(meshId);
|
|
26049
|
-
|
|
26053
|
+
const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
|
|
26054
|
+
if (hasActiveAssignment) return null;
|
|
26055
|
+
let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
|
|
26050
26056
|
if (targetIdx === -1) {
|
|
26051
|
-
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.
|
|
26057
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
|
|
26058
|
+
}
|
|
26059
|
+
if (targetIdx === -1) {
|
|
26060
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
|
|
26052
26061
|
}
|
|
26053
26062
|
if (targetIdx === -1) return null;
|
|
26054
26063
|
const entry = queue[targetIdx];
|
|
@@ -26068,6 +26077,40 @@ function updateTaskStatus(meshId, taskId, status) {
|
|
|
26068
26077
|
writeQueue(meshId, queue);
|
|
26069
26078
|
return queue[idx];
|
|
26070
26079
|
}
|
|
26080
|
+
function cancelTask(meshId, taskId, opts) {
|
|
26081
|
+
const queue = readQueue(meshId);
|
|
26082
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
26083
|
+
if (idx === -1) return null;
|
|
26084
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26085
|
+
queue[idx].status = "cancelled";
|
|
26086
|
+
queue[idx].updatedAt = now;
|
|
26087
|
+
queue[idx].cancelledAt = now;
|
|
26088
|
+
if (opts?.reason) queue[idx].cancelReason = opts.reason;
|
|
26089
|
+
writeQueue(meshId, queue);
|
|
26090
|
+
return queue[idx];
|
|
26091
|
+
}
|
|
26092
|
+
function requeueTask(meshId, taskId, opts) {
|
|
26093
|
+
const queue = readQueue(meshId);
|
|
26094
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
26095
|
+
if (idx === -1) return null;
|
|
26096
|
+
const entry = queue[idx];
|
|
26097
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
26098
|
+
entry.status = "pending";
|
|
26099
|
+
delete entry.assignedNodeId;
|
|
26100
|
+
delete entry.assignedSessionId;
|
|
26101
|
+
delete entry.cancelledAt;
|
|
26102
|
+
delete entry.cancelReason;
|
|
26103
|
+
if (opts?.clearTargetNode) delete entry.targetNodeId;
|
|
26104
|
+
if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
|
|
26105
|
+
if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
|
|
26106
|
+
if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
|
|
26107
|
+
entry.updatedAt = now;
|
|
26108
|
+
entry.requeuedAt = now;
|
|
26109
|
+
entry.requeueCount = (entry.requeueCount || 0) + 1;
|
|
26110
|
+
if (opts?.reason) entry.requeueReason = opts.reason;
|
|
26111
|
+
writeQueue(meshId, queue);
|
|
26112
|
+
return entry;
|
|
26113
|
+
}
|
|
26071
26114
|
function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
26072
26115
|
const queue = readQueue(meshId);
|
|
26073
26116
|
for (let i = queue.length - 1; i >= 0; i--) {
|
|
@@ -26086,7 +26129,14 @@ function getMeshQueueStats(meshId) {
|
|
|
26086
26129
|
pending: queue.filter((q) => q.status === "pending").length,
|
|
26087
26130
|
assigned: queue.filter((q) => q.status === "assigned").length,
|
|
26088
26131
|
completed: queue.filter((q) => q.status === "completed").length,
|
|
26089
|
-
failed: queue.filter((q) => q.status === "failed").length
|
|
26132
|
+
failed: queue.filter((q) => q.status === "failed").length,
|
|
26133
|
+
cancelled: queue.filter((q) => q.status === "cancelled").length,
|
|
26134
|
+
activeAssignments: queue.filter((q) => q.status === "assigned").map((q) => ({
|
|
26135
|
+
id: q.id,
|
|
26136
|
+
nodeId: q.assignedNodeId,
|
|
26137
|
+
sessionId: q.assignedSessionId,
|
|
26138
|
+
message: q.message
|
|
26139
|
+
}))
|
|
26090
26140
|
};
|
|
26091
26141
|
}
|
|
26092
26142
|
function setLogLevel(level) {
|
|
@@ -26245,6 +26295,9 @@ function drainPendingMeshCoordinatorEvents() {
|
|
|
26245
26295
|
function readNonEmptyString(value) {
|
|
26246
26296
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
26247
26297
|
}
|
|
26298
|
+
function resolveEventSessionId(event, fallback) {
|
|
26299
|
+
return readNonEmptyString(event.targetSessionId) || readNonEmptyString(event.sessionId) || readNonEmptyString(event.instanceId) || readNonEmptyString(fallback);
|
|
26300
|
+
}
|
|
26248
26301
|
function isMeshCoordinatorEvent(eventName) {
|
|
26249
26302
|
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
26250
26303
|
}
|
|
@@ -26256,38 +26309,74 @@ function formatCompletionMetadata(event) {
|
|
|
26256
26309
|
].filter(Boolean);
|
|
26257
26310
|
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
26258
26311
|
}
|
|
26312
|
+
function getMeshWithCache(components, meshId) {
|
|
26313
|
+
const localMesh = getMesh(meshId);
|
|
26314
|
+
if (localMesh) return localMesh;
|
|
26315
|
+
return components.router?.getCachedInlineMesh(meshId);
|
|
26316
|
+
}
|
|
26259
26317
|
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
26260
26318
|
const task = claimNextTask(meshId, nodeId, sessionId);
|
|
26261
|
-
if (!task)
|
|
26319
|
+
if (!task) {
|
|
26320
|
+
return false;
|
|
26321
|
+
}
|
|
26262
26322
|
LOG.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
|
|
26323
|
+
const mesh = getMeshWithCache(components, meshId);
|
|
26324
|
+
const node = mesh?.nodes.find((n) => n.id === nodeId);
|
|
26325
|
+
if (node?.daemonId && components.dispatchMeshCommand) {
|
|
26326
|
+
const isLocalNode = components.cliManager.adapters.has(sessionId);
|
|
26327
|
+
if (!isLocalNode) {
|
|
26328
|
+
components.dispatchMeshCommand(node.daemonId, "agent_command", {
|
|
26329
|
+
targetSessionId: sessionId,
|
|
26330
|
+
cliType: providerType,
|
|
26331
|
+
action: "send_chat",
|
|
26332
|
+
message: task.message
|
|
26333
|
+
}).catch((e) => {
|
|
26334
|
+
LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
|
|
26335
|
+
updateTaskStatus(meshId, task.id, "failed");
|
|
26336
|
+
});
|
|
26337
|
+
return true;
|
|
26338
|
+
}
|
|
26339
|
+
}
|
|
26263
26340
|
components.cliManager.handleCliCommand("agent_command", {
|
|
26264
26341
|
targetSessionId: sessionId,
|
|
26265
26342
|
cliType: providerType,
|
|
26266
26343
|
action: "send_chat",
|
|
26267
|
-
|
|
26344
|
+
message: task.message
|
|
26268
26345
|
}).catch((e) => {
|
|
26269
|
-
LOG.error("MeshQueue", `Failed to dispatch task to node ${nodeId}: ${e?.message}`);
|
|
26346
|
+
LOG.error("MeshQueue", `Failed to dispatch task locally to node ${nodeId}: ${e?.message}`);
|
|
26347
|
+
updateTaskStatus(meshId, task.id, "failed");
|
|
26270
26348
|
});
|
|
26271
26349
|
return true;
|
|
26272
26350
|
}
|
|
26273
26351
|
function triggerMeshQueue(components, meshId) {
|
|
26274
|
-
const mesh =
|
|
26352
|
+
const mesh = getMeshWithCache(components, meshId);
|
|
26275
26353
|
if (!mesh) return;
|
|
26276
26354
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
26277
26355
|
for (const inst of cliInstances) {
|
|
26278
26356
|
const state = inst.getState();
|
|
26279
26357
|
const settings = state.settings || {};
|
|
26280
26358
|
const instMeshId = readNonEmptyString(settings.meshNodeFor);
|
|
26281
|
-
if (instMeshId !== meshId
|
|
26359
|
+
if (instMeshId !== meshId) continue;
|
|
26282
26360
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
26283
26361
|
if (!nodeId) continue;
|
|
26284
|
-
|
|
26362
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
26363
|
+
if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
|
|
26364
|
+
if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
|
|
26285
26365
|
const sessionId = state.instanceId;
|
|
26286
26366
|
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
26287
26367
|
if (providerType) {
|
|
26288
26368
|
tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
|
|
26289
26369
|
}
|
|
26290
26370
|
}
|
|
26371
|
+
for (const [key, idle] of remoteIdleSessions.entries()) {
|
|
26372
|
+
const node = mesh.nodes.find((n) => n.id === idle.nodeId);
|
|
26373
|
+
if (node) {
|
|
26374
|
+
const assigned = tryAssignQueueTask(components, meshId, idle.nodeId, idle.sessionId, idle.providerType);
|
|
26375
|
+
if (assigned) {
|
|
26376
|
+
remoteIdleSessions.delete(key);
|
|
26377
|
+
}
|
|
26378
|
+
}
|
|
26379
|
+
}
|
|
26291
26380
|
}
|
|
26292
26381
|
function buildMeshSystemMessage(args) {
|
|
26293
26382
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
@@ -26334,20 +26423,67 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
|
|
|
26334
26423
|
return "";
|
|
26335
26424
|
}
|
|
26336
26425
|
function injectMeshSystemMessage(components, args) {
|
|
26426
|
+
let completedTaskForLedger = null;
|
|
26337
26427
|
if (args.event === "agent:generating_completed") {
|
|
26338
|
-
const sessionId =
|
|
26339
|
-
const nodeId = readNonEmptyString(args.
|
|
26428
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
26429
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
26340
26430
|
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
26341
26431
|
if (sessionId) {
|
|
26342
|
-
updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
26432
|
+
const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
26433
|
+
completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
|
|
26343
26434
|
if (nodeId && providerType) {
|
|
26344
26435
|
setTimeout(() => {
|
|
26345
26436
|
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
26346
26437
|
}, 500);
|
|
26347
26438
|
}
|
|
26348
26439
|
}
|
|
26440
|
+
} else if (args.event === "agent:ready") {
|
|
26441
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
26442
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
26443
|
+
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
26444
|
+
const completedTask = sessionId ? updateSessionTaskStatus(args.meshId, sessionId, "completed") : null;
|
|
26445
|
+
if (completedTask) {
|
|
26446
|
+
completedTaskForLedger = { id: completedTask.id };
|
|
26447
|
+
try {
|
|
26448
|
+
appendLedgerEntry(args.meshId, {
|
|
26449
|
+
kind: "task_completed",
|
|
26450
|
+
nodeId: nodeId || void 0,
|
|
26451
|
+
sessionId,
|
|
26452
|
+
providerType: providerType || void 0,
|
|
26453
|
+
payload: {
|
|
26454
|
+
event: args.event,
|
|
26455
|
+
nodeLabel: args.nodeLabel,
|
|
26456
|
+
taskId: completedTask.id,
|
|
26457
|
+
completedViaReady: true,
|
|
26458
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
|
|
26459
|
+
finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
|
|
26460
|
+
}
|
|
26461
|
+
});
|
|
26462
|
+
} catch (e) {
|
|
26463
|
+
LOG.warn("MeshLedger", `Failed to record task_completed from ready: ${e?.message || e}`);
|
|
26464
|
+
}
|
|
26465
|
+
}
|
|
26466
|
+
if (sessionId && nodeId && providerType) {
|
|
26467
|
+
remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
|
|
26468
|
+
setTimeout(() => {
|
|
26469
|
+
const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
26470
|
+
if (assigned) {
|
|
26471
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
26472
|
+
}
|
|
26473
|
+
}, 500);
|
|
26474
|
+
}
|
|
26475
|
+
} else if (args.event === "agent:generating_started") {
|
|
26476
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
26477
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
26478
|
+
if (sessionId && nodeId) {
|
|
26479
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
26480
|
+
}
|
|
26349
26481
|
} else if (args.event === "agent:stopped") {
|
|
26350
|
-
const sessionId =
|
|
26482
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
26483
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
26484
|
+
if (sessionId && nodeId) {
|
|
26485
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
26486
|
+
}
|
|
26351
26487
|
if (sessionId) {
|
|
26352
26488
|
updateSessionTaskStatus(args.meshId, sessionId, "failed");
|
|
26353
26489
|
}
|
|
@@ -26357,13 +26493,15 @@ function injectMeshSystemMessage(components, args) {
|
|
|
26357
26493
|
try {
|
|
26358
26494
|
appendLedgerEntry(args.meshId, {
|
|
26359
26495
|
kind: ledgerKind,
|
|
26360
|
-
nodeId: readNonEmptyString(args.
|
|
26361
|
-
sessionId:
|
|
26496
|
+
nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
26497
|
+
sessionId: resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0,
|
|
26362
26498
|
providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
|
|
26363
26499
|
payload: {
|
|
26364
26500
|
event: args.event,
|
|
26365
26501
|
nodeLabel: args.nodeLabel,
|
|
26366
|
-
|
|
26502
|
+
taskId: completedTaskForLedger?.id || void 0,
|
|
26503
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
|
|
26504
|
+
finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
|
|
26367
26505
|
}
|
|
26368
26506
|
});
|
|
26369
26507
|
} catch (e) {
|
|
@@ -26376,8 +26514,8 @@ function injectMeshSystemMessage(components, args) {
|
|
|
26376
26514
|
const mesh = getMesh(args.meshId);
|
|
26377
26515
|
const maxRetries = mesh?.policy?.maxTaskRetries ?? 1;
|
|
26378
26516
|
recoveryContext = getSessionRecoveryContext(args.meshId, {
|
|
26379
|
-
sessionId:
|
|
26380
|
-
nodeId: readNonEmptyString(args.
|
|
26517
|
+
sessionId: resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0,
|
|
26518
|
+
nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
26381
26519
|
maxRetries
|
|
26382
26520
|
});
|
|
26383
26521
|
recoveryContext.failedProviderType = readNonEmptyString(args.metadataEvent.providerType) || null;
|
|
@@ -26472,12 +26610,14 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
26472
26610
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
26473
26611
|
return injectMeshSystemMessage(components, {
|
|
26474
26612
|
meshId,
|
|
26613
|
+
nodeId,
|
|
26475
26614
|
nodeLabel,
|
|
26476
26615
|
event: eventName,
|
|
26477
26616
|
metadataEvent: {
|
|
26478
|
-
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
26617
|
+
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId) || readNonEmptyString(payload.instanceId),
|
|
26479
26618
|
providerType: readNonEmptyString(payload.providerType),
|
|
26480
|
-
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
26619
|
+
providerSessionId: readNonEmptyString(payload.providerSessionId),
|
|
26620
|
+
finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary)
|
|
26481
26621
|
}
|
|
26482
26622
|
});
|
|
26483
26623
|
}
|
|
@@ -26496,15 +26636,17 @@ function setupMeshEventForwarding(components) {
|
|
|
26496
26636
|
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
26497
26637
|
const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
|
|
26498
26638
|
if (!isMeshDelegate) return;
|
|
26499
|
-
const mesh = meshIdFromRuntime ?
|
|
26639
|
+
const mesh = meshIdFromRuntime ? getMeshWithCache(components, meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
26500
26640
|
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
26501
26641
|
if (!meshId) return;
|
|
26502
26642
|
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
26503
26643
|
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
26644
|
+
const resolvedNodeId = targetNode?.id || runtimeNodeId;
|
|
26504
26645
|
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
26505
26646
|
injectMeshSystemMessage(components, {
|
|
26506
26647
|
meshId,
|
|
26507
26648
|
sourceInstanceId: instanceId,
|
|
26649
|
+
nodeId: resolvedNodeId,
|
|
26508
26650
|
nodeLabel,
|
|
26509
26651
|
event: event.event,
|
|
26510
26652
|
metadataEvent: event
|
|
@@ -33701,11 +33843,13 @@ async function handleOpenPanel(h, args) {
|
|
|
33701
33843
|
async function handlePtyInput(h, args) {
|
|
33702
33844
|
const { cliType, data, targetSessionId } = args || {};
|
|
33703
33845
|
if (!data) return { success: false, error: "data required" };
|
|
33846
|
+
const cleanData = typeof data === "string" ? data.replace(/\x1b\[[?>][0-9;]*c/g, "") : data;
|
|
33847
|
+
if (!cleanData) return { success: true };
|
|
33704
33848
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
33705
33849
|
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
33706
33850
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
33707
33851
|
}
|
|
33708
|
-
await adapter.writeRaw(
|
|
33852
|
+
await adapter.writeRaw(cleanData);
|
|
33709
33853
|
return { success: true };
|
|
33710
33854
|
}
|
|
33711
33855
|
function handlePtyResize(_h, args) {
|
|
@@ -34532,9 +34676,6 @@ function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
|
34532
34676
|
const cliType = String(input.cliType || "").trim();
|
|
34533
34677
|
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
34534
34678
|
const env2 = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
|
|
34535
|
-
if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
|
|
34536
|
-
cliArgs.unshift("--ignore-user-config");
|
|
34537
|
-
}
|
|
34538
34679
|
if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
|
|
34539
34680
|
cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
34540
34681
|
}
|
|
@@ -35478,7 +35619,9 @@ function resolveHermesMeshCoordinatorSetup(options) {
|
|
|
35478
35619
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
35479
35620
|
meshId: options.meshId,
|
|
35480
35621
|
nodeExecutable: options.nodeExecutable,
|
|
35481
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
35622
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
35623
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
35624
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
35482
35625
|
});
|
|
35483
35626
|
if (!mcpServer) {
|
|
35484
35627
|
return {
|
|
@@ -35545,7 +35688,9 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
35545
35688
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
35546
35689
|
meshId,
|
|
35547
35690
|
nodeExecutable: options.nodeExecutable,
|
|
35548
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
35691
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
35692
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
35693
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
35549
35694
|
});
|
|
35550
35695
|
if (!mcpServer) {
|
|
35551
35696
|
return {
|
|
@@ -35567,6 +35712,22 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
35567
35712
|
if (!instructions || !template?.trim()) {
|
|
35568
35713
|
return { kind: "unsupported", reason: "Provider manual MCP setup is missing instructions or template" };
|
|
35569
35714
|
}
|
|
35715
|
+
const renderedTemplate = renderMeshCoordinatorTemplate(template, {
|
|
35716
|
+
meshId,
|
|
35717
|
+
workspace,
|
|
35718
|
+
serverName,
|
|
35719
|
+
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
35720
|
+
});
|
|
35721
|
+
const isCliCommand = !renderedTemplate.trim().includes("\n") && !renderedTemplate.trim().startsWith("{");
|
|
35722
|
+
if (isCliCommand) {
|
|
35723
|
+
return {
|
|
35724
|
+
kind: "cli_command",
|
|
35725
|
+
serverName,
|
|
35726
|
+
command: renderedTemplate.trim(),
|
|
35727
|
+
requiresRestart: mcpConfig.requiresRestart === true,
|
|
35728
|
+
instructions
|
|
35729
|
+
};
|
|
35730
|
+
}
|
|
35570
35731
|
return {
|
|
35571
35732
|
kind: "manual",
|
|
35572
35733
|
serverName,
|
|
@@ -35574,12 +35735,7 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
35574
35735
|
configPathCommand: mcpConfig.configPathCommand,
|
|
35575
35736
|
requiresRestart: mcpConfig.requiresRestart === true,
|
|
35576
35737
|
instructions,
|
|
35577
|
-
template:
|
|
35578
|
-
meshId,
|
|
35579
|
-
workspace,
|
|
35580
|
-
serverName,
|
|
35581
|
-
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
35582
|
-
})
|
|
35738
|
+
template: renderedTemplate
|
|
35583
35739
|
};
|
|
35584
35740
|
}
|
|
35585
35741
|
return {
|
|
@@ -35608,11 +35764,27 @@ function resolveAdhdevMcpServerLaunch(options) {
|
|
|
35608
35764
|
if (!entryPath) return null;
|
|
35609
35765
|
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
|
|
35610
35766
|
if (!nodeExecutable) return null;
|
|
35767
|
+
const transport = resolveMcpTransport(options.adhdevMcpTransport);
|
|
35768
|
+
const args = [entryPath, "--mode", transport, "--repo-mesh", options.meshId];
|
|
35769
|
+
const port = resolveMcpPort(options.adhdevMcpPort);
|
|
35770
|
+
if (port !== void 0) args.push("--port", String(port));
|
|
35611
35771
|
return {
|
|
35612
35772
|
command: nodeExecutable,
|
|
35613
|
-
args
|
|
35773
|
+
args
|
|
35614
35774
|
};
|
|
35615
35775
|
}
|
|
35776
|
+
function resolveMcpTransport(explicitTransport) {
|
|
35777
|
+
if (explicitTransport === "local" || explicitTransport === "ipc") return explicitTransport;
|
|
35778
|
+
const envTransport = process.env.ADHDEV_COORDINATOR_MCP_TRANSPORT?.trim();
|
|
35779
|
+
return envTransport === "local" ? "local" : "ipc";
|
|
35780
|
+
}
|
|
35781
|
+
function resolveMcpPort(explicitPort) {
|
|
35782
|
+
if (typeof explicitPort === "number" && Number.isInteger(explicitPort) && explicitPort > 0) return explicitPort;
|
|
35783
|
+
const raw = process.env.ADHDEV_COORDINATOR_MCP_PORT?.trim();
|
|
35784
|
+
if (!raw) return void 0;
|
|
35785
|
+
const parsed = Number(raw);
|
|
35786
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
35787
|
+
}
|
|
35616
35788
|
function resolveMcpNodeExecutable(explicitExecutable) {
|
|
35617
35789
|
const explicit = explicitExecutable?.trim();
|
|
35618
35790
|
if (explicit) return explicit;
|
|
@@ -36424,6 +36596,34 @@ function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
|
36424
36596
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
36425
36597
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
36426
36598
|
}
|
|
36599
|
+
function stripHermesCoordinatorTempModelProviderOverrides(config2) {
|
|
36600
|
+
const {
|
|
36601
|
+
model: _model,
|
|
36602
|
+
provider: _provider,
|
|
36603
|
+
default_model: _defaultModel,
|
|
36604
|
+
defaultProvider: _defaultProvider,
|
|
36605
|
+
default_provider: _defaultProviderSnake,
|
|
36606
|
+
modelProvider: _modelProvider,
|
|
36607
|
+
model_provider: _modelProviderSnake,
|
|
36608
|
+
...sanitized
|
|
36609
|
+
} = config2;
|
|
36610
|
+
const delegation = sanitized.delegation;
|
|
36611
|
+
if (delegation && typeof delegation === "object" && !Array.isArray(delegation)) {
|
|
36612
|
+
const {
|
|
36613
|
+
model: _delegationModel,
|
|
36614
|
+
provider: _delegationProvider,
|
|
36615
|
+
modelProvider: _delegationModelProvider,
|
|
36616
|
+
model_provider: _delegationModelProviderSnake,
|
|
36617
|
+
...delegationRest
|
|
36618
|
+
} = delegation;
|
|
36619
|
+
if (Object.keys(delegationRest).length > 0) {
|
|
36620
|
+
sanitized.delegation = delegationRest;
|
|
36621
|
+
} else {
|
|
36622
|
+
delete sanitized.delegation;
|
|
36623
|
+
}
|
|
36624
|
+
}
|
|
36625
|
+
return sanitized;
|
|
36626
|
+
}
|
|
36427
36627
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
36428
36628
|
if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
|
|
36429
36629
|
for (const fileName of [".env", "auth.json"]) {
|
|
@@ -40855,7 +41055,8 @@ async function initDaemonComponents(config2) {
|
|
|
40855
41055
|
cdpManagers,
|
|
40856
41056
|
sessionRegistry,
|
|
40857
41057
|
detectedIdes: detectedIdesRef,
|
|
40858
|
-
refreshProviderAvailability
|
|
41058
|
+
refreshProviderAvailability,
|
|
41059
|
+
dispatchMeshCommand: config2.dispatchMeshCommand
|
|
40859
41060
|
};
|
|
40860
41061
|
setupMeshEventForwarding(components);
|
|
40861
41062
|
return components;
|
|
@@ -40913,7 +41114,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
40913
41114
|
}
|
|
40914
41115
|
cdpManagers.clear();
|
|
40915
41116
|
}
|
|
40916
|
-
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, import_fs6, import_path3, import_crypto4, import_events2, import_fs7, import_path4, import_crypto5, fs2, path8, os22, os8, os9, path14, import_child_process2, os10, path15, os11, import_child_process3, import_fs8, import_promises5, path, import_util4, import_promises6, path22, path32, fs, os4, path5, import_crypto6, path6, path7, import_fs9, import_path5, import_child_process4, import_fs10, import_os3, path9, import_child_process5, os32, path10, import_fs11, os42, import_child_process6, http, crypto2, fs3, path11, os5, fs4, os6, path12, import_crypto7, fs5, path13, os7, os13, path18, crypto4, import_fs12, import_child_process7, os12, path16, crypto3, fs6, import_module, path17, import_stream2, import_child_process8, import_child_process9, net2, os15, path20, fs7, path19, os14, fs8, path21, os16, import_child_process10, import_crypto8, import_fs13, import_module2, os17, import_path6, os18, import_child_process11, import_child_process12, fs9, os19, path222, import_os4, import_path7, fs10, fs11, path23, os20, import_child_process13, import_os5, http2, fs15, path27, fs12, path24, fs13, path25, fs14, path26, os21, import_child_process14, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __require2, __esm2, __export2, __copyProps2, __toCommonJS2, DEFAULT_MESH_POLICY, init_repo_mesh_types, git_worktree_exports, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER, init_git_worktree, config_exports, DEFAULT_CONFIG, MACHINE_ID_PREFIX, init_config, mesh_config_exports, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES, init_mesh_config, coordinator_prompt_exports, TOOLS_SECTION, TOOL_EXPOSURE_PREFLIGHT_SECTION, WORKFLOW_SECTION, init_coordinator_prompt, mesh_ledger_exports, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, meshLedgerEvents, init_mesh_ledger, init_mesh_work_queue, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, init_logger, mesh_events_exports, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, init_mesh_events, NORMAL_TRACE_BUFFER_SIZE, DEV_TRACE_BUFFER_SIZE, DEFAULT_CONFIG2, currentConfig, init_debug_config, DEFAULT_BINDING_CANDIDATES, cachedBinding, cachedBindingError, GhosttyVtTerminalBackend, init_ghostty_vt_backend, TerminalCtor, XtermTerminalBackend, init_xterm_backend, DEFAULT_SCROLLBACK, loggedTerminalBackends, TerminalScreen, init_terminal_screen, init_spawn_env, cachedPty, NodePtyRuntimeTransport, NodePtyTransportFactory, init_pty_transport, TerminalTranscriptAccumulator, buildCliSpawnEnv, init_provider_cli_shared, init_provider_cli_parse, init_provider_cli_config, init_provider_cli_runtime, provider_cli_adapter_exports, ProviderCliAdapter, init_provider_cli_adapter, execFileAsync, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_BUFFER, GitCommandError, DEFAULT_MAX_FILES, DEFAULT_MAX_BYTES, summarizeGitStatus, InMemoryGitSnapshotStore, DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS, MIN_GIT_WORKSPACE_POLL_INTERVAL_MS, GitWorkspaceMonitor, GIT_COMMAND_NAMES, SNAPSHOT_REASONS, FAILURE_REASONS, defaultSnapshotStore, defaultGitCommandServices, BUSY_STATUSES, TERMINAL_STATUSES, TurnSnapshotTracker, MAX_WORKSPACES, MAX_ACTIVITY, MAX_SAVED_SESSIONS, DEFAULT_STATE, BUILTIN_IDE_DEFINITIONS, registeredIDEs, LIVE_LIFECYCLES, DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, LIVE_RUNTIME_LIFECYCLES, DaemonCdpManager, CdpDomHandlers, DEFAULT_MONITOR_CONFIG, StatusMonitor, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET, HISTORY_DIR, RETAIN_DAYS, SAVED_HISTORY_INDEX_VERSION, SAVED_HISTORY_INDEX_FILE, SAVED_HISTORY_INDEX_LOCK_SUFFIX, SAVED_HISTORY_INDEX_LOCK_WAIT_MS, SAVED_HISTORY_INDEX_LOCK_STALE_MS, SAVED_HISTORY_INDEX_LOCK_POLL_MS, SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES, savedHistorySessionCache, savedHistoryFileSummaryCache, savedHistoryBackgroundRefresh, savedHistoryRollupInFlight, ChatHistoryWriter, IDE_PROVIDER_SESSION_CAPABILITIES_BASE, EXTENSION_PROVIDER_SESSION_CAPABILITIES_BASE, ExtensionProviderInstance, VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES, DEFAULT_APPROVAL_POSITIVE_HINTS, IdeProviderInstance, DEFAULT_CDP_SCAN_INTERVAL_MS, DEFAULT_CDP_DISCOVERY_INTERVAL_MS, DEFAULT_STATUS_INITIAL_REPORT_DELAY_MS, DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS, DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS, MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_READY_TIMEOUT_MS, STANDALONE_CDP_SCAN_INTERVAL_MS, DaemonCdpScanner, DaemonCdpInitializer, WORKING_STATUSES, FULL_STATUS_ACTIVE_CHAT_OPTIONS, LIVE_STATUS_ACTIVE_CHAT_OPTIONS, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT, VALID_INPUT_MEDIA_TYPES, VALID_INPUT_STRATEGIES, TEXT_ONLY_MESSAGE_INPUT_SUPPORT, IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, CLI_CHAT_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES, globalStore, RECENT_SEND_WINDOW_MS, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS, HERMES_CLI_STARTING_SEND_SETTLE_MS, recentSendByTarget, DEFAULT_DEBUG_SANITIZE_OPTIONS, SECRET_KEY_PATTERN, KEY_TO_VK, COMMAND_DEBUG_LEVELS, DaemonCommandHandler, IMAGE_MIME_EXTENSIONS, MATERIALIZED_IMAGE_MAX_AGE_MS, MATERIALIZED_IMAGE_CLEANUP_INTERVAL_MS, lastMaterializedImageCleanupAt, CachedDatabaseSync, CliProviderInstance, AcpProviderInstance, chalkModule, chalkApi, COORDINATOR_DELEGATED_ENV_UNSETS, DaemonCliManager, VALID_CAPABILITY_MEDIA_TYPES, VALID_INPUT_STRATEGIES2, KNOWN_PROVIDER_FIELDS, VALUE_CONTROL_TYPES, ProviderLoader, _providerLoader, LOG_DIR2, MAX_FILE_SIZE, MAX_DAYS, SENSITIVE_KEYS, currentDate2, currentFile, writeCount2, SKIP_COMMANDS, DEFAULT_SERVER_NAME, DEFAULT_ADHDEV_MCP_COMMAND, HERMES_CLI_TYPE, HERMES_MCP_CONFIG_PATH, READ_DEBUG_ENABLED, recentReadDebugSignatureBySession, UPGRADE_HELPER_ENV, CHANNEL_NPM_TAG, CHANNEL_SERVER_URL, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter, DaemonStatusReporter, DEFAULT_DAEMON_PORT, DAEMON_WS_PATH, ProviderStreamAdapter, DaemonAgentStreamManager, AgentStreamPoller, ProviderInstanceManager, ARCHIVE_PATH, MAX_ENTRIES_PER_PROVIDER, VersionArchive, DEV_SERVER_PORT, DevServer, SessionHostRuntimeTransport, SessionHostPtyTransportFactory, DEFAULT_SESSION_HOST_APP_NAME, DEFAULT_STANDALONE_SESSION_HOST_APP_NAME, STARTUP_TIMEOUT_MS, STARTUP_POLL_MS, SessionHostCompatibilityError, EXTENSION_CATALOG, SessionRegistry;
|
|
41117
|
+
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, import_fs6, import_path3, import_crypto4, import_events2, import_fs7, import_path4, import_crypto5, fs2, path8, os22, os8, os9, path14, import_child_process2, os10, path15, os11, import_child_process3, import_fs8, import_promises5, path, import_util4, import_promises6, path22, path32, fs, os4, path5, import_crypto6, path6, path7, import_fs9, import_path5, import_child_process4, import_fs10, import_os3, path9, import_child_process5, os32, path10, import_fs11, os42, import_child_process6, http, crypto2, fs3, path11, os5, fs4, os6, path12, import_crypto7, fs5, path13, os7, os13, path18, crypto4, import_fs12, import_child_process7, os12, path16, crypto3, fs6, import_module, path17, import_stream2, import_child_process8, import_child_process9, net2, os15, path20, fs7, path19, os14, fs8, path21, os16, import_child_process10, import_crypto8, import_fs13, import_module2, os17, import_path6, os18, import_child_process11, import_child_process12, fs9, os19, path222, import_os4, import_path7, fs10, fs11, path23, os20, import_child_process13, import_os5, http2, fs15, path27, fs12, path24, fs13, path25, fs14, path26, os21, import_child_process14, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __require2, __esm2, __export2, __copyProps2, __toCommonJS2, DEFAULT_MESH_POLICY, init_repo_mesh_types, git_worktree_exports, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER, init_git_worktree, config_exports, DEFAULT_CONFIG, MACHINE_ID_PREFIX, init_config, mesh_config_exports, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES, init_mesh_config, coordinator_prompt_exports, TOOLS_SECTION, TOOL_EXPOSURE_PREFLIGHT_SECTION, WORKFLOW_SECTION, init_coordinator_prompt, mesh_ledger_exports, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, meshLedgerEvents, init_mesh_ledger, mesh_work_queue_exports, init_mesh_work_queue, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, init_logger, mesh_events_exports, remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, init_mesh_events, NORMAL_TRACE_BUFFER_SIZE, DEV_TRACE_BUFFER_SIZE, DEFAULT_CONFIG2, currentConfig, init_debug_config, DEFAULT_BINDING_CANDIDATES, cachedBinding, cachedBindingError, GhosttyVtTerminalBackend, init_ghostty_vt_backend, TerminalCtor, XtermTerminalBackend, init_xterm_backend, DEFAULT_SCROLLBACK, loggedTerminalBackends, TerminalScreen, init_terminal_screen, init_spawn_env, cachedPty, NodePtyRuntimeTransport, NodePtyTransportFactory, init_pty_transport, TerminalTranscriptAccumulator, buildCliSpawnEnv, init_provider_cli_shared, init_provider_cli_parse, init_provider_cli_config, init_provider_cli_runtime, provider_cli_adapter_exports, ProviderCliAdapter, init_provider_cli_adapter, execFileAsync, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_BUFFER, GitCommandError, DEFAULT_MAX_FILES, DEFAULT_MAX_BYTES, summarizeGitStatus, InMemoryGitSnapshotStore, DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS, MIN_GIT_WORKSPACE_POLL_INTERVAL_MS, GitWorkspaceMonitor, GIT_COMMAND_NAMES, SNAPSHOT_REASONS, FAILURE_REASONS, defaultSnapshotStore, defaultGitCommandServices, BUSY_STATUSES, TERMINAL_STATUSES, TurnSnapshotTracker, MAX_WORKSPACES, MAX_ACTIVITY, MAX_SAVED_SESSIONS, DEFAULT_STATE, BUILTIN_IDE_DEFINITIONS, registeredIDEs, LIVE_LIFECYCLES, DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, LIVE_RUNTIME_LIFECYCLES, DaemonCdpManager, CdpDomHandlers, DEFAULT_MONITOR_CONFIG, StatusMonitor, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET, HISTORY_DIR, RETAIN_DAYS, SAVED_HISTORY_INDEX_VERSION, SAVED_HISTORY_INDEX_FILE, SAVED_HISTORY_INDEX_LOCK_SUFFIX, SAVED_HISTORY_INDEX_LOCK_WAIT_MS, SAVED_HISTORY_INDEX_LOCK_STALE_MS, SAVED_HISTORY_INDEX_LOCK_POLL_MS, SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES, savedHistorySessionCache, savedHistoryFileSummaryCache, savedHistoryBackgroundRefresh, savedHistoryRollupInFlight, ChatHistoryWriter, IDE_PROVIDER_SESSION_CAPABILITIES_BASE, EXTENSION_PROVIDER_SESSION_CAPABILITIES_BASE, ExtensionProviderInstance, VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES, DEFAULT_APPROVAL_POSITIVE_HINTS, IdeProviderInstance, DEFAULT_CDP_SCAN_INTERVAL_MS, DEFAULT_CDP_DISCOVERY_INTERVAL_MS, DEFAULT_STATUS_INITIAL_REPORT_DELAY_MS, DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS, DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS, MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_READY_TIMEOUT_MS, STANDALONE_CDP_SCAN_INTERVAL_MS, DaemonCdpScanner, DaemonCdpInitializer, WORKING_STATUSES, FULL_STATUS_ACTIVE_CHAT_OPTIONS, LIVE_STATUS_ACTIVE_CHAT_OPTIONS, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT, VALID_INPUT_MEDIA_TYPES, VALID_INPUT_STRATEGIES, TEXT_ONLY_MESSAGE_INPUT_SUPPORT, IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, CLI_CHAT_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES, globalStore, RECENT_SEND_WINDOW_MS, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS, HERMES_CLI_STARTING_SEND_SETTLE_MS, recentSendByTarget, DEFAULT_DEBUG_SANITIZE_OPTIONS, SECRET_KEY_PATTERN, KEY_TO_VK, COMMAND_DEBUG_LEVELS, DaemonCommandHandler, IMAGE_MIME_EXTENSIONS, MATERIALIZED_IMAGE_MAX_AGE_MS, MATERIALIZED_IMAGE_CLEANUP_INTERVAL_MS, lastMaterializedImageCleanupAt, CachedDatabaseSync, CliProviderInstance, AcpProviderInstance, chalkModule, chalkApi, COORDINATOR_DELEGATED_ENV_UNSETS, DaemonCliManager, VALID_CAPABILITY_MEDIA_TYPES, VALID_INPUT_STRATEGIES2, KNOWN_PROVIDER_FIELDS, VALUE_CONTROL_TYPES, ProviderLoader, _providerLoader, LOG_DIR2, MAX_FILE_SIZE, MAX_DAYS, SENSITIVE_KEYS, currentDate2, currentFile, writeCount2, SKIP_COMMANDS, DEFAULT_SERVER_NAME, DEFAULT_ADHDEV_MCP_COMMAND, HERMES_CLI_TYPE, HERMES_MCP_CONFIG_PATH, READ_DEBUG_ENABLED, recentReadDebugSignatureBySession, UPGRADE_HELPER_ENV, CHANNEL_NPM_TAG, CHANNEL_SERVER_URL, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter, DaemonStatusReporter, DEFAULT_DAEMON_PORT, DAEMON_WS_PATH, ProviderStreamAdapter, DaemonAgentStreamManager, AgentStreamPoller, ProviderInstanceManager, ARCHIVE_PATH, MAX_ENTRIES_PER_PROVIDER, VersionArchive, DEV_SERVER_PORT, DevServer, SessionHostRuntimeTransport, SessionHostPtyTransportFactory, DEFAULT_SESSION_HOST_APP_NAME, DEFAULT_STANDALONE_SESSION_HOST_APP_NAME, STARTUP_TIMEOUT_MS, STARTUP_POLL_MS, SessionHostCompatibilityError, EXTENSION_CATALOG, SessionRegistry;
|
|
40917
41118
|
var init_dist2 = __esm({
|
|
40918
41119
|
"../daemon-core/dist/index.mjs"() {
|
|
40919
41120
|
"use strict";
|
|
@@ -41246,6 +41447,17 @@ Follow these recovery rules:
|
|
|
41246
41447
|
meshLedgerEvents = new import_events2.EventEmitter();
|
|
41247
41448
|
}
|
|
41248
41449
|
});
|
|
41450
|
+
mesh_work_queue_exports = {};
|
|
41451
|
+
__export2(mesh_work_queue_exports, {
|
|
41452
|
+
cancelTask: () => cancelTask,
|
|
41453
|
+
claimNextTask: () => claimNextTask,
|
|
41454
|
+
enqueueTask: () => enqueueTask,
|
|
41455
|
+
getMeshQueueStats: () => getMeshQueueStats,
|
|
41456
|
+
getQueue: () => getQueue,
|
|
41457
|
+
requeueTask: () => requeueTask,
|
|
41458
|
+
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
41459
|
+
updateTaskStatus: () => updateTaskStatus
|
|
41460
|
+
});
|
|
41249
41461
|
init_mesh_work_queue = __esm2({
|
|
41250
41462
|
"src/mesh/mesh-work-queue.ts"() {
|
|
41251
41463
|
"use strict";
|
|
@@ -41325,12 +41537,15 @@ Follow these recovery rules:
|
|
|
41325
41537
|
init_logger();
|
|
41326
41538
|
init_mesh_ledger();
|
|
41327
41539
|
init_mesh_work_queue();
|
|
41540
|
+
remoteIdleSessions = /* @__PURE__ */ new Map();
|
|
41328
41541
|
MAX_PENDING_EVENTS = 50;
|
|
41329
41542
|
pendingMeshCoordinatorEvents = [];
|
|
41330
41543
|
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
41544
|
+
"agent:generating_started",
|
|
41331
41545
|
"agent:generating_completed",
|
|
41332
41546
|
"agent:waiting_approval",
|
|
41333
41547
|
"agent:stopped",
|
|
41548
|
+
"agent:ready",
|
|
41334
41549
|
"monitor:long_generating"
|
|
41335
41550
|
]);
|
|
41336
41551
|
EVENT_TO_LEDGER_KIND = {
|
|
@@ -41865,6 +42080,8 @@ Follow these recovery rules:
|
|
|
41865
42080
|
statusHistory = [];
|
|
41866
42081
|
// ─── CLI Scripts (script-based parsing) ───
|
|
41867
42082
|
cliScripts;
|
|
42083
|
+
/** Per-session opaque state object created by cliScripts.createState(), reset on stop. */
|
|
42084
|
+
scriptState = null;
|
|
41868
42085
|
runtimeSettings = {};
|
|
41869
42086
|
/** Full accumulated rendered PTY transcript for parser/readback use */
|
|
41870
42087
|
accumulatedBuffer = "";
|
|
@@ -41941,9 +42158,13 @@ ${lastSnapshot}`;
|
|
|
41941
42158
|
this.lastScreenChangeAt = 0;
|
|
41942
42159
|
this.lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
|
|
41943
42160
|
}
|
|
42161
|
+
getAccumulatedRawBufferCacheKey() {
|
|
42162
|
+
return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
42163
|
+
}
|
|
41944
42164
|
getFreshParsedStatusCache() {
|
|
41945
42165
|
const cached2 = this.parsedStatusCache;
|
|
41946
|
-
|
|
42166
|
+
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
42167
|
+
if (cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === this.lastScreenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
|
|
41947
42168
|
return cached2.result;
|
|
41948
42169
|
}
|
|
41949
42170
|
return null;
|
|
@@ -42046,6 +42267,7 @@ ${lastSnapshot}`;
|
|
|
42046
42267
|
this.cliScripts = scripts;
|
|
42047
42268
|
this.parsedStatusCache = null;
|
|
42048
42269
|
this.parseErrorMessage = null;
|
|
42270
|
+
this.scriptState = typeof scripts.createState === "function" ? scripts.createState() : null;
|
|
42049
42271
|
const scriptNames = listCliScriptNames(scripts);
|
|
42050
42272
|
LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
42051
42273
|
}
|
|
@@ -42163,6 +42385,7 @@ ${lastSnapshot}`;
|
|
|
42163
42385
|
this.ready = false;
|
|
42164
42386
|
this.startupParseGate = false;
|
|
42165
42387
|
this.spawnAt = 0;
|
|
42388
|
+
this.scriptState = null;
|
|
42166
42389
|
this.onStatusChange?.();
|
|
42167
42390
|
});
|
|
42168
42391
|
this.spawnAt = Date.now();
|
|
@@ -42916,6 +43139,11 @@ ${lastSnapshot}`;
|
|
|
42916
43139
|
};
|
|
42917
43140
|
}
|
|
42918
43141
|
// ─── Script Execution ──────────────────────────
|
|
43142
|
+
invokeCliScript(script, input) {
|
|
43143
|
+
const hasStateFactory = typeof this.cliScripts?.createState === "function";
|
|
43144
|
+
const expectsStateArgument = hasStateFactory || this.scriptState !== null || script.length >= 2;
|
|
43145
|
+
return expectsStateArgument ? script(this.scriptState, input) : script(input);
|
|
43146
|
+
}
|
|
42919
43147
|
runParseSession() {
|
|
42920
43148
|
if (typeof this.cliScripts?.parseSession !== "function") {
|
|
42921
43149
|
this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
|
|
@@ -42936,7 +43164,10 @@ ${lastSnapshot}`;
|
|
|
42936
43164
|
scope: this.currentTurnScope,
|
|
42937
43165
|
runtimeSettings: this.runtimeSettings
|
|
42938
43166
|
});
|
|
42939
|
-
const session = this.
|
|
43167
|
+
const session = this.invokeCliScript(
|
|
43168
|
+
this.cliScripts.parseSession,
|
|
43169
|
+
{ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) }
|
|
43170
|
+
);
|
|
42940
43171
|
this.parseErrorMessage = null;
|
|
42941
43172
|
return session && typeof session === "object" ? session : null;
|
|
42942
43173
|
} catch (e) {
|
|
@@ -42950,7 +43181,7 @@ ${lastSnapshot}`;
|
|
|
42950
43181
|
if (!this.cliScripts?.detectStatus) return null;
|
|
42951
43182
|
try {
|
|
42952
43183
|
const screenText = this.terminalScreen.getText();
|
|
42953
|
-
const status = this.cliScripts.detectStatus
|
|
43184
|
+
const status = this.invokeCliScript(this.cliScripts.detectStatus, {
|
|
42954
43185
|
tail: text.slice(-500),
|
|
42955
43186
|
screenText,
|
|
42956
43187
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -42969,7 +43200,7 @@ ${lastSnapshot}`;
|
|
|
42969
43200
|
try {
|
|
42970
43201
|
const screenText = this.terminalScreen.getText();
|
|
42971
43202
|
const buffer = screenText || this.accumulatedBuffer;
|
|
42972
|
-
return this.cliScripts.parseApproval
|
|
43203
|
+
return this.invokeCliScript(this.cliScripts.parseApproval, {
|
|
42973
43204
|
buffer,
|
|
42974
43205
|
screenText,
|
|
42975
43206
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -43025,7 +43256,8 @@ ${lastSnapshot}`;
|
|
|
43025
43256
|
const screenText = this.readTerminalScreenText();
|
|
43026
43257
|
const parseScreenText = this.getParseScreenText(screenText);
|
|
43027
43258
|
const cached2 = this.parsedStatusCache;
|
|
43028
|
-
|
|
43259
|
+
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
43260
|
+
if (cached2 && cached2.responseBuffer === this.responseBuffer && cached2.currentTurnScope === this.currentTurnScope && cached2.recentOutputBuffer === this.recentOutputBuffer && cached2.accumulatedBuffer === this.accumulatedBuffer && cached2.accumulatedRawBufferKey === accumulatedRawBufferKey && cached2.screenText === parseScreenText && cached2.currentStatus === this.currentStatus && cached2.activeModal === this.activeModal && cached2.cliName === this.cliName) {
|
|
43029
43261
|
return cached2.result;
|
|
43030
43262
|
}
|
|
43031
43263
|
const parsed = this.runParseSession();
|
|
@@ -43053,6 +43285,7 @@ ${lastSnapshot}`;
|
|
|
43053
43285
|
currentTurnScope: this.currentTurnScope,
|
|
43054
43286
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
43055
43287
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
43288
|
+
accumulatedRawBufferKey,
|
|
43056
43289
|
screenText: parseScreenText,
|
|
43057
43290
|
currentStatus: this.currentStatus,
|
|
43058
43291
|
activeModal: this.activeModal,
|
|
@@ -43077,7 +43310,7 @@ ${lastSnapshot}`;
|
|
|
43077
43310
|
scope: this.currentTurnScope,
|
|
43078
43311
|
runtimeSettings: this.runtimeSettings
|
|
43079
43312
|
});
|
|
43080
|
-
return await Promise.resolve(fn({
|
|
43313
|
+
return await Promise.resolve(fn(this.scriptState, {
|
|
43081
43314
|
...input,
|
|
43082
43315
|
args: args && typeof args === "object" ? { ...args } : {}
|
|
43083
43316
|
}));
|
|
@@ -48296,6 +48529,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
48296
48529
|
this.completedDebounceTimer = null;
|
|
48297
48530
|
}, 3e3);
|
|
48298
48531
|
}
|
|
48532
|
+
} else if (newStatus === "idle" && this.lastStatus === "starting") {
|
|
48533
|
+
this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });
|
|
48299
48534
|
} else if (newStatus === "stopped") {
|
|
48300
48535
|
if (this.generatingDebounceTimer) {
|
|
48301
48536
|
clearTimeout(this.generatingDebounceTimer);
|
|
@@ -53014,6 +53249,51 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53014
53249
|
return { success: false, error: e.message };
|
|
53015
53250
|
}
|
|
53016
53251
|
}
|
|
53252
|
+
case "get_mesh_queue": {
|
|
53253
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53254
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
53255
|
+
try {
|
|
53256
|
+
const { getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
53257
|
+
const status = Array.isArray(args?.status) ? args.status.map((s) => typeof s === "string" ? s.trim() : "").filter(Boolean) : void 0;
|
|
53258
|
+
const queue = getQueue2(meshId, { status });
|
|
53259
|
+
return { success: true, queue };
|
|
53260
|
+
} catch (e) {
|
|
53261
|
+
return { success: false, error: e.message };
|
|
53262
|
+
}
|
|
53263
|
+
}
|
|
53264
|
+
case "cancel_mesh_queue_task": {
|
|
53265
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53266
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
53267
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
53268
|
+
try {
|
|
53269
|
+
const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
53270
|
+
const reason = typeof args?.reason === "string" ? args.reason : void 0;
|
|
53271
|
+
const task = cancelTask2(meshId, taskId, { reason });
|
|
53272
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
53273
|
+
return { success: true, task };
|
|
53274
|
+
} catch (e) {
|
|
53275
|
+
return { success: false, error: e.message };
|
|
53276
|
+
}
|
|
53277
|
+
}
|
|
53278
|
+
case "requeue_mesh_queue_task": {
|
|
53279
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53280
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
53281
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
53282
|
+
try {
|
|
53283
|
+
const { requeueTask: requeueTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
53284
|
+
const task = requeueTask2(meshId, taskId, {
|
|
53285
|
+
reason: typeof args?.reason === "string" ? args.reason : void 0,
|
|
53286
|
+
targetNodeId: typeof args?.targetNodeId === "string" ? args.targetNodeId.trim() : void 0,
|
|
53287
|
+
targetSessionId: typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : void 0,
|
|
53288
|
+
clearTargetNode: args?.clearTargetNode === true,
|
|
53289
|
+
clearTargetSession: args?.clearTargetSession !== false
|
|
53290
|
+
});
|
|
53291
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
53292
|
+
return { success: true, task };
|
|
53293
|
+
} catch (e) {
|
|
53294
|
+
return { success: false, error: e.message };
|
|
53295
|
+
}
|
|
53296
|
+
}
|
|
53017
53297
|
case "add_mesh_node": {
|
|
53018
53298
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53019
53299
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -53171,7 +53451,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53171
53451
|
appendLedgerEntry2(meshId, {
|
|
53172
53452
|
kind: "node_removed",
|
|
53173
53453
|
nodeId,
|
|
53174
|
-
payload: {
|
|
53454
|
+
payload: {
|
|
53455
|
+
worktree: !!node?.isLocalWorktree,
|
|
53456
|
+
sessionCleanupMode,
|
|
53457
|
+
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
53458
|
+
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
53459
|
+
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0
|
|
53460
|
+
}
|
|
53175
53461
|
});
|
|
53176
53462
|
} catch {
|
|
53177
53463
|
}
|
|
@@ -53342,6 +53628,93 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53342
53628
|
meshCoordinatorSetup: coordinatorSetup
|
|
53343
53629
|
};
|
|
53344
53630
|
}
|
|
53631
|
+
if (coordinatorSetup.kind === "cli_command") {
|
|
53632
|
+
let cliCmdSystemPrompt = "";
|
|
53633
|
+
try {
|
|
53634
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
53635
|
+
} catch (error48) {
|
|
53636
|
+
const message = error48?.message || String(error48);
|
|
53637
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
53638
|
+
return {
|
|
53639
|
+
success: false,
|
|
53640
|
+
code: "mesh_coordinator_prompt_failed",
|
|
53641
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
53642
|
+
meshId,
|
|
53643
|
+
cliType,
|
|
53644
|
+
workspace
|
|
53645
|
+
};
|
|
53646
|
+
}
|
|
53647
|
+
try {
|
|
53648
|
+
const { execFileSync: execCmdSync } = await import("child_process");
|
|
53649
|
+
const cmdParts = coordinatorSetup.command.trim().split(/\s+/);
|
|
53650
|
+
const [regCmd, ...regArgs] = cmdParts;
|
|
53651
|
+
LOG.info("MeshCoordinator", `Running MCP registration: ${coordinatorSetup.command}`);
|
|
53652
|
+
execCmdSync(regCmd, regArgs, { stdio: "pipe", timeout: 15e3 });
|
|
53653
|
+
} catch (error48) {
|
|
53654
|
+
LOG.warn("MeshCoordinator", `MCP registration command failed (may be pre-registered): ${error48?.message || error48}`);
|
|
53655
|
+
}
|
|
53656
|
+
const cliCmdArgs = [];
|
|
53657
|
+
const cliCmdEnv = {};
|
|
53658
|
+
if (cliCmdSystemPrompt) {
|
|
53659
|
+
if (cliType === "codex-cli") {
|
|
53660
|
+
cliCmdArgs.push("-c", `developer_instructions=${JSON.stringify(cliCmdSystemPrompt)}`);
|
|
53661
|
+
} else if (cliType === "gemini-cli") {
|
|
53662
|
+
try {
|
|
53663
|
+
const { writeFileSync: wfs, existsSync: efs, readFileSync: rfs } = await import("fs");
|
|
53664
|
+
const geminiMdPath = `${workspace}/GEMINI.md`;
|
|
53665
|
+
const marker = "<!-- adhdev-mesh-coordinator-prompt -->";
|
|
53666
|
+
const markerEnd = "<!-- /adhdev-mesh-coordinator-prompt -->";
|
|
53667
|
+
const block = `${marker}
|
|
53668
|
+
${cliCmdSystemPrompt}
|
|
53669
|
+
${markerEnd}`;
|
|
53670
|
+
if (efs(geminiMdPath)) {
|
|
53671
|
+
const existing = rfs(geminiMdPath, "utf-8");
|
|
53672
|
+
const replaced = existing.replace(
|
|
53673
|
+
new RegExp(`${marker}[\\s\\S]*?${markerEnd}`, "g"),
|
|
53674
|
+
block
|
|
53675
|
+
);
|
|
53676
|
+
wfs(geminiMdPath, replaced.includes(marker) ? replaced : `${existing}
|
|
53677
|
+
|
|
53678
|
+
${block}`);
|
|
53679
|
+
} else {
|
|
53680
|
+
wfs(geminiMdPath, block);
|
|
53681
|
+
}
|
|
53682
|
+
LOG.info("MeshCoordinator", `Wrote coordinator prompt to ${workspace}/GEMINI.md`);
|
|
53683
|
+
} catch (e) {
|
|
53684
|
+
LOG.warn("MeshCoordinator", `Could not write GEMINI.md: ${e?.message || e}`);
|
|
53685
|
+
}
|
|
53686
|
+
}
|
|
53687
|
+
}
|
|
53688
|
+
const cliCmdLaunch = await this.deps.cliManager.handleCliCommand("launch_cli", {
|
|
53689
|
+
cliType,
|
|
53690
|
+
dir: workspace,
|
|
53691
|
+
cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
|
|
53692
|
+
env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
|
|
53693
|
+
settings: { meshCoordinatorFor: meshId }
|
|
53694
|
+
});
|
|
53695
|
+
if (!cliCmdLaunch?.success) {
|
|
53696
|
+
return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
|
|
53697
|
+
}
|
|
53698
|
+
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
|
|
53699
|
+
try {
|
|
53700
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
53701
|
+
appendLedgerEntry2(meshId, {
|
|
53702
|
+
kind: "coordinator_started",
|
|
53703
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
53704
|
+
providerType: cliType,
|
|
53705
|
+
payload: { workspace }
|
|
53706
|
+
});
|
|
53707
|
+
} catch {
|
|
53708
|
+
}
|
|
53709
|
+
return {
|
|
53710
|
+
success: true,
|
|
53711
|
+
meshId,
|
|
53712
|
+
cliType,
|
|
53713
|
+
workspace,
|
|
53714
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
53715
|
+
mcpRegistered: true
|
|
53716
|
+
};
|
|
53717
|
+
}
|
|
53345
53718
|
const configFormat = coordinatorSetup.configFormat;
|
|
53346
53719
|
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
53347
53720
|
return {
|
|
@@ -53396,9 +53769,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53396
53769
|
args: coordinatorSetup.mcpServer.args
|
|
53397
53770
|
};
|
|
53398
53771
|
if (args?.inlineMesh) {
|
|
53772
|
+
const modeArgIndex = coordinatorSetup.mcpServer.args.findIndex((value) => value === "--mode");
|
|
53773
|
+
const mcpTransport = modeArgIndex >= 0 ? coordinatorSetup.mcpServer.args[modeArgIndex + 1] : "ipc";
|
|
53399
53774
|
mcpServerEntry.env = {
|
|
53400
53775
|
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
53401
|
-
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
53776
|
+
ADHDEV_MCP_TRANSPORT: mcpTransport === "local" ? "local" : "ipc"
|
|
53402
53777
|
};
|
|
53403
53778
|
}
|
|
53404
53779
|
try {
|
|
@@ -53417,7 +53792,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
53417
53792
|
if (hadExistingMcpConfig) {
|
|
53418
53793
|
try {
|
|
53419
53794
|
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
|
|
53420
|
-
|
|
53795
|
+
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
53796
|
+
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
53421
53797
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
53422
53798
|
} catch (error48) {
|
|
53423
53799
|
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error48?.message || error48}`);
|
|
@@ -57240,6 +57616,11 @@ function annotateRapidReadChatAdvisory(payload, options) {
|
|
|
57240
57616
|
// src/tools/mesh-tools.ts
|
|
57241
57617
|
init_dist2();
|
|
57242
57618
|
var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
|
|
57619
|
+
function readString(value) {
|
|
57620
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
57621
|
+
}
|
|
57622
|
+
var DUPLICATE_DISPATCH_WINDOW_MS = 6e4;
|
|
57623
|
+
var STALE_ASSIGNED_QUEUE_MS = 30 * 6e4;
|
|
57243
57624
|
async function refreshMeshFromDaemon(ctx) {
|
|
57244
57625
|
if (!(ctx.transport instanceof IpcTransport)) return;
|
|
57245
57626
|
try {
|
|
@@ -57260,6 +57641,138 @@ async function findNodeWithRefresh(ctx, nodeId) {
|
|
|
57260
57641
|
if (!refreshed) throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
|
|
57261
57642
|
return refreshed;
|
|
57262
57643
|
}
|
|
57644
|
+
async function findOptionalNodeWithRefresh(ctx, nodeId) {
|
|
57645
|
+
const hit = ctx.mesh.nodes.find((n) => n.id === nodeId);
|
|
57646
|
+
if (hit) return hit;
|
|
57647
|
+
await refreshMeshFromDaemon(ctx);
|
|
57648
|
+
return ctx.mesh.nodes.find((n) => n.id === nodeId) ?? null;
|
|
57649
|
+
}
|
|
57650
|
+
function hasRecentDuplicateDispatch(ctx, args) {
|
|
57651
|
+
const now = Date.now();
|
|
57652
|
+
const normalizedMessage = args.message.trim();
|
|
57653
|
+
for (const task of getQueue(ctx.mesh.id)) {
|
|
57654
|
+
const timestamp2 = new Date(task.updatedAt || task.createdAt).getTime();
|
|
57655
|
+
if (!Number.isFinite(timestamp2) || now - timestamp2 > DUPLICATE_DISPATCH_WINDOW_MS) continue;
|
|
57656
|
+
if (task.targetNodeId && task.targetNodeId !== args.node_id) continue;
|
|
57657
|
+
if (task.assignedNodeId && task.assignedNodeId !== args.node_id) continue;
|
|
57658
|
+
if (args.session_id && task.targetSessionId !== args.session_id && task.assignedSessionId !== args.session_id) continue;
|
|
57659
|
+
if (task.message?.trim() === normalizedMessage) {
|
|
57660
|
+
return { duplicate: true, entry: task, source: "queue" };
|
|
57661
|
+
}
|
|
57662
|
+
}
|
|
57663
|
+
const entries = readLedgerEntries(ctx.mesh.id, { tail: 200 });
|
|
57664
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
57665
|
+
const entry = entries[i];
|
|
57666
|
+
const timestamp2 = new Date(entry.timestamp).getTime();
|
|
57667
|
+
if (Number.isFinite(timestamp2) && now - timestamp2 > DUPLICATE_DISPATCH_WINDOW_MS) break;
|
|
57668
|
+
if (entry.kind !== "task_dispatched") continue;
|
|
57669
|
+
if (entry.nodeId !== args.node_id) continue;
|
|
57670
|
+
if (args.session_id && entry.sessionId !== args.session_id) continue;
|
|
57671
|
+
if (typeof entry.payload?.message !== "string") continue;
|
|
57672
|
+
if (entry.payload.message.trim() === normalizedMessage) {
|
|
57673
|
+
return { duplicate: true, entry, source: "ledger" };
|
|
57674
|
+
}
|
|
57675
|
+
}
|
|
57676
|
+
return { duplicate: false };
|
|
57677
|
+
}
|
|
57678
|
+
function buildMissingNodeReadChatRecovery(ctx, args) {
|
|
57679
|
+
const entries = readLedgerEntries(ctx.mesh.id, { tail: 300 });
|
|
57680
|
+
const relatedEntries = entries.filter((entry) => entry.nodeId === args.node_id || entry.sessionId === args.session_id);
|
|
57681
|
+
const completedEntries = relatedEntries.filter((entry) => entry.kind === "task_completed");
|
|
57682
|
+
const lastDispatch = [...relatedEntries].reverse().find((entry) => entry.kind === "task_dispatched");
|
|
57683
|
+
const lastTerminal = [...relatedEntries].reverse().find((entry) => entry.kind === "task_completed" || entry.kind === "task_failed" || entry.kind === "task_stalled");
|
|
57684
|
+
const lastRemoved = [...relatedEntries].reverse().find((entry) => entry.kind === "node_removed");
|
|
57685
|
+
const lastLaunch = [...relatedEntries].reverse().find((entry) => entry.kind === "session_launched");
|
|
57686
|
+
const providerSessionId = args.provider_session_id || readString(lastTerminal?.payload?.providerSessionId) || readString(lastLaunch?.payload?.providerSessionId) || readString(lastDispatch?.payload?.providerSessionId);
|
|
57687
|
+
const finalSummary = readString(lastTerminal?.payload?.finalSummary) || readString(lastTerminal?.payload?.compactSummary) || readString(lastTerminal?.payload?.summary);
|
|
57688
|
+
const ledger = {
|
|
57689
|
+
taskCompletedFound: completedEntries.length > 0,
|
|
57690
|
+
nodeRemovedFound: !!lastRemoved,
|
|
57691
|
+
providerType: lastTerminal?.providerType || lastLaunch?.providerType || lastDispatch?.providerType,
|
|
57692
|
+
providerSessionId,
|
|
57693
|
+
nodeRemovedAt: lastRemoved?.timestamp,
|
|
57694
|
+
sessionCleanupMode: readString(lastRemoved?.payload?.sessionCleanupMode),
|
|
57695
|
+
readDebugLocator: readString(lastTerminal?.payload?.readDebugLocator) || readString(lastTerminal?.payload?.debugBundlePath)
|
|
57696
|
+
};
|
|
57697
|
+
if (finalSummary) {
|
|
57698
|
+
return {
|
|
57699
|
+
success: true,
|
|
57700
|
+
compact: args.compact === true,
|
|
57701
|
+
recoveredFromLedger: true,
|
|
57702
|
+
nodeId: args.node_id,
|
|
57703
|
+
sessionId: args.session_id,
|
|
57704
|
+
summary: finalSummary,
|
|
57705
|
+
ledger,
|
|
57706
|
+
messages: [{ role: "assistant", content: finalSummary, isHistorical: true }]
|
|
57707
|
+
};
|
|
57708
|
+
}
|
|
57709
|
+
return {
|
|
57710
|
+
success: false,
|
|
57711
|
+
recoverable: true,
|
|
57712
|
+
code: "mesh_removed_node_transcript_unavailable",
|
|
57713
|
+
error: `Node '${args.node_id}' is not a current member of mesh '${ctx.mesh.name}'.`,
|
|
57714
|
+
nodeId: args.node_id,
|
|
57715
|
+
sessionId: args.session_id,
|
|
57716
|
+
providerSessionId,
|
|
57717
|
+
reason: "node_not_in_current_mesh_snapshot",
|
|
57718
|
+
ledger,
|
|
57719
|
+
completedSessionSeenInLedger: ledger.taskCompletedFound,
|
|
57720
|
+
lastDispatch: lastDispatch ? {
|
|
57721
|
+
timestamp: lastDispatch.timestamp,
|
|
57722
|
+
sessionId: lastDispatch.sessionId,
|
|
57723
|
+
providerType: lastDispatch.providerType,
|
|
57724
|
+
taskId: typeof lastDispatch.payload?.taskId === "string" ? lastDispatch.payload.taskId : void 0,
|
|
57725
|
+
messagePreview: typeof lastDispatch.payload?.message === "string" ? lastDispatch.payload.message.slice(0, 500) : void 0
|
|
57726
|
+
} : null,
|
|
57727
|
+
lastTerminalEvent: lastTerminal ? {
|
|
57728
|
+
kind: lastTerminal.kind,
|
|
57729
|
+
timestamp: lastTerminal.timestamp,
|
|
57730
|
+
sessionId: lastTerminal.sessionId,
|
|
57731
|
+
providerType: lastTerminal.providerType,
|
|
57732
|
+
taskId: typeof lastTerminal.payload?.taskId === "string" ? lastTerminal.payload.taskId : void 0,
|
|
57733
|
+
payload: lastTerminal.payload
|
|
57734
|
+
} : null,
|
|
57735
|
+
nextSteps: [
|
|
57736
|
+
providerSessionId ? `Retry mesh_read_chat with provider_session_id='${providerSessionId}' on a current live node for the same daemon if one exists.` : "If the node UI shows a provider transcript id, retry mesh_read_chat/mesh_read_debug with provider_session_id.",
|
|
57737
|
+
"Use mesh_read_debug with the provider_session_id or daemon-side debug bundle locator if available.",
|
|
57738
|
+
"Check mesh_task_history for task_completed and node_removed entries before redispatching; do not resend solely because transcript recovery failed.",
|
|
57739
|
+
"If this node was removed with stop_and_delete, the runtime transcript may be gone; rely on the ledger summary/locator or ask the operator for the saved UI output."
|
|
57740
|
+
],
|
|
57741
|
+
recoveryHints: [
|
|
57742
|
+
"The worktree/node may have been removed or the mesh snapshot may be stale after task completion.",
|
|
57743
|
+
"If you have a provider_session_id, retry mesh_read_chat with that value while targeting a live node for the same daemon if available.",
|
|
57744
|
+
"Use mesh_read_debug with provider_session_id, or inspect the daemon/session-host history locator if the transcript has already been archived.",
|
|
57745
|
+
"Avoid redispatching the same task solely because read_chat could not recover the transcript; check task_history and git status first."
|
|
57746
|
+
]
|
|
57747
|
+
};
|
|
57748
|
+
}
|
|
57749
|
+
function annotateQueueStaleness(queue) {
|
|
57750
|
+
const now = Date.now();
|
|
57751
|
+
return queue.map((task) => {
|
|
57752
|
+
const taskStatus = typeof task?.status === "string" ? task.status : void 0;
|
|
57753
|
+
const annotated = {
|
|
57754
|
+
...task,
|
|
57755
|
+
taskStatus,
|
|
57756
|
+
dispatchedAt: task?.createdAt,
|
|
57757
|
+
...taskStatus === "assigned" ? { activeTaskId: task.id } : {},
|
|
57758
|
+
...taskStatus === "completed" || taskStatus === "failed" ? {
|
|
57759
|
+
isHistorical: true,
|
|
57760
|
+
completedAt: task.updatedAt
|
|
57761
|
+
} : {}
|
|
57762
|
+
};
|
|
57763
|
+
if (taskStatus !== "assigned") return annotated;
|
|
57764
|
+
const updatedAt = new Date(task.updatedAt).getTime();
|
|
57765
|
+
const ageMs = Number.isFinite(updatedAt) ? now - updatedAt : null;
|
|
57766
|
+
if (ageMs === null || ageMs < STALE_ASSIGNED_QUEUE_MS) return annotated;
|
|
57767
|
+
return {
|
|
57768
|
+
...annotated,
|
|
57769
|
+
stale: true,
|
|
57770
|
+
staleAssigned: true,
|
|
57771
|
+
staleReason: "assigned task has not reached a terminal state within 30 minutes",
|
|
57772
|
+
assignedAgeMs: ageMs
|
|
57773
|
+
};
|
|
57774
|
+
});
|
|
57775
|
+
}
|
|
57263
57776
|
function unwrapCommandPayload(value) {
|
|
57264
57777
|
let current = value;
|
|
57265
57778
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -57272,6 +57785,26 @@ function unwrapCommandPayload(value) {
|
|
|
57272
57785
|
}
|
|
57273
57786
|
return current;
|
|
57274
57787
|
}
|
|
57788
|
+
function isTerminalSessionRecord(session) {
|
|
57789
|
+
const status = typeof session?.status === "string" ? session.status.toLowerCase() : "";
|
|
57790
|
+
const lifecycle = typeof session?.lifecycle === "string" ? session.lifecycle.toLowerCase() : "";
|
|
57791
|
+
const state = typeof session?.state === "string" ? session.state.toLowerCase() : "";
|
|
57792
|
+
return [status, lifecycle, state].some((value) => ["stopped", "failed", "terminated", "exited", "closed"].includes(value));
|
|
57793
|
+
}
|
|
57794
|
+
function isIdleSessionRecord(session) {
|
|
57795
|
+
if (isTerminalSessionRecord(session)) return false;
|
|
57796
|
+
const status = typeof session?.status === "string" ? session.status.toLowerCase() : "";
|
|
57797
|
+
const chatStatus = typeof session?.activeChat?.status === "string" ? session.activeChat.status.toLowerCase() : "";
|
|
57798
|
+
return status === "idle" || chatStatus === "waiting_input";
|
|
57799
|
+
}
|
|
57800
|
+
function chooseDispatchableSession(sessions, providerType, meshId, nodeId) {
|
|
57801
|
+
const live = sessions.filter((session) => !isTerminalSessionRecord(session));
|
|
57802
|
+
const matchingProvider = (session) => !providerType || session?.providerType === providerType || session?.cliType === providerType;
|
|
57803
|
+
const meshSessions = live.filter(
|
|
57804
|
+
(session) => session?.settings?.meshNodeFor === meshId || session?.settings?.meshNodeId === nodeId
|
|
57805
|
+
);
|
|
57806
|
+
return meshSessions.find((session) => isIdleSessionRecord(session) && matchingProvider(session)) || meshSessions.find(matchingProvider) || live.find((session) => isIdleSessionRecord(session) && matchingProvider(session)) || live.find(matchingProvider) || live.find(isIdleSessionRecord) || live[0];
|
|
57807
|
+
}
|
|
57275
57808
|
function findNestedPayload(value, predicate) {
|
|
57276
57809
|
const seen = /* @__PURE__ */ new Set();
|
|
57277
57810
|
const stack = [{ payload: value, depth: 0 }];
|
|
@@ -57300,12 +57833,136 @@ function extractGitDiff(value) {
|
|
|
57300
57833
|
function extractLaunchPayload(value) {
|
|
57301
57834
|
return findNestedPayload(value, (payload) => Boolean(payload?.sessionId || payload?.id || payload?.runtimeSessionId));
|
|
57302
57835
|
}
|
|
57836
|
+
function classifyMeshLaunchFailure(error48) {
|
|
57837
|
+
const message = error48 instanceof Error ? error48.message : String(error48 || "launch failed");
|
|
57838
|
+
const lower = message.toLowerCase();
|
|
57839
|
+
if (lower.includes("p2p") || lower.includes("datachannel") || lower.includes("node-datachannel")) {
|
|
57840
|
+
return { code: "p2p_unavailable", reason: "daemon_mesh_p2p_transport_unavailable", transport: "daemon_mesh_p2p" };
|
|
57841
|
+
}
|
|
57842
|
+
if (lower.includes("cannot connect to daemon ipc") || lower.includes("daemon ipc command")) {
|
|
57843
|
+
return { code: "local_ipc_unavailable", reason: "local_daemon_ipc_unavailable", transport: "local_ipc" };
|
|
57844
|
+
}
|
|
57845
|
+
if (lower.includes("timed out") || lower.includes("timeout")) {
|
|
57846
|
+
return { code: "mesh_transport_timeout", reason: "mesh_transport_timeout", transport: "mesh_transport" };
|
|
57847
|
+
}
|
|
57848
|
+
return { code: "mesh_launch_failed", reason: "provider_launch_failed", transport: "mesh_transport" };
|
|
57849
|
+
}
|
|
57850
|
+
function buildWorktreeCleanupHint(node) {
|
|
57851
|
+
if (!node.isLocalWorktree) return void 0;
|
|
57852
|
+
return {
|
|
57853
|
+
tool: "mesh_remove_node",
|
|
57854
|
+
args: { node_id: node.id, session_cleanup_mode: "preserve" },
|
|
57855
|
+
hint: `If the worktree is no longer needed, remove the orphan worktree node with mesh_remove_node(node_id: "${node.id}").`
|
|
57856
|
+
};
|
|
57857
|
+
}
|
|
57858
|
+
function buildRecoverableLaunchFailure(ctx, node, providerType, error48) {
|
|
57859
|
+
const message = error48 instanceof Error ? error48.message : String(error48 || "launch failed");
|
|
57860
|
+
const classified = classifyMeshLaunchFailure(error48);
|
|
57861
|
+
const cleanup = buildWorktreeCleanupHint(node);
|
|
57862
|
+
return {
|
|
57863
|
+
success: false,
|
|
57864
|
+
recoverable: true,
|
|
57865
|
+
code: classified.code,
|
|
57866
|
+
reason: classified.reason,
|
|
57867
|
+
transport: classified.transport,
|
|
57868
|
+
error: message,
|
|
57869
|
+
meshId: ctx.mesh.id,
|
|
57870
|
+
nodeId: node.id,
|
|
57871
|
+
daemonId: node.daemonId,
|
|
57872
|
+
workspace: node.workspace,
|
|
57873
|
+
isLocalWorktree: node.isLocalWorktree === true,
|
|
57874
|
+
worktreeBranch: node.worktreeBranch,
|
|
57875
|
+
clonedFromNodeId: node.clonedFromNodeId,
|
|
57876
|
+
...providerType ? { resolvedProviderType: providerType } : {},
|
|
57877
|
+
retryHint: `Retry mesh_launch_session(node_id: "${node.id}"${providerType ? `, type: "${providerType}"` : ""}) after daemon mesh transport/P2P is healthy.`,
|
|
57878
|
+
...cleanup ? { cleanup } : {},
|
|
57879
|
+
nextStepHints: [
|
|
57880
|
+
`Retry mesh_launch_session(node_id: "${node.id}"${providerType ? `, type: "${providerType}"` : ""}) after checking daemon/P2P health.`,
|
|
57881
|
+
...cleanup ? [`Cleanup orphan worktree node with mesh_remove_node(node_id: "${node.id}") if retry is not desired.`] : [],
|
|
57882
|
+
"Run mesh_status to see the degraded reason and recovery hints before redispatching work."
|
|
57883
|
+
]
|
|
57884
|
+
};
|
|
57885
|
+
}
|
|
57886
|
+
function recordRecoverableLaunchFailure(ctx, node, providerType, error48) {
|
|
57887
|
+
const failure2 = buildRecoverableLaunchFailure(ctx, node, providerType, error48);
|
|
57888
|
+
try {
|
|
57889
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
57890
|
+
kind: "recovery_attempted",
|
|
57891
|
+
nodeId: node.id,
|
|
57892
|
+
providerType,
|
|
57893
|
+
payload: {
|
|
57894
|
+
event: "session_launch_failed",
|
|
57895
|
+
...failure2
|
|
57896
|
+
}
|
|
57897
|
+
});
|
|
57898
|
+
} catch {
|
|
57899
|
+
}
|
|
57900
|
+
return failure2;
|
|
57901
|
+
}
|
|
57902
|
+
function getLatestActiveLaunchFailure(meshId, nodeId) {
|
|
57903
|
+
const entries = readLedgerEntries(meshId, { tail: 200 });
|
|
57904
|
+
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
57905
|
+
const entry = entries[i];
|
|
57906
|
+
if (entry.nodeId !== nodeId) continue;
|
|
57907
|
+
if (entry.kind === "session_launched" || entry.kind === "node_removed") return null;
|
|
57908
|
+
if (entry.kind === "recovery_attempted" && entry.payload?.event === "session_launch_failed") {
|
|
57909
|
+
return { timestamp: entry.timestamp, ...entry.payload };
|
|
57910
|
+
}
|
|
57911
|
+
}
|
|
57912
|
+
return null;
|
|
57913
|
+
}
|
|
57914
|
+
async function ipcDispatchToRemoteAgent(ctx, node, args) {
|
|
57915
|
+
const transport = ctx.transport;
|
|
57916
|
+
const daemonId = node.daemonId;
|
|
57917
|
+
let sessionId = args.session_id?.trim() || "";
|
|
57918
|
+
const providerPriorityList = Array.isArray(node.policy?.providerPriority) ? node.policy.providerPriority : [];
|
|
57919
|
+
let resolvedProviderType = args.providerType?.trim() || providerPriorityList[0] || "";
|
|
57920
|
+
if (!sessionId) {
|
|
57921
|
+
try {
|
|
57922
|
+
const relayResult = await transport.meshCommand(daemonId, "get_status_metadata", {});
|
|
57923
|
+
const innerResult = relayResult?.result ?? relayResult;
|
|
57924
|
+
const statusObj = innerResult?.status ?? innerResult;
|
|
57925
|
+
const sessions = Array.isArray(statusObj?.sessions) ? statusObj.sessions : [];
|
|
57926
|
+
const targetSession = chooseDispatchableSession(sessions, resolvedProviderType, ctx.mesh.id, node.id);
|
|
57927
|
+
if (targetSession?.id || targetSession?.sessionId) {
|
|
57928
|
+
sessionId = targetSession.id || targetSession.sessionId;
|
|
57929
|
+
if (!resolvedProviderType) {
|
|
57930
|
+
resolvedProviderType = targetSession.providerType || targetSession.cliType || "";
|
|
57931
|
+
}
|
|
57932
|
+
}
|
|
57933
|
+
} catch (e) {
|
|
57934
|
+
}
|
|
57935
|
+
}
|
|
57936
|
+
if (!resolvedProviderType) {
|
|
57937
|
+
return { success: false, error: `Cannot dispatch to remote node '${node.id}': providerType unknown. Set providerPriority on the node policy or call mesh_launch_session first.` };
|
|
57938
|
+
}
|
|
57939
|
+
try {
|
|
57940
|
+
const dispatchResult = await transport.meshCommand(daemonId, "agent_command", {
|
|
57941
|
+
...sessionId ? { targetSessionId: sessionId } : {},
|
|
57942
|
+
agentType: resolvedProviderType,
|
|
57943
|
+
cliType: resolvedProviderType,
|
|
57944
|
+
action: "send_chat",
|
|
57945
|
+
message: args.message
|
|
57946
|
+
});
|
|
57947
|
+
const dispatchPayload = unwrapCommandPayload(dispatchResult);
|
|
57948
|
+
if (dispatchPayload?.success === false || dispatchResult?.success === false) {
|
|
57949
|
+
return { success: false, error: `P2P dispatch failed: ${dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task"}` };
|
|
57950
|
+
}
|
|
57951
|
+
return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType };
|
|
57952
|
+
} catch (e) {
|
|
57953
|
+
return { success: false, error: `P2P dispatch failed: ${e?.message || String(e)}` };
|
|
57954
|
+
}
|
|
57955
|
+
}
|
|
57303
57956
|
function resolveCoordinatorNode(ctx) {
|
|
57304
57957
|
const preferredNodeId = typeof ctx.mesh.coordinator?.preferredNodeId === "string" ? ctx.mesh.coordinator.preferredNodeId.trim() : "";
|
|
57305
57958
|
if (preferredNodeId) {
|
|
57306
57959
|
const preferred = ctx.mesh.nodes.find((n) => n.id === preferredNodeId && typeof n.daemonId === "string" && n.daemonId.trim());
|
|
57307
57960
|
if (preferred) return preferred;
|
|
57308
57961
|
}
|
|
57962
|
+
if (ctx.localMachineId) {
|
|
57963
|
+
const byMachine = ctx.mesh.nodes.find((n) => n.machineId === ctx.localMachineId);
|
|
57964
|
+
if (byMachine) return byMachine;
|
|
57965
|
+
}
|
|
57309
57966
|
if (ctx.localDaemonId) {
|
|
57310
57967
|
return ctx.mesh.nodes.find((n) => n.daemonId === ctx.localDaemonId);
|
|
57311
57968
|
}
|
|
@@ -57395,7 +58052,8 @@ function getNodeLaunchReadiness(node) {
|
|
|
57395
58052
|
};
|
|
57396
58053
|
}
|
|
57397
58054
|
async function commandForNode(ctx, node, command, args = {}) {
|
|
57398
|
-
|
|
58055
|
+
const isLocalNode = ctx.localMachineId && node.machineId === ctx.localMachineId || ctx.localDaemonId && node.daemonId === ctx.localDaemonId;
|
|
58056
|
+
if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
|
|
57399
58057
|
return ctx.transport.meshCommand(node.daemonId, command, args);
|
|
57400
58058
|
}
|
|
57401
58059
|
if (isLocalTransport(ctx.transport)) {
|
|
@@ -57405,10 +58063,12 @@ async function commandForNode(ctx, node, command, args = {}) {
|
|
|
57405
58063
|
}
|
|
57406
58064
|
var MESH_STATUS_TOOL = {
|
|
57407
58065
|
name: "mesh_status",
|
|
57408
|
-
description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions. Use this to decide which node to send work to.",
|
|
58066
|
+
description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions, recovery hints, and recommended next steps. Use this to decide which node to send work to or how to recover from failures.",
|
|
57409
58067
|
inputSchema: {
|
|
57410
58068
|
type: "object",
|
|
57411
|
-
properties: {
|
|
58069
|
+
properties: {
|
|
58070
|
+
_gemini_compat: { type: "string", description: "Dummy property for Gemini compatibility. Ignore this." }
|
|
58071
|
+
}
|
|
57412
58072
|
}
|
|
57413
58073
|
};
|
|
57414
58074
|
var MESH_LIST_NODES_TOOL = {
|
|
@@ -57416,7 +58076,9 @@ var MESH_LIST_NODES_TOOL = {
|
|
|
57416
58076
|
description: "List all nodes in the mesh with their capabilities, platform, and workspace paths.",
|
|
57417
58077
|
inputSchema: {
|
|
57418
58078
|
type: "object",
|
|
57419
|
-
properties: {
|
|
58079
|
+
properties: {
|
|
58080
|
+
_gemini_compat: { type: "string", description: "Dummy property for Gemini compatibility. Ignore this." }
|
|
58081
|
+
}
|
|
57420
58082
|
}
|
|
57421
58083
|
};
|
|
57422
58084
|
var MESH_ENQUEUE_TASK_TOOL = {
|
|
@@ -57432,18 +58094,46 @@ var MESH_ENQUEUE_TASK_TOOL = {
|
|
|
57432
58094
|
};
|
|
57433
58095
|
var MESH_VIEW_QUEUE_TOOL = {
|
|
57434
58096
|
name: "mesh_view_queue",
|
|
57435
|
-
description: "View the current status of the mesh work queue (pending, assigned, completed, failed tasks).",
|
|
58097
|
+
description: "View the current status of the mesh work queue (pending, assigned, completed, failed, cancelled tasks).",
|
|
57436
58098
|
inputSchema: {
|
|
57437
58099
|
type: "object",
|
|
57438
58100
|
properties: {
|
|
57439
58101
|
status: {
|
|
57440
58102
|
type: "array",
|
|
57441
58103
|
items: { type: "string" },
|
|
57442
|
-
description: "Filter by task status: pending, assigned, completed, failed. Returns all if omitted."
|
|
58104
|
+
description: "Filter by task status: pending, assigned, completed, failed, cancelled. Returns all if omitted."
|
|
57443
58105
|
}
|
|
57444
58106
|
}
|
|
57445
58107
|
}
|
|
57446
58108
|
};
|
|
58109
|
+
var MESH_QUEUE_CANCEL_TOOL = {
|
|
58110
|
+
name: "mesh_queue_cancel",
|
|
58111
|
+
description: "Cancel a pending/assigned/completed/failed mesh queue task without deleting audit history. Use this to retire stale queue items that target dead sessions.",
|
|
58112
|
+
inputSchema: {
|
|
58113
|
+
type: "object",
|
|
58114
|
+
properties: {
|
|
58115
|
+
task_id: { type: "string", description: "Queue task ID to cancel." },
|
|
58116
|
+
reason: { type: "string", description: "Optional operator-visible reason for cancellation." }
|
|
58117
|
+
},
|
|
58118
|
+
required: ["task_id"]
|
|
58119
|
+
}
|
|
58120
|
+
};
|
|
58121
|
+
var MESH_QUEUE_REQUEUE_TOOL = {
|
|
58122
|
+
name: "mesh_queue_requeue",
|
|
58123
|
+
description: "Return a mesh queue task to pending for retry. By default clears stale assigned owner and target session so another live session can claim it.",
|
|
58124
|
+
inputSchema: {
|
|
58125
|
+
type: "object",
|
|
58126
|
+
properties: {
|
|
58127
|
+
task_id: { type: "string", description: "Queue task ID to requeue." },
|
|
58128
|
+
reason: { type: "string", description: "Optional operator-visible reason for requeueing." },
|
|
58129
|
+
target_node_id: { type: "string", description: "Optional replacement target node ID." },
|
|
58130
|
+
target_session_id: { type: "string", description: "Optional replacement target runtime session ID." },
|
|
58131
|
+
clear_target_node: { type: "boolean", description: "When true, remove any existing target node constraint." },
|
|
58132
|
+
keep_target_session: { type: "boolean", description: "When true, preserve an existing target session if target_session_id is not provided. Defaults false to avoid stale session targets." }
|
|
58133
|
+
},
|
|
58134
|
+
required: ["task_id"]
|
|
58135
|
+
}
|
|
58136
|
+
};
|
|
57447
58137
|
var MESH_SEND_TASK_TOOL = {
|
|
57448
58138
|
name: "mesh_send_task",
|
|
57449
58139
|
description: "Legacy push-based task assignment. Enqueues a task specifically targeted at a given node. The node will pull it immediately if idle.",
|
|
@@ -57613,6 +58303,8 @@ var ALL_MESH_TOOLS = [
|
|
|
57613
58303
|
MESH_LIST_NODES_TOOL,
|
|
57614
58304
|
MESH_ENQUEUE_TASK_TOOL,
|
|
57615
58305
|
MESH_VIEW_QUEUE_TOOL,
|
|
58306
|
+
MESH_QUEUE_CANCEL_TOOL,
|
|
58307
|
+
MESH_QUEUE_REQUEUE_TOOL,
|
|
57616
58308
|
MESH_SEND_TASK_TOOL,
|
|
57617
58309
|
MESH_READ_CHAT_TOOL,
|
|
57618
58310
|
MESH_READ_DEBUG_TOOL,
|
|
@@ -57630,6 +58322,7 @@ async function meshStatus(ctx) {
|
|
|
57630
58322
|
await refreshMeshFromDaemon(ctx);
|
|
57631
58323
|
const { mesh, transport } = ctx;
|
|
57632
58324
|
const results = [];
|
|
58325
|
+
const ledgerSummary = getLedgerSummary(mesh.id);
|
|
57633
58326
|
for (const node of mesh.nodes) {
|
|
57634
58327
|
const entry = {
|
|
57635
58328
|
nodeId: node.id,
|
|
@@ -57663,6 +58356,45 @@ async function meshStatus(ctx) {
|
|
|
57663
58356
|
entry.health = "degraded";
|
|
57664
58357
|
entry.error = e.message;
|
|
57665
58358
|
}
|
|
58359
|
+
const recoveryContext = getSessionRecoveryContext(mesh.id, { nodeId: node.id });
|
|
58360
|
+
if (recoveryContext.consecutiveNodeFailures > 0) {
|
|
58361
|
+
entry.recoveryHints = {
|
|
58362
|
+
consecutiveFailures: recoveryContext.consecutiveNodeFailures,
|
|
58363
|
+
lastTaskMessage: recoveryContext.lastTaskMessage,
|
|
58364
|
+
advice: recoveryContext.advice,
|
|
58365
|
+
retryRecommended: recoveryContext.retryRecommended
|
|
58366
|
+
};
|
|
58367
|
+
}
|
|
58368
|
+
const activeLaunchFailure = getLatestActiveLaunchFailure(mesh.id, node.id);
|
|
58369
|
+
if (activeLaunchFailure && node.isLocalWorktree) {
|
|
58370
|
+
entry.health = "degraded";
|
|
58371
|
+
entry.degradedReason = "worktree_launch_failed";
|
|
58372
|
+
entry.launchReady = false;
|
|
58373
|
+
entry.launchBlockedReason = activeLaunchFailure.code || "mesh_launch_failed";
|
|
58374
|
+
entry.launchBlockedMessage = activeLaunchFailure.error || "Previous worktree session launch failed";
|
|
58375
|
+
entry.lastLaunchFailure = activeLaunchFailure;
|
|
58376
|
+
}
|
|
58377
|
+
const nextStepHints = [];
|
|
58378
|
+
if (entry.degradedReason === "worktree_launch_failed") {
|
|
58379
|
+
nextStepHints.push(`Retry mesh_launch_session(node_id: "${node.id}") after daemon mesh transport/P2P is healthy.`);
|
|
58380
|
+
nextStepHints.push(`If retry is not desired, cleanup the orphan worktree node with mesh_remove_node(node_id: "${node.id}").`);
|
|
58381
|
+
} else if (entry.health === "online" && node.isLocalWorktree) {
|
|
58382
|
+
nextStepHints.push(`Merge worktree to base via mesh_refine_node(node_id: "${node.id}")`);
|
|
58383
|
+
} else if (entry.health === "dirty") {
|
|
58384
|
+
nextStepHints.push(`Commit changes via mesh_checkpoint(node_id: "${node.id}", message: "...")`);
|
|
58385
|
+
} else if (entry.health === "degraded" && entry.error?.includes("git")) {
|
|
58386
|
+
nextStepHints.push("Initialize git repository or check workspace path.");
|
|
58387
|
+
}
|
|
58388
|
+
if (recoveryContext.consecutiveNodeFailures > 0) {
|
|
58389
|
+
if (recoveryContext.retryRecommended) {
|
|
58390
|
+
nextStepHints.push(`Retry task on this node or launch a fresh session.`);
|
|
58391
|
+
} else {
|
|
58392
|
+
nextStepHints.push(`Consider reassigning work to a different node.`);
|
|
58393
|
+
}
|
|
58394
|
+
}
|
|
58395
|
+
if (nextStepHints.length > 0) {
|
|
58396
|
+
entry.nextStepHints = nextStepHints;
|
|
58397
|
+
}
|
|
57666
58398
|
const relatedRepos = await collectRelatedRepoStatuses(ctx, node);
|
|
57667
58399
|
if (relatedRepos.length) entry.relatedRepos = relatedRepos;
|
|
57668
58400
|
results.push(entry);
|
|
@@ -57676,7 +58408,7 @@ async function meshStatus(ctx) {
|
|
|
57676
58408
|
nodes: results
|
|
57677
58409
|
};
|
|
57678
58410
|
try {
|
|
57679
|
-
response.ledgerSummary =
|
|
58411
|
+
response.ledgerSummary = ledgerSummary;
|
|
57680
58412
|
} catch {
|
|
57681
58413
|
}
|
|
57682
58414
|
if (ctx.transport instanceof IpcTransport) {
|
|
@@ -57720,12 +58452,38 @@ async function meshListNodes(ctx) {
|
|
|
57720
58452
|
async function meshEnqueueTask(ctx, args) {
|
|
57721
58453
|
try {
|
|
57722
58454
|
const task = enqueueTask(ctx.mesh.id, args.message);
|
|
57723
|
-
if (ctx.transport
|
|
57724
|
-
ctx.transport.
|
|
58455
|
+
if (isLocalTransport(ctx.transport) && !(ctx.transport instanceof IpcTransport)) {
|
|
58456
|
+
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57725
58457
|
});
|
|
57726
|
-
|
|
58458
|
+
return JSON.stringify({ success: true, taskId: task.id, status: task.status });
|
|
58459
|
+
}
|
|
58460
|
+
if (ctx.transport instanceof IpcTransport) {
|
|
57727
58461
|
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57728
58462
|
});
|
|
58463
|
+
const dispatchPromises = [];
|
|
58464
|
+
for (const node of ctx.mesh.nodes) {
|
|
58465
|
+
const isLocalNode = ctx.localMachineId && node.machineId === ctx.localMachineId || ctx.localDaemonId && node.daemonId === ctx.localDaemonId;
|
|
58466
|
+
if (isLocalNode || !node.daemonId) continue;
|
|
58467
|
+
dispatchPromises.push(
|
|
58468
|
+
ipcDispatchToRemoteAgent(ctx, node, { message: args.message }).then((result) => {
|
|
58469
|
+
if (result.success) {
|
|
58470
|
+
try {
|
|
58471
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
58472
|
+
kind: "task_dispatched",
|
|
58473
|
+
nodeId: node.id,
|
|
58474
|
+
sessionId: result.sessionId,
|
|
58475
|
+
payload: { message: args.message, via: "p2p_direct", taskId: task.id }
|
|
58476
|
+
});
|
|
58477
|
+
} catch {
|
|
58478
|
+
}
|
|
58479
|
+
}
|
|
58480
|
+
}).catch(() => {
|
|
58481
|
+
})
|
|
58482
|
+
);
|
|
58483
|
+
}
|
|
58484
|
+
Promise.all(dispatchPromises).catch(() => {
|
|
58485
|
+
});
|
|
58486
|
+
return JSON.stringify({ success: true, taskId: task.id, status: task.status });
|
|
57729
58487
|
}
|
|
57730
58488
|
return JSON.stringify({ success: true, taskId: task.id, status: task.status });
|
|
57731
58489
|
} catch (e) {
|
|
@@ -57734,8 +58492,51 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
57734
58492
|
}
|
|
57735
58493
|
async function meshViewQueue(ctx, args) {
|
|
57736
58494
|
try {
|
|
57737
|
-
const queue = getQueue(ctx.mesh.id, { status: args.status });
|
|
57738
|
-
|
|
58495
|
+
const queue = annotateQueueStaleness(getQueue(ctx.mesh.id, { status: args.status }));
|
|
58496
|
+
const staleAssignedTasks = queue.filter((task) => task?.status === "assigned" && task?.staleAssigned);
|
|
58497
|
+
return JSON.stringify({
|
|
58498
|
+
success: true,
|
|
58499
|
+
queue,
|
|
58500
|
+
staleAssignedTasks,
|
|
58501
|
+
staleAssignedCount: staleAssignedTasks.length,
|
|
58502
|
+
// Back-compat alias for callers already reading the first hardening payload.
|
|
58503
|
+
staleAssignments: staleAssignedTasks
|
|
58504
|
+
}, null, 2);
|
|
58505
|
+
} catch (e) {
|
|
58506
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58507
|
+
}
|
|
58508
|
+
}
|
|
58509
|
+
async function meshQueueCancel(ctx, args) {
|
|
58510
|
+
try {
|
|
58511
|
+
const taskId = (args.task_id || args.taskId || "").trim();
|
|
58512
|
+
if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
|
|
58513
|
+
const task = cancelTask(ctx.mesh.id, taskId, { reason: args.reason });
|
|
58514
|
+
if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
|
|
58515
|
+
return JSON.stringify({ success: true, task }, null, 2);
|
|
58516
|
+
} catch (e) {
|
|
58517
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58518
|
+
}
|
|
58519
|
+
}
|
|
58520
|
+
async function meshQueueRequeue(ctx, args) {
|
|
58521
|
+
try {
|
|
58522
|
+
const taskId = (args.task_id || args.taskId || "").trim();
|
|
58523
|
+
if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
|
|
58524
|
+
const targetNodeId = (args.target_node_id || args.targetNodeId || "").trim() || void 0;
|
|
58525
|
+
const targetSessionId = (args.target_session_id || args.targetSessionId || "").trim() || void 0;
|
|
58526
|
+
const keepTargetSession = args.keep_target_session === true || args.keepTargetSession === true;
|
|
58527
|
+
const task = requeueTask(ctx.mesh.id, taskId, {
|
|
58528
|
+
reason: args.reason,
|
|
58529
|
+
targetNodeId,
|
|
58530
|
+
targetSessionId,
|
|
58531
|
+
clearTargetNode: args.clear_target_node === true || args.clearTargetNode === true,
|
|
58532
|
+
clearTargetSession: targetSessionId ? false : !keepTargetSession
|
|
58533
|
+
});
|
|
58534
|
+
if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
|
|
58535
|
+
if (isLocalTransport(ctx.transport)) {
|
|
58536
|
+
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
58537
|
+
});
|
|
58538
|
+
}
|
|
58539
|
+
return JSON.stringify({ success: true, task }, null, 2);
|
|
57739
58540
|
} catch (e) {
|
|
57740
58541
|
return JSON.stringify({ success: false, error: e.message });
|
|
57741
58542
|
}
|
|
@@ -57745,6 +58546,24 @@ async function meshSendTask(ctx, args) {
|
|
|
57745
58546
|
if (node.policy?.readOnly) {
|
|
57746
58547
|
return JSON.stringify({ error: `Node '${args.node_id}' is read-only` });
|
|
57747
58548
|
}
|
|
58549
|
+
const duplicate = hasRecentDuplicateDispatch(ctx, args);
|
|
58550
|
+
if (duplicate.duplicate) {
|
|
58551
|
+
return JSON.stringify({
|
|
58552
|
+
success: true,
|
|
58553
|
+
duplicate: true,
|
|
58554
|
+
dispatched: false,
|
|
58555
|
+
warning: "Duplicate mesh_send_task suppressed: the same node/session/message was dispatched recently.",
|
|
58556
|
+
nodeId: args.node_id,
|
|
58557
|
+
sessionId: args.session_id,
|
|
58558
|
+
source: duplicate.source,
|
|
58559
|
+
previousDispatch: duplicate.entry ? {
|
|
58560
|
+
id: duplicate.entry.id,
|
|
58561
|
+
timestamp: duplicate.entry.timestamp || duplicate.entry.updatedAt || duplicate.entry.createdAt,
|
|
58562
|
+
nodeId: duplicate.entry.nodeId || duplicate.entry.targetNodeId || duplicate.entry.assignedNodeId,
|
|
58563
|
+
sessionId: duplicate.entry.sessionId || duplicate.entry.targetSessionId || duplicate.entry.assignedSessionId
|
|
58564
|
+
} : void 0
|
|
58565
|
+
});
|
|
58566
|
+
}
|
|
57748
58567
|
try {
|
|
57749
58568
|
if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
57750
58569
|
const res = await ctx.transport.meshEnqueueTask(node.daemonId, {
|
|
@@ -57754,11 +58573,66 @@ async function meshSendTask(ctx, args) {
|
|
|
57754
58573
|
});
|
|
57755
58574
|
return JSON.stringify(res);
|
|
57756
58575
|
}
|
|
57757
|
-
const
|
|
57758
|
-
if (ctx.transport instanceof IpcTransport && node.daemonId &&
|
|
57759
|
-
|
|
58576
|
+
const isLocalNode = ctx.localMachineId && node.machineId === ctx.localMachineId || ctx.localDaemonId && node.daemonId === ctx.localDaemonId;
|
|
58577
|
+
if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
|
|
58578
|
+
const cached2 = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id || ""));
|
|
58579
|
+
const result = await ipcDispatchToRemoteAgent(ctx, node, {
|
|
58580
|
+
session_id: args.session_id,
|
|
58581
|
+
message: args.message,
|
|
58582
|
+
providerType: cached2?.providerType
|
|
57760
58583
|
});
|
|
57761
|
-
|
|
58584
|
+
if (result.success) {
|
|
58585
|
+
const dispatchedSessionId = args.session_id || result.sessionId;
|
|
58586
|
+
try {
|
|
58587
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
58588
|
+
kind: "task_dispatched",
|
|
58589
|
+
nodeId: args.node_id,
|
|
58590
|
+
sessionId: dispatchedSessionId,
|
|
58591
|
+
payload: {
|
|
58592
|
+
message: args.message,
|
|
58593
|
+
via: "p2p_direct",
|
|
58594
|
+
...dispatchedSessionId ? { targetSessionId: dispatchedSessionId } : {}
|
|
58595
|
+
}
|
|
58596
|
+
});
|
|
58597
|
+
} catch {
|
|
58598
|
+
}
|
|
58599
|
+
}
|
|
58600
|
+
return JSON.stringify({ ...result, nodeId: args.node_id, dispatched: result.success === true });
|
|
58601
|
+
}
|
|
58602
|
+
if (args.session_id && isLocalTransport(ctx.transport)) {
|
|
58603
|
+
const cached2 = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
|
|
58604
|
+
const dispatchResult = await commandForNode(ctx, node, "agent_command", {
|
|
58605
|
+
targetSessionId: args.session_id,
|
|
58606
|
+
...cached2?.providerType ? { agentType: cached2.providerType, cliType: cached2.providerType, providerType: cached2.providerType } : {},
|
|
58607
|
+
action: "send_chat",
|
|
58608
|
+
message: args.message
|
|
58609
|
+
});
|
|
58610
|
+
const dispatchPayload = unwrapCommandPayload(dispatchResult);
|
|
58611
|
+
if (dispatchPayload?.success === false || dispatchResult?.success === false) {
|
|
58612
|
+
return JSON.stringify({
|
|
58613
|
+
success: false,
|
|
58614
|
+
nodeId: args.node_id,
|
|
58615
|
+
sessionId: args.session_id,
|
|
58616
|
+
error: dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task"
|
|
58617
|
+
});
|
|
58618
|
+
}
|
|
58619
|
+
try {
|
|
58620
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
58621
|
+
kind: "task_dispatched",
|
|
58622
|
+
nodeId: args.node_id,
|
|
58623
|
+
sessionId: args.session_id,
|
|
58624
|
+
providerType: cached2?.providerType,
|
|
58625
|
+
payload: { message: args.message, via: "local_direct" }
|
|
58626
|
+
});
|
|
58627
|
+
} catch {
|
|
58628
|
+
}
|
|
58629
|
+
return JSON.stringify({ success: true, dispatched: true, nodeId: args.node_id, sessionId: args.session_id });
|
|
58630
|
+
}
|
|
58631
|
+
const task = enqueueTask(ctx.mesh.id, args.message, {
|
|
58632
|
+
targetNodeId: args.node_id,
|
|
58633
|
+
targetSessionId: args.session_id
|
|
58634
|
+
});
|
|
58635
|
+
if (isLocalTransport(ctx.transport) || ctx.transport instanceof IpcTransport) {
|
|
57762
58636
|
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57763
58637
|
});
|
|
57764
58638
|
}
|
|
@@ -57768,7 +58642,10 @@ async function meshSendTask(ctx, args) {
|
|
|
57768
58642
|
}
|
|
57769
58643
|
}
|
|
57770
58644
|
async function meshReadChat(ctx, args) {
|
|
57771
|
-
const node = await
|
|
58645
|
+
const node = await findOptionalNodeWithRefresh(ctx, args.node_id);
|
|
58646
|
+
if (!node) {
|
|
58647
|
+
return JSON.stringify(buildMissingNodeReadChatRecovery(ctx, args), null, 2);
|
|
58648
|
+
}
|
|
57772
58649
|
if (isLocalTransport(ctx.transport)) {
|
|
57773
58650
|
const cached2 = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
|
|
57774
58651
|
const providerSessionId = typeof args.provider_session_id === "string" && args.provider_session_id.trim() ? args.provider_session_id.trim() : cached2?.providerSessionId;
|
|
@@ -57871,19 +58748,28 @@ async function meshLaunchSession(ctx, args) {
|
|
|
57871
58748
|
const coordinatorNode = resolveCoordinatorNode(ctx);
|
|
57872
58749
|
const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
|
|
57873
58750
|
const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
|
|
57874
|
-
|
|
57875
|
-
|
|
57876
|
-
|
|
57877
|
-
|
|
57878
|
-
|
|
57879
|
-
|
|
57880
|
-
|
|
57881
|
-
|
|
57882
|
-
|
|
57883
|
-
|
|
57884
|
-
|
|
57885
|
-
|
|
58751
|
+
let result;
|
|
58752
|
+
try {
|
|
58753
|
+
result = await commandForNode(ctx, node, "launch_cli", {
|
|
58754
|
+
cliType: resolvedProviderType,
|
|
58755
|
+
dir: node.workspace,
|
|
58756
|
+
settings: {
|
|
58757
|
+
meshNodeFor: ctx.mesh.id,
|
|
58758
|
+
meshNodeId: args.node_id,
|
|
58759
|
+
spawnedSessionVisibility,
|
|
58760
|
+
...coordinatorDaemonId ? { meshCoordinatorDaemonId: coordinatorDaemonId } : {},
|
|
58761
|
+
...coordinatorNode?.id ? { meshCoordinatorNodeId: coordinatorNode.id } : {},
|
|
58762
|
+
launchedByCoordinator: true
|
|
58763
|
+
}
|
|
58764
|
+
});
|
|
58765
|
+
} catch (e) {
|
|
58766
|
+
return JSON.stringify(recordRecoverableLaunchFailure(ctx, node, resolvedProviderType, e), null, 2);
|
|
58767
|
+
}
|
|
57886
58768
|
const launchPayload = extractLaunchPayload(result);
|
|
58769
|
+
if (launchPayload?.success === false || result?.success === false) {
|
|
58770
|
+
const launchError = new Error(launchPayload?.error || result?.error || "launch_cli rejected the session launch");
|
|
58771
|
+
return JSON.stringify(recordRecoverableLaunchFailure(ctx, node, resolvedProviderType, launchError), null, 2);
|
|
58772
|
+
}
|
|
57887
58773
|
const runtimeSessionId = typeof launchPayload?.sessionId === "string" ? launchPayload.sessionId : typeof launchPayload?.id === "string" ? launchPayload.id : typeof launchPayload?.runtimeSessionId === "string" ? launchPayload.runtimeSessionId : "";
|
|
57888
58774
|
const providerSessionId = typeof launchPayload?.providerSessionId === "string" && launchPayload.providerSessionId.trim() ? launchPayload.providerSessionId.trim() : void 0;
|
|
57889
58775
|
if (runtimeSessionId) {
|
|
@@ -57902,7 +58788,8 @@ async function meshLaunchSession(ctx, args) {
|
|
|
57902
58788
|
});
|
|
57903
58789
|
} catch {
|
|
57904
58790
|
}
|
|
57905
|
-
|
|
58791
|
+
const isLocalNode = ctx.localMachineId && node.machineId === ctx.localMachineId || ctx.localDaemonId && node.daemonId === ctx.localDaemonId;
|
|
58792
|
+
if (ctx.transport instanceof IpcTransport && node.daemonId && !isLocalNode) {
|
|
57906
58793
|
ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57907
58794
|
});
|
|
57908
58795
|
} else if (isLocalTransport(ctx.transport)) {
|
|
@@ -57952,7 +58839,7 @@ async function meshLaunchSession(ctx, args) {
|
|
|
57952
58839
|
}
|
|
57953
58840
|
return JSON.stringify({ ...res, resolvedProviderType }, null, 2);
|
|
57954
58841
|
} catch (e) {
|
|
57955
|
-
return JSON.stringify(
|
|
58842
|
+
return JSON.stringify(recordRecoverableLaunchFailure(ctx, node, resolvedProviderType, e), null, 2);
|
|
57956
58843
|
}
|
|
57957
58844
|
} else {
|
|
57958
58845
|
return JSON.stringify({ error: "Cloud mesh launch_session requires node daemonId" });
|
|
@@ -59840,6 +60727,15 @@ async function startMcpServer(opts) {
|
|
|
59840
60727
|
process.exit(1);
|
|
59841
60728
|
}
|
|
59842
60729
|
let localDaemonId;
|
|
60730
|
+
let localMachineId;
|
|
60731
|
+
if (transport instanceof LocalTransport || transport instanceof IpcTransport) {
|
|
60732
|
+
try {
|
|
60733
|
+
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
60734
|
+
const cfg = loadConfig2();
|
|
60735
|
+
if (cfg.registeredMachineId) localMachineId = cfg.registeredMachineId;
|
|
60736
|
+
} catch {
|
|
60737
|
+
}
|
|
60738
|
+
}
|
|
59843
60739
|
if (transport instanceof IpcTransport) {
|
|
59844
60740
|
try {
|
|
59845
60741
|
const statusResult = await transport.getStatus();
|
|
@@ -59848,7 +60744,7 @@ async function startMcpServer(opts) {
|
|
|
59848
60744
|
} catch {
|
|
59849
60745
|
}
|
|
59850
60746
|
}
|
|
59851
|
-
const meshCtx = { mesh, transport, ...localDaemonId ? { localDaemonId } : {} };
|
|
60747
|
+
const meshCtx = { mesh, transport, ...localDaemonId ? { localDaemonId } : {}, ...localMachineId ? { localMachineId } : {} };
|
|
59852
60748
|
const coordinatorPrompt = await buildMeshModeCoordinatorPrompt(mesh);
|
|
59853
60749
|
const server2 = new import_server.Server(
|
|
59854
60750
|
{ name: "adhdev-mcp-server", version: "0.9.76" },
|
|
@@ -59888,6 +60784,12 @@ async function startMcpServer(opts) {
|
|
|
59888
60784
|
case "mesh_view_queue":
|
|
59889
60785
|
text = await meshViewQueue(meshCtx, a);
|
|
59890
60786
|
break;
|
|
60787
|
+
case "mesh_queue_cancel":
|
|
60788
|
+
text = await meshQueueCancel(meshCtx, a);
|
|
60789
|
+
break;
|
|
60790
|
+
case "mesh_queue_requeue":
|
|
60791
|
+
text = await meshQueueRequeue(meshCtx, a);
|
|
60792
|
+
break;
|
|
59891
60793
|
case "mesh_send_task":
|
|
59892
60794
|
text = await meshSendTask(meshCtx, a);
|
|
59893
60795
|
break;
|