@adhdev/daemon-core 0.9.77-rc.4 → 0.9.77-rc.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/boot/daemon-lifecycle.d.ts +3 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +3 -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 +389 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +386 -44
- 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 +25 -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 +160 -3
- 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 = "";
|
|
@@ -2773,7 +2928,7 @@ ${lastSnapshot}`;
|
|
|
2773
2928
|
}
|
|
2774
2929
|
getFreshParsedStatusCache() {
|
|
2775
2930
|
const cached = this.parsedStatusCache;
|
|
2776
|
-
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.screenText === this.lastScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
2931
|
+
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBuffer === this.accumulatedRawBuffer && cached.screenText === this.lastScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
2777
2932
|
return cached.result;
|
|
2778
2933
|
}
|
|
2779
2934
|
return null;
|
|
@@ -2876,6 +3031,7 @@ ${lastSnapshot}`;
|
|
|
2876
3031
|
this.cliScripts = scripts;
|
|
2877
3032
|
this.parsedStatusCache = null;
|
|
2878
3033
|
this.parseErrorMessage = null;
|
|
3034
|
+
this.scriptState = typeof scripts.createState === "function" ? scripts.createState() : null;
|
|
2879
3035
|
const scriptNames = listCliScriptNames(scripts);
|
|
2880
3036
|
LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
2881
3037
|
}
|
|
@@ -2993,6 +3149,7 @@ ${lastSnapshot}`;
|
|
|
2993
3149
|
this.ready = false;
|
|
2994
3150
|
this.startupParseGate = false;
|
|
2995
3151
|
this.spawnAt = 0;
|
|
3152
|
+
this.scriptState = null;
|
|
2996
3153
|
this.onStatusChange?.();
|
|
2997
3154
|
});
|
|
2998
3155
|
this.spawnAt = Date.now();
|
|
@@ -3746,6 +3903,11 @@ ${lastSnapshot}`;
|
|
|
3746
3903
|
};
|
|
3747
3904
|
}
|
|
3748
3905
|
// ─── Script Execution ──────────────────────────
|
|
3906
|
+
invokeCliScript(script, input) {
|
|
3907
|
+
const hasStateFactory = typeof this.cliScripts?.createState === "function";
|
|
3908
|
+
const expectsStateArgument = hasStateFactory || this.scriptState !== null || script.length >= 2;
|
|
3909
|
+
return expectsStateArgument ? script(this.scriptState, input) : script(input);
|
|
3910
|
+
}
|
|
3749
3911
|
runParseSession() {
|
|
3750
3912
|
if (typeof this.cliScripts?.parseSession !== "function") {
|
|
3751
3913
|
this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
|
|
@@ -3766,7 +3928,10 @@ ${lastSnapshot}`;
|
|
|
3766
3928
|
scope: this.currentTurnScope,
|
|
3767
3929
|
runtimeSettings: this.runtimeSettings
|
|
3768
3930
|
});
|
|
3769
|
-
const session = this.
|
|
3931
|
+
const session = this.invokeCliScript(
|
|
3932
|
+
this.cliScripts.parseSession,
|
|
3933
|
+
{ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) }
|
|
3934
|
+
);
|
|
3770
3935
|
this.parseErrorMessage = null;
|
|
3771
3936
|
return session && typeof session === "object" ? session : null;
|
|
3772
3937
|
} catch (e) {
|
|
@@ -3780,7 +3945,7 @@ ${lastSnapshot}`;
|
|
|
3780
3945
|
if (!this.cliScripts?.detectStatus) return null;
|
|
3781
3946
|
try {
|
|
3782
3947
|
const screenText = this.terminalScreen.getText();
|
|
3783
|
-
const status = this.cliScripts.detectStatus
|
|
3948
|
+
const status = this.invokeCliScript(this.cliScripts.detectStatus, {
|
|
3784
3949
|
tail: text.slice(-500),
|
|
3785
3950
|
screenText,
|
|
3786
3951
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -3799,7 +3964,7 @@ ${lastSnapshot}`;
|
|
|
3799
3964
|
try {
|
|
3800
3965
|
const screenText = this.terminalScreen.getText();
|
|
3801
3966
|
const buffer = screenText || this.accumulatedBuffer;
|
|
3802
|
-
return this.cliScripts.parseApproval
|
|
3967
|
+
return this.invokeCliScript(this.cliScripts.parseApproval, {
|
|
3803
3968
|
buffer,
|
|
3804
3969
|
screenText,
|
|
3805
3970
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -3855,7 +4020,7 @@ ${lastSnapshot}`;
|
|
|
3855
4020
|
const screenText = this.readTerminalScreenText();
|
|
3856
4021
|
const parseScreenText = this.getParseScreenText(screenText);
|
|
3857
4022
|
const cached = this.parsedStatusCache;
|
|
3858
|
-
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.screenText === parseScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
4023
|
+
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.accumulatedRawBuffer === this.accumulatedRawBuffer && cached.screenText === parseScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
3859
4024
|
return cached.result;
|
|
3860
4025
|
}
|
|
3861
4026
|
const parsed = this.runParseSession();
|
|
@@ -3883,6 +4048,7 @@ ${lastSnapshot}`;
|
|
|
3883
4048
|
currentTurnScope: this.currentTurnScope,
|
|
3884
4049
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
3885
4050
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
4051
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
3886
4052
|
screenText: parseScreenText,
|
|
3887
4053
|
currentStatus: this.currentStatus,
|
|
3888
4054
|
activeModal: this.activeModal,
|
|
@@ -3907,7 +4073,7 @@ ${lastSnapshot}`;
|
|
|
3907
4073
|
scope: this.currentTurnScope,
|
|
3908
4074
|
runtimeSettings: this.runtimeSettings
|
|
3909
4075
|
});
|
|
3910
|
-
return await Promise.resolve(fn({
|
|
4076
|
+
return await Promise.resolve(fn(this.scriptState, {
|
|
3911
4077
|
...input,
|
|
3912
4078
|
args: args && typeof args === "object" ? { ...args } : {}
|
|
3913
4079
|
}));
|
|
@@ -14983,11 +15149,13 @@ async function handleOpenPanel(h, args) {
|
|
|
14983
15149
|
async function handlePtyInput(h, args) {
|
|
14984
15150
|
const { cliType, data, targetSessionId } = args || {};
|
|
14985
15151
|
if (!data) return { success: false, error: "data required" };
|
|
15152
|
+
const cleanData = typeof data === "string" ? data.replace(/\x1b\[[?>][0-9;]*c/g, "") : data;
|
|
15153
|
+
if (!cleanData) return { success: true };
|
|
14986
15154
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
14987
15155
|
if (!adapter || typeof adapter.writeRaw !== "function") {
|
|
14988
15156
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || "unknown"}` };
|
|
14989
15157
|
}
|
|
14990
|
-
await adapter.writeRaw(
|
|
15158
|
+
await adapter.writeRaw(cleanData);
|
|
14991
15159
|
return { success: true };
|
|
14992
15160
|
}
|
|
14993
15161
|
function handlePtyResize(_h, args) {
|
|
@@ -16617,6 +16785,8 @@ var CliProviderInstance = class {
|
|
|
16617
16785
|
this.completedDebounceTimer = null;
|
|
16618
16786
|
}, 3e3);
|
|
16619
16787
|
}
|
|
16788
|
+
} else if (newStatus === "idle" && this.lastStatus === "starting") {
|
|
16789
|
+
this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });
|
|
16620
16790
|
} else if (newStatus === "stopped") {
|
|
16621
16791
|
if (this.generatingDebounceTimer) {
|
|
16622
16792
|
clearTimeout(this.generatingDebounceTimer);
|
|
@@ -18365,9 +18535,6 @@ function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
|
18365
18535
|
const cliType = String(input.cliType || "").trim();
|
|
18366
18536
|
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
18367
18537
|
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
18538
|
if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
|
|
18372
18539
|
cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
18373
18540
|
}
|
|
@@ -21613,7 +21780,9 @@ function resolveHermesMeshCoordinatorSetup(options) {
|
|
|
21613
21780
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
21614
21781
|
meshId: options.meshId,
|
|
21615
21782
|
nodeExecutable: options.nodeExecutable,
|
|
21616
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
21783
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
21784
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
21785
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
21617
21786
|
});
|
|
21618
21787
|
if (!mcpServer) {
|
|
21619
21788
|
return {
|
|
@@ -21680,7 +21849,9 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21680
21849
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
21681
21850
|
meshId,
|
|
21682
21851
|
nodeExecutable: options.nodeExecutable,
|
|
21683
|
-
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
21852
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath,
|
|
21853
|
+
adhdevMcpTransport: options.adhdevMcpTransport,
|
|
21854
|
+
adhdevMcpPort: options.adhdevMcpPort
|
|
21684
21855
|
});
|
|
21685
21856
|
if (!mcpServer) {
|
|
21686
21857
|
return {
|
|
@@ -21702,6 +21873,22 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21702
21873
|
if (!instructions || !template?.trim()) {
|
|
21703
21874
|
return { kind: "unsupported", reason: "Provider manual MCP setup is missing instructions or template" };
|
|
21704
21875
|
}
|
|
21876
|
+
const renderedTemplate = renderMeshCoordinatorTemplate(template, {
|
|
21877
|
+
meshId,
|
|
21878
|
+
workspace,
|
|
21879
|
+
serverName,
|
|
21880
|
+
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
21881
|
+
});
|
|
21882
|
+
const isCliCommand = !renderedTemplate.trim().includes("\n") && !renderedTemplate.trim().startsWith("{");
|
|
21883
|
+
if (isCliCommand) {
|
|
21884
|
+
return {
|
|
21885
|
+
kind: "cli_command",
|
|
21886
|
+
serverName,
|
|
21887
|
+
command: renderedTemplate.trim(),
|
|
21888
|
+
requiresRestart: mcpConfig.requiresRestart === true,
|
|
21889
|
+
instructions
|
|
21890
|
+
};
|
|
21891
|
+
}
|
|
21705
21892
|
return {
|
|
21706
21893
|
kind: "manual",
|
|
21707
21894
|
serverName,
|
|
@@ -21709,12 +21896,7 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
21709
21896
|
configPathCommand: mcpConfig.configPathCommand,
|
|
21710
21897
|
requiresRestart: mcpConfig.requiresRestart === true,
|
|
21711
21898
|
instructions,
|
|
21712
|
-
template:
|
|
21713
|
-
meshId,
|
|
21714
|
-
workspace,
|
|
21715
|
-
serverName,
|
|
21716
|
-
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND
|
|
21717
|
-
})
|
|
21899
|
+
template: renderedTemplate
|
|
21718
21900
|
};
|
|
21719
21901
|
}
|
|
21720
21902
|
return {
|
|
@@ -21743,11 +21925,27 @@ function resolveAdhdevMcpServerLaunch(options) {
|
|
|
21743
21925
|
if (!entryPath) return null;
|
|
21744
21926
|
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
|
|
21745
21927
|
if (!nodeExecutable) return null;
|
|
21928
|
+
const transport = resolveMcpTransport(options.adhdevMcpTransport);
|
|
21929
|
+
const args = [entryPath, "--mode", transport, "--repo-mesh", options.meshId];
|
|
21930
|
+
const port = resolveMcpPort(options.adhdevMcpPort);
|
|
21931
|
+
if (port !== void 0) args.push("--port", String(port));
|
|
21746
21932
|
return {
|
|
21747
21933
|
command: nodeExecutable,
|
|
21748
|
-
args
|
|
21934
|
+
args
|
|
21749
21935
|
};
|
|
21750
21936
|
}
|
|
21937
|
+
function resolveMcpTransport(explicitTransport) {
|
|
21938
|
+
if (explicitTransport === "local" || explicitTransport === "ipc") return explicitTransport;
|
|
21939
|
+
const envTransport = process.env.ADHDEV_COORDINATOR_MCP_TRANSPORT?.trim();
|
|
21940
|
+
return envTransport === "local" ? "local" : "ipc";
|
|
21941
|
+
}
|
|
21942
|
+
function resolveMcpPort(explicitPort) {
|
|
21943
|
+
if (typeof explicitPort === "number" && Number.isInteger(explicitPort) && explicitPort > 0) return explicitPort;
|
|
21944
|
+
const raw = process.env.ADHDEV_COORDINATOR_MCP_PORT?.trim();
|
|
21945
|
+
if (!raw) return void 0;
|
|
21946
|
+
const parsed = Number(raw);
|
|
21947
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
21948
|
+
}
|
|
21751
21949
|
function resolveMcpNodeExecutable(explicitExecutable) {
|
|
21752
21950
|
const explicit = explicitExecutable?.trim();
|
|
21753
21951
|
if (explicit) return explicit;
|
|
@@ -23568,6 +23766,51 @@ var DaemonCommandRouter = class {
|
|
|
23568
23766
|
return { success: false, error: e.message };
|
|
23569
23767
|
}
|
|
23570
23768
|
}
|
|
23769
|
+
case "get_mesh_queue": {
|
|
23770
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23771
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
23772
|
+
try {
|
|
23773
|
+
const { getQueue: getQueue2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
23774
|
+
const status = Array.isArray(args?.status) ? args.status.map((s) => typeof s === "string" ? s.trim() : "").filter(Boolean) : void 0;
|
|
23775
|
+
const queue = getQueue2(meshId, { status });
|
|
23776
|
+
return { success: true, queue };
|
|
23777
|
+
} catch (e) {
|
|
23778
|
+
return { success: false, error: e.message };
|
|
23779
|
+
}
|
|
23780
|
+
}
|
|
23781
|
+
case "cancel_mesh_queue_task": {
|
|
23782
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23783
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
23784
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
23785
|
+
try {
|
|
23786
|
+
const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
23787
|
+
const reason = typeof args?.reason === "string" ? args.reason : void 0;
|
|
23788
|
+
const task = cancelTask2(meshId, taskId, { reason });
|
|
23789
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
23790
|
+
return { success: true, task };
|
|
23791
|
+
} catch (e) {
|
|
23792
|
+
return { success: false, error: e.message };
|
|
23793
|
+
}
|
|
23794
|
+
}
|
|
23795
|
+
case "requeue_mesh_queue_task": {
|
|
23796
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23797
|
+
const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
|
|
23798
|
+
if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
|
|
23799
|
+
try {
|
|
23800
|
+
const { requeueTask: requeueTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
|
|
23801
|
+
const task = requeueTask2(meshId, taskId, {
|
|
23802
|
+
reason: typeof args?.reason === "string" ? args.reason : void 0,
|
|
23803
|
+
targetNodeId: typeof args?.targetNodeId === "string" ? args.targetNodeId.trim() : void 0,
|
|
23804
|
+
targetSessionId: typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : void 0,
|
|
23805
|
+
clearTargetNode: args?.clearTargetNode === true,
|
|
23806
|
+
clearTargetSession: args?.clearTargetSession !== false
|
|
23807
|
+
});
|
|
23808
|
+
if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
|
|
23809
|
+
return { success: true, task };
|
|
23810
|
+
} catch (e) {
|
|
23811
|
+
return { success: false, error: e.message };
|
|
23812
|
+
}
|
|
23813
|
+
}
|
|
23571
23814
|
case "add_mesh_node": {
|
|
23572
23815
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
23573
23816
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -23725,7 +23968,13 @@ var DaemonCommandRouter = class {
|
|
|
23725
23968
|
appendLedgerEntry2(meshId, {
|
|
23726
23969
|
kind: "node_removed",
|
|
23727
23970
|
nodeId,
|
|
23728
|
-
payload: {
|
|
23971
|
+
payload: {
|
|
23972
|
+
worktree: !!node?.isLocalWorktree,
|
|
23973
|
+
sessionCleanupMode,
|
|
23974
|
+
workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
|
|
23975
|
+
daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
|
|
23976
|
+
worktreeBranch: typeof node?.worktreeBranch === "string" ? node.worktreeBranch : void 0
|
|
23977
|
+
}
|
|
23729
23978
|
});
|
|
23730
23979
|
} catch {
|
|
23731
23980
|
}
|
|
@@ -23896,6 +24145,93 @@ var DaemonCommandRouter = class {
|
|
|
23896
24145
|
meshCoordinatorSetup: coordinatorSetup
|
|
23897
24146
|
};
|
|
23898
24147
|
}
|
|
24148
|
+
if (coordinatorSetup.kind === "cli_command") {
|
|
24149
|
+
let cliCmdSystemPrompt = "";
|
|
24150
|
+
try {
|
|
24151
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
24152
|
+
} catch (error) {
|
|
24153
|
+
const message = error?.message || String(error);
|
|
24154
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
24155
|
+
return {
|
|
24156
|
+
success: false,
|
|
24157
|
+
code: "mesh_coordinator_prompt_failed",
|
|
24158
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
24159
|
+
meshId,
|
|
24160
|
+
cliType,
|
|
24161
|
+
workspace
|
|
24162
|
+
};
|
|
24163
|
+
}
|
|
24164
|
+
try {
|
|
24165
|
+
const { execFileSync: execCmdSync } = await import("child_process");
|
|
24166
|
+
const cmdParts = coordinatorSetup.command.trim().split(/\s+/);
|
|
24167
|
+
const [regCmd, ...regArgs] = cmdParts;
|
|
24168
|
+
LOG.info("MeshCoordinator", `Running MCP registration: ${coordinatorSetup.command}`);
|
|
24169
|
+
execCmdSync(regCmd, regArgs, { stdio: "pipe", timeout: 15e3 });
|
|
24170
|
+
} catch (error) {
|
|
24171
|
+
LOG.warn("MeshCoordinator", `MCP registration command failed (may be pre-registered): ${error?.message || error}`);
|
|
24172
|
+
}
|
|
24173
|
+
const cliCmdArgs = [];
|
|
24174
|
+
const cliCmdEnv = {};
|
|
24175
|
+
if (cliCmdSystemPrompt) {
|
|
24176
|
+
if (cliType === "codex-cli") {
|
|
24177
|
+
cliCmdArgs.push("-c", `developer_instructions=${JSON.stringify(cliCmdSystemPrompt)}`);
|
|
24178
|
+
} else if (cliType === "gemini-cli") {
|
|
24179
|
+
try {
|
|
24180
|
+
const { writeFileSync: wfs, existsSync: efs, readFileSync: rfs } = await import("fs");
|
|
24181
|
+
const geminiMdPath = `${workspace}/GEMINI.md`;
|
|
24182
|
+
const marker = "<!-- adhdev-mesh-coordinator-prompt -->";
|
|
24183
|
+
const markerEnd = "<!-- /adhdev-mesh-coordinator-prompt -->";
|
|
24184
|
+
const block = `${marker}
|
|
24185
|
+
${cliCmdSystemPrompt}
|
|
24186
|
+
${markerEnd}`;
|
|
24187
|
+
if (efs(geminiMdPath)) {
|
|
24188
|
+
const existing = rfs(geminiMdPath, "utf-8");
|
|
24189
|
+
const replaced = existing.replace(
|
|
24190
|
+
new RegExp(`${marker}[\\s\\S]*?${markerEnd}`, "g"),
|
|
24191
|
+
block
|
|
24192
|
+
);
|
|
24193
|
+
wfs(geminiMdPath, replaced.includes(marker) ? replaced : `${existing}
|
|
24194
|
+
|
|
24195
|
+
${block}`);
|
|
24196
|
+
} else {
|
|
24197
|
+
wfs(geminiMdPath, block);
|
|
24198
|
+
}
|
|
24199
|
+
LOG.info("MeshCoordinator", `Wrote coordinator prompt to ${workspace}/GEMINI.md`);
|
|
24200
|
+
} catch (e) {
|
|
24201
|
+
LOG.warn("MeshCoordinator", `Could not write GEMINI.md: ${e?.message || e}`);
|
|
24202
|
+
}
|
|
24203
|
+
}
|
|
24204
|
+
}
|
|
24205
|
+
const cliCmdLaunch = await this.deps.cliManager.handleCliCommand("launch_cli", {
|
|
24206
|
+
cliType,
|
|
24207
|
+
dir: workspace,
|
|
24208
|
+
cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : void 0,
|
|
24209
|
+
env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : void 0,
|
|
24210
|
+
settings: { meshCoordinatorFor: meshId }
|
|
24211
|
+
});
|
|
24212
|
+
if (!cliCmdLaunch?.success) {
|
|
24213
|
+
return { success: false, error: cliCmdLaunch?.error || "Failed to launch CLI session" };
|
|
24214
|
+
}
|
|
24215
|
+
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
|
|
24216
|
+
try {
|
|
24217
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
24218
|
+
appendLedgerEntry2(meshId, {
|
|
24219
|
+
kind: "coordinator_started",
|
|
24220
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
24221
|
+
providerType: cliType,
|
|
24222
|
+
payload: { workspace }
|
|
24223
|
+
});
|
|
24224
|
+
} catch {
|
|
24225
|
+
}
|
|
24226
|
+
return {
|
|
24227
|
+
success: true,
|
|
24228
|
+
meshId,
|
|
24229
|
+
cliType,
|
|
24230
|
+
workspace,
|
|
24231
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
24232
|
+
mcpRegistered: true
|
|
24233
|
+
};
|
|
24234
|
+
}
|
|
23899
24235
|
const configFormat = coordinatorSetup.configFormat;
|
|
23900
24236
|
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
23901
24237
|
return {
|
|
@@ -23950,9 +24286,11 @@ var DaemonCommandRouter = class {
|
|
|
23950
24286
|
args: coordinatorSetup.mcpServer.args
|
|
23951
24287
|
};
|
|
23952
24288
|
if (args?.inlineMesh) {
|
|
24289
|
+
const modeArgIndex = coordinatorSetup.mcpServer.args.findIndex((value) => value === "--mode");
|
|
24290
|
+
const mcpTransport = modeArgIndex >= 0 ? coordinatorSetup.mcpServer.args[modeArgIndex + 1] : "ipc";
|
|
23953
24291
|
mcpServerEntry.env = {
|
|
23954
24292
|
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
23955
|
-
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
24293
|
+
ADHDEV_MCP_TRANSPORT: mcpTransport === "local" ? "local" : "ipc"
|
|
23956
24294
|
};
|
|
23957
24295
|
}
|
|
23958
24296
|
try {
|
|
@@ -31999,7 +32337,8 @@ async function initDaemonComponents(config) {
|
|
|
31999
32337
|
cdpManagers,
|
|
32000
32338
|
sessionRegistry,
|
|
32001
32339
|
detectedIdes: detectedIdesRef,
|
|
32002
|
-
refreshProviderAvailability
|
|
32340
|
+
refreshProviderAvailability,
|
|
32341
|
+
dispatchMeshCommand: config.dispatchMeshCommand
|
|
32003
32342
|
};
|
|
32004
32343
|
setupMeshEventForwarding(components);
|
|
32005
32344
|
return components;
|
|
@@ -32130,6 +32469,7 @@ export {
|
|
|
32130
32469
|
buildThoughtChatMessage,
|
|
32131
32470
|
buildToolChatMessage,
|
|
32132
32471
|
buildUserChatMessage,
|
|
32472
|
+
cancelTask,
|
|
32133
32473
|
claimNextTask,
|
|
32134
32474
|
classifyChatMessageVisibility,
|
|
32135
32475
|
classifyHotChatSessionsForSubscriptionFlush,
|
|
@@ -32173,6 +32513,7 @@ export {
|
|
|
32173
32513
|
getLogLevel,
|
|
32174
32514
|
getMesh,
|
|
32175
32515
|
getMeshByRepo,
|
|
32516
|
+
getMeshQueueStats,
|
|
32176
32517
|
getNpmExecOptions,
|
|
32177
32518
|
getQueue,
|
|
32178
32519
|
getRecentActivity,
|
|
@@ -32241,6 +32582,7 @@ export {
|
|
|
32241
32582
|
registerExtensionProviders,
|
|
32242
32583
|
removeNode,
|
|
32243
32584
|
removeWorktree,
|
|
32585
|
+
requeueTask,
|
|
32244
32586
|
resetConfig,
|
|
32245
32587
|
resetDebugRuntimeConfig,
|
|
32246
32588
|
resetState,
|