@adhdev/daemon-core 0.9.82-rc.22 → 0.9.82-rc.24
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/commands/router.d.ts +2 -0
- package/dist/index.js +309 -173
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +309 -173
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events.d.ts +5 -5
- package/package.json +1 -1
- package/src/commands/router.ts +68 -26
- package/src/mesh/mesh-events.ts +80 -29
- package/src/mesh/mesh-work-queue.ts +132 -119
package/dist/index.js
CHANGED
|
@@ -1360,6 +1360,36 @@ function getQueuePath(meshId) {
|
|
|
1360
1360
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1361
1361
|
return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.json`);
|
|
1362
1362
|
}
|
|
1363
|
+
function getLockPath(meshId) {
|
|
1364
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1365
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.lock`);
|
|
1366
|
+
}
|
|
1367
|
+
function withQueueLock(meshId, fn) {
|
|
1368
|
+
const lockPath = getLockPath(meshId);
|
|
1369
|
+
let fd = -1;
|
|
1370
|
+
for (let i = 0; i < 10; i++) {
|
|
1371
|
+
try {
|
|
1372
|
+
fd = (0, import_fs4.openSync)(lockPath, "wx");
|
|
1373
|
+
break;
|
|
1374
|
+
} catch {
|
|
1375
|
+
const deadline = Date.now() + 30;
|
|
1376
|
+
while (Date.now() < deadline) {
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
try {
|
|
1381
|
+
return fn();
|
|
1382
|
+
} finally {
|
|
1383
|
+
if (fd !== -1) try {
|
|
1384
|
+
(0, import_fs4.closeSync)(fd);
|
|
1385
|
+
} catch {
|
|
1386
|
+
}
|
|
1387
|
+
try {
|
|
1388
|
+
(0, import_fs4.unlinkSync)(lockPath);
|
|
1389
|
+
} catch {
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1363
1393
|
function readQueue(meshId) {
|
|
1364
1394
|
const path28 = getQueuePath(meshId);
|
|
1365
1395
|
if (!(0, import_fs4.existsSync)(path28)) return [];
|
|
@@ -1375,20 +1405,22 @@ function writeQueue(meshId, queue) {
|
|
|
1375
1405
|
(0, import_fs4.writeFileSync)(path28, JSON.stringify(queue, null, 2), "utf-8");
|
|
1376
1406
|
}
|
|
1377
1407
|
function enqueueTask(meshId, message, opts) {
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1408
|
+
return withQueueLock(meshId, () => {
|
|
1409
|
+
const queue = readQueue(meshId);
|
|
1410
|
+
const entry = {
|
|
1411
|
+
id: (0, import_crypto5.randomUUID)(),
|
|
1412
|
+
meshId,
|
|
1413
|
+
message,
|
|
1414
|
+
status: "pending",
|
|
1415
|
+
targetNodeId: opts?.targetNodeId,
|
|
1416
|
+
targetSessionId: opts?.targetSessionId,
|
|
1417
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1418
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1419
|
+
};
|
|
1420
|
+
queue.push(entry);
|
|
1421
|
+
writeQueue(meshId, queue);
|
|
1422
|
+
return entry;
|
|
1423
|
+
});
|
|
1392
1424
|
}
|
|
1393
1425
|
function getQueue(meshId, opts) {
|
|
1394
1426
|
let queue = readQueue(meshId);
|
|
@@ -1399,100 +1431,109 @@ function getQueue(meshId, opts) {
|
|
|
1399
1431
|
return queue;
|
|
1400
1432
|
}
|
|
1401
1433
|
function claimNextTask(meshId, nodeId, sessionId) {
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1434
|
+
return withQueueLock(meshId, () => {
|
|
1435
|
+
const queue = readQueue(meshId);
|
|
1436
|
+
const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
|
|
1437
|
+
if (hasActiveAssignment) return null;
|
|
1438
|
+
let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
|
|
1439
|
+
if (targetIdx === -1) {
|
|
1440
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
|
|
1441
|
+
}
|
|
1442
|
+
if (targetIdx === -1) {
|
|
1443
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
|
|
1444
|
+
}
|
|
1445
|
+
if (targetIdx === -1) return null;
|
|
1446
|
+
const entry = queue[targetIdx];
|
|
1447
|
+
entry.status = "assigned";
|
|
1448
|
+
entry.assignedNodeId = nodeId;
|
|
1449
|
+
entry.assignedSessionId = sessionId;
|
|
1450
|
+
entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1451
|
+
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1452
|
+
writeQueue(meshId, queue);
|
|
1453
|
+
return entry;
|
|
1454
|
+
});
|
|
1421
1455
|
}
|
|
1422
1456
|
function updateTaskStatus(meshId, taskId, status) {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1457
|
+
return withQueueLock(meshId, () => {
|
|
1458
|
+
const queue = readQueue(meshId);
|
|
1459
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1460
|
+
if (idx === -1) return null;
|
|
1461
|
+
queue[idx].status = status;
|
|
1462
|
+
queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1463
|
+
writeQueue(meshId, queue);
|
|
1464
|
+
return queue[idx];
|
|
1465
|
+
});
|
|
1430
1466
|
}
|
|
1431
1467
|
function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
...autoLaunch,
|
|
1438
|
-
updatedAt
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
return queue[idx];
|
|
1468
|
+
return withQueueLock(meshId, () => {
|
|
1469
|
+
const queue = readQueue(meshId);
|
|
1470
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1471
|
+
if (idx === -1) return null;
|
|
1472
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1473
|
+
queue[idx].autoLaunch = { ...autoLaunch, updatedAt: now };
|
|
1474
|
+
queue[idx].updatedAt = now;
|
|
1475
|
+
writeQueue(meshId, queue);
|
|
1476
|
+
return queue[idx];
|
|
1477
|
+
});
|
|
1443
1478
|
}
|
|
1444
1479
|
function cancelTask(meshId, taskId, opts) {
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1480
|
+
return withQueueLock(meshId, () => {
|
|
1481
|
+
const queue = readQueue(meshId);
|
|
1482
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1483
|
+
if (idx === -1) return null;
|
|
1484
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1485
|
+
queue[idx].status = "cancelled";
|
|
1486
|
+
queue[idx].updatedAt = now;
|
|
1487
|
+
queue[idx].cancelledAt = now;
|
|
1488
|
+
if (opts?.reason) queue[idx].cancelReason = opts.reason;
|
|
1489
|
+
writeQueue(meshId, queue);
|
|
1490
|
+
return queue[idx];
|
|
1491
|
+
});
|
|
1455
1492
|
}
|
|
1456
1493
|
function requeueTask(meshId, taskId, opts) {
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1494
|
+
return withQueueLock(meshId, () => {
|
|
1495
|
+
const queue = readQueue(meshId);
|
|
1496
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1497
|
+
if (idx === -1) return null;
|
|
1498
|
+
const entry = queue[idx];
|
|
1499
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1500
|
+
entry.status = "pending";
|
|
1501
|
+
delete entry.assignedNodeId;
|
|
1502
|
+
delete entry.assignedSessionId;
|
|
1503
|
+
delete entry.cancelledAt;
|
|
1504
|
+
delete entry.cancelReason;
|
|
1505
|
+
if (opts?.clearTargetNode) delete entry.targetNodeId;
|
|
1506
|
+
if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
|
|
1507
|
+
if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
|
|
1508
|
+
if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
|
|
1509
|
+
entry.updatedAt = now;
|
|
1510
|
+
entry.requeuedAt = now;
|
|
1511
|
+
entry.requeueCount = (entry.requeueCount || 0) + 1;
|
|
1512
|
+
if (opts?.reason) entry.requeueReason = opts.reason;
|
|
1513
|
+
writeQueue(meshId, queue);
|
|
1514
|
+
return entry;
|
|
1515
|
+
});
|
|
1477
1516
|
}
|
|
1478
1517
|
function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
bestTime
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1518
|
+
return withQueueLock(meshId, () => {
|
|
1519
|
+
const queue = readQueue(meshId);
|
|
1520
|
+
let bestIdx = -1;
|
|
1521
|
+
let bestTime = 0;
|
|
1522
|
+
for (let i = queue.length - 1; i >= 0; i--) {
|
|
1523
|
+
if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
|
|
1524
|
+
const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
|
|
1525
|
+
if (time > bestTime) {
|
|
1526
|
+
bestTime = time;
|
|
1527
|
+
bestIdx = i;
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
if (bestIdx === -1) return null;
|
|
1532
|
+
queue[bestIdx].status = status;
|
|
1533
|
+
queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1534
|
+
writeQueue(meshId, queue);
|
|
1535
|
+
return queue[bestIdx];
|
|
1536
|
+
});
|
|
1496
1537
|
}
|
|
1497
1538
|
function getMeshQueueStats(meshId) {
|
|
1498
1539
|
const queue = readQueue(meshId);
|
|
@@ -1901,21 +1942,70 @@ __export(mesh_events_exports, {
|
|
|
1901
1942
|
triggerMeshQueue: () => triggerMeshQueue,
|
|
1902
1943
|
tryAssignQueueTask: () => tryAssignQueueTask
|
|
1903
1944
|
});
|
|
1945
|
+
function sweepExpiredRemoteIdleSessions() {
|
|
1946
|
+
const now = Date.now();
|
|
1947
|
+
for (const [key, session] of remoteIdleSessions) {
|
|
1948
|
+
if (session.expiresAt <= now) remoteIdleSessions.delete(key);
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
function getPendingEventsPath(meshId) {
|
|
1952
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1953
|
+
return (0, import_path5.join)(getLedgerDir(), `${safe}.pending-events.jsonl`);
|
|
1954
|
+
}
|
|
1904
1955
|
function queuePendingMeshCoordinatorEvent(event) {
|
|
1905
|
-
|
|
1956
|
+
try {
|
|
1957
|
+
(0, import_fs6.appendFileSync)(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
|
|
1958
|
+
return true;
|
|
1959
|
+
} catch (e) {
|
|
1960
|
+
LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
|
|
1906
1961
|
return false;
|
|
1907
1962
|
}
|
|
1908
|
-
pendingMeshCoordinatorEvents.push(event);
|
|
1909
|
-
return true;
|
|
1910
1963
|
}
|
|
1911
|
-
function drainPendingMeshCoordinatorEvents() {
|
|
1912
|
-
|
|
1964
|
+
function drainPendingMeshCoordinatorEvents(meshId) {
|
|
1965
|
+
if (!meshId) return [];
|
|
1966
|
+
const path28 = getPendingEventsPath(meshId);
|
|
1967
|
+
if (!(0, import_fs6.existsSync)(path28)) return [];
|
|
1968
|
+
try {
|
|
1969
|
+
const raw = (0, import_fs6.readFileSync)(path28, "utf-8");
|
|
1970
|
+
try {
|
|
1971
|
+
(0, import_fs6.unlinkSync)(path28);
|
|
1972
|
+
} catch {
|
|
1973
|
+
}
|
|
1974
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
1975
|
+
try {
|
|
1976
|
+
return [JSON.parse(line)];
|
|
1977
|
+
} catch {
|
|
1978
|
+
return [];
|
|
1979
|
+
}
|
|
1980
|
+
});
|
|
1981
|
+
} catch {
|
|
1982
|
+
return [];
|
|
1983
|
+
}
|
|
1913
1984
|
}
|
|
1914
|
-
function getPendingMeshCoordinatorEvents() {
|
|
1915
|
-
|
|
1985
|
+
function getPendingMeshCoordinatorEvents(meshId) {
|
|
1986
|
+
if (!meshId) return [];
|
|
1987
|
+
const path28 = getPendingEventsPath(meshId);
|
|
1988
|
+
if (!(0, import_fs6.existsSync)(path28)) return [];
|
|
1989
|
+
try {
|
|
1990
|
+
const raw = (0, import_fs6.readFileSync)(path28, "utf-8");
|
|
1991
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
1992
|
+
try {
|
|
1993
|
+
return [JSON.parse(line)];
|
|
1994
|
+
} catch {
|
|
1995
|
+
return [];
|
|
1996
|
+
}
|
|
1997
|
+
});
|
|
1998
|
+
} catch {
|
|
1999
|
+
return [];
|
|
2000
|
+
}
|
|
1916
2001
|
}
|
|
1917
|
-
function clearPendingMeshCoordinatorEvents() {
|
|
1918
|
-
|
|
2002
|
+
function clearPendingMeshCoordinatorEvents(meshId) {
|
|
2003
|
+
if (!meshId) return;
|
|
2004
|
+
const path28 = getPendingEventsPath(meshId);
|
|
2005
|
+
if ((0, import_fs6.existsSync)(path28)) try {
|
|
2006
|
+
(0, import_fs6.unlinkSync)(path28);
|
|
2007
|
+
} catch {
|
|
2008
|
+
}
|
|
1919
2009
|
}
|
|
1920
2010
|
function readNonEmptyString(value) {
|
|
1921
2011
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
@@ -1979,7 +2069,16 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
1979
2069
|
message: task.message
|
|
1980
2070
|
}).catch((e) => {
|
|
1981
2071
|
LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
|
|
1982
|
-
updateTaskStatus(meshId, task.id, "
|
|
2072
|
+
updateTaskStatus(meshId, task.id, "pending");
|
|
2073
|
+
try {
|
|
2074
|
+
appendLedgerEntry(meshId, {
|
|
2075
|
+
kind: "dispatch_failed",
|
|
2076
|
+
nodeId,
|
|
2077
|
+
sessionId,
|
|
2078
|
+
payload: { taskId: task.id, error: e?.message, retryable: true }
|
|
2079
|
+
});
|
|
2080
|
+
} catch {
|
|
2081
|
+
}
|
|
1983
2082
|
});
|
|
1984
2083
|
return true;
|
|
1985
2084
|
}
|
|
@@ -2322,9 +2421,9 @@ function injectMeshSystemMessage(components, args) {
|
|
|
2322
2421
|
const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
2323
2422
|
completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
|
|
2324
2423
|
if (nodeId && providerType) {
|
|
2325
|
-
|
|
2424
|
+
setImmediate(() => {
|
|
2326
2425
|
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
2327
|
-
}
|
|
2426
|
+
});
|
|
2328
2427
|
}
|
|
2329
2428
|
}
|
|
2330
2429
|
} else if (args.event === "agent:ready") {
|
|
@@ -2362,13 +2461,17 @@ function injectMeshSystemMessage(components, args) {
|
|
|
2362
2461
|
}
|
|
2363
2462
|
}
|
|
2364
2463
|
if (sessionId && nodeId && providerType) {
|
|
2365
|
-
|
|
2366
|
-
|
|
2464
|
+
sweepExpiredRemoteIdleSessions();
|
|
2465
|
+
remoteIdleSessions.set(`${nodeId}:${sessionId}`, {
|
|
2466
|
+
nodeId,
|
|
2467
|
+
sessionId,
|
|
2468
|
+
providerType,
|
|
2469
|
+
expiresAt: Date.now() + REMOTE_IDLE_SESSION_TTL_MS
|
|
2470
|
+
});
|
|
2471
|
+
setImmediate(() => {
|
|
2367
2472
|
const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
2368
|
-
if (assigned) {
|
|
2369
|
-
|
|
2370
|
-
}
|
|
2371
|
-
}, 500);
|
|
2473
|
+
if (assigned) remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
2474
|
+
});
|
|
2372
2475
|
}
|
|
2373
2476
|
} else if (args.event === "agent:generating_started") {
|
|
2374
2477
|
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
@@ -2571,19 +2674,20 @@ function setupMeshEventForwarding(components) {
|
|
|
2571
2674
|
});
|
|
2572
2675
|
});
|
|
2573
2676
|
}
|
|
2574
|
-
var
|
|
2677
|
+
var import_fs6, import_path5, REMOTE_IDLE_SESSION_TTL_MS, remoteIdleSessions, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
|
|
2575
2678
|
var init_mesh_events = __esm({
|
|
2576
2679
|
"src/mesh/mesh-events.ts"() {
|
|
2577
2680
|
"use strict";
|
|
2681
|
+
import_fs6 = require("fs");
|
|
2682
|
+
import_path5 = require("path");
|
|
2578
2683
|
init_config();
|
|
2579
2684
|
init_mesh_config();
|
|
2580
2685
|
init_cli_detector();
|
|
2581
2686
|
init_logger();
|
|
2582
2687
|
init_mesh_ledger();
|
|
2583
2688
|
init_mesh_work_queue();
|
|
2689
|
+
REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
|
|
2584
2690
|
remoteIdleSessions = /* @__PURE__ */ new Map();
|
|
2585
|
-
MAX_PENDING_EVENTS = 50;
|
|
2586
|
-
pendingMeshCoordinatorEvents = [];
|
|
2587
2691
|
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
2588
2692
|
"agent:generating_started",
|
|
2589
2693
|
"agent:generating_completed",
|
|
@@ -7872,8 +7976,8 @@ var P2pRelayFailureError = class extends Error {
|
|
|
7872
7976
|
};
|
|
7873
7977
|
|
|
7874
7978
|
// src/config/state-store.ts
|
|
7875
|
-
var
|
|
7876
|
-
var
|
|
7979
|
+
var import_fs7 = require("fs");
|
|
7980
|
+
var import_path6 = require("path");
|
|
7877
7981
|
init_config();
|
|
7878
7982
|
var DEFAULT_STATE = {
|
|
7879
7983
|
recentActivity: [],
|
|
@@ -7887,7 +7991,7 @@ function isPlainObject2(value) {
|
|
|
7887
7991
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
7888
7992
|
}
|
|
7889
7993
|
function getStatePath() {
|
|
7890
|
-
return (0,
|
|
7994
|
+
return (0, import_path6.join)(getConfigDir(), "state.json");
|
|
7891
7995
|
}
|
|
7892
7996
|
function normalizeState(raw) {
|
|
7893
7997
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -7923,11 +8027,11 @@ function normalizeState(raw) {
|
|
|
7923
8027
|
}
|
|
7924
8028
|
function loadState() {
|
|
7925
8029
|
const statePath = getStatePath();
|
|
7926
|
-
if (!(0,
|
|
8030
|
+
if (!(0, import_fs7.existsSync)(statePath)) {
|
|
7927
8031
|
return { ...DEFAULT_STATE };
|
|
7928
8032
|
}
|
|
7929
8033
|
try {
|
|
7930
|
-
const raw = (0,
|
|
8034
|
+
const raw = (0, import_fs7.readFileSync)(statePath, "utf-8");
|
|
7931
8035
|
return normalizeState(JSON.parse(raw));
|
|
7932
8036
|
} catch {
|
|
7933
8037
|
return { ...DEFAULT_STATE };
|
|
@@ -7936,7 +8040,7 @@ function loadState() {
|
|
|
7936
8040
|
function saveState(state) {
|
|
7937
8041
|
const statePath = getStatePath();
|
|
7938
8042
|
const normalized = normalizeState(state);
|
|
7939
|
-
(0,
|
|
8043
|
+
(0, import_fs7.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
7940
8044
|
}
|
|
7941
8045
|
function resetState() {
|
|
7942
8046
|
saveState({ ...DEFAULT_STATE });
|
|
@@ -7944,7 +8048,7 @@ function resetState() {
|
|
|
7944
8048
|
|
|
7945
8049
|
// src/detection/ide-detector.ts
|
|
7946
8050
|
var import_child_process2 = require("child_process");
|
|
7947
|
-
var
|
|
8051
|
+
var import_fs8 = require("fs");
|
|
7948
8052
|
var import_os2 = require("os");
|
|
7949
8053
|
var path10 = __toESM(require("path"));
|
|
7950
8054
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
@@ -7968,7 +8072,7 @@ function findCliCommand(command) {
|
|
|
7968
8072
|
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
7969
8073
|
const candidate = trimmed.startsWith("~") ? path10.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
7970
8074
|
const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
|
|
7971
|
-
return (0,
|
|
8075
|
+
return (0, import_fs8.existsSync)(resolved) ? resolved : null;
|
|
7972
8076
|
}
|
|
7973
8077
|
try {
|
|
7974
8078
|
const result = (0, import_child_process2.execSync)(
|
|
@@ -7999,9 +8103,9 @@ function checkPathExists(paths) {
|
|
|
7999
8103
|
if (normalized.includes("*")) {
|
|
8000
8104
|
const username = home.split(/[\\/]/).pop() || "";
|
|
8001
8105
|
const resolved = normalized.replace("*", username);
|
|
8002
|
-
if ((0,
|
|
8106
|
+
if ((0, import_fs8.existsSync)(resolved)) return resolved;
|
|
8003
8107
|
} else {
|
|
8004
|
-
if ((0,
|
|
8108
|
+
if ((0, import_fs8.existsSync)(normalized)) return normalized;
|
|
8005
8109
|
}
|
|
8006
8110
|
}
|
|
8007
8111
|
return null;
|
|
@@ -8015,7 +8119,7 @@ async function detectIDEs(providerLoader) {
|
|
|
8015
8119
|
let resolvedCli = cliPath;
|
|
8016
8120
|
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
8017
8121
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
8018
|
-
if ((0,
|
|
8122
|
+
if ((0, import_fs8.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
8019
8123
|
}
|
|
8020
8124
|
if (!resolvedCli && appPath && os22 === "win32") {
|
|
8021
8125
|
const { dirname: dirname9 } = await import("path");
|
|
@@ -8028,7 +8132,7 @@ async function detectIDEs(providerLoader) {
|
|
|
8028
8132
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
8029
8133
|
];
|
|
8030
8134
|
for (const c of candidates) {
|
|
8031
|
-
if ((0,
|
|
8135
|
+
if ((0, import_fs8.existsSync)(c)) {
|
|
8032
8136
|
resolvedCli = c;
|
|
8033
8137
|
break;
|
|
8034
8138
|
}
|
|
@@ -17181,7 +17285,7 @@ var DaemonCommandHandler = class {
|
|
|
17181
17285
|
var os13 = __toESM(require("os"));
|
|
17182
17286
|
var path18 = __toESM(require("path"));
|
|
17183
17287
|
var crypto4 = __toESM(require("crypto"));
|
|
17184
|
-
var
|
|
17288
|
+
var import_fs9 = require("fs");
|
|
17185
17289
|
var import_child_process6 = require("child_process");
|
|
17186
17290
|
var import_chalk = __toESM(require("chalk"));
|
|
17187
17291
|
init_provider_cli_adapter();
|
|
@@ -19653,7 +19757,7 @@ function commandExists(command) {
|
|
|
19653
19757
|
const trimmed = command.trim();
|
|
19654
19758
|
if (!trimmed) return false;
|
|
19655
19759
|
if (isExplicitCommand(trimmed)) {
|
|
19656
|
-
return (0,
|
|
19760
|
+
return (0, import_fs9.existsSync)(expandExecutable(trimmed));
|
|
19657
19761
|
}
|
|
19658
19762
|
try {
|
|
19659
19763
|
(0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -19682,10 +19786,10 @@ function hasCliArg(args, flag) {
|
|
|
19682
19786
|
}
|
|
19683
19787
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
19684
19788
|
const baseDir = path18.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
19685
|
-
(0,
|
|
19789
|
+
(0, import_fs9.mkdirSync)(baseDir, { recursive: true });
|
|
19686
19790
|
const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
|
|
19687
19791
|
const filePath = path18.join(baseDir, `${workspaceHash}.json`);
|
|
19688
|
-
(0,
|
|
19792
|
+
(0, import_fs9.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
19689
19793
|
return filePath;
|
|
19690
19794
|
}
|
|
19691
19795
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
@@ -23864,7 +23968,7 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
|
|
|
23864
23968
|
|
|
23865
23969
|
// src/commands/router.ts
|
|
23866
23970
|
var import_os3 = require("os");
|
|
23867
|
-
var
|
|
23971
|
+
var import_path7 = require("path");
|
|
23868
23972
|
var fs10 = __toESM(require("fs"));
|
|
23869
23973
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
23870
23974
|
var CHANNEL_SERVER_URL = {
|
|
@@ -24188,8 +24292,21 @@ function summarizeMeshSessionRecord(record) {
|
|
|
24188
24292
|
isCached: false
|
|
24189
24293
|
};
|
|
24190
24294
|
}
|
|
24295
|
+
function liveSessionRecordMatchesMeshNode(record, meshId, nodeId) {
|
|
24296
|
+
const recordNodeId = readStringValue(record?.meta?.meshNodeId);
|
|
24297
|
+
if (!recordNodeId || recordNodeId !== nodeId) return false;
|
|
24298
|
+
const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
|
|
24299
|
+
return !recordMeshId || recordMeshId === meshId;
|
|
24300
|
+
}
|
|
24301
|
+
function liveSessionRecordMatchesMeshWorkspace(record, meshId, workspace) {
|
|
24302
|
+
const recordWorkspace = readStringValue(record?.workspace);
|
|
24303
|
+
if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
|
|
24304
|
+
const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
|
|
24305
|
+
if (recordMeshId) return recordMeshId === meshId;
|
|
24306
|
+
return record?.meta?.launchedByCoordinator === true || !!readStringValue(record?.meta?.meshNodeId);
|
|
24307
|
+
}
|
|
24191
24308
|
function readLiveMeshNodeWorkspace(args) {
|
|
24192
|
-
const directNodeWorkspace = args.liveSessionRecords.find((record) =>
|
|
24309
|
+
const directNodeWorkspace = args.liveSessionRecords.find((record) => liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId) && readStringValue(record?.workspace));
|
|
24193
24310
|
if (directNodeWorkspace) {
|
|
24194
24311
|
return readStringValue(directNodeWorkspace.workspace) || "";
|
|
24195
24312
|
}
|
|
@@ -24203,10 +24320,9 @@ function readLiveMeshNodeWorkspace(args) {
|
|
|
24203
24320
|
}
|
|
24204
24321
|
function collectLiveMeshSessionRecords(args) {
|
|
24205
24322
|
const matches = args.liveSessionRecords.filter((record) => {
|
|
24206
|
-
if (readStringValue(record?.meta?.meshNodeId) === args.nodeId) return true;
|
|
24207
|
-
const recordWorkspace = readStringValue(record?.workspace);
|
|
24208
24323
|
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
24209
|
-
|
|
24324
|
+
if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId)) return true;
|
|
24325
|
+
return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record, args.meshId, nodeWorkspace);
|
|
24210
24326
|
});
|
|
24211
24327
|
if (args.allowCoordinatorSession) {
|
|
24212
24328
|
for (const record of args.liveSessionRecords) {
|
|
@@ -24282,7 +24398,7 @@ function truncateValidationOutput(value) {
|
|
|
24282
24398
|
}
|
|
24283
24399
|
function readPackageScripts(workspace) {
|
|
24284
24400
|
try {
|
|
24285
|
-
const packageJsonPath = (0,
|
|
24401
|
+
const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
|
|
24286
24402
|
const parsed = JSON.parse(fs10.readFileSync(packageJsonPath, "utf-8"));
|
|
24287
24403
|
return parsed?.scripts && typeof parsed.scripts === "object" && !Array.isArray(parsed.scripts) ? parsed.scripts : {};
|
|
24288
24404
|
} catch {
|
|
@@ -24490,13 +24606,13 @@ function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
|
24490
24606
|
}
|
|
24491
24607
|
function resolveHermesUserHome() {
|
|
24492
24608
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
24493
|
-
return explicitHome || (0,
|
|
24609
|
+
return explicitHome || (0, import_path7.join)((0, import_os3.homedir)(), ".hermes");
|
|
24494
24610
|
}
|
|
24495
24611
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
24496
24612
|
const sourceHome = resolveHermesUserHome();
|
|
24497
|
-
const sourceConfigPath = (0,
|
|
24613
|
+
const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
|
|
24498
24614
|
if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
24499
|
-
if ((0,
|
|
24615
|
+
if ((0, import_path7.resolve)(sourceConfigPath) === (0, import_path7.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
24500
24616
|
const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
24501
24617
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
24502
24618
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
@@ -24530,10 +24646,10 @@ function stripHermesCoordinatorTempModelProviderOverrides(config) {
|
|
|
24530
24646
|
return sanitized;
|
|
24531
24647
|
}
|
|
24532
24648
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
24533
|
-
if ((0,
|
|
24649
|
+
if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
|
|
24534
24650
|
for (const fileName of [".env", "auth.json"]) {
|
|
24535
|
-
const sourcePath = (0,
|
|
24536
|
-
const targetPath = (0,
|
|
24651
|
+
const sourcePath = (0, import_path7.join)(sourceHome, fileName);
|
|
24652
|
+
const targetPath = (0, import_path7.join)(targetHome, fileName);
|
|
24537
24653
|
if (!fs10.existsSync(sourcePath)) continue;
|
|
24538
24654
|
try {
|
|
24539
24655
|
fs10.copyFileSync(sourcePath, targetPath);
|
|
@@ -24740,7 +24856,7 @@ var DaemonCommandRouter = class {
|
|
|
24740
24856
|
}
|
|
24741
24857
|
const { resolveWorktreePath: resolveWorktreePath2, listWorktrees: listWorktrees2, removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
24742
24858
|
const normalizePath = (value) => {
|
|
24743
|
-
const resolved = (0,
|
|
24859
|
+
const resolved = (0, import_path7.resolve)(value);
|
|
24744
24860
|
try {
|
|
24745
24861
|
return fs10.realpathSync(resolved);
|
|
24746
24862
|
} catch {
|
|
@@ -25141,7 +25257,8 @@ var DaemonCommandRouter = class {
|
|
|
25141
25257
|
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
|
|
25142
25258
|
}
|
|
25143
25259
|
case "get_pending_mesh_events": {
|
|
25144
|
-
const
|
|
25260
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
25261
|
+
const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
|
|
25145
25262
|
return { success: true, events };
|
|
25146
25263
|
}
|
|
25147
25264
|
case "launch_cli":
|
|
@@ -26362,7 +26479,7 @@ ${block}`);
|
|
|
26362
26479
|
workspace
|
|
26363
26480
|
};
|
|
26364
26481
|
}
|
|
26365
|
-
const { existsSync:
|
|
26482
|
+
const { existsSync: existsSync26, readFileSync: readFileSync18, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
|
|
26366
26483
|
const { dirname: dirname9 } = await import("path");
|
|
26367
26484
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
26368
26485
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -26405,14 +26522,14 @@ ${block}`);
|
|
|
26405
26522
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
26406
26523
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
26407
26524
|
}
|
|
26408
|
-
const hadExistingMcpConfig =
|
|
26525
|
+
const hadExistingMcpConfig = existsSync26(mcpConfigPath);
|
|
26409
26526
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
26410
26527
|
if (hermesBaseConfig) {
|
|
26411
26528
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
|
|
26412
26529
|
}
|
|
26413
26530
|
if (hadExistingMcpConfig) {
|
|
26414
26531
|
try {
|
|
26415
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
26532
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync18(mcpConfigPath, "utf-8"), configFormat);
|
|
26416
26533
|
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
26417
26534
|
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
26418
26535
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
@@ -26600,29 +26717,48 @@ ${block}`);
|
|
|
26600
26717
|
}
|
|
26601
26718
|
if (workspace) {
|
|
26602
26719
|
if (!fs10.existsSync(workspace)) {
|
|
26603
|
-
|
|
26604
|
-
|
|
26605
|
-
|
|
26606
|
-
|
|
26607
|
-
|
|
26608
|
-
|
|
26609
|
-
|
|
26610
|
-
|
|
26611
|
-
|
|
26720
|
+
let remoteProbeApplied = false;
|
|
26721
|
+
if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
|
|
26722
|
+
try {
|
|
26723
|
+
const remoteResult = await Promise.race([
|
|
26724
|
+
this.deps.dispatchMeshCommand(daemonId, "git_status", { workspace }),
|
|
26725
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 8e3))
|
|
26726
|
+
]);
|
|
26727
|
+
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
26728
|
+
if (remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean") {
|
|
26729
|
+
status.git = remoteGit;
|
|
26730
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
26731
|
+
remoteProbeApplied = true;
|
|
26732
|
+
}
|
|
26733
|
+
} catch {
|
|
26734
|
+
}
|
|
26612
26735
|
}
|
|
26613
|
-
|
|
26614
|
-
|
|
26615
|
-
|
|
26616
|
-
|
|
26617
|
-
|
|
26618
|
-
|
|
26619
|
-
|
|
26620
|
-
|
|
26621
|
-
|
|
26736
|
+
if (!remoteProbeApplied) {
|
|
26737
|
+
if (applyCachedInlineMeshNodeStatus(status, node)) {
|
|
26738
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
26739
|
+
nodeStatuses.push(status);
|
|
26740
|
+
continue;
|
|
26741
|
+
}
|
|
26742
|
+
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
26743
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
26744
|
+
nodeStatuses.push(status);
|
|
26745
|
+
continue;
|
|
26746
|
+
}
|
|
26622
26747
|
}
|
|
26623
|
-
}
|
|
26624
|
-
|
|
26625
|
-
|
|
26748
|
+
} else {
|
|
26749
|
+
try {
|
|
26750
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
26751
|
+
status.git = gitStatus;
|
|
26752
|
+
if (gitStatus.isGitRepo) {
|
|
26753
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
26754
|
+
} else {
|
|
26755
|
+
status.health = "degraded";
|
|
26756
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
26757
|
+
}
|
|
26758
|
+
} catch {
|
|
26759
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
26760
|
+
status.health = "degraded";
|
|
26761
|
+
}
|
|
26626
26762
|
}
|
|
26627
26763
|
}
|
|
26628
26764
|
} else {
|