@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.mjs
CHANGED
|
@@ -1351,13 +1351,43 @@ __export(mesh_work_queue_exports, {
|
|
|
1351
1351
|
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
1352
1352
|
updateTaskStatus: () => updateTaskStatus
|
|
1353
1353
|
});
|
|
1354
|
-
import { existsSync as existsSync6, writeFileSync as writeFileSync3, readFileSync as readFileSync4 } from "fs";
|
|
1354
|
+
import { existsSync as existsSync6, writeFileSync as writeFileSync3, readFileSync as readFileSync4, openSync, closeSync, unlinkSync } from "fs";
|
|
1355
1355
|
import { join as join6 } from "path";
|
|
1356
1356
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
1357
1357
|
function getQueuePath(meshId) {
|
|
1358
1358
|
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1359
1359
|
return join6(getLedgerDir(), `${safe}.queue.json`);
|
|
1360
1360
|
}
|
|
1361
|
+
function getLockPath(meshId) {
|
|
1362
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1363
|
+
return join6(getLedgerDir(), `${safe}.queue.lock`);
|
|
1364
|
+
}
|
|
1365
|
+
function withQueueLock(meshId, fn) {
|
|
1366
|
+
const lockPath = getLockPath(meshId);
|
|
1367
|
+
let fd = -1;
|
|
1368
|
+
for (let i = 0; i < 10; i++) {
|
|
1369
|
+
try {
|
|
1370
|
+
fd = openSync(lockPath, "wx");
|
|
1371
|
+
break;
|
|
1372
|
+
} catch {
|
|
1373
|
+
const deadline = Date.now() + 30;
|
|
1374
|
+
while (Date.now() < deadline) {
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
try {
|
|
1379
|
+
return fn();
|
|
1380
|
+
} finally {
|
|
1381
|
+
if (fd !== -1) try {
|
|
1382
|
+
closeSync(fd);
|
|
1383
|
+
} catch {
|
|
1384
|
+
}
|
|
1385
|
+
try {
|
|
1386
|
+
unlinkSync(lockPath);
|
|
1387
|
+
} catch {
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1361
1391
|
function readQueue(meshId) {
|
|
1362
1392
|
const path28 = getQueuePath(meshId);
|
|
1363
1393
|
if (!existsSync6(path28)) return [];
|
|
@@ -1373,20 +1403,22 @@ function writeQueue(meshId, queue) {
|
|
|
1373
1403
|
writeFileSync3(path28, JSON.stringify(queue, null, 2), "utf-8");
|
|
1374
1404
|
}
|
|
1375
1405
|
function enqueueTask(meshId, message, opts) {
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1406
|
+
return withQueueLock(meshId, () => {
|
|
1407
|
+
const queue = readQueue(meshId);
|
|
1408
|
+
const entry = {
|
|
1409
|
+
id: randomUUID5(),
|
|
1410
|
+
meshId,
|
|
1411
|
+
message,
|
|
1412
|
+
status: "pending",
|
|
1413
|
+
targetNodeId: opts?.targetNodeId,
|
|
1414
|
+
targetSessionId: opts?.targetSessionId,
|
|
1415
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1416
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1417
|
+
};
|
|
1418
|
+
queue.push(entry);
|
|
1419
|
+
writeQueue(meshId, queue);
|
|
1420
|
+
return entry;
|
|
1421
|
+
});
|
|
1390
1422
|
}
|
|
1391
1423
|
function getQueue(meshId, opts) {
|
|
1392
1424
|
let queue = readQueue(meshId);
|
|
@@ -1397,100 +1429,109 @@ function getQueue(meshId, opts) {
|
|
|
1397
1429
|
return queue;
|
|
1398
1430
|
}
|
|
1399
1431
|
function claimNextTask(meshId, nodeId, sessionId) {
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1432
|
+
return withQueueLock(meshId, () => {
|
|
1433
|
+
const queue = readQueue(meshId);
|
|
1434
|
+
const hasActiveAssignment = queue.some((q) => q.status === "assigned" && (q.assignedSessionId === sessionId || q.assignedNodeId === nodeId));
|
|
1435
|
+
if (hasActiveAssignment) return null;
|
|
1436
|
+
let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
|
|
1437
|
+
if (targetIdx === -1) {
|
|
1438
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
|
|
1439
|
+
}
|
|
1440
|
+
if (targetIdx === -1) {
|
|
1441
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
|
|
1442
|
+
}
|
|
1443
|
+
if (targetIdx === -1) return null;
|
|
1444
|
+
const entry = queue[targetIdx];
|
|
1445
|
+
entry.status = "assigned";
|
|
1446
|
+
entry.assignedNodeId = nodeId;
|
|
1447
|
+
entry.assignedSessionId = sessionId;
|
|
1448
|
+
entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1449
|
+
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1450
|
+
writeQueue(meshId, queue);
|
|
1451
|
+
return entry;
|
|
1452
|
+
});
|
|
1419
1453
|
}
|
|
1420
1454
|
function updateTaskStatus(meshId, taskId, status) {
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1455
|
+
return withQueueLock(meshId, () => {
|
|
1456
|
+
const queue = readQueue(meshId);
|
|
1457
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1458
|
+
if (idx === -1) return null;
|
|
1459
|
+
queue[idx].status = status;
|
|
1460
|
+
queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1461
|
+
writeQueue(meshId, queue);
|
|
1462
|
+
return queue[idx];
|
|
1463
|
+
});
|
|
1428
1464
|
}
|
|
1429
1465
|
function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
...autoLaunch,
|
|
1436
|
-
updatedAt
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
return queue[idx];
|
|
1466
|
+
return withQueueLock(meshId, () => {
|
|
1467
|
+
const queue = readQueue(meshId);
|
|
1468
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1469
|
+
if (idx === -1) return null;
|
|
1470
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1471
|
+
queue[idx].autoLaunch = { ...autoLaunch, updatedAt: now };
|
|
1472
|
+
queue[idx].updatedAt = now;
|
|
1473
|
+
writeQueue(meshId, queue);
|
|
1474
|
+
return queue[idx];
|
|
1475
|
+
});
|
|
1441
1476
|
}
|
|
1442
1477
|
function cancelTask(meshId, taskId, opts) {
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1478
|
+
return withQueueLock(meshId, () => {
|
|
1479
|
+
const queue = readQueue(meshId);
|
|
1480
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1481
|
+
if (idx === -1) return null;
|
|
1482
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1483
|
+
queue[idx].status = "cancelled";
|
|
1484
|
+
queue[idx].updatedAt = now;
|
|
1485
|
+
queue[idx].cancelledAt = now;
|
|
1486
|
+
if (opts?.reason) queue[idx].cancelReason = opts.reason;
|
|
1487
|
+
writeQueue(meshId, queue);
|
|
1488
|
+
return queue[idx];
|
|
1489
|
+
});
|
|
1453
1490
|
}
|
|
1454
1491
|
function requeueTask(meshId, taskId, opts) {
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1492
|
+
return withQueueLock(meshId, () => {
|
|
1493
|
+
const queue = readQueue(meshId);
|
|
1494
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
1495
|
+
if (idx === -1) return null;
|
|
1496
|
+
const entry = queue[idx];
|
|
1497
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1498
|
+
entry.status = "pending";
|
|
1499
|
+
delete entry.assignedNodeId;
|
|
1500
|
+
delete entry.assignedSessionId;
|
|
1501
|
+
delete entry.cancelledAt;
|
|
1502
|
+
delete entry.cancelReason;
|
|
1503
|
+
if (opts?.clearTargetNode) delete entry.targetNodeId;
|
|
1504
|
+
if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
|
|
1505
|
+
if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
|
|
1506
|
+
if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
|
|
1507
|
+
entry.updatedAt = now;
|
|
1508
|
+
entry.requeuedAt = now;
|
|
1509
|
+
entry.requeueCount = (entry.requeueCount || 0) + 1;
|
|
1510
|
+
if (opts?.reason) entry.requeueReason = opts.reason;
|
|
1511
|
+
writeQueue(meshId, queue);
|
|
1512
|
+
return entry;
|
|
1513
|
+
});
|
|
1475
1514
|
}
|
|
1476
1515
|
function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
bestTime
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1516
|
+
return withQueueLock(meshId, () => {
|
|
1517
|
+
const queue = readQueue(meshId);
|
|
1518
|
+
let bestIdx = -1;
|
|
1519
|
+
let bestTime = 0;
|
|
1520
|
+
for (let i = queue.length - 1; i >= 0; i--) {
|
|
1521
|
+
if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
|
|
1522
|
+
const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
|
|
1523
|
+
if (time > bestTime) {
|
|
1524
|
+
bestTime = time;
|
|
1525
|
+
bestIdx = i;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
if (bestIdx === -1) return null;
|
|
1530
|
+
queue[bestIdx].status = status;
|
|
1531
|
+
queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1532
|
+
writeQueue(meshId, queue);
|
|
1533
|
+
return queue[bestIdx];
|
|
1534
|
+
});
|
|
1494
1535
|
}
|
|
1495
1536
|
function getMeshQueueStats(meshId) {
|
|
1496
1537
|
const queue = readQueue(meshId);
|
|
@@ -1895,21 +1936,72 @@ __export(mesh_events_exports, {
|
|
|
1895
1936
|
triggerMeshQueue: () => triggerMeshQueue,
|
|
1896
1937
|
tryAssignQueueTask: () => tryAssignQueueTask
|
|
1897
1938
|
});
|
|
1939
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync9, readFileSync as readFileSync5, unlinkSync as unlinkSync3 } from "fs";
|
|
1940
|
+
import { join as join9 } from "path";
|
|
1941
|
+
function sweepExpiredRemoteIdleSessions() {
|
|
1942
|
+
const now = Date.now();
|
|
1943
|
+
for (const [key, session] of remoteIdleSessions) {
|
|
1944
|
+
if (session.expiresAt <= now) remoteIdleSessions.delete(key);
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
function getPendingEventsPath(meshId) {
|
|
1948
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1949
|
+
return join9(getLedgerDir(), `${safe}.pending-events.jsonl`);
|
|
1950
|
+
}
|
|
1898
1951
|
function queuePendingMeshCoordinatorEvent(event) {
|
|
1899
|
-
|
|
1952
|
+
try {
|
|
1953
|
+
appendFileSync3(getPendingEventsPath(event.meshId), JSON.stringify(event) + "\n", "utf-8");
|
|
1954
|
+
return true;
|
|
1955
|
+
} catch (e) {
|
|
1956
|
+
LOG.warn("MeshEvents", `Failed to persist pending coordinator event: ${e?.message || e}`);
|
|
1900
1957
|
return false;
|
|
1901
1958
|
}
|
|
1902
|
-
pendingMeshCoordinatorEvents.push(event);
|
|
1903
|
-
return true;
|
|
1904
1959
|
}
|
|
1905
|
-
function drainPendingMeshCoordinatorEvents() {
|
|
1906
|
-
|
|
1960
|
+
function drainPendingMeshCoordinatorEvents(meshId) {
|
|
1961
|
+
if (!meshId) return [];
|
|
1962
|
+
const path28 = getPendingEventsPath(meshId);
|
|
1963
|
+
if (!existsSync9(path28)) return [];
|
|
1964
|
+
try {
|
|
1965
|
+
const raw = readFileSync5(path28, "utf-8");
|
|
1966
|
+
try {
|
|
1967
|
+
unlinkSync3(path28);
|
|
1968
|
+
} catch {
|
|
1969
|
+
}
|
|
1970
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
1971
|
+
try {
|
|
1972
|
+
return [JSON.parse(line)];
|
|
1973
|
+
} catch {
|
|
1974
|
+
return [];
|
|
1975
|
+
}
|
|
1976
|
+
});
|
|
1977
|
+
} catch {
|
|
1978
|
+
return [];
|
|
1979
|
+
}
|
|
1907
1980
|
}
|
|
1908
|
-
function getPendingMeshCoordinatorEvents() {
|
|
1909
|
-
|
|
1981
|
+
function getPendingMeshCoordinatorEvents(meshId) {
|
|
1982
|
+
if (!meshId) return [];
|
|
1983
|
+
const path28 = getPendingEventsPath(meshId);
|
|
1984
|
+
if (!existsSync9(path28)) return [];
|
|
1985
|
+
try {
|
|
1986
|
+
const raw = readFileSync5(path28, "utf-8");
|
|
1987
|
+
return raw.split("\n").filter(Boolean).flatMap((line) => {
|
|
1988
|
+
try {
|
|
1989
|
+
return [JSON.parse(line)];
|
|
1990
|
+
} catch {
|
|
1991
|
+
return [];
|
|
1992
|
+
}
|
|
1993
|
+
});
|
|
1994
|
+
} catch {
|
|
1995
|
+
return [];
|
|
1996
|
+
}
|
|
1910
1997
|
}
|
|
1911
|
-
function clearPendingMeshCoordinatorEvents() {
|
|
1912
|
-
|
|
1998
|
+
function clearPendingMeshCoordinatorEvents(meshId) {
|
|
1999
|
+
if (!meshId) return;
|
|
2000
|
+
const path28 = getPendingEventsPath(meshId);
|
|
2001
|
+
if (existsSync9(path28)) try {
|
|
2002
|
+
unlinkSync3(path28);
|
|
2003
|
+
} catch {
|
|
2004
|
+
}
|
|
1913
2005
|
}
|
|
1914
2006
|
function readNonEmptyString(value) {
|
|
1915
2007
|
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
@@ -1973,7 +2065,16 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
|
|
|
1973
2065
|
message: task.message
|
|
1974
2066
|
}).catch((e) => {
|
|
1975
2067
|
LOG.error("MeshQueue", `Failed to dispatch task via P2P to remote node ${nodeId}: ${e?.message}`);
|
|
1976
|
-
updateTaskStatus(meshId, task.id, "
|
|
2068
|
+
updateTaskStatus(meshId, task.id, "pending");
|
|
2069
|
+
try {
|
|
2070
|
+
appendLedgerEntry(meshId, {
|
|
2071
|
+
kind: "dispatch_failed",
|
|
2072
|
+
nodeId,
|
|
2073
|
+
sessionId,
|
|
2074
|
+
payload: { taskId: task.id, error: e?.message, retryable: true }
|
|
2075
|
+
});
|
|
2076
|
+
} catch {
|
|
2077
|
+
}
|
|
1977
2078
|
});
|
|
1978
2079
|
return true;
|
|
1979
2080
|
}
|
|
@@ -2316,9 +2417,9 @@ function injectMeshSystemMessage(components, args) {
|
|
|
2316
2417
|
const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
2317
2418
|
completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
|
|
2318
2419
|
if (nodeId && providerType) {
|
|
2319
|
-
|
|
2420
|
+
setImmediate(() => {
|
|
2320
2421
|
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
2321
|
-
}
|
|
2422
|
+
});
|
|
2322
2423
|
}
|
|
2323
2424
|
}
|
|
2324
2425
|
} else if (args.event === "agent:ready") {
|
|
@@ -2356,13 +2457,17 @@ function injectMeshSystemMessage(components, args) {
|
|
|
2356
2457
|
}
|
|
2357
2458
|
}
|
|
2358
2459
|
if (sessionId && nodeId && providerType) {
|
|
2359
|
-
|
|
2360
|
-
|
|
2460
|
+
sweepExpiredRemoteIdleSessions();
|
|
2461
|
+
remoteIdleSessions.set(`${nodeId}:${sessionId}`, {
|
|
2462
|
+
nodeId,
|
|
2463
|
+
sessionId,
|
|
2464
|
+
providerType,
|
|
2465
|
+
expiresAt: Date.now() + REMOTE_IDLE_SESSION_TTL_MS
|
|
2466
|
+
});
|
|
2467
|
+
setImmediate(() => {
|
|
2361
2468
|
const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
2362
|
-
if (assigned) {
|
|
2363
|
-
|
|
2364
|
-
}
|
|
2365
|
-
}, 500);
|
|
2469
|
+
if (assigned) remoteIdleSessions.delete(`${nodeId}:${sessionId}`);
|
|
2470
|
+
});
|
|
2366
2471
|
}
|
|
2367
2472
|
} else if (args.event === "agent:generating_started") {
|
|
2368
2473
|
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
@@ -2565,7 +2670,7 @@ function setupMeshEventForwarding(components) {
|
|
|
2565
2670
|
});
|
|
2566
2671
|
});
|
|
2567
2672
|
}
|
|
2568
|
-
var
|
|
2673
|
+
var REMOTE_IDLE_SESSION_TTL_MS, remoteIdleSessions, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
|
|
2569
2674
|
var init_mesh_events = __esm({
|
|
2570
2675
|
"src/mesh/mesh-events.ts"() {
|
|
2571
2676
|
"use strict";
|
|
@@ -2575,9 +2680,8 @@ var init_mesh_events = __esm({
|
|
|
2575
2680
|
init_logger();
|
|
2576
2681
|
init_mesh_ledger();
|
|
2577
2682
|
init_mesh_work_queue();
|
|
2683
|
+
REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
|
|
2578
2684
|
remoteIdleSessions = /* @__PURE__ */ new Map();
|
|
2579
|
-
MAX_PENDING_EVENTS = 50;
|
|
2580
|
-
pendingMeshCoordinatorEvents = [];
|
|
2581
2685
|
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
2582
2686
|
"agent:generating_started",
|
|
2583
2687
|
"agent:generating_completed",
|
|
@@ -7635,8 +7739,8 @@ var P2pRelayFailureError = class extends Error {
|
|
|
7635
7739
|
|
|
7636
7740
|
// src/config/state-store.ts
|
|
7637
7741
|
init_config();
|
|
7638
|
-
import { existsSync as
|
|
7639
|
-
import { join as
|
|
7742
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
7743
|
+
import { join as join10 } from "path";
|
|
7640
7744
|
var DEFAULT_STATE = {
|
|
7641
7745
|
recentActivity: [],
|
|
7642
7746
|
savedProviderSessions: [],
|
|
@@ -7649,7 +7753,7 @@ function isPlainObject2(value) {
|
|
|
7649
7753
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
7650
7754
|
}
|
|
7651
7755
|
function getStatePath() {
|
|
7652
|
-
return
|
|
7756
|
+
return join10(getConfigDir(), "state.json");
|
|
7653
7757
|
}
|
|
7654
7758
|
function normalizeState(raw) {
|
|
7655
7759
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -7685,11 +7789,11 @@ function normalizeState(raw) {
|
|
|
7685
7789
|
}
|
|
7686
7790
|
function loadState() {
|
|
7687
7791
|
const statePath = getStatePath();
|
|
7688
|
-
if (!
|
|
7792
|
+
if (!existsSync10(statePath)) {
|
|
7689
7793
|
return { ...DEFAULT_STATE };
|
|
7690
7794
|
}
|
|
7691
7795
|
try {
|
|
7692
|
-
const raw =
|
|
7796
|
+
const raw = readFileSync6(statePath, "utf-8");
|
|
7693
7797
|
return normalizeState(JSON.parse(raw));
|
|
7694
7798
|
} catch {
|
|
7695
7799
|
return { ...DEFAULT_STATE };
|
|
@@ -7706,7 +7810,7 @@ function resetState() {
|
|
|
7706
7810
|
|
|
7707
7811
|
// src/detection/ide-detector.ts
|
|
7708
7812
|
import { execSync } from "child_process";
|
|
7709
|
-
import { existsSync as
|
|
7813
|
+
import { existsSync as existsSync11 } from "fs";
|
|
7710
7814
|
import { platform as platform2, homedir as homedir5 } from "os";
|
|
7711
7815
|
import * as path10 from "path";
|
|
7712
7816
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
@@ -7730,7 +7834,7 @@ function findCliCommand(command) {
|
|
|
7730
7834
|
if (path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
7731
7835
|
const candidate = trimmed.startsWith("~") ? path10.join(homedir5(), trimmed.slice(1)) : trimmed;
|
|
7732
7836
|
const resolved = path10.isAbsolute(candidate) ? candidate : path10.resolve(candidate);
|
|
7733
|
-
return
|
|
7837
|
+
return existsSync11(resolved) ? resolved : null;
|
|
7734
7838
|
}
|
|
7735
7839
|
try {
|
|
7736
7840
|
const result = execSync(
|
|
@@ -7761,9 +7865,9 @@ function checkPathExists(paths) {
|
|
|
7761
7865
|
if (normalized.includes("*")) {
|
|
7762
7866
|
const username = home.split(/[\\/]/).pop() || "";
|
|
7763
7867
|
const resolved = normalized.replace("*", username);
|
|
7764
|
-
if (
|
|
7868
|
+
if (existsSync11(resolved)) return resolved;
|
|
7765
7869
|
} else {
|
|
7766
|
-
if (
|
|
7870
|
+
if (existsSync11(normalized)) return normalized;
|
|
7767
7871
|
}
|
|
7768
7872
|
}
|
|
7769
7873
|
return null;
|
|
@@ -7777,7 +7881,7 @@ async function detectIDEs(providerLoader) {
|
|
|
7777
7881
|
let resolvedCli = cliPath;
|
|
7778
7882
|
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
7779
7883
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
7780
|
-
if (
|
|
7884
|
+
if (existsSync11(bundledCli)) resolvedCli = bundledCli;
|
|
7781
7885
|
}
|
|
7782
7886
|
if (!resolvedCli && appPath && os22 === "win32") {
|
|
7783
7887
|
const { dirname: dirname9 } = await import("path");
|
|
@@ -7790,7 +7894,7 @@ async function detectIDEs(providerLoader) {
|
|
|
7790
7894
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
7791
7895
|
];
|
|
7792
7896
|
for (const c of candidates) {
|
|
7793
|
-
if (
|
|
7897
|
+
if (existsSync11(c)) {
|
|
7794
7898
|
resolvedCli = c;
|
|
7795
7899
|
break;
|
|
7796
7900
|
}
|
|
@@ -16946,7 +17050,7 @@ init_config();
|
|
|
16946
17050
|
import * as os13 from "os";
|
|
16947
17051
|
import * as path18 from "path";
|
|
16948
17052
|
import * as crypto4 from "crypto";
|
|
16949
|
-
import { existsSync as
|
|
17053
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
16950
17054
|
import { execFileSync } from "child_process";
|
|
16951
17055
|
import chalk from "chalk";
|
|
16952
17056
|
|
|
@@ -19420,7 +19524,7 @@ function commandExists(command) {
|
|
|
19420
19524
|
const trimmed = command.trim();
|
|
19421
19525
|
if (!trimmed) return false;
|
|
19422
19526
|
if (isExplicitCommand(trimmed)) {
|
|
19423
|
-
return
|
|
19527
|
+
return existsSync15(expandExecutable(trimmed));
|
|
19424
19528
|
}
|
|
19425
19529
|
try {
|
|
19426
19530
|
execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -22689,10 +22793,10 @@ import * as yaml from "js-yaml";
|
|
|
22689
22793
|
// src/commands/mesh-coordinator.ts
|
|
22690
22794
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
22691
22795
|
import { createHash as createHash2 } from "crypto";
|
|
22692
|
-
import { existsSync as
|
|
22796
|
+
import { existsSync as existsSync18, readdirSync as readdirSync7, realpathSync as realpathSync2 } from "fs";
|
|
22693
22797
|
import { createRequire as createRequire2 } from "module";
|
|
22694
22798
|
import * as os17 from "os";
|
|
22695
|
-
import { dirname as dirname4, isAbsolute as isAbsolute11, join as
|
|
22799
|
+
import { dirname as dirname4, isAbsolute as isAbsolute11, join as join21, resolve as resolve13 } from "path";
|
|
22696
22800
|
var DEFAULT_SERVER_NAME = "adhdev-mesh";
|
|
22697
22801
|
var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
|
|
22698
22802
|
var HERMES_CLI_TYPE = "hermes-cli";
|
|
@@ -22715,7 +22819,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
|
|
|
22715
22819
|
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
22716
22820
|
};
|
|
22717
22821
|
}
|
|
22718
|
-
const configPath =
|
|
22822
|
+
const configPath = join21(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
|
|
22719
22823
|
if (!configPath.trim()) {
|
|
22720
22824
|
return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
|
|
22721
22825
|
}
|
|
@@ -22836,14 +22940,14 @@ function resolveHermesCoordinatorHome(meshId, workspace) {
|
|
|
22836
22940
|
const key = `${meshId || "mesh"}
|
|
22837
22941
|
${resolve13(workspace || os17.tmpdir())}`;
|
|
22838
22942
|
const hash = createHash2("sha256").update(key).digest("hex").slice(0, 16);
|
|
22839
|
-
return
|
|
22943
|
+
return join21(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
|
|
22840
22944
|
}
|
|
22841
22945
|
function resolveMcpConfigPath(configPath, workspace) {
|
|
22842
22946
|
const trimmed = configPath.trim();
|
|
22843
22947
|
if (trimmed === "~") return os17.homedir();
|
|
22844
|
-
if (trimmed.startsWith("~/")) return
|
|
22948
|
+
if (trimmed.startsWith("~/")) return join21(os17.homedir(), trimmed.slice(2));
|
|
22845
22949
|
if (isAbsolute11(trimmed)) return trimmed;
|
|
22846
|
-
return
|
|
22950
|
+
return join21(workspace, trimmed);
|
|
22847
22951
|
}
|
|
22848
22952
|
function resolveAdhdevMcpServerLaunch(options) {
|
|
22849
22953
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
|
|
@@ -22899,15 +23003,15 @@ function addNodeCandidatesFromPath(pathValue, addCandidate) {
|
|
|
22899
23003
|
for (const entry of (pathValue || "").split(":")) {
|
|
22900
23004
|
const dir = entry.trim();
|
|
22901
23005
|
if (!dir) continue;
|
|
22902
|
-
addCandidate(
|
|
23006
|
+
addCandidate(join21(dir, "node"));
|
|
22903
23007
|
}
|
|
22904
23008
|
}
|
|
22905
23009
|
function addNodeCandidatesFromNvm(homeDir, addCandidate) {
|
|
22906
|
-
const versionsDir =
|
|
23010
|
+
const versionsDir = join21(homeDir, ".nvm", "versions", "node");
|
|
22907
23011
|
try {
|
|
22908
23012
|
const versionDirs = readdirSync7(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
|
|
22909
23013
|
for (const versionDir of versionDirs) {
|
|
22910
|
-
addCandidate(
|
|
23014
|
+
addCandidate(join21(versionsDir, versionDir, "bin", "node"));
|
|
22911
23015
|
}
|
|
22912
23016
|
} catch {
|
|
22913
23017
|
}
|
|
@@ -22958,7 +23062,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
22958
23062
|
if (normalized) return normalized;
|
|
22959
23063
|
}
|
|
22960
23064
|
try {
|
|
22961
|
-
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] :
|
|
23065
|
+
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join21(process.cwd(), "adhdev-daemon.js");
|
|
22962
23066
|
const req = createRequire2(requireBase);
|
|
22963
23067
|
const resolvedModule = req.resolve("@adhdev/mcp-server");
|
|
22964
23068
|
return normalizeExistingPath(resolvedModule) || resolvedModule;
|
|
@@ -22968,7 +23072,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
22968
23072
|
}
|
|
22969
23073
|
function normalizeExistingPath(filePath) {
|
|
22970
23074
|
try {
|
|
22971
|
-
if (!
|
|
23075
|
+
if (!existsSync18(filePath)) return null;
|
|
22972
23076
|
return realpathSync2.native(filePath);
|
|
22973
23077
|
} catch {
|
|
22974
23078
|
return null;
|
|
@@ -23955,8 +24059,21 @@ function summarizeMeshSessionRecord(record) {
|
|
|
23955
24059
|
isCached: false
|
|
23956
24060
|
};
|
|
23957
24061
|
}
|
|
24062
|
+
function liveSessionRecordMatchesMeshNode(record, meshId, nodeId) {
|
|
24063
|
+
const recordNodeId = readStringValue(record?.meta?.meshNodeId);
|
|
24064
|
+
if (!recordNodeId || recordNodeId !== nodeId) return false;
|
|
24065
|
+
const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
|
|
24066
|
+
return !recordMeshId || recordMeshId === meshId;
|
|
24067
|
+
}
|
|
24068
|
+
function liveSessionRecordMatchesMeshWorkspace(record, meshId, workspace) {
|
|
24069
|
+
const recordWorkspace = readStringValue(record?.workspace);
|
|
24070
|
+
if (!recordWorkspace || !workspace || recordWorkspace !== workspace) return false;
|
|
24071
|
+
const recordMeshId = readStringValue(record?.meta?.meshNodeFor);
|
|
24072
|
+
if (recordMeshId) return recordMeshId === meshId;
|
|
24073
|
+
return record?.meta?.launchedByCoordinator === true || !!readStringValue(record?.meta?.meshNodeId);
|
|
24074
|
+
}
|
|
23958
24075
|
function readLiveMeshNodeWorkspace(args) {
|
|
23959
|
-
const directNodeWorkspace = args.liveSessionRecords.find((record) =>
|
|
24076
|
+
const directNodeWorkspace = args.liveSessionRecords.find((record) => liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId) && readStringValue(record?.workspace));
|
|
23960
24077
|
if (directNodeWorkspace) {
|
|
23961
24078
|
return readStringValue(directNodeWorkspace.workspace) || "";
|
|
23962
24079
|
}
|
|
@@ -23970,10 +24087,9 @@ function readLiveMeshNodeWorkspace(args) {
|
|
|
23970
24087
|
}
|
|
23971
24088
|
function collectLiveMeshSessionRecords(args) {
|
|
23972
24089
|
const matches = args.liveSessionRecords.filter((record) => {
|
|
23973
|
-
if (readStringValue(record?.meta?.meshNodeId) === args.nodeId) return true;
|
|
23974
|
-
const recordWorkspace = readStringValue(record?.workspace);
|
|
23975
24090
|
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
23976
|
-
|
|
24091
|
+
if (liveSessionRecordMatchesMeshNode(record, args.meshId, args.nodeId)) return true;
|
|
24092
|
+
return !!nodeWorkspace && liveSessionRecordMatchesMeshWorkspace(record, args.meshId, nodeWorkspace);
|
|
23977
24093
|
});
|
|
23978
24094
|
if (args.allowCoordinatorSession) {
|
|
23979
24095
|
for (const record of args.liveSessionRecords) {
|
|
@@ -24908,7 +25024,8 @@ var DaemonCommandRouter = class {
|
|
|
24908
25024
|
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
|
|
24909
25025
|
}
|
|
24910
25026
|
case "get_pending_mesh_events": {
|
|
24911
|
-
const
|
|
25027
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
25028
|
+
const events = drainPendingMeshCoordinatorEvents(meshId || void 0);
|
|
24912
25029
|
return { success: true, events };
|
|
24913
25030
|
}
|
|
24914
25031
|
case "launch_cli":
|
|
@@ -26129,7 +26246,7 @@ ${block}`);
|
|
|
26129
26246
|
workspace
|
|
26130
26247
|
};
|
|
26131
26248
|
}
|
|
26132
|
-
const { existsSync:
|
|
26249
|
+
const { existsSync: existsSync26, readFileSync: readFileSync18, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
|
|
26133
26250
|
const { dirname: dirname9 } = await import("path");
|
|
26134
26251
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
26135
26252
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -26172,14 +26289,14 @@ ${block}`);
|
|
|
26172
26289
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
26173
26290
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
26174
26291
|
}
|
|
26175
|
-
const hadExistingMcpConfig =
|
|
26292
|
+
const hadExistingMcpConfig = existsSync26(mcpConfigPath);
|
|
26176
26293
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
26177
26294
|
if (hermesBaseConfig) {
|
|
26178
26295
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
|
|
26179
26296
|
}
|
|
26180
26297
|
if (hadExistingMcpConfig) {
|
|
26181
26298
|
try {
|
|
26182
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
26299
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync18(mcpConfigPath, "utf-8"), configFormat);
|
|
26183
26300
|
const existingCoordinatorConfig = hermesManualFallback ? stripHermesCoordinatorTempModelProviderOverrides(parsedExistingMcpConfig) : parsedExistingMcpConfig;
|
|
26184
26301
|
existingMcpConfig = { ...existingMcpConfig, ...existingCoordinatorConfig };
|
|
26185
26302
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
@@ -26367,29 +26484,48 @@ ${block}`);
|
|
|
26367
26484
|
}
|
|
26368
26485
|
if (workspace) {
|
|
26369
26486
|
if (!fs10.existsSync(workspace)) {
|
|
26370
|
-
|
|
26371
|
-
|
|
26372
|
-
|
|
26373
|
-
|
|
26374
|
-
|
|
26375
|
-
|
|
26376
|
-
|
|
26377
|
-
|
|
26378
|
-
|
|
26487
|
+
let remoteProbeApplied = false;
|
|
26488
|
+
if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
|
|
26489
|
+
try {
|
|
26490
|
+
const remoteResult = await Promise.race([
|
|
26491
|
+
this.deps.dispatchMeshCommand(daemonId, "git_status", { workspace }),
|
|
26492
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 8e3))
|
|
26493
|
+
]);
|
|
26494
|
+
const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
|
|
26495
|
+
if (remoteGit && typeof remoteGit === "object" && typeof remoteGit.isGitRepo === "boolean") {
|
|
26496
|
+
status.git = remoteGit;
|
|
26497
|
+
status.health = remoteGit.isGitRepo ? deriveMeshNodeHealthFromGit(remoteGit) : "degraded";
|
|
26498
|
+
remoteProbeApplied = true;
|
|
26499
|
+
}
|
|
26500
|
+
} catch {
|
|
26501
|
+
}
|
|
26379
26502
|
}
|
|
26380
|
-
|
|
26381
|
-
|
|
26382
|
-
|
|
26383
|
-
|
|
26384
|
-
|
|
26385
|
-
|
|
26386
|
-
|
|
26387
|
-
|
|
26388
|
-
|
|
26503
|
+
if (!remoteProbeApplied) {
|
|
26504
|
+
if (applyCachedInlineMeshNodeStatus(status, node)) {
|
|
26505
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
26506
|
+
nodeStatuses.push(status);
|
|
26507
|
+
continue;
|
|
26508
|
+
}
|
|
26509
|
+
if (meshRecord?.source === "inline_cache" && !isSelfNode) {
|
|
26510
|
+
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === "online" || isSelfNode);
|
|
26511
|
+
nodeStatuses.push(status);
|
|
26512
|
+
continue;
|
|
26513
|
+
}
|
|
26389
26514
|
}
|
|
26390
|
-
}
|
|
26391
|
-
|
|
26392
|
-
|
|
26515
|
+
} else {
|
|
26516
|
+
try {
|
|
26517
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 1e4, refreshUpstream: true });
|
|
26518
|
+
status.git = gitStatus;
|
|
26519
|
+
if (gitStatus.isGitRepo) {
|
|
26520
|
+
status.health = deriveMeshNodeHealthFromGit(gitStatus);
|
|
26521
|
+
} else {
|
|
26522
|
+
status.health = "degraded";
|
|
26523
|
+
if (gitStatus.error && !status.error) status.error = gitStatus.error;
|
|
26524
|
+
}
|
|
26525
|
+
} catch {
|
|
26526
|
+
if (!applyCachedInlineMeshNodeStatus(status, node)) {
|
|
26527
|
+
status.health = "degraded";
|
|
26528
|
+
}
|
|
26393
26529
|
}
|
|
26394
26530
|
}
|
|
26395
26531
|
} else {
|