@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.mjs
CHANGED
|
@@ -973,6 +973,17 @@ var init_mesh_ledger = __esm({
|
|
|
973
973
|
});
|
|
974
974
|
|
|
975
975
|
// src/mesh/mesh-work-queue.ts
|
|
976
|
+
var mesh_work_queue_exports = {};
|
|
977
|
+
__export(mesh_work_queue_exports, {
|
|
978
|
+
cancelTask: () => cancelTask,
|
|
979
|
+
claimNextTask: () => claimNextTask,
|
|
980
|
+
enqueueTask: () => enqueueTask,
|
|
981
|
+
getMeshQueueStats: () => getMeshQueueStats,
|
|
982
|
+
getQueue: () => getQueue,
|
|
983
|
+
requeueTask: () => requeueTask,
|
|
984
|
+
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
985
|
+
updateTaskStatus: () => updateTaskStatus
|
|
986
|
+
});
|
|
976
987
|
import { existsSync as existsSync6, writeFileSync as writeFileSync3, readFileSync as readFileSync4 } from "fs";
|
|
977
988
|
import { join as join6 } from "path";
|
|
978
989
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -1002,6 +1013,7 @@ function enqueueTask(meshId, message, opts) {
|
|
|
1002
1013
|
message,
|
|
1003
1014
|
status: "pending",
|
|
1004
1015
|
targetNodeId: opts?.targetNodeId,
|
|
1016
|
+
targetSessionId: opts?.targetSessionId,
|
|
1005
1017
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1006
1018
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1007
1019
|
};
|
|
@@ -1019,9 +1031,14 @@ function getQueue(meshId, opts) {
|
|
|
1019
1031
|
}
|
|
1020
1032
|
function claimNextTask(meshId, nodeId, sessionId) {
|
|
1021
1033
|
const queue = readQueue(meshId);
|
|
1022
|
-
|
|
1034
|
+
const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
|
|
1035
|
+
if (hasActiveAssignment) return null;
|
|
1036
|
+
let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
|
|
1037
|
+
if (targetIdx === -1) {
|
|
1038
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
|
|
1039
|
+
}
|
|
1023
1040
|
if (targetIdx === -1) {
|
|
1024
|
-
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId);
|
|
1041
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
|
|
1025
1042
|
}
|
|
1026
1043
|
if (targetIdx === -1) return null;
|
|
1027
1044
|
const entry = queue[targetIdx];
|
|
@@ -1041,6 +1058,40 @@ function updateTaskStatus(meshId, taskId, status) {
|
|
|
1041
1058
|
writeQueue(meshId, queue);
|
|
1042
1059
|
return queue[idx];
|
|
1043
1060
|
}
|
|
1061
|
+
function cancelTask(meshId, taskId, opts) {
|
|
1062
|
+
const queue = readQueue(meshId);
|
|
1063
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1064
|
+
if (idx === -1) return null;
|
|
1065
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1066
|
+
queue[idx].status = "cancelled";
|
|
1067
|
+
queue[idx].updatedAt = now;
|
|
1068
|
+
queue[idx].cancelledAt = now;
|
|
1069
|
+
if (opts?.reason) queue[idx].cancelReason = opts.reason;
|
|
1070
|
+
writeQueue(meshId, queue);
|
|
1071
|
+
return queue[idx];
|
|
1072
|
+
}
|
|
1073
|
+
function requeueTask(meshId, taskId, opts) {
|
|
1074
|
+
const queue = readQueue(meshId);
|
|
1075
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1076
|
+
if (idx === -1) return null;
|
|
1077
|
+
const entry = queue[idx];
|
|
1078
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1079
|
+
entry.status = "pending";
|
|
1080
|
+
delete entry.assignedNodeId;
|
|
1081
|
+
delete entry.assignedSessionId;
|
|
1082
|
+
delete entry.cancelledAt;
|
|
1083
|
+
delete entry.cancelReason;
|
|
1084
|
+
if (opts?.clearTargetNode) delete entry.targetNodeId;
|
|
1085
|
+
if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
|
|
1086
|
+
if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
|
|
1087
|
+
if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
|
|
1088
|
+
entry.updatedAt = now;
|
|
1089
|
+
entry.requeuedAt = now;
|
|
1090
|
+
entry.requeueCount = (entry.requeueCount || 0) + 1;
|
|
1091
|
+
if (opts?.reason) entry.requeueReason = opts.reason;
|
|
1092
|
+
writeQueue(meshId, queue);
|
|
1093
|
+
return entry;
|
|
1094
|
+
}
|
|
1044
1095
|
function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
1045
1096
|
const queue = readQueue(meshId);
|
|
1046
1097
|
for (let i = queue.length - 1; i >= 0; i--) {
|
|
@@ -1059,7 +1110,14 @@ function getMeshQueueStats(meshId) {
|
|
|
1059
1110
|
pending: queue.filter((q) => q.status === "pending").length,
|
|
1060
1111
|
assigned: queue.filter((q) => q.status === "assigned").length,
|
|
1061
1112
|
completed: queue.filter((q) => q.status === "completed").length,
|
|
1062
|
-
failed: queue.filter((q) => q.status === "failed").length
|
|
1113
|
+
failed: queue.filter((q) => q.status === "failed").length,
|
|
1114
|
+
cancelled: queue.filter((q) => q.status === "cancelled").length,
|
|
1115
|
+
activeAssignments: queue.filter((q) => q.status === "assigned").map((q) => ({
|
|
1116
|
+
id: q.id,
|
|
1117
|
+
nodeId: q.assignedNodeId,
|
|
1118
|
+
sessionId: q.assignedSessionId,
|
|
1119
|
+
message: q.message
|
|
1120
|
+
}))
|
|
1063
1121
|
};
|
|
1064
1122
|
}
|
|
1065
1123
|
var init_mesh_work_queue = __esm({
|
|
@@ -1298,6 +1356,9 @@ function drainPendingMeshCoordinatorEvents() {
|
|
|
1298
1356
|
function readNonEmptyString(value) {
|
|
1299
1357
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
1300
1358
|
}
|
|
1359
|
+
function resolveEventSessionId(event, fallback) {
|
|
1360
|
+
return readNonEmptyString(event.targetSessionId) || readNonEmptyString(event.sessionId) || readNonEmptyString(event.instanceId) || readNonEmptyString(fallback);
|
|
1361
|
+
}
|
|
1301
1362
|
function isMeshCoordinatorEvent(eventName) {
|
|
1302
1363
|
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
1303
1364
|
}
|
|
@@ -1309,38 +1370,74 @@ function formatCompletionMetadata(event) {
|
|
|
1309
1370
|
].filter(Boolean);
|
|
1310
1371
|
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
1311
1372
|
}
|
|
1373
|
+
function getMeshWithCache(components, meshId) {
|
|
1374
|
+
const localMesh = getMesh(meshId);
|
|
1375
|
+
if (localMesh) return localMesh;
|
|
1376
|
+
return components.router?.getCachedInlineMesh(meshId);
|
|
1377
|
+
}
|
|
1312
1378
|
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
1313
1379
|
const task = claimNextTask(meshId, nodeId, sessionId);
|
|
1314
|
-
if (!task)
|
|
1380
|
+
if (!task) {
|
|
1381
|
+
return false;
|
|
1382
|
+
}
|
|
1315
1383
|
LOG.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
|
|
1384
|
+
const mesh = getMeshWithCache(components, meshId);
|
|
1385
|
+
const node = mesh?.nodes.find((n) => n.id === nodeId);
|
|
1386
|
+
if (node?.daemonId && components.dispatchMeshCommand) {
|
|
1387
|
+
const isLocalNode = components.cliManager.adapters.has(sessionId);
|
|
1388
|
+
if (!isLocalNode) {
|
|
1389
|
+
components.dispatchMeshCommand(node.daemonId, "agent_command", {
|
|
1390
|
+
targetSessionId: sessionId,
|
|
1391
|
+
cliType: providerType,
|
|
1392
|
+
action: "send_chat",
|
|
1393
|
+
message: task.message
|
|
1394
|
+
}).catch((e) => {
|
|
1395
|
+
LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
|
|
1396
|
+
updateTaskStatus(meshId, task.id, "failed");
|
|
1397
|
+
});
|
|
1398
|
+
return true;
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1316
1401
|
components.cliManager.handleCliCommand("agent_command", {
|
|
1317
1402
|
targetSessionId: sessionId,
|
|
1318
1403
|
cliType: providerType,
|
|
1319
1404
|
action: "send_chat",
|
|
1320
|
-
|
|
1405
|
+
message: task.message
|
|
1321
1406
|
}).catch((e) => {
|
|
1322
|
-
LOG.error("MeshQueue", `Failed to dispatch task to node ${nodeId}: ${e?.message}`);
|
|
1407
|
+
LOG.error("MeshQueue", `Failed to dispatch task locally to node ${nodeId}: ${e?.message}`);
|
|
1408
|
+
updateTaskStatus(meshId, task.id, "failed");
|
|
1323
1409
|
});
|
|
1324
1410
|
return true;
|
|
1325
1411
|
}
|
|
1326
1412
|
function triggerMeshQueue(components, meshId) {
|
|
1327
|
-
const mesh =
|
|
1413
|
+
const mesh = getMeshWithCache(components, meshId);
|
|
1328
1414
|
if (!mesh) return;
|
|
1329
1415
|
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
1330
1416
|
for (const inst of cliInstances) {
|
|
1331
1417
|
const state = inst.getState();
|
|
1332
1418
|
const settings = state.settings || {};
|
|
1333
1419
|
const instMeshId = readNonEmptyString(settings.meshNodeFor);
|
|
1334
|
-
if (instMeshId !== meshId
|
|
1420
|
+
if (instMeshId !== meshId) continue;
|
|
1335
1421
|
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
1336
1422
|
if (!nodeId) continue;
|
|
1337
|
-
|
|
1423
|
+
const status = readNonEmptyString(state.status).toLowerCase();
|
|
1424
|
+
if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
|
|
1425
|
+
if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
|
|
1338
1426
|
const sessionId = state.instanceId;
|
|
1339
1427
|
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
1340
1428
|
if (providerType) {
|
|
1341
1429
|
tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
|
|
1342
1430
|
}
|
|
1343
1431
|
}
|
|
1432
|
+
for (const [key, idle] of remoteIdleSessions.entries()) {
|
|
1433
|
+
const node = mesh.nodes.find((n) => n.id === idle.nodeId);
|
|
1434
|
+
if (node) {
|
|
1435
|
+
const assigned = tryAssignQueueTask(components, meshId, idle.nodeId, idle.sessionId, idle.providerType);
|
|
1436
|
+
if (assigned) {
|
|
1437
|
+
remoteIdleSessions.delete(key);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1344
1441
|
}
|
|
1345
1442
|
function buildMeshSystemMessage(args) {
|
|
1346
1443
|
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
@@ -1387,20 +1484,67 @@ Do NOT retry on this node. Consider reassigning to a different node or asking th
|
|
|
1387
1484
|
return "";
|
|
1388
1485
|
}
|
|
1389
1486
|
function injectMeshSystemMessage(components, args) {
|
|
1487
|
+
let completedTaskForLedger = null;
|
|
1390
1488
|
if (args.event === "agent:generating_completed") {
|
|
1391
|
-
const sessionId =
|
|
1392
|
-
const nodeId = readNonEmptyString(args.
|
|
1489
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
1490
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
1393
1491
|
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
1394
1492
|
if (sessionId) {
|
|
1395
|
-
updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
1493
|
+
const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
1494
|
+
completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
|
|
1396
1495
|
if (nodeId && providerType) {
|
|
1397
1496
|
setTimeout(() => {
|
|
1398
1497
|
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
1399
1498
|
}, 500);
|
|
1400
1499
|
}
|
|
1401
1500
|
}
|
|
1501
|
+
} else if (args.event === "agent:ready") {
|
|
1502
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
1503
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
1504
|
+
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
1505
|
+
const completedTask = sessionId ? updateSessionTaskStatus(args.meshId, sessionId, "completed") : null;
|
|
1506
|
+
if (completedTask) {
|
|
1507
|
+
completedTaskForLedger = { id: completedTask.id };
|
|
1508
|
+
try {
|
|
1509
|
+
appendLedgerEntry(args.meshId, {
|
|
1510
|
+
kind: "task_completed",
|
|
1511
|
+
nodeId: nodeId || void 0,
|
|
1512
|
+
sessionId,
|
|
1513
|
+
providerType: providerType || void 0,
|
|
1514
|
+
payload: {
|
|
1515
|
+
event: args.event,
|
|
1516
|
+
nodeLabel: args.nodeLabel,
|
|
1517
|
+
taskId: completedTask.id,
|
|
1518
|
+
completedViaReady: true,
|
|
1519
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
|
|
1520
|
+
finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
|
|
1521
|
+
}
|
|
1522
|
+
});
|
|
1523
|
+
} catch (e) {
|
|
1524
|
+
LOG.warn("MeshLedger", `Failed to record task_completed from ready: ${e?.message || e}`);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
if (sessionId && nodeId && providerType) {
|
|
1528
|
+
remoteIdleSessions.set(`${nodeId}:${sessionId}`, { nodeId, sessionId, providerType });
|
|
1529
|
+
setTimeout(() => {
|
|
1530
|
+
const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
1531
|
+
if (assigned) {
|
|
1532
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
1533
|
+
}
|
|
1534
|
+
}, 500);
|
|
1535
|
+
}
|
|
1536
|
+
} else if (args.event === "agent:generating_started") {
|
|
1537
|
+
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
1538
|
+
const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
1539
|
+
if (sessionId && nodeId) {
|
|
1540
|
+
remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
1541
|
+
}
|
|
1402
1542
|
} else if (args.event === "agent:stopped") {
|
|
1403
|
-
const sessionId =
|
|
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
|
+
}
|
|
1404
1548
|
if (sessionId) {
|
|
1405
1549
|
updateSessionTaskStatus(args.meshId, sessionId, "failed");
|
|
1406
1550
|
}
|
|
@@ -1410,13 +1554,15 @@ function injectMeshSystemMessage(components, args) {
|
|
|
1410
1554
|
try {
|
|
1411
1555
|
appendLedgerEntry(args.meshId, {
|
|
1412
1556
|
kind: ledgerKind,
|
|
1413
|
-
nodeId: readNonEmptyString(args.
|
|
1414
|
-
sessionId:
|
|
1557
|
+
nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
1558
|
+
sessionId: resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0,
|
|
1415
1559
|
providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
|
|
1416
1560
|
payload: {
|
|
1417
1561
|
event: args.event,
|
|
1418
1562
|
nodeLabel: args.nodeLabel,
|
|
1419
|
-
|
|
1563
|
+
taskId: completedTaskForLedger?.id || void 0,
|
|
1564
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
|
|
1565
|
+
finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
|
|
1420
1566
|
}
|
|
1421
1567
|
});
|
|
1422
1568
|
} catch (e) {
|
|
@@ -1429,8 +1575,8 @@ function injectMeshSystemMessage(components, args) {
|
|
|
1429
1575
|
const mesh = getMesh(args.meshId);
|
|
1430
1576
|
const maxRetries = mesh?.policy?.maxTaskRetries ?? 1;
|
|
1431
1577
|
recoveryContext = getSessionRecoveryContext(args.meshId, {
|
|
1432
|
-
sessionId:
|
|
1433
|
-
nodeId: readNonEmptyString(args.
|
|
1578
|
+
sessionId: resolveEventSessionId(args.metadataEvent, args.sourceInstanceId) || void 0,
|
|
1579
|
+
nodeId: readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
1434
1580
|
maxRetries
|
|
1435
1581
|
});
|
|
1436
1582
|
recoveryContext.failedProviderType = readNonEmptyString(args.metadataEvent.providerType) || null;
|
|
@@ -1525,12 +1671,14 @@ function handleMeshForwardEvent(components, payload) {
|
|
|
1525
1671
|
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
1526
1672
|
return injectMeshSystemMessage(components, {
|
|
1527
1673
|
meshId,
|
|
1674
|
+
nodeId,
|
|
1528
1675
|
nodeLabel,
|
|
1529
1676
|
event: eventName,
|
|
1530
1677
|
metadataEvent: {
|
|
1531
|
-
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
1678
|
+
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId) || readNonEmptyString(payload.instanceId),
|
|
1532
1679
|
providerType: readNonEmptyString(payload.providerType),
|
|
1533
|
-
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
1680
|
+
providerSessionId: readNonEmptyString(payload.providerSessionId),
|
|
1681
|
+
finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary)
|
|
1534
1682
|
}
|
|
1535
1683
|
});
|
|
1536
1684
|
}
|
|
@@ -1549,22 +1697,24 @@ function setupMeshEventForwarding(components) {
|
|
|
1549
1697
|
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
1550
1698
|
const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
|
|
1551
1699
|
if (!isMeshDelegate) return;
|
|
1552
|
-
const mesh = meshIdFromRuntime ?
|
|
1700
|
+
const mesh = meshIdFromRuntime ? getMeshWithCache(components, meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
1553
1701
|
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
1554
1702
|
if (!meshId) return;
|
|
1555
1703
|
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
1556
1704
|
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
1705
|
+
const resolvedNodeId = targetNode?.id || runtimeNodeId;
|
|
1557
1706
|
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
1558
1707
|
injectMeshSystemMessage(components, {
|
|
1559
1708
|
meshId,
|
|
1560
1709
|
sourceInstanceId: instanceId,
|
|
1710
|
+
nodeId: resolvedNodeId,
|
|
1561
1711
|
nodeLabel,
|
|
1562
1712
|
event: event.event,
|
|
1563
1713
|
metadataEvent: event
|
|
1564
1714
|
});
|
|
1565
1715
|
});
|
|
1566
1716
|
}
|
|
1567
|
-
var MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND;
|
|
1717
|
+
var remoteIdleSessions, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND;
|
|
1568
1718
|
var init_mesh_events = __esm({
|
|
1569
1719
|
"src/mesh/mesh-events.ts"() {
|
|
1570
1720
|
"use strict";
|
|
@@ -1572,12 +1722,15 @@ var init_mesh_events = __esm({
|
|
|
1572
1722
|
init_logger();
|
|
1573
1723
|
init_mesh_ledger();
|
|
1574
1724
|
init_mesh_work_queue();
|
|
1725
|
+
remoteIdleSessions = /* @__PURE__ */ new Map();
|
|
1575
1726
|
MAX_PENDING_EVENTS = 50;
|
|
1576
1727
|
pendingMeshCoordinatorEvents = [];
|
|
1577
1728
|
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
1729
|
+
"agent:generating_started",
|
|
1578
1730
|
"agent:generating_completed",
|
|
1579
1731
|
"agent:waiting_approval",
|
|
1580
1732
|
"agent:stopped",
|
|
1733
|
+
"agent:ready",
|
|
1581
1734
|
"monitor:long_generating"
|
|
1582
1735
|
]);
|
|
1583
1736
|
EVENT_TO_LEDGER_KIND = {
|
|
@@ -2695,6 +2848,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
2695
2848
|
statusHistory = [];
|
|
2696
2849
|
// ─── CLI Scripts (script-based parsing) ───
|
|
2697
2850
|
cliScripts;
|
|
2851
|
+
/** Per-session opaque state object created by cliScripts.createState(), reset on stop. */
|
|
2852
|
+
scriptState = null;
|
|
2698
2853
|
runtimeSettings = {};
|
|
2699
2854
|
/** Full accumulated rendered PTY transcript for parser/readback use */
|
|
2700
2855
|
accumulatedBuffer = "";
|
|
@@ -2771,9 +2926,13 @@ ${lastSnapshot}`;
|
|
|
2771
2926
|
this.lastScreenChangeAt = 0;
|
|
2772
2927
|
this.lastScreenSnapshotReadAt = Number.NEGATIVE_INFINITY;
|
|
2773
2928
|
}
|
|
2929
|
+
getAccumulatedRawBufferCacheKey() {
|
|
2930
|
+
return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
2931
|
+
}
|
|
2774
2932
|
getFreshParsedStatusCache() {
|
|
2775
2933
|
const cached = this.parsedStatusCache;
|
|
2776
|
-
|
|
2934
|
+
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
2935
|
+
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) {
|
|
2777
2936
|
return cached.result;
|
|
2778
2937
|
}
|
|
2779
2938
|
return null;
|
|
@@ -2876,6 +3035,7 @@ ${lastSnapshot}`;
|
|
|
2876
3035
|
this.cliScripts = scripts;
|
|
2877
3036
|
this.parsedStatusCache = null;
|
|
2878
3037
|
this.parseErrorMessage = null;
|
|
3038
|
+
this.scriptState = typeof scripts.createState === "function" ? scripts.createState() : null;
|
|
2879
3039
|
const scriptNames = listCliScriptNames(scripts);
|
|
2880
3040
|
LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
2881
3041
|
}
|
|
@@ -2993,6 +3153,7 @@ ${lastSnapshot}`;
|
|
|
2993
3153
|
this.ready = false;
|
|
2994
3154
|
this.startupParseGate = false;
|
|
2995
3155
|
this.spawnAt = 0;
|
|
3156
|
+
this.scriptState = null;
|
|
2996
3157
|
this.onStatusChange?.();
|
|
2997
3158
|
});
|
|
2998
3159
|
this.spawnAt = Date.now();
|
|
@@ -3746,6 +3907,11 @@ ${lastSnapshot}`;
|
|
|
3746
3907
|
};
|
|
3747
3908
|
}
|
|
3748
3909
|
// ─── Script Execution ──────────────────────────
|
|
3910
|
+
invokeCliScript(script, input) {
|
|
3911
|
+
const hasStateFactory = typeof this.cliScripts?.createState === "function";
|
|
3912
|
+
const expectsStateArgument = hasStateFactory || this.scriptState !== null || script.length >= 2;
|
|
3913
|
+
return expectsStateArgument ? script(this.scriptState, input) : script(input);
|
|
3914
|
+
}
|
|
3749
3915
|
runParseSession() {
|
|
3750
3916
|
if (typeof this.cliScripts?.parseSession !== "function") {
|
|
3751
3917
|
this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
|
|
@@ -3766,7 +3932,10 @@ ${lastSnapshot}`;
|
|
|
3766
3932
|
scope: this.currentTurnScope,
|
|
3767
3933
|
runtimeSettings: this.runtimeSettings
|
|
3768
3934
|
});
|
|
3769
|
-
const session = this.
|
|
3935
|
+
const session = this.invokeCliScript(
|
|
3936
|
+
this.cliScripts.parseSession,
|
|
3937
|
+
{ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) }
|
|
3938
|
+
);
|
|
3770
3939
|
this.parseErrorMessage = null;
|
|
3771
3940
|
return session && typeof session === "object" ? session : null;
|
|
3772
3941
|
} catch (e) {
|
|
@@ -3780,7 +3949,7 @@ ${lastSnapshot}`;
|
|
|
3780
3949
|
if (!this.cliScripts?.detectStatus) return null;
|
|
3781
3950
|
try {
|
|
3782
3951
|
const screenText = this.terminalScreen.getText();
|
|
3783
|
-
const status = this.cliScripts.detectStatus
|
|
3952
|
+
const status = this.invokeCliScript(this.cliScripts.detectStatus, {
|
|
3784
3953
|
tail: text.slice(-500),
|
|
3785
3954
|
screenText,
|
|
3786
3955
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -3799,7 +3968,7 @@ ${lastSnapshot}`;
|
|
|
3799
3968
|
try {
|
|
3800
3969
|
const screenText = this.terminalScreen.getText();
|
|
3801
3970
|
const buffer = screenText || this.accumulatedBuffer;
|
|
3802
|
-
return this.cliScripts.parseApproval
|
|
3971
|
+
return this.invokeCliScript(this.cliScripts.parseApproval, {
|
|
3803
3972
|
buffer,
|
|
3804
3973
|
screenText,
|
|
3805
3974
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -3855,7 +4024,8 @@ ${lastSnapshot}`;
|
|
|
3855
4024
|
const screenText = this.readTerminalScreenText();
|
|
3856
4025
|
const parseScreenText = this.getParseScreenText(screenText);
|
|
3857
4026
|
const cached = this.parsedStatusCache;
|
|
3858
|
-
|
|
4027
|
+
const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
|
|
4028
|
+
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) {
|
|
3859
4029
|
return cached.result;
|
|
3860
4030
|
}
|
|
3861
4031
|
const parsed = this.runParseSession();
|
|
@@ -3883,6 +4053,7 @@ ${lastSnapshot}`;
|
|
|
3883
4053
|
currentTurnScope: this.currentTurnScope,
|
|
3884
4054
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
3885
4055
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
4056
|
+
accumulatedRawBufferKey,
|
|
3886
4057
|
screenText: parseScreenText,
|
|
3887
4058
|
currentStatus: this.currentStatus,
|
|
3888
4059
|
activeModal: this.activeModal,
|
|
@@ -3907,7 +4078,7 @@ ${lastSnapshot}`;
|
|
|
3907
4078
|
scope: this.currentTurnScope,
|
|
3908
4079
|
runtimeSettings: this.runtimeSettings
|
|
3909
4080
|
});
|
|
3910
|
-
return await Promise.resolve(fn({
|
|
4081
|
+
return await Promise.resolve(fn(this.scriptState, {
|
|
3911
4082
|
...input,
|
|
3912
4083
|
args: args && typeof args === "object" ? { ...args } : {}
|
|
3913
4084
|
}));
|
|
@@ -14983,11 +15154,13 @@ async function handleOpenPanel(h, args) {
|
|
|
14983
15154
|
async function handlePtyInput(h, args) {
|
|
14984
15155
|
const { cliType, data, targetSessionId } = args || {};
|
|
14985
15156
|
if (!data) return { success: false, error: "data required" };
|
|
15157
|
+
const cleanData = typeof data === "string" ? data.replace(/\x1b\[[?>][0-9;]*c/g, "") : data;
|
|
15158
|
+
if (!cleanData) return { success: true };
|
|
14986
15159
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
14987
15160
|
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
14988
15161
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
14989
15162
|
}
|
|
14990
|
-
await adapter.writeRaw(
|
|
15163
|
+
await adapter.writeRaw(cleanData);
|
|
14991
15164
|
return { success: true };
|
|
14992
15165
|
}
|
|
14993
15166
|
function handlePtyResize(_h, args) {
|
|
@@ -16617,6 +16790,8 @@ var CliProviderInstance = class {
|
|
|
16617
16790
|
this.completedDebounceTimer = null;
|
|
16618
16791
|
}, 3e3);
|
|
16619
16792
|
}
|
|
16793
|
+
} else if (newStatus === "idle" && this.lastStatus === "starting") {
|
|
16794
|
+
this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });
|
|
16620
16795
|
} else if (newStatus === "stopped") {
|
|
16621
16796
|
if (this.generatingDebounceTimer) {
|
|
16622
16797
|
clearTimeout(this.generatingDebounceTimer);
|
|
@@ -18365,9 +18540,6 @@ function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
|
18365
18540
|
const cliType = String(input.cliType || "").trim();
|
|
18366
18541
|
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
18367
18542
|
const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
|
|
18368
|
-
if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
|
|
18369
|
-
cliArgs.unshift("--ignore-user-config");
|
|
18370
|
-
}
|
|
18371
18543
|
if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
|
|
18372
18544
|
cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
18373
18545
|
}
|
|
@@ -21613,7 +21785,9 @@ function resolveHermesMeshCoordinatorSetup(options) {
|
|
|
21613
21785
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
21614
21786
|
meshId: options.meshId,
|
|
21615
21787
|
nodeExecutable: options.nodeExecutable,
|
|
21616
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
21788
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
21789
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
21790
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
21617
21791
|
});
|
|
21618
21792
|
if (!mcpServer) {
|
|
21619
21793
|
return {
|
|
@@ -21680,7 +21854,9 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21680
21854
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
21681
21855
|
meshId,
|
|
21682
21856
|
nodeExecutable: options.nodeExecutable,
|
|
21683
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
21857
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
21858
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
21859
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
21684
21860
|
});
|
|
21685
21861
|
if (!mcpServer) {
|
|
21686
21862
|
return {
|
|
@@ -21702,6 +21878,22 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21702
21878
|
if (!instructions || !template?.trim()) {
|
|
21703
21879
|
return { kind: "unsupported", reason: "Provider manual MCP setup is missing instructions or template" };
|
|
21704
21880
|
}
|
|
21881
|
+
const renderedTemplate = renderMeshCoordinatorTemplate(template, {
|
|
21882
|
+
meshId,
|
|
21883
|
+
workspace,
|
|
21884
|
+
serverName,
|
|
21885
|
+
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
21886
|
+
});
|
|
21887
|
+
const isCliCommand = !renderedTemplate.trim().includes("\n") && !renderedTemplate.trim().startsWith("{");
|
|
21888
|
+
if (isCliCommand) {
|
|
21889
|
+
return {
|
|
21890
|
+
kind: "cli_command",
|
|
21891
|
+
serverName,
|
|
21892
|
+
command: renderedTemplate.trim(),
|
|
21893
|
+
requiresRestart: mcpConfig.requiresRestart === true,
|
|
21894
|
+
instructions
|
|
21895
|
+
};
|
|
21896
|
+
}
|
|
21705
21897
|
return {
|
|
21706
21898
|
kind: "manual",
|
|
21707
21899
|
serverName,
|
|
@@ -21709,12 +21901,7 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21709
21901
|
configPathCommand: mcpConfig.configPathCommand,
|
|
21710
21902
|
requiresRestart: mcpConfig.requiresRestart === true,
|
|
21711
21903
|
instructions,
|
|
21712
|
-
template:
|
|
21713
|
-
meshId,
|
|
21714
|
-
workspace,
|
|
21715
|
-
serverName,
|
|
21716
|
-
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
21717
|
-
})
|
|
21904
|
+
template: renderedTemplate
|
|
21718
21905
|
};
|
|
21719
21906
|
}
|
|
21720
21907
|
return {
|
|
@@ -21743,11 +21930,27 @@ function resolveAdhdevMcpServerLaunch(options) {
|
|
|
21743
21930
|
if (!entryPath) return null;
|
|
21744
21931
|
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
|
|
21745
21932
|
if (!nodeExecutable) return null;
|
|
21933
|
+
const transport = resolveMcpTransport(options.adhdevMcpTransport);
|
|
21934
|
+
const args = [entryPath, "--mode", transport, "--repo-mesh", options.meshId];
|
|
21935
|
+
const port = resolveMcpPort(options.adhdevMcpPort);
|
|
21936
|
+
if (port !== void 0) args.push("--port", String(port));
|
|
21746
21937
|
return {
|
|
21747
21938
|
command: nodeExecutable,
|
|
21748
|
-
args
|
|
21939
|
+
args
|
|
21749
21940
|
};
|
|
21750
21941
|
}
|
|
21942
|
+
function resolveMcpTransport(explicitTransport) {
|
|
21943
|
+
if (explicitTransport === "local" || explicitTransport === "ipc") return explicitTransport;
|
|
21944
|
+
const envTransport = process.env.ADHDEV_COORDINATOR_MCP_TRANSPORT?.trim();
|
|
21945
|
+
return envTransport === "local" ? "local" : "ipc";
|
|
21946
|
+
}
|
|
21947
|
+
function resolveMcpPort(explicitPort) {
|
|
21948
|
+
if (typeof explicitPort === "number" && Number.isInteger(explicitPort) && explicitPort > 0) return explicitPort;
|
|
21949
|
+
const raw = process.env.ADHDEV_COORDINATOR_MCP_PORT?.trim();
|
|
21950
|
+
if (!raw) return void 0;
|
|
21951
|
+
const parsed = Number(raw);
|
|
21952
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
21953
|
+
}
|
|
21751
21954
|
function resolveMcpNodeExecutable(explicitExecutable) {
|
|
21752
21955
|
const explicit = explicitExecutable?.trim();
|
|
21753
21956
|
if (explicit) return explicit;
|
|
@@ -22588,6 +22791,34 @@ function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
|
22588
22791
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
22589
22792
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
22590
22793
|
}
|
|
22794
|
+
function stripHermesCoordinatorTempModelProviderOverrides(config) {
|
|
22795
|
+
const {
|
|
22796
|
+
model: _model,
|
|
22797
|
+
provider: _provider,
|
|
22798
|
+
default_model: _defaultModel,
|
|
22799
|
+
defaultProvider: _defaultProvider,
|
|
22800
|
+
default_provider: _defaultProviderSnake,
|
|
22801
|
+
modelProvider: _modelProvider,
|
|
22802
|
+
model_provider: _modelProviderSnake,
|
|
22803
|
+
...sanitized
|
|
22804
|
+
} = config;
|
|
22805
|
+
const delegation = sanitized.delegation;
|
|
22806
|
+
if (delegation && typeof delegation === "object" && !Array.isArray(delegation)) {
|
|
22807
|
+
const {
|
|
22808
|
+
model: _delegationModel,
|
|
22809
|
+
provider: _delegationProvider,
|
|
22810
|
+
modelProvider: _delegationModelProvider,
|
|
22811
|
+
model_provider: _delegationModelProviderSnake,
|
|
22812
|
+
...delegationRest
|
|
22813
|
+
} = delegation;
|
|
22814
|
+
if (Object.keys(delegationRest).length > 0) {
|
|
22815
|
+
sanitized.delegation = delegationRest;
|
|
22816
|
+
} else {
|
|
22817
|
+
delete sanitized.delegation;
|
|
22818
|
+
}
|
|
22819
|
+
}
|
|
22820
|
+
return sanitized;
|
|
22821
|
+
}
|
|
22591
22822
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
22592
22823
|
if (pathResolve(sourceHome) === pathResolve(targetHome)) return;
|
|
22593
22824
|
for (const fileName of [".env", "auth.json"]) {
|
|
@@ -23568,6 +23799,51 @@ var DaemonCommandRouter = class {
|
|
|
23568
23799
|
return { success: false, error: e.message };
|
|
23569
23800
|
}
|
|
23570
23801
|
}
|
|
23802
|
+
case "get_mesh_queue": {
|
|
23803
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23804
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
23805
|
+
try {
|
|
23806
|
+
const { getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
23807
|
+
const status = Array.isArray(args?.status) ? args.status.map((s) => typeof s === "string" ? s.trim() : "").filter(Boolean) : void 0;
|
|
23808
|
+
const queue = getQueue2(meshId, { status });
|
|
23809
|
+
return { success: true, queue };
|
|
23810
|
+
} catch (e) {
|
|
23811
|
+
return { success: false, error: e.message };
|
|
23812
|
+
}
|
|
23813
|
+
}
|
|
23814
|
+
case "cancel_mesh_queue_task": {
|
|
23815
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23816
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
23817
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
23818
|
+
try {
|
|
23819
|
+
const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
23820
|
+
const reason = typeof args?.reason === "string" ? args.reason : void 0;
|
|
23821
|
+
const task = cancelTask2(meshId, taskId, { reason });
|
|
23822
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
23823
|
+
return { success: true, task };
|
|
23824
|
+
} catch (e) {
|
|
23825
|
+
return { success: false, error: e.message };
|
|
23826
|
+
}
|
|
23827
|
+
}
|
|
23828
|
+
case "requeue_mesh_queue_task": {
|
|
23829
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23830
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
23831
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
23832
|
+
try {
|
|
23833
|
+
const { requeueTask: requeueTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
23834
|
+
const task = requeueTask2(meshId, taskId, {
|
|
23835
|
+
reason: typeof args?.reason === "string" ? args.reason : void 0,
|
|
23836
|
+
targetNodeId: typeof args?.targetNodeId === "string" ? args.targetNodeId.trim() : void 0,
|
|
23837
|
+
targetSessionId: typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : void 0,
|
|
23838
|
+
clearTargetNode: args?.clearTargetNode === true,
|
|
23839
|
+
clearTargetSession: args?.clearTargetSession !== false
|
|
23840
|
+
});
|
|
23841
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
23842
|
+
return { success: true, task };
|
|
23843
|
+
} catch (e) {
|
|
23844
|
+
return { success: false, error: e.message };
|
|
23845
|
+
}
|
|
23846
|
+
}
|
|
23571
23847
|
case "add_mesh_node": {
|
|
23572
23848
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23573
23849
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -23725,7 +24001,13 @@ var DaemonCommandRouter = class {
|
|
|
23725
24001
|
appendLedgerEntry2(meshId, {
|
|
23726
24002
|
kind: "node_removed",
|
|
23727
24003
|
nodeId,
|
|
23728
|
-
payload: {
|
|
24004
|
+
payload: {
|
|
24005
|
+
worktree: !!node?.isLocalWorktree,
|
|
24006
|
+
sessionCleanupMode,
|
|
24007
|
+
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
24008
|
+
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
24009
|
+
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0
|
|
24010
|
+
}
|
|
23729
24011
|
});
|
|
23730
24012
|
} catch {
|
|
23731
24013
|
}
|
|
@@ -23896,6 +24178,93 @@ var DaemonCommandRouter = class {
|
|
|
23896
24178
|
meshCoordinatorSetup: coordinatorSetup
|
|
23897
24179
|
};
|
|
23898
24180
|
}
|
|
24181
|
+
if (coordinatorSetup.kind === "cli_command") {
|
|
24182
|
+
let cliCmdSystemPrompt = "";
|
|
24183
|
+
try {
|
|
24184
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
24185
|
+
} catch (error) {
|
|
24186
|
+
const message = error?.message || String(error);
|
|
24187
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
24188
|
+
return {
|
|
24189
|
+
success: false,
|
|
24190
|
+
code: "mesh_coordinator_prompt_failed",
|
|
24191
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
24192
|
+
meshId,
|
|
24193
|
+
cliType,
|
|
24194
|
+
workspace
|
|
24195
|
+
};
|
|
24196
|
+
}
|
|
24197
|
+
try {
|
|
24198
|
+
const { execFileSync: execCmdSync } = await import("child_process");
|
|
24199
|
+
const cmdParts = coordinatorSetup.command.trim().split(/\s+/);
|
|
24200
|
+
const [regCmd, ...regArgs] = cmdParts;
|
|
24201
|
+
LOG.info("MeshCoordinator", `Running MCP registration: ${coordinatorSetup.command}`);
|
|
24202
|
+
execCmdSync(regCmd, regArgs, { stdio: "pipe", timeout: 15e3 });
|
|
24203
|
+
} catch (error) {
|
|
24204
|
+
LOG.warn("MeshCoordinator", `MCP registration command failed (may be pre-registered): ${error?.message || error}`);
|
|
24205
|
+
}
|
|
24206
|
+
const cliCmdArgs = [];
|
|
24207
|
+
const cliCmdEnv = {};
|
|
24208
|
+
if (cliCmdSystemPrompt) {
|
|
24209
|
+
if (cliType === "codex-cli") {
|
|
24210
|
+
cliCmdArgs.push("-c", `developer_instructions=${JSON.stringify(cliCmdSystemPrompt)}`);
|
|
24211
|
+
} else if (cliType === "gemini-cli") {
|
|
24212
|
+
try {
|
|
24213
|
+
const { writeFileSync: wfs, existsSync: efs, readFileSync: rfs } = await import("fs");
|
|
24214
|
+
const geminiMdPath = `${workspace}/GEMINI.md`;
|
|
24215
|
+
const marker = "<!-- adhdev-mesh-coordinator-prompt -->";
|
|
24216
|
+
const markerEnd = "<!-- /adhdev-mesh-coordinator-prompt -->";
|
|
24217
|
+
const block = `${marker}
|
|
24218
|
+
${cliCmdSystemPrompt}
|
|
24219
|
+
${markerEnd}`;
|
|
24220
|
+
if (efs(geminiMdPath)) {
|
|
24221
|
+
const existing = rfs(geminiMdPath, "utf-8");
|
|
24222
|
+
const replaced = existing.replace(
|
|
24223
|
+
new RegExp(`${marker}[\\s\\S]*?${markerEnd}`, "g"),
|
|
24224
|
+
block
|
|
24225
|
+
);
|
|
24226
|
+
wfs(geminiMdPath, replaced.includes(marker) ? replaced : `${existing}
|
|
24227
|
+
|
|
24228
|
+
${block}`);
|
|
24229
|
+
} else {
|
|
24230
|
+
wfs(geminiMdPath, block);
|
|
24231
|
+
}
|
|
24232
|
+
LOG.info("MeshCoordinator", `Wrote coordinator prompt to ${workspace}/GEMINI.md`);
|
|
24233
|
+
} catch (e) {
|
|
24234
|
+
LOG.warn("MeshCoordinator", `Could not write GEMINI.md: ${e?.message || e}`);
|
|
24235
|
+
}
|
|
24236
|
+
}
|
|
24237
|
+
}
|
|
24238
|
+
const cliCmdLaunch = await this.deps.cliManager.handleCliCommand("launch_cli", {
|
|
24239
|
+
cliType,
|
|
24240
|
+
dir: workspace,
|
|
24241
|
+
cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
|
|
24242
|
+
env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
|
|
24243
|
+
settings: { meshCoordinatorFor: meshId }
|
|
24244
|
+
});
|
|
24245
|
+
if (!cliCmdLaunch?.success) {
|
|
24246
|
+
return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
|
|
24247
|
+
}
|
|
24248
|
+
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
|
|
24249
|
+
try {
|
|
24250
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
24251
|
+
appendLedgerEntry2(meshId, {
|
|
24252
|
+
kind: "coordinator_started",
|
|
24253
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
24254
|
+
providerType: cliType,
|
|
24255
|
+
payload: { workspace }
|
|
24256
|
+
});
|
|
24257
|
+
} catch {
|
|
24258
|
+
}
|
|
24259
|
+
return {
|
|
24260
|
+
success: true,
|
|
24261
|
+
meshId,
|
|
24262
|
+
cliType,
|
|
24263
|
+
workspace,
|
|
24264
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
24265
|
+
mcpRegistered: true
|
|
24266
|
+
};
|
|
24267
|
+
}
|
|
23899
24268
|
const configFormat = coordinatorSetup.configFormat;
|
|
23900
24269
|
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
23901
24270
|
return {
|
|
@@ -23950,9 +24319,11 @@ var DaemonCommandRouter = class {
|
|
|
23950
24319
|
args: coordinatorSetup.mcpServer.args
|
|
23951
24320
|
};
|
|
23952
24321
|
if (args?.inlineMesh) {
|
|
24322
|
+
const modeArgIndex = coordinatorSetup.mcpServer.args.findIndex((value) => value === "--mode");
|
|
24323
|
+
const mcpTransport = modeArgIndex >= 0 ? coordinatorSetup.mcpServer.args[modeArgIndex + 1] : "ipc";
|
|
23953
24324
|
mcpServerEntry.env = {
|
|
23954
24325
|
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
23955
|
-
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
24326
|
+
ADHDEV_MCP_TRANSPORT: mcpTransport === "local" ? "local" : "ipc"
|
|
23956
24327
|
};
|
|
23957
24328
|
}
|
|
23958
24329
|
try {
|
|
@@ -23971,7 +24342,8 @@ var DaemonCommandRouter = class {
|
|
|
23971
24342
|
if (hadExistingMcpConfig) {
|
|
23972
24343
|
try {
|
|
23973
24344
|
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
|
|
23974
|
-
|
|
24345
|
+
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
24346
|
+
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
23975
24347
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
23976
24348
|
} catch (error) {
|
|
23977
24349
|
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
@@ -31999,7 +32371,8 @@ async function initDaemonComponents(config) {
|
|
|
31999
32371
|
cdpManagers,
|
|
32000
32372
|
sessionRegistry,
|
|
32001
32373
|
detectedIdes: detectedIdesRef,
|
|
32002
|
-
refreshProviderAvailability
|
|
32374
|
+
refreshProviderAvailability,
|
|
32375
|
+
dispatchMeshCommand: config.dispatchMeshCommand
|
|
32003
32376
|
};
|
|
32004
32377
|
setupMeshEventForwarding(components);
|
|
32005
32378
|
return components;
|
|
@@ -32130,6 +32503,7 @@ export {
|
|
|
32130
32503
|
buildThoughtChatMessage,
|
|
32131
32504
|
buildToolChatMessage,
|
|
32132
32505
|
buildUserChatMessage,
|
|
32506
|
+
cancelTask,
|
|
32133
32507
|
claimNextTask,
|
|
32134
32508
|
classifyChatMessageVisibility,
|
|
32135
32509
|
classifyHotChatSessionsForSubscriptionFlush,
|
|
@@ -32173,6 +32547,7 @@ export {
|
|
|
32173
32547
|
getLogLevel,
|
|
32174
32548
|
getMesh,
|
|
32175
32549
|
getMeshByRepo,
|
|
32550
|
+
getMeshQueueStats,
|
|
32176
32551
|
getNpmExecOptions,
|
|
32177
32552
|
getQueue,
|
|
32178
32553
|
getRecentActivity,
|
|
@@ -32241,6 +32616,7 @@ export {
|
|
|
32241
32616
|
registerExtensionProviders,
|
|
32242
32617
|
removeNode,
|
|
32243
32618
|
removeWorktree,
|
|
32619
|
+
requeueTask,
|
|
32244
32620
|
resetConfig,
|
|
32245
32621
|
resetDebugRuntimeConfig,
|
|
32246
32622
|
resetState,
|