@adhdev/daemon-core 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/boot/daemon-lifecycle.d.ts +3 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +4 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +14 -4
- package/dist/commands/mesh-coordinator.d.ts +10 -0
- package/dist/commands/router.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +424 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +421 -45
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events.d.ts +2 -7
- package/dist/mesh/mesh-work-queue.d.ts +35 -1
- package/dist/shared-types.d.ts +14 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +5 -0
- package/src/cli-adapters/provider-cli-adapter.ts +34 -4
- package/src/cli-adapters/provider-cli-shared.ts +14 -4
- package/src/commands/cli-manager.ts +0 -4
- package/src/commands/mesh-coordinator.ts +55 -7
- package/src/commands/router.ts +193 -4
- package/src/commands/stream-commands.ts +8 -1
- package/src/index.ts +2 -2
- package/src/mesh/mesh-events.ts +147 -20
- package/src/mesh/mesh-work-queue.ts +103 -6
- package/src/providers/cli-provider-instance.ts +2 -0
- package/src/shared-types.ts +14 -0
package/dist/index.js
CHANGED
|
@@ -978,6 +978,17 @@ var init_mesh_ledger = __esm({
|
|
|
978
978
|
});
|
|
979
979
|
|
|
980
980
|
// src/mesh/mesh-work-queue.ts
|
|
981
|
+
var mesh_work_queue_exports = {};
|
|
982
|
+
__export(mesh_work_queue_exports, {
|
|
983
|
+
cancelTask: () => cancelTask,
|
|
984
|
+
claimNextTask: () => claimNextTask,
|
|
985
|
+
enqueueTask: () => enqueueTask,
|
|
986
|
+
getMeshQueueStats: () => getMeshQueueStats,
|
|
987
|
+
getQueue: () => getQueue,
|
|
988
|
+
requeueTask: () => requeueTask,
|
|
989
|
+
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
990
|
+
updateTaskStatus: () => updateTaskStatus
|
|
991
|
+
});
|
|
981
992
|
function getQueuePath(meshId) {
|
|
982
993
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
983
994
|
return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.json`);
|
|
@@ -1004,6 +1015,7 @@ function enqueueTask(meshId, message, opts) {
|
|
|
1004
1015
|
message,
|
|
1005
1016
|
status: "pending",
|
|
1006
1017
|
targetNodeId: opts?.targetNodeId,
|
|
1018
|
+
targetSessionId: opts?.targetSessionId,
|
|
1007
1019
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1008
1020
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1009
1021
|
};
|
|
@@ -1021,9 +1033,14 @@ function getQueue(meshId, opts) {
|
|
|
1021
1033
|
}
|
|
1022
1034
|
function claimNextTask(meshId, nodeId, sessionId) {
|
|
1023
1035
|
const queue = readQueue(meshId);
|
|
1024
|
-
|
|
1036
|
+
const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
|
|
1037
|
+
if (hasActiveAssignment) return null;
|
|
1038
|
+
let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
|
|
1039
|
+
if (targetIdx === -1) {
|
|
1040
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
|
|
1041
|
+
}
|
|
1025
1042
|
if (targetIdx === -1) {
|
|
1026
|
-
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId);
|
|
1043
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
|
|
1027
1044
|
}
|
|
1028
1045
|
if (targetIdx === -1) return null;
|
|
1029
1046
|
const entry = queue[targetIdx];
|
|
@@ -1043,6 +1060,40 @@ function updateTaskStatus(meshId, taskId, status) {
|
|
|
1043
1060
|
writeQueue(meshId, queue);
|
|
1044
1061
|
return queue[idx];
|
|
1045
1062
|
}
|
|
1063
|
+
function cancelTask(meshId, taskId, opts) {
|
|
1064
|
+
const queue = readQueue(meshId);
|
|
1065
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1066
|
+
if (idx === -1) return null;
|
|
1067
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1068
|
+
queue[idx].status = "cancelled";
|
|
1069
|
+
queue[idx].updatedAt = now;
|
|
1070
|
+
queue[idx].cancelledAt = now;
|
|
1071
|
+
if (opts?.reason) queue[idx].cancelReason = opts.reason;
|
|
1072
|
+
writeQueue(meshId, queue);
|
|
1073
|
+
return queue[idx];
|
|
1074
|
+
}
|
|
1075
|
+
function requeueTask(meshId, taskId, opts) {
|
|
1076
|
+
const queue = readQueue(meshId);
|
|
1077
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1078
|
+
if (idx === -1) return null;
|
|
1079
|
+
const entry = queue[idx];
|
|
1080
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1081
|
+
entry.status = "pending";
|
|
1082
|
+
delete entry.assignedNodeId;
|
|
1083
|
+
delete entry.assignedSessionId;
|
|
1084
|
+
delete entry.cancelledAt;
|
|
1085
|
+
delete entry.cancelReason;
|
|
1086
|
+
if (opts?.clearTargetNode) delete entry.targetNodeId;
|
|
1087
|
+
if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
|
|
1088
|
+
if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
|
|
1089
|
+
if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
|
|
1090
|
+
entry.updatedAt = now;
|
|
1091
|
+
entry.requeuedAt = now;
|
|
1092
|
+
entry.requeueCount = (entry.requeueCount || 0) + 1;
|
|
1093
|
+
if (opts?.reason) entry.requeueReason = opts.reason;
|
|
1094
|
+
writeQueue(meshId, queue);
|
|
1095
|
+
return entry;
|
|
1096
|
+
}
|
|
1046
1097
|
function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
1047
1098
|
const queue = readQueue(meshId);
|
|
1048
1099
|
for (let i = queue.length - 1; i >= 0; i--) {
|
|
@@ -1061,7 +1112,14 @@ function getMeshQueueStats(meshId) {
|
|
|
1061
1112
|
pending: queue.filter((q) => q.status === "pending").length,
|
|
1062
1113
|
assigned: queue.filter((q) => q.status === "assigned").length,
|
|
1063
1114
|
completed: queue.filter((q) => q.status === "completed").length,
|
|
1064
|
-
failed: queue.filter((q) => q.status === "failed").length
|
|
1115
|
+
failed: queue.filter((q) => q.status === "failed").length,
|
|
1116
|
+
cancelled: queue.filter((q) => q.status === "cancelled").length,
|
|
1117
|
+
activeAssignments: queue.filter((q) => q.status === "assigned").map((q) => ({
|
|
1118
|
+
id: q.id,
|
|
1119
|
+
nodeId: q.assignedNodeId,
|
|
1120
|
+
sessionId: q.assignedSessionId,
|
|
1121
|
+
message: q.message
|
|
1122
|
+
}))
|
|
1065
1123
|
};
|
|
1066
1124
|
}
|
|
1067
1125
|
var import_fs4, import_path4, import_crypto5;
|
|
@@ -1304,6 +1362,9 @@ function drainPendingMeshCoordinatorEvents() {
|
|
|
1304
1362
|
function readNonEmptyString(value) {
|
|
1305
1363
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
1306
1364
|
}
|
|
1365
|
+
function resolveEventSessionId(event, fallback) {
|
|
1366
|
+
return readNonEmptyString(event.targetSessionId) || readNonEmptyString(event.sessionId) || readNonEmptyString(event.instanceId) || readNonEmptyString(fallback);
|
|
1367
|
+
}
|
|
1307
1368
|
function isMeshCoordinatorEvent(eventName) {
|
|
1308
1369
|
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
1309
1370
|
}
|
|
@@ -1315,38 +1376,74 @@ function formatCompletionMetadata(event) {
|
|
|
1315
1376
|
].filter(Boolean);
|
|
1316
1377
|
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
1317
1378
|
}
|
|
1379
|
+
function getMeshWithCache(components, meshId) {
|
|
1380
|
+
const localMesh = getMesh(meshId);
|
|
1381
|
+
if (localMesh) return localMesh;
|
|
1382
|
+
return components.router?.getCachedInlineMesh(meshId);
|
|
1383
|
+
}
|
|
1318
1384
|
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
1319
1385
|
const task = claimNextTask(meshId, nodeId, sessionId);
|
|
1320
|
-
if (!task)
|
|
1386
|
+
if (!task) {
|
|
1387
|
+
return false;
|
|
1388
|
+
}
|
|
1321
1389
|
LOG.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
|
|
1390
|
+
const mesh = getMeshWithCache(components, meshId);
|
|
1391
|
+
const node = mesh?.nodes.find((n) => n.id === nodeId);
|
|
1392
|
+
if (node?.daemonId && components.dispatchMeshCommand) {
|
|
1393
|
+
const isLocalNode = components.cliManager.adapters.has(sessionId);
|
|
1394
|
+
if (!isLocalNode) {
|
|
1395
|
+
components.dispatchMeshCommand(node.daemonId, "agent_command", {
|
|
1396
|
+
targetSessionId: sessionId,
|
|
1397
|
+
cliType: providerType,
|
|
1398
|
+
action: "send_chat",
|
|
1399
|
+
message: task.message
|
|
1400
|
+
}).catch((e) => {
|
|
1401
|
+
LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
|
|
1402
|
+
updateTaskStatus(meshId, task.id, "failed");
|
|
1403
|
+
});
|
|
1404
|
+
return true;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1322
1407
|
components.cliManager.handleCliCommand("agent_command", {
|
|
1323
1408
|
targetSessionId: sessionId,
|
|
1324
1409
|
cliType: providerType,
|
|
1325
1410
|
action: "send_chat",
|
|
1326
|
-
|
|
1411
|
+
message: task.message
|
|
1327
1412
|
}).catch((e) => {
|
|
1328
|
-
LOG.error("MeshQueue", `Failed to dispatch task to node ${nodeId}: ${e?.message}`);
|
|
1413
|
+
LOG.error("MeshQueue", `Failed to dispatch task locally to node ${nodeId}: ${e?.message}`);
|
|
1414
|
+
updateTaskStatus(meshId, task.id, "failed");
|
|
1329
1415
|
});
|
|
1330
1416
|
return true;
|
|
1331
1417
|
}
|
|
1332
1418
|
function triggerMeshQueue(components, meshId) {
|
|
1333
|
-
const mesh =
|
|
1419
|
+
const mesh = getMeshWithCache(components, meshId);
|
|
1334
1420
|
if (!mesh) return;
|
|
1335
1421
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
1336
1422
|
for (const inst of cliInstances) {
|
|
1337
1423
|
const state = inst.getState();
|
|
1338
1424
|
const settings = state.settings || {};
|
|
1339
1425
|
const instMeshId = readNonEmptyString(settings.meshNodeFor);
|
|
1340
|
-
if (instMeshId !== meshId
|
|
1426
|
+
if (instMeshId !== meshId) continue;
|
|
1341
1427
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
1342
1428
|
if (!nodeId) continue;
|
|
1343
|
-
|
|
1429
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
1430
|
+
if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
|
|
1431
|
+
if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
|
|
1344
1432
|
const sessionId = state.instanceId;
|
|
1345
1433
|
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
1346
1434
|
if (providerType) {
|
|
1347
1435
|
tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
|
|
1348
1436
|
}
|
|
1349
1437
|
}
|
|
1438
|
+
for (const [key, idle] of remoteIdleSessions.entries()) {
|
|
1439
|
+
const node = mesh.nodes.find((n) => n.id === idle.nodeId);
|
|
1440
|
+
if (node) {
|
|
1441
|
+
const assigned = tryAssignQueueTask(components, meshId, idle.nodeId, idle.sessionId, idle.providerType);
|
|
1442
|
+
if (assigned) {
|
|
1443
|
+
remoteIdleSessions.delete(key);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1350
1447
|
}
|
|
1351
1448
|
function buildMeshSystemMessage(args) {
|
|
1352
1449
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
@@ -1393,20 +1490,67 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
|
|
|
1393
1490
|
return "";
|
|
1394
1491
|
}
|
|
1395
1492
|
function injectMeshSystemMessage(components, args) {
|
|
1493
|
+
let completedTaskForLedger = null;
|
|
1396
1494
|
if (args.event === "agent:generating_completed") {
|
|
1397
|
-
const sessionId =
|
|
1398
|
-
const nodeId = readNonEmptyString(args.
|
|
1495
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
1496
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
1399
1497
|
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
1400
1498
|
if (sessionId) {
|
|
1401
|
-
updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
1499
|
+
const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
1500
|
+
completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
|
|
1402
1501
|
if (nodeId && providerType) {
|
|
1403
1502
|
setTimeout(() => {
|
|
1404
1503
|
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
1405
1504
|
}, 500);
|
|
1406
1505
|
}
|
|
1407
1506
|
}
|
|
1507
|
+
} else if (args.event === "agent:ready") {
|
|
1508
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
1509
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
1510
|
+
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
1511
|
+
const completedTask = sessionId ? updateSessionTaskStatus(args.meshId, sessionId, "completed") : null;
|
|
1512
|
+
if (completedTask) {
|
|
1513
|
+
completedTaskForLedger = { id: completedTask.id };
|
|
1514
|
+
try {
|
|
1515
|
+
appendLedgerEntry(args.meshId, {
|
|
1516
|
+
kind: "task_completed",
|
|
1517
|
+
nodeId: nodeId || void 0,
|
|
1518
|
+
sessionId,
|
|
1519
|
+
providerType: providerType || void 0,
|
|
1520
|
+
payload: {
|
|
1521
|
+
event: args.event,
|
|
1522
|
+
nodeLabel: args.nodeLabel,
|
|
1523
|
+
taskId: completedTask.id,
|
|
1524
|
+
completedViaReady: true,
|
|
1525
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
|
|
1526
|
+
finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
|
|
1527
|
+
}
|
|
1528
|
+
});
|
|
1529
|
+
} catch (e) {
|
|
1530
|
+
LOG.warn("MeshLedger", `Failed to record task_completed from ready: ${e?.message || e}`);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
if (sessionId && nodeId && providerType) {
|
|
1534
|
+
remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
|
|
1535
|
+
setTimeout(() => {
|
|
1536
|
+
const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
1537
|
+
if (assigned) {
|
|
1538
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
1539
|
+
}
|
|
1540
|
+
}, 500);
|
|
1541
|
+
}
|
|
1542
|
+
} else if (args.event === "agent:generating_started") {
|
|
1543
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
1544
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
1545
|
+
if (sessionId && nodeId) {
|
|
1546
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
1547
|
+
}
|
|
1408
1548
|
} else if (args.event === "agent:stopped") {
|
|
1409
|
-
const sessionId =
|
|
1549
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
1550
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
1551
|
+
if (sessionId && nodeId) {
|
|
1552
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
1553
|
+
}
|
|
1410
1554
|
if (sessionId) {
|
|
1411
1555
|
updateSessionTaskStatus(args.meshId, sessionId, "failed");
|
|
1412
1556
|
}
|
|
@@ -1416,13 +1560,15 @@ function injectMeshSystemMessage(components, args) {
|
|
|
1416
1560
|
try {
|
|
1417
1561
|
appendLedgerEntry(args.meshId, {
|
|
1418
1562
|
kind: ledgerKind,
|
|
1419
|
-
nodeId: readNonEmptyString(args.
|
|
1420
|
-
sessionId:
|
|
1563
|
+
nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
1564
|
+
sessionId: resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0,
|
|
1421
1565
|
providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
|
|
1422
1566
|
payload: {
|
|
1423
1567
|
event: args.event,
|
|
1424
1568
|
nodeLabel: args.nodeLabel,
|
|
1425
|
-
|
|
1569
|
+
taskId: completedTaskForLedger?.id || void 0,
|
|
1570
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
|
|
1571
|
+
finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
|
|
1426
1572
|
}
|
|
1427
1573
|
});
|
|
1428
1574
|
} catch (e) {
|
|
@@ -1435,8 +1581,8 @@ function injectMeshSystemMessage(components, args) {
|
|
|
1435
1581
|
const mesh = getMesh(args.meshId);
|
|
1436
1582
|
const maxRetries = mesh?.policy?.maxTaskRetries ?? 1;
|
|
1437
1583
|
recoveryContext = getSessionRecoveryContext(args.meshId, {
|
|
1438
|
-
sessionId:
|
|
1439
|
-
nodeId: readNonEmptyString(args.
|
|
1584
|
+
sessionId: resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0,
|
|
1585
|
+
nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
1440
1586
|
maxRetries
|
|
1441
1587
|
});
|
|
1442
1588
|
recoveryContext.failedProviderType = readNonEmptyString(args.metadataEvent.providerType) || null;
|
|
@@ -1531,12 +1677,14 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
1531
1677
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
1532
1678
|
return injectMeshSystemMessage(components, {
|
|
1533
1679
|
meshId,
|
|
1680
|
+
nodeId,
|
|
1534
1681
|
nodeLabel,
|
|
1535
1682
|
event: eventName,
|
|
1536
1683
|
metadataEvent: {
|
|
1537
|
-
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
1684
|
+
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId) || readNonEmptyString(payload.instanceId),
|
|
1538
1685
|
providerType: readNonEmptyString(payload.providerType),
|
|
1539
|
-
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
1686
|
+
providerSessionId: readNonEmptyString(payload.providerSessionId),
|
|
1687
|
+
finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary)
|
|
1540
1688
|
}
|
|
1541
1689
|
});
|
|
1542
1690
|
}
|
|
@@ -1555,22 +1703,24 @@ function setupMeshEventForwarding(components) {
|
|
|
1555
1703
|
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
1556
1704
|
const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
|
|
1557
1705
|
if (!isMeshDelegate) return;
|
|
1558
|
-
const mesh = meshIdFromRuntime ?
|
|
1706
|
+
const mesh = meshIdFromRuntime ? getMeshWithCache(components, meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
1559
1707
|
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
1560
1708
|
if (!meshId) return;
|
|
1561
1709
|
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
1562
1710
|
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
1711
|
+
const resolvedNodeId = targetNode?.id || runtimeNodeId;
|
|
1563
1712
|
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
1564
1713
|
injectMeshSystemMessage(components, {
|
|
1565
1714
|
meshId,
|
|
1566
1715
|
sourceInstanceId: instanceId,
|
|
1716
|
+
nodeId: resolvedNodeId,
|
|
1567
1717
|
nodeLabel,
|
|
1568
1718
|
event: event.event,
|
|
1569
1719
|
metadataEvent: event
|
|
1570
1720
|
});
|
|
1571
1721
|
});
|
|
1572
1722
|
}
|
|
1573
|
-
var MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND;
|
|
1723
|
+
var remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND;
|
|
1574
1724
|
var init_mesh_events = __esm({
|
|
1575
1725
|
"src/mesh/mesh-events.ts"() {
|
|
1576
1726
|
"use strict";
|
|
@@ -1578,12 +1728,15 @@ var init_mesh_events = __esm({
|
|
|
1578
1728
|
init_logger();
|
|
1579
1729
|
init_mesh_ledger();
|
|
1580
1730
|
init_mesh_work_queue();
|
|
1731
|
+
remoteIdleSessions = /* @__PURE__ */ new Map();
|
|
1581
1732
|
MAX_PENDING_EVENTS = 50;
|
|
1582
1733
|
pendingMeshCoordinatorEvents = [];
|
|
1583
1734
|
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
1735
|
+
"agent:generating_started",
|
|
1584
1736
|
"agent:generating_completed",
|
|
1585
1737
|
"agent:waiting_approval",
|
|
1586
1738
|
"agent:stopped",
|
|
1739
|
+
"agent:ready",
|
|
1587
1740
|
"monitor:long_generating"
|
|
1588
1741
|
]);
|
|
1589
1742
|
EVENT_TO_LEDGER_KIND = {
|
|
@@ -2699,6 +2852,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
2699
2852
|
statusHistory = [];
|
|
2700
2853
|
// ─── CLI Scripts (script-based parsing) ───
|
|
2701
2854
|
cliScripts;
|
|
2855
|
+
/** Per-session opaque state object created by cliScripts.createState(), reset on stop. */
|
|
2856
|
+
scriptState = null;
|
|
2702
2857
|
runtimeSettings = {};
|
|
2703
2858
|
/** Full accumulated rendered PTY transcript for parser/readback use */
|
|
2704
2859
|
accumulatedBuffer = "";
|
|
@@ -2775,9 +2930,13 @@ ${lastSnapshot}`;
|
|
|
2775
2930
|
this.lastScreenChangeAt = 0;
|
|
2776
2931
|
this.lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
|
|
2777
2932
|
}
|
|
2933
|
+
getAccumulatedRawBufferCacheKey() {
|
|
2934
|
+
return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
2935
|
+
}
|
|
2778
2936
|
getFreshParsedStatusCache() {
|
|
2779
2937
|
const cached = this.parsedStatusCache;
|
|
2780
|
-
|
|
2938
|
+
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
2939
|
+
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBufferKey === accumulatedRawBufferKey && cached.screenText === this.lastScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
2781
2940
|
return cached.result;
|
|
2782
2941
|
}
|
|
2783
2942
|
return null;
|
|
@@ -2880,6 +3039,7 @@ ${lastSnapshot}`;
|
|
|
2880
3039
|
this.cliScripts = scripts;
|
|
2881
3040
|
this.parsedStatusCache = null;
|
|
2882
3041
|
this.parseErrorMessage = null;
|
|
3042
|
+
this.scriptState = typeof scripts.createState === "function" ? scripts.createState() : null;
|
|
2883
3043
|
const scriptNames = listCliScriptNames(scripts);
|
|
2884
3044
|
LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
2885
3045
|
}
|
|
@@ -2997,6 +3157,7 @@ ${lastSnapshot}`;
|
|
|
2997
3157
|
this.ready = false;
|
|
2998
3158
|
this.startupParseGate = false;
|
|
2999
3159
|
this.spawnAt = 0;
|
|
3160
|
+
this.scriptState = null;
|
|
3000
3161
|
this.onStatusChange?.();
|
|
3001
3162
|
});
|
|
3002
3163
|
this.spawnAt = Date.now();
|
|
@@ -3750,6 +3911,11 @@ ${lastSnapshot}`;
|
|
|
3750
3911
|
};
|
|
3751
3912
|
}
|
|
3752
3913
|
// ─── Script Execution ──────────────────────────
|
|
3914
|
+
invokeCliScript(script, input) {
|
|
3915
|
+
const hasStateFactory = typeof this.cliScripts?.createState === "function";
|
|
3916
|
+
const expectsStateArgument = hasStateFactory || this.scriptState !== null || script.length >= 2;
|
|
3917
|
+
return expectsStateArgument ? script(this.scriptState, input) : script(input);
|
|
3918
|
+
}
|
|
3753
3919
|
runParseSession() {
|
|
3754
3920
|
if (typeof this.cliScripts?.parseSession !== "function") {
|
|
3755
3921
|
this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
|
|
@@ -3770,7 +3936,10 @@ ${lastSnapshot}`;
|
|
|
3770
3936
|
scope: this.currentTurnScope,
|
|
3771
3937
|
runtimeSettings: this.runtimeSettings
|
|
3772
3938
|
});
|
|
3773
|
-
const session = this.
|
|
3939
|
+
const session = this.invokeCliScript(
|
|
3940
|
+
this.cliScripts.parseSession,
|
|
3941
|
+
{ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) }
|
|
3942
|
+
);
|
|
3774
3943
|
this.parseErrorMessage = null;
|
|
3775
3944
|
return session && typeof session === "object" ? session : null;
|
|
3776
3945
|
} catch (e) {
|
|
@@ -3784,7 +3953,7 @@ ${lastSnapshot}`;
|
|
|
3784
3953
|
if (!this.cliScripts?.detectStatus) return null;
|
|
3785
3954
|
try {
|
|
3786
3955
|
const screenText = this.terminalScreen.getText();
|
|
3787
|
-
const status = this.cliScripts.detectStatus
|
|
3956
|
+
const status = this.invokeCliScript(this.cliScripts.detectStatus, {
|
|
3788
3957
|
tail: text.slice(-500),
|
|
3789
3958
|
screenText,
|
|
3790
3959
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -3803,7 +3972,7 @@ ${lastSnapshot}`;
|
|
|
3803
3972
|
try {
|
|
3804
3973
|
const screenText = this.terminalScreen.getText();
|
|
3805
3974
|
const buffer = screenText || this.accumulatedBuffer;
|
|
3806
|
-
return this.cliScripts.parseApproval
|
|
3975
|
+
return this.invokeCliScript(this.cliScripts.parseApproval, {
|
|
3807
3976
|
buffer,
|
|
3808
3977
|
screenText,
|
|
3809
3978
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -3859,7 +4028,8 @@ ${lastSnapshot}`;
|
|
|
3859
4028
|
const screenText = this.readTerminalScreenText();
|
|
3860
4029
|
const parseScreenText = this.getParseScreenText(screenText);
|
|
3861
4030
|
const cached = this.parsedStatusCache;
|
|
3862
|
-
|
|
4031
|
+
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
4032
|
+
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBufferKey === accumulatedRawBufferKey && cached.screenText === parseScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
3863
4033
|
return cached.result;
|
|
3864
4034
|
}
|
|
3865
4035
|
const parsed = this.runParseSession();
|
|
@@ -3887,6 +4057,7 @@ ${lastSnapshot}`;
|
|
|
3887
4057
|
currentTurnScope: this.currentTurnScope,
|
|
3888
4058
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
3889
4059
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
4060
|
+
accumulatedRawBufferKey,
|
|
3890
4061
|
screenText: parseScreenText,
|
|
3891
4062
|
currentStatus: this.currentStatus,
|
|
3892
4063
|
activeModal: this.activeModal,
|
|
@@ -3911,7 +4082,7 @@ ${lastSnapshot}`;
|
|
|
3911
4082
|
scope: this.currentTurnScope,
|
|
3912
4083
|
runtimeSettings: this.runtimeSettings
|
|
3913
4084
|
});
|
|
3914
|
-
return await Promise.resolve(fn({
|
|
4085
|
+
return await Promise.resolve(fn(this.scriptState, {
|
|
3915
4086
|
...input,
|
|
3916
4087
|
args: args && typeof args === "object" ? { ...args } : {}
|
|
3917
4088
|
}));
|
|
@@ -4722,6 +4893,7 @@ __export(index_exports, {
|
|
|
4722
4893
|
buildThoughtChatMessage: () => buildThoughtChatMessage,
|
|
4723
4894
|
buildToolChatMessage: () => buildToolChatMessage,
|
|
4724
4895
|
buildUserChatMessage: () => buildUserChatMessage,
|
|
4896
|
+
cancelTask: () => cancelTask,
|
|
4725
4897
|
claimNextTask: () => claimNextTask,
|
|
4726
4898
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
4727
4899
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
|
|
@@ -4765,6 +4937,7 @@ __export(index_exports, {
|
|
|
4765
4937
|
getLogLevel: () => getLogLevel,
|
|
4766
4938
|
getMesh: () => getMesh,
|
|
4767
4939
|
getMeshByRepo: () => getMeshByRepo,
|
|
4940
|
+
getMeshQueueStats: () => getMeshQueueStats,
|
|
4768
4941
|
getNpmExecOptions: () => getNpmExecOptions,
|
|
4769
4942
|
getQueue: () => getQueue,
|
|
4770
4943
|
getRecentActivity: () => getRecentActivity,
|
|
@@ -4833,6 +5006,7 @@ __export(index_exports, {
|
|
|
4833
5006
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
4834
5007
|
removeNode: () => removeNode,
|
|
4835
5008
|
removeWorktree: () => removeWorktree,
|
|
5009
|
+
requeueTask: () => requeueTask,
|
|
4836
5010
|
resetConfig: () => resetConfig,
|
|
4837
5011
|
resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
|
|
4838
5012
|
resetState: () => resetState,
|
|
@@ -15205,11 +15379,13 @@ async function handleOpenPanel(h, args) {
|
|
|
15205
15379
|
async function handlePtyInput(h, args) {
|
|
15206
15380
|
const { cliType, data, targetSessionId } = args || {};
|
|
15207
15381
|
if (!data) return { success: false, error: "data required" };
|
|
15382
|
+
const cleanData = typeof data === "string" ? data.replace(/\x1b\[[?>][0-9;]*c/g, "") : data;
|
|
15383
|
+
if (!cleanData) return { success: true };
|
|
15208
15384
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
15209
15385
|
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
15210
15386
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
15211
15387
|
}
|
|
15212
|
-
await adapter.writeRaw(
|
|
15388
|
+
await adapter.writeRaw(cleanData);
|
|
15213
15389
|
return { success: true };
|
|
15214
15390
|
}
|
|
15215
15391
|
function handlePtyResize(_h, args) {
|
|
@@ -16839,6 +17015,8 @@ var CliProviderInstance = class {
|
|
|
16839
17015
|
this.completedDebounceTimer = null;
|
|
16840
17016
|
}, 3e3);
|
|
16841
17017
|
}
|
|
17018
|
+
} else if (newStatus === "idle" && this.lastStatus === "starting") {
|
|
17019
|
+
this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });
|
|
16842
17020
|
} else if (newStatus === "stopped") {
|
|
16843
17021
|
if (this.generatingDebounceTimer) {
|
|
16844
17022
|
clearTimeout(this.generatingDebounceTimer);
|
|
@@ -18582,9 +18760,6 @@ function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
|
18582
18760
|
const cliType = String(input.cliType || "").trim();
|
|
18583
18761
|
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
18584
18762
|
const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
|
|
18585
|
-
if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
|
|
18586
|
-
cliArgs.unshift("--ignore-user-config");
|
|
18587
|
-
}
|
|
18588
18763
|
if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
|
|
18589
18764
|
cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
18590
18765
|
}
|
|
@@ -21830,7 +22005,9 @@ function resolveHermesMeshCoordinatorSetup(options) {
|
|
|
21830
22005
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
21831
22006
|
meshId: options.meshId,
|
|
21832
22007
|
nodeExecutable: options.nodeExecutable,
|
|
21833
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
22008
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
22009
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
22010
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
21834
22011
|
});
|
|
21835
22012
|
if (!mcpServer) {
|
|
21836
22013
|
return {
|
|
@@ -21897,7 +22074,9 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21897
22074
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
21898
22075
|
meshId,
|
|
21899
22076
|
nodeExecutable: options.nodeExecutable,
|
|
21900
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
22077
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
22078
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
22079
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
21901
22080
|
});
|
|
21902
22081
|
if (!mcpServer) {
|
|
21903
22082
|
return {
|
|
@@ -21919,6 +22098,22 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21919
22098
|
if (!instructions || !template?.trim()) {
|
|
21920
22099
|
return { kind: "unsupported", reason: "Provider manual MCP setup is missing instructions or template" };
|
|
21921
22100
|
}
|
|
22101
|
+
const renderedTemplate = renderMeshCoordinatorTemplate(template, {
|
|
22102
|
+
meshId,
|
|
22103
|
+
workspace,
|
|
22104
|
+
serverName,
|
|
22105
|
+
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
22106
|
+
});
|
|
22107
|
+
const isCliCommand = !renderedTemplate.trim().includes("\n") && !renderedTemplate.trim().startsWith("{");
|
|
22108
|
+
if (isCliCommand) {
|
|
22109
|
+
return {
|
|
22110
|
+
kind: "cli_command",
|
|
22111
|
+
serverName,
|
|
22112
|
+
command: renderedTemplate.trim(),
|
|
22113
|
+
requiresRestart: mcpConfig.requiresRestart === true,
|
|
22114
|
+
instructions
|
|
22115
|
+
};
|
|
22116
|
+
}
|
|
21922
22117
|
return {
|
|
21923
22118
|
kind: "manual",
|
|
21924
22119
|
serverName,
|
|
@@ -21926,12 +22121,7 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21926
22121
|
configPathCommand: mcpConfig.configPathCommand,
|
|
21927
22122
|
requiresRestart: mcpConfig.requiresRestart === true,
|
|
21928
22123
|
instructions,
|
|
21929
|
-
template:
|
|
21930
|
-
meshId,
|
|
21931
|
-
workspace,
|
|
21932
|
-
serverName,
|
|
21933
|
-
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
21934
|
-
})
|
|
22124
|
+
template: renderedTemplate
|
|
21935
22125
|
};
|
|
21936
22126
|
}
|
|
21937
22127
|
return {
|
|
@@ -21960,11 +22150,27 @@ function resolveAdhdevMcpServerLaunch(options) {
|
|
|
21960
22150
|
if (!entryPath) return null;
|
|
21961
22151
|
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
|
|
21962
22152
|
if (!nodeExecutable) return null;
|
|
22153
|
+
const transport = resolveMcpTransport(options.adhdevMcpTransport);
|
|
22154
|
+
const args = [entryPath, "--mode", transport, "--repo-mesh", options.meshId];
|
|
22155
|
+
const port = resolveMcpPort(options.adhdevMcpPort);
|
|
22156
|
+
if (port !== void 0) args.push("--port", String(port));
|
|
21963
22157
|
return {
|
|
21964
22158
|
command: nodeExecutable,
|
|
21965
|
-
args
|
|
22159
|
+
args
|
|
21966
22160
|
};
|
|
21967
22161
|
}
|
|
22162
|
+
function resolveMcpTransport(explicitTransport) {
|
|
22163
|
+
if (explicitTransport === "local" || explicitTransport === "ipc") return explicitTransport;
|
|
22164
|
+
const envTransport = process.env.ADHDEV_COORDINATOR_MCP_TRANSPORT?.trim();
|
|
22165
|
+
return envTransport === "local" ? "local" : "ipc";
|
|
22166
|
+
}
|
|
22167
|
+
function resolveMcpPort(explicitPort) {
|
|
22168
|
+
if (typeof explicitPort === "number" && Number.isInteger(explicitPort) && explicitPort > 0) return explicitPort;
|
|
22169
|
+
const raw = process.env.ADHDEV_COORDINATOR_MCP_PORT?.trim();
|
|
22170
|
+
if (!raw) return void 0;
|
|
22171
|
+
const parsed = Number(raw);
|
|
22172
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
22173
|
+
}
|
|
21968
22174
|
function resolveMcpNodeExecutable(explicitExecutable) {
|
|
21969
22175
|
const explicit = explicitExecutable?.trim();
|
|
21970
22176
|
if (explicit) return explicit;
|
|
@@ -22805,6 +23011,34 @@ function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
|
22805
23011
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
22806
23012
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
22807
23013
|
}
|
|
23014
|
+
function stripHermesCoordinatorTempModelProviderOverrides(config) {
|
|
23015
|
+
const {
|
|
23016
|
+
model: _model,
|
|
23017
|
+
provider: _provider,
|
|
23018
|
+
default_model: _defaultModel,
|
|
23019
|
+
defaultProvider: _defaultProvider,
|
|
23020
|
+
default_provider: _defaultProviderSnake,
|
|
23021
|
+
modelProvider: _modelProvider,
|
|
23022
|
+
model_provider: _modelProviderSnake,
|
|
23023
|
+
...sanitized
|
|
23024
|
+
} = config;
|
|
23025
|
+
const delegation = sanitized.delegation;
|
|
23026
|
+
if (delegation && typeof delegation === "object" && !Array.isArray(delegation)) {
|
|
23027
|
+
const {
|
|
23028
|
+
model: _delegationModel,
|
|
23029
|
+
provider: _delegationProvider,
|
|
23030
|
+
modelProvider: _delegationModelProvider,
|
|
23031
|
+
model_provider: _delegationModelProviderSnake,
|
|
23032
|
+
...delegationRest
|
|
23033
|
+
} = delegation;
|
|
23034
|
+
if (Object.keys(delegationRest).length > 0) {
|
|
23035
|
+
sanitized.delegation = delegationRest;
|
|
23036
|
+
} else {
|
|
23037
|
+
delete sanitized.delegation;
|
|
23038
|
+
}
|
|
23039
|
+
}
|
|
23040
|
+
return sanitized;
|
|
23041
|
+
}
|
|
22808
23042
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
22809
23043
|
if ((0, import_path6.resolve)(sourceHome) === (0, import_path6.resolve)(targetHome)) return;
|
|
22810
23044
|
for (const fileName of [".env", "auth.json"]) {
|
|
@@ -23785,6 +24019,51 @@ var DaemonCommandRouter = class {
|
|
|
23785
24019
|
return { success: false, error: e.message };
|
|
23786
24020
|
}
|
|
23787
24021
|
}
|
|
24022
|
+
case "get_mesh_queue": {
|
|
24023
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
24024
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
24025
|
+
try {
|
|
24026
|
+
const { getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
24027
|
+
const status = Array.isArray(args?.status) ? args.status.map((s) => typeof s === "string" ? s.trim() : "").filter(Boolean) : void 0;
|
|
24028
|
+
const queue = getQueue2(meshId, { status });
|
|
24029
|
+
return { success: true, queue };
|
|
24030
|
+
} catch (e) {
|
|
24031
|
+
return { success: false, error: e.message };
|
|
24032
|
+
}
|
|
24033
|
+
}
|
|
24034
|
+
case "cancel_mesh_queue_task": {
|
|
24035
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
24036
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
24037
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
24038
|
+
try {
|
|
24039
|
+
const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
24040
|
+
const reason = typeof args?.reason === "string" ? args.reason : void 0;
|
|
24041
|
+
const task = cancelTask2(meshId, taskId, { reason });
|
|
24042
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
24043
|
+
return { success: true, task };
|
|
24044
|
+
} catch (e) {
|
|
24045
|
+
return { success: false, error: e.message };
|
|
24046
|
+
}
|
|
24047
|
+
}
|
|
24048
|
+
case "requeue_mesh_queue_task": {
|
|
24049
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
24050
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
24051
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
24052
|
+
try {
|
|
24053
|
+
const { requeueTask: requeueTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
24054
|
+
const task = requeueTask2(meshId, taskId, {
|
|
24055
|
+
reason: typeof args?.reason === "string" ? args.reason : void 0,
|
|
24056
|
+
targetNodeId: typeof args?.targetNodeId === "string" ? args.targetNodeId.trim() : void 0,
|
|
24057
|
+
targetSessionId: typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : void 0,
|
|
24058
|
+
clearTargetNode: args?.clearTargetNode === true,
|
|
24059
|
+
clearTargetSession: args?.clearTargetSession !== false
|
|
24060
|
+
});
|
|
24061
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
24062
|
+
return { success: true, task };
|
|
24063
|
+
} catch (e) {
|
|
24064
|
+
return { success: false, error: e.message };
|
|
24065
|
+
}
|
|
24066
|
+
}
|
|
23788
24067
|
case "add_mesh_node": {
|
|
23789
24068
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23790
24069
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -23942,7 +24221,13 @@ var DaemonCommandRouter = class {
|
|
|
23942
24221
|
appendLedgerEntry2(meshId, {
|
|
23943
24222
|
kind: "node_removed",
|
|
23944
24223
|
nodeId,
|
|
23945
|
-
payload: {
|
|
24224
|
+
payload: {
|
|
24225
|
+
worktree: !!node?.isLocalWorktree,
|
|
24226
|
+
sessionCleanupMode,
|
|
24227
|
+
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
24228
|
+
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
24229
|
+
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0
|
|
24230
|
+
}
|
|
23946
24231
|
});
|
|
23947
24232
|
} catch {
|
|
23948
24233
|
}
|
|
@@ -24113,6 +24398,93 @@ var DaemonCommandRouter = class {
|
|
|
24113
24398
|
meshCoordinatorSetup: coordinatorSetup
|
|
24114
24399
|
};
|
|
24115
24400
|
}
|
|
24401
|
+
if (coordinatorSetup.kind === "cli_command") {
|
|
24402
|
+
let cliCmdSystemPrompt = "";
|
|
24403
|
+
try {
|
|
24404
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
24405
|
+
} catch (error) {
|
|
24406
|
+
const message = error?.message || String(error);
|
|
24407
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
24408
|
+
return {
|
|
24409
|
+
success: false,
|
|
24410
|
+
code: "mesh_coordinator_prompt_failed",
|
|
24411
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
24412
|
+
meshId,
|
|
24413
|
+
cliType,
|
|
24414
|
+
workspace
|
|
24415
|
+
};
|
|
24416
|
+
}
|
|
24417
|
+
try {
|
|
24418
|
+
const { execFileSync: execCmdSync } = await import("child_process");
|
|
24419
|
+
const cmdParts = coordinatorSetup.command.trim().split(/\s+/);
|
|
24420
|
+
const [regCmd, ...regArgs] = cmdParts;
|
|
24421
|
+
LOG.info("MeshCoordinator", `Running MCP registration: ${coordinatorSetup.command}`);
|
|
24422
|
+
execCmdSync(regCmd, regArgs, { stdio: "pipe", timeout: 15e3 });
|
|
24423
|
+
} catch (error) {
|
|
24424
|
+
LOG.warn("MeshCoordinator", `MCP registration command failed (may be pre-registered): ${error?.message || error}`);
|
|
24425
|
+
}
|
|
24426
|
+
const cliCmdArgs = [];
|
|
24427
|
+
const cliCmdEnv = {};
|
|
24428
|
+
if (cliCmdSystemPrompt) {
|
|
24429
|
+
if (cliType === "codex-cli") {
|
|
24430
|
+
cliCmdArgs.push("-c", `developer_instructions=${JSON.stringify(cliCmdSystemPrompt)}`);
|
|
24431
|
+
} else if (cliType === "gemini-cli") {
|
|
24432
|
+
try {
|
|
24433
|
+
const { writeFileSync: wfs, existsSync: efs, readFileSync: rfs } = await import("fs");
|
|
24434
|
+
const geminiMdPath = `${workspace}/GEMINI.md`;
|
|
24435
|
+
const marker = "<!-- adhdev-mesh-coordinator-prompt -->";
|
|
24436
|
+
const markerEnd = "<!-- /adhdev-mesh-coordinator-prompt -->";
|
|
24437
|
+
const block = `${marker}
|
|
24438
|
+
${cliCmdSystemPrompt}
|
|
24439
|
+
${markerEnd}`;
|
|
24440
|
+
if (efs(geminiMdPath)) {
|
|
24441
|
+
const existing = rfs(geminiMdPath, "utf-8");
|
|
24442
|
+
const replaced = existing.replace(
|
|
24443
|
+
new RegExp(`${marker}[\\s\\S]*?${markerEnd}`, "g"),
|
|
24444
|
+
block
|
|
24445
|
+
);
|
|
24446
|
+
wfs(geminiMdPath, replaced.includes(marker) ? replaced : `${existing}
|
|
24447
|
+
|
|
24448
|
+
${block}`);
|
|
24449
|
+
} else {
|
|
24450
|
+
wfs(geminiMdPath, block);
|
|
24451
|
+
}
|
|
24452
|
+
LOG.info("MeshCoordinator", `Wrote coordinator prompt to ${workspace}/GEMINI.md`);
|
|
24453
|
+
} catch (e) {
|
|
24454
|
+
LOG.warn("MeshCoordinator", `Could not write GEMINI.md: ${e?.message || e}`);
|
|
24455
|
+
}
|
|
24456
|
+
}
|
|
24457
|
+
}
|
|
24458
|
+
const cliCmdLaunch = await this.deps.cliManager.handleCliCommand("launch_cli", {
|
|
24459
|
+
cliType,
|
|
24460
|
+
dir: workspace,
|
|
24461
|
+
cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
|
|
24462
|
+
env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
|
|
24463
|
+
settings: { meshCoordinatorFor: meshId }
|
|
24464
|
+
});
|
|
24465
|
+
if (!cliCmdLaunch?.success) {
|
|
24466
|
+
return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
|
|
24467
|
+
}
|
|
24468
|
+
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
|
|
24469
|
+
try {
|
|
24470
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
24471
|
+
appendLedgerEntry2(meshId, {
|
|
24472
|
+
kind: "coordinator_started",
|
|
24473
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
24474
|
+
providerType: cliType,
|
|
24475
|
+
payload: { workspace }
|
|
24476
|
+
});
|
|
24477
|
+
} catch {
|
|
24478
|
+
}
|
|
24479
|
+
return {
|
|
24480
|
+
success: true,
|
|
24481
|
+
meshId,
|
|
24482
|
+
cliType,
|
|
24483
|
+
workspace,
|
|
24484
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
24485
|
+
mcpRegistered: true
|
|
24486
|
+
};
|
|
24487
|
+
}
|
|
24116
24488
|
const configFormat = coordinatorSetup.configFormat;
|
|
24117
24489
|
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
24118
24490
|
return {
|
|
@@ -24167,9 +24539,11 @@ var DaemonCommandRouter = class {
|
|
|
24167
24539
|
args: coordinatorSetup.mcpServer.args
|
|
24168
24540
|
};
|
|
24169
24541
|
if (args?.inlineMesh) {
|
|
24542
|
+
const modeArgIndex = coordinatorSetup.mcpServer.args.findIndex((value) => value === "--mode");
|
|
24543
|
+
const mcpTransport = modeArgIndex >= 0 ? coordinatorSetup.mcpServer.args[modeArgIndex + 1] : "ipc";
|
|
24170
24544
|
mcpServerEntry.env = {
|
|
24171
24545
|
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
24172
|
-
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
24546
|
+
ADHDEV_MCP_TRANSPORT: mcpTransport === "local" ? "local" : "ipc"
|
|
24173
24547
|
};
|
|
24174
24548
|
}
|
|
24175
24549
|
try {
|
|
@@ -24188,7 +24562,8 @@ var DaemonCommandRouter = class {
|
|
|
24188
24562
|
if (hadExistingMcpConfig) {
|
|
24189
24563
|
try {
|
|
24190
24564
|
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
|
|
24191
|
-
|
|
24565
|
+
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
24566
|
+
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
24192
24567
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
24193
24568
|
} catch (error) {
|
|
24194
24569
|
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
@@ -32211,7 +32586,8 @@ async function initDaemonComponents(config) {
|
|
|
32211
32586
|
cdpManagers,
|
|
32212
32587
|
sessionRegistry,
|
|
32213
32588
|
detectedIdes: detectedIdesRef,
|
|
32214
|
-
refreshProviderAvailability
|
|
32589
|
+
refreshProviderAvailability,
|
|
32590
|
+
dispatchMeshCommand: config.dispatchMeshCommand
|
|
32215
32591
|
};
|
|
32216
32592
|
setupMeshEventForwarding(components);
|
|
32217
32593
|
return components;
|
|
@@ -32343,6 +32719,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
32343
32719
|
buildThoughtChatMessage,
|
|
32344
32720
|
buildToolChatMessage,
|
|
32345
32721
|
buildUserChatMessage,
|
|
32722
|
+
cancelTask,
|
|
32346
32723
|
claimNextTask,
|
|
32347
32724
|
classifyChatMessageVisibility,
|
|
32348
32725
|
classifyHotChatSessionsForSubscriptionFlush,
|
|
@@ -32386,6 +32763,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
32386
32763
|
getLogLevel,
|
|
32387
32764
|
getMesh,
|
|
32388
32765
|
getMeshByRepo,
|
|
32766
|
+
getMeshQueueStats,
|
|
32389
32767
|
getNpmExecOptions,
|
|
32390
32768
|
getQueue,
|
|
32391
32769
|
getRecentActivity,
|
|
@@ -32454,6 +32832,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
32454
32832
|
registerExtensionProviders,
|
|
32455
32833
|
removeNode,
|
|
32456
32834
|
removeWorktree,
|
|
32835
|
+
requeueTask,
|
|
32457
32836
|
resetConfig,
|
|
32458
32837
|
resetDebugRuntimeConfig,
|
|
32459
32838
|
resetState,
|