@adhdev/daemon-standalone 1.0.38 → 1.0.39-rc.10
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/index.js +3052 -4246
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/public/assets/{index-69StxR7K.css → index-BRvsAKU_.css} +1 -1
- package/public/assets/index-Hsc3-7gC.js +121 -0
- package/public/assets/{terminal-BZj_X5zy.js → terminal-BiinNPQS.js} +1 -1
- package/public/assets/{vendor-cL4V2vaO.js → vendor-DgFmqOGd.js} +1 -1
- package/public/index.html +3 -3
- package/vendor/mcp-server/index.js +358 -199
- package/vendor/mcp-server/index.js.map +1 -1
- package/vendor/session-host-daemon/index.js +0 -0
- package/vendor/session-host-daemon/index.mjs +0 -0
- package/public/assets/index-B7t7s0FW.js +0 -121
|
@@ -36,7 +36,8 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/transports/ipc.ts
|
|
39
|
-
var
|
|
39
|
+
var import_daemon_core = require("@adhdev/daemon-core");
|
|
40
|
+
var DEFAULT_IPC_PORT = import_daemon_core.IDENTITY.defaultPort;
|
|
40
41
|
var DEFAULT_IPC_PATH = "/ipc";
|
|
41
42
|
var DEFAULT_IPC_COMMAND_TIMEOUT_MS = 15e3;
|
|
42
43
|
var IPC_COMMAND_TIMEOUTS_MS = {
|
|
@@ -621,7 +622,7 @@ function withStatusProbeMarker(args = {}) {
|
|
|
621
622
|
}
|
|
622
623
|
|
|
623
624
|
// src/tools/mesh-tools-internal.ts
|
|
624
|
-
var
|
|
625
|
+
var import_daemon_core4 = require("@adhdev/daemon-core");
|
|
625
626
|
|
|
626
627
|
// src/tools/mesh-tool-shared.ts
|
|
627
628
|
function readString(value) {
|
|
@@ -672,7 +673,7 @@ function elideLargeNestedValue(key, value) {
|
|
|
672
673
|
}
|
|
673
674
|
|
|
674
675
|
// src/tools/mesh-session-helpers.ts
|
|
675
|
-
var
|
|
676
|
+
var import_daemon_core2 = require("@adhdev/daemon-core");
|
|
676
677
|
function readSessionRecordId(session) {
|
|
677
678
|
return readString(session?.id) || readString(session?.sessionId) || readString(session?.session_id) || readString(session?.runtimeSessionId) || readString(session?.runtime_session_id) || readString(session?.instanceId) || readString(session?.instance_id);
|
|
678
679
|
}
|
|
@@ -701,7 +702,7 @@ function isUnmanagedSessionRecord(session) {
|
|
|
701
702
|
return !launchedByCoordinator;
|
|
702
703
|
}
|
|
703
704
|
function isWorkerTaskMode(taskMode, readonly) {
|
|
704
|
-
return !(0,
|
|
705
|
+
return !(0, import_daemon_core2.isTaskReadonly)({ readonly, taskMode });
|
|
705
706
|
}
|
|
706
707
|
function addSessionRecord(target, session) {
|
|
707
708
|
if (!session || typeof session !== "object" || isTerminalSessionRecord(session)) return;
|
|
@@ -766,7 +767,7 @@ function isIdleSessionRecord(session) {
|
|
|
766
767
|
}
|
|
767
768
|
|
|
768
769
|
// src/tools/mesh-node-identity.ts
|
|
769
|
-
var
|
|
770
|
+
var import_daemon_core3 = require("@adhdev/daemon-core");
|
|
770
771
|
function resolveCoordinatorNode(ctx) {
|
|
771
772
|
const preferredNodeId = typeof ctx.mesh.coordinator?.preferredNodeId === "string" ? ctx.mesh.coordinator.preferredNodeId.trim() : "";
|
|
772
773
|
if (preferredNodeId) {
|
|
@@ -778,13 +779,13 @@ function resolveCoordinatorNode(ctx) {
|
|
|
778
779
|
if (byMachine) return byMachine;
|
|
779
780
|
}
|
|
780
781
|
if (ctx.localDaemonId) {
|
|
781
|
-
return ctx.mesh.nodes.find((n) => (0,
|
|
782
|
+
return ctx.mesh.nodes.find((n) => (0, import_daemon_core3.daemonIdsEquivalent)(readNodeDaemonId(n), ctx.localDaemonId));
|
|
782
783
|
}
|
|
783
784
|
return void 0;
|
|
784
785
|
}
|
|
785
786
|
function resolveCoordinatorDaemonId(ctx) {
|
|
786
787
|
const resolved = readString(resolveCoordinatorNode(ctx)?.daemonId) || readString(ctx.localDaemonId) || readString(ctx.localMachineId);
|
|
787
|
-
return (0,
|
|
788
|
+
return (0, import_daemon_core3.canonicalDaemonId)(resolved) ?? readString(resolved);
|
|
788
789
|
}
|
|
789
790
|
function readNodeMachineId(node) {
|
|
790
791
|
return readString(node.machineId) || readString(node.machine_id) || readString(node.machine?.id) || readString(node.machine?.machineId) || readString(node.lastProbe?.machineId) || readString(node.last_probe?.machine_id) || readString(node.lastProbe?.machine?.id) || readString(node.lastProbe?.machine?.machineId) || readString(node.last_probe?.machine?.id) || readString(node.last_probe?.machine?.machine_id);
|
|
@@ -851,8 +852,8 @@ function buildNodeMachineIdentity(ctx, node) {
|
|
|
851
852
|
function nodeHasLocalDaemonEvidence(ctx, node) {
|
|
852
853
|
const isLocal = (session) => {
|
|
853
854
|
if (!session || typeof session !== "object") return false;
|
|
854
|
-
if (ctx.localDaemonId && (0,
|
|
855
|
-
if (ctx.localDaemonId && (0,
|
|
855
|
+
if (ctx.localDaemonId && (0, import_daemon_core3.daemonIdsEquivalent)(session.runtime?.owner, ctx.localDaemonId)) return true;
|
|
856
|
+
if (ctx.localDaemonId && (0, import_daemon_core3.daemonIdsEquivalent)(session.daemonClient?.daemonId, ctx.localDaemonId)) return true;
|
|
856
857
|
return false;
|
|
857
858
|
};
|
|
858
859
|
const sessionArrays = [
|
|
@@ -891,7 +892,7 @@ function isDirectLocalNode(ctx, node) {
|
|
|
891
892
|
const machineId = readNodeMachineId(node);
|
|
892
893
|
const daemonId = readNodeDaemonId(node);
|
|
893
894
|
return Boolean(
|
|
894
|
-
ctx.localMachineId && (0,
|
|
895
|
+
ctx.localMachineId && (0, import_daemon_core3.daemonIdsEquivalent)(machineId, ctx.localMachineId) || ctx.localDaemonId && (0, import_daemon_core3.daemonIdsEquivalent)(daemonId, ctx.localDaemonId) || nodeHasLocalDaemonEvidence(ctx, node)
|
|
895
896
|
);
|
|
896
897
|
}
|
|
897
898
|
function isConfiguredCoordinatorNode(ctx, node) {
|
|
@@ -900,8 +901,8 @@ function isConfiguredCoordinatorNode(ctx, node) {
|
|
|
900
901
|
if (!nodeId) return false;
|
|
901
902
|
const nodeDaemonId = readNodeDaemonId(node);
|
|
902
903
|
const nodeMachineId = readNodeMachineId(node);
|
|
903
|
-
if (nodeDaemonId && ctx.localDaemonId && !(0,
|
|
904
|
-
if (nodeMachineId && ctx.localMachineId && !(0,
|
|
904
|
+
if (nodeDaemonId && ctx.localDaemonId && !(0, import_daemon_core3.daemonIdsEquivalent)(nodeDaemonId, ctx.localDaemonId)) return false;
|
|
905
|
+
if (nodeMachineId && ctx.localMachineId && !(0, import_daemon_core3.daemonIdsEquivalent)(nodeMachineId, ctx.localMachineId)) return false;
|
|
905
906
|
const preferredNodeId = readString(ctx.mesh.coordinator?.preferredNodeId) || readString(ctx.mesh.coordinator?.preferred_node_id);
|
|
906
907
|
if (preferredNodeId) return nodeId === preferredNodeId;
|
|
907
908
|
const first = ctx.mesh.nodes?.[0];
|
|
@@ -921,7 +922,7 @@ function getLocalControlPlaneMatchReason(ctx, node) {
|
|
|
921
922
|
function findClonedFromNode(ctx, node) {
|
|
922
923
|
const clonedFromNodeId = readString(node.clonedFromNodeId) || readString(node.cloned_from_node_id);
|
|
923
924
|
if (!clonedFromNodeId) return void 0;
|
|
924
|
-
return ctx.mesh.nodes.find((n) => (0,
|
|
925
|
+
return ctx.mesh.nodes.find((n) => (0, import_daemon_core3.meshNodeIdMatches)(n, clonedFromNodeId));
|
|
925
926
|
}
|
|
926
927
|
function resolvePreferredWorktreeNodeId(ctx) {
|
|
927
928
|
const worktreeNodes = (ctx.mesh.nodes || []).filter((n) => n.isLocalWorktree === true);
|
|
@@ -936,7 +937,7 @@ function isLocalControlPlaneNode(ctx, node) {
|
|
|
936
937
|
// src/tools/mesh-tool-schemas.ts
|
|
937
938
|
var MESH_STATUS_TOOL = {
|
|
938
939
|
name: "mesh_status",
|
|
939
|
-
description:
|
|
940
|
+
description: `Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions, recovery hints, and recommended next steps. Use this to decide which node to send work to or how to recover from failures. Also reports the running daemon build per daemonId under top-level daemonBuilds ({commit, commitShort, version}); when a live daemon was built from a commit BEHIND its workspace HEAD it adds staleDaemonBuilds[] + staleDaemonBuildWarning \u2014 meaning a just-merged refinery/mesh-tool fix is NOT yet live on that daemon (awaiting deploy/restart; a local dist rebuild does not update a cloud daemon). When a daemon has a durable failed-upgrade notice on record it adds daemonUpgradeFailures{daemonId \u2192 {summary, recordedAt, ageLabel, targetVersion, noticePath, logPath}} + daemonUpgradeFailureWarning \u2014 meaning that daemon's LAST upgrade attempt failed and was rolled back, so it is still on the PREVIOUS version (an upgrade/restart response only ever reports "scheduled", never success). Do not repeatedly call this to wait for generating delegated work; wait for pendingCoordinatorEvents/completion events or an explicit user status request.`,
|
|
940
941
|
inputSchema: {
|
|
941
942
|
type: "object",
|
|
942
943
|
properties: {
|
|
@@ -966,7 +967,7 @@ var MESH_ENQUEUE_TASK_TOOL = {
|
|
|
966
967
|
type: "object",
|
|
967
968
|
properties: {
|
|
968
969
|
message: { type: "string", description: "The task instruction for the agent." },
|
|
969
|
-
task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before dispatch." },
|
|
970
|
+
task_mode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "Optional task-mode contract. live_debug_readonly rejects obvious write/commit/push/deploy/destructive instructions before dispatch \u2014 and in exchange runs without the one-active-per-node write isolation (N read-only tasks may run in parallel on one busy node, no worktree needed) under a separate, larger read-only concurrency cap. Prefer it for investigation/diagnosis: it is the cheaper mode to schedule, not just the restricted one." },
|
|
970
971
|
taskMode: { type: "string", enum: ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"], description: "CamelCase alias for task_mode." },
|
|
971
972
|
readonly: { type: "boolean", description: "Optional read-only axis (orthogonal to task_mode). When true the task runs without the one-active-per-node write isolation (N read-only tasks may run in parallel on one node), is counted under the read-only safety cap, and rejects write/commit/push/deploy/destructive instructions like live_debug_readonly. Equivalent to task_mode=live_debug_readonly but composable with any task_mode." },
|
|
972
973
|
read_only: { type: "boolean", description: "Snake-case alias for readonly." },
|
|
@@ -1883,7 +1884,7 @@ function summarizeCompactSubmodules(submodules) {
|
|
|
1883
1884
|
...outOfSync.length > 0 ? { outOfSyncPaths: outOfSync } : {}
|
|
1884
1885
|
};
|
|
1885
1886
|
}
|
|
1886
|
-
var MESH_COMPACT_PRESERVED_MARKER_FIELDS = ["dataFreshness", "quota"];
|
|
1887
|
+
var MESH_COMPACT_PRESERVED_MARKER_FIELDS = ["dataFreshness", "quota", "isLocalWorktree"];
|
|
1887
1888
|
function summarizeNodeQuota(quota) {
|
|
1888
1889
|
if (!quota || typeof quota !== "object" || Array.isArray(quota)) return void 0;
|
|
1889
1890
|
const out = {};
|
|
@@ -1959,6 +1960,27 @@ function compactNodeSeverity(entry) {
|
|
|
1959
1960
|
if (entry.staleDaemonBuild || entry.submodulesOutOfSync || entry.recoveryHints) return 1;
|
|
1960
1961
|
return 0;
|
|
1961
1962
|
}
|
|
1963
|
+
function pinnedRepresentativeNodeIds(compacted) {
|
|
1964
|
+
const byDaemon = /* @__PURE__ */ new Map();
|
|
1965
|
+
for (const n of compacted) {
|
|
1966
|
+
if (!n || typeof n !== "object") continue;
|
|
1967
|
+
const daemonId = typeof n.daemonId === "string" && n.daemonId ? n.daemonId : "";
|
|
1968
|
+
if (!daemonId) continue;
|
|
1969
|
+
const current = byDaemon.get(daemonId);
|
|
1970
|
+
if (!current) {
|
|
1971
|
+
byDaemon.set(daemonId, n);
|
|
1972
|
+
continue;
|
|
1973
|
+
}
|
|
1974
|
+
if (current.isLocalWorktree === true && n.isLocalWorktree !== true) {
|
|
1975
|
+
byDaemon.set(daemonId, n);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
const pinned = /* @__PURE__ */ new Set();
|
|
1979
|
+
for (const n of byDaemon.values()) {
|
|
1980
|
+
if (n?.nodeId !== void 0) pinned.add(String(n.nodeId));
|
|
1981
|
+
}
|
|
1982
|
+
return pinned;
|
|
1983
|
+
}
|
|
1962
1984
|
function isNoteworthyCompactNode(entry) {
|
|
1963
1985
|
if (!entry || typeof entry !== "object") return true;
|
|
1964
1986
|
if (entry.health && entry.health !== "online") return true;
|
|
@@ -2316,7 +2338,7 @@ function annotateRapidReadChatAdvisory(payload, options) {
|
|
|
2316
2338
|
}
|
|
2317
2339
|
|
|
2318
2340
|
// src/tools/mesh-tools-internal.ts
|
|
2319
|
-
var
|
|
2341
|
+
var import_daemon_core5 = require("@adhdev/daemon-core");
|
|
2320
2342
|
var import_node_crypto = require("crypto");
|
|
2321
2343
|
var SESSION_PROVIDER_METADATA_TTL_MS = 30 * 6e4;
|
|
2322
2344
|
var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
|
|
@@ -2376,20 +2398,38 @@ function buildDirectTaskPayload(message, via, opts) {
|
|
|
2376
2398
|
};
|
|
2377
2399
|
}
|
|
2378
2400
|
function findNode(mesh, nodeId) {
|
|
2379
|
-
const node = mesh.nodes.find((n) => (0,
|
|
2401
|
+
const node = mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
|
|
2380
2402
|
if (!node) throw new Error(`Node '${nodeId}' is not a member of mesh '${mesh.name}'`);
|
|
2381
2403
|
return node;
|
|
2382
2404
|
}
|
|
2383
2405
|
var DUPLICATE_DISPATCH_WINDOW_MS = 6e4;
|
|
2384
2406
|
async function refreshMeshFromDaemon(ctx) {
|
|
2407
|
+
const settledNodeIds = /* @__PURE__ */ new Set();
|
|
2385
2408
|
try {
|
|
2386
2409
|
const result = await ctx.transport.command("get_mesh", { meshId: ctx.mesh.id });
|
|
2387
|
-
if (!result?.success || !Array.isArray(result.mesh?.nodes)) return;
|
|
2410
|
+
if (!result?.success || !Array.isArray(result.mesh?.nodes)) return { settledNodeIds };
|
|
2388
2411
|
const refreshedNodes = result.mesh.nodes.filter((n) => n?.id).map((n) => n);
|
|
2389
|
-
|
|
2412
|
+
const merged = [...refreshedNodes];
|
|
2413
|
+
for (const existing of ctx.mesh.nodes) {
|
|
2414
|
+
const existingId = existing?.id;
|
|
2415
|
+
if (!existingId) continue;
|
|
2416
|
+
if (merged.some((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, existingId))) continue;
|
|
2417
|
+
if (isLocalControlPlaneNode(ctx, existing)) {
|
|
2418
|
+
settledNodeIds.add(existingId);
|
|
2419
|
+
continue;
|
|
2420
|
+
}
|
|
2421
|
+
const clonedFromNodeId = readString(existing?.clonedFromNodeId) || readString(existing?.cloned_from_node_id);
|
|
2422
|
+
if (clonedFromNodeId && refreshedNodes.some((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, clonedFromNodeId))) {
|
|
2423
|
+
settledNodeIds.add(existingId);
|
|
2424
|
+
continue;
|
|
2425
|
+
}
|
|
2426
|
+
merged.push(existing);
|
|
2427
|
+
}
|
|
2428
|
+
ctx.mesh.nodes.splice(0, ctx.mesh.nodes.length, ...merged);
|
|
2390
2429
|
ctx.mesh.updatedAt = result.mesh.updatedAt ?? ctx.mesh.updatedAt;
|
|
2391
2430
|
} catch {
|
|
2392
2431
|
}
|
|
2432
|
+
return { settledNodeIds };
|
|
2393
2433
|
}
|
|
2394
2434
|
async function syncCoordinatorDaemonMeshCache(ctx) {
|
|
2395
2435
|
if (!(ctx.transport instanceof IpcTransport)) return;
|
|
@@ -2401,24 +2441,76 @@ async function syncCoordinatorDaemonMeshCache(ctx) {
|
|
|
2401
2441
|
} catch {
|
|
2402
2442
|
}
|
|
2403
2443
|
}
|
|
2444
|
+
async function resolveNodeFromOwningDaemons(ctx, nodeId) {
|
|
2445
|
+
const transport = ctx.transport;
|
|
2446
|
+
if (typeof transport?.meshCommand !== "function") return { node: null, ownerUnreachable: false };
|
|
2447
|
+
const localDaemonId = ctx.localDaemonId;
|
|
2448
|
+
const candidates = [];
|
|
2449
|
+
const pushCandidate = (id) => {
|
|
2450
|
+
if (typeof id !== "string" || !id.trim()) return;
|
|
2451
|
+
if (localDaemonId && (0, import_daemon_core4.daemonIdsEquivalent)(id, localDaemonId)) return;
|
|
2452
|
+
if (!candidates.includes(id)) candidates.push(id);
|
|
2453
|
+
};
|
|
2454
|
+
for (const node of ctx.mesh.nodes) pushCandidate(node?.daemonId);
|
|
2455
|
+
pushCandidate(ctx.mesh?.meshHost?.hostDaemonId);
|
|
2456
|
+
if (candidates.length === 0) return { node: null, ownerUnreachable: false };
|
|
2457
|
+
let ownerUnreachable = false;
|
|
2458
|
+
for (const daemonId of candidates) {
|
|
2459
|
+
let result;
|
|
2460
|
+
try {
|
|
2461
|
+
result = await transport.meshCommand(daemonId, "get_mesh", { meshId: ctx.mesh.id });
|
|
2462
|
+
} catch {
|
|
2463
|
+
ownerUnreachable = true;
|
|
2464
|
+
continue;
|
|
2465
|
+
}
|
|
2466
|
+
const nodes = result?.mesh?.nodes ?? result?.result?.mesh?.nodes;
|
|
2467
|
+
if (!result?.success || !Array.isArray(nodes)) {
|
|
2468
|
+
if (result && result.success === false) ownerUnreachable = true;
|
|
2469
|
+
continue;
|
|
2470
|
+
}
|
|
2471
|
+
const found = nodes.find((n) => n?.id && (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
|
|
2472
|
+
if (!found) continue;
|
|
2473
|
+
const existingIndex = ctx.mesh.nodes.findIndex((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
|
|
2474
|
+
if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = found;
|
|
2475
|
+
else ctx.mesh.nodes.push(found);
|
|
2476
|
+
return { node: found, ownerUnreachable: false };
|
|
2477
|
+
}
|
|
2478
|
+
return { node: null, ownerUnreachable };
|
|
2479
|
+
}
|
|
2404
2480
|
async function findNodeWithRefresh(ctx, nodeId) {
|
|
2405
|
-
const hit = ctx.mesh.nodes.find((n) => (0,
|
|
2481
|
+
const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
|
|
2406
2482
|
if (hit && !hit.isLocalWorktree) return hit;
|
|
2407
|
-
await refreshMeshFromDaemon(ctx);
|
|
2408
|
-
const refreshed = ctx.mesh.nodes.find((n) => (0,
|
|
2409
|
-
if (
|
|
2410
|
-
|
|
2483
|
+
const { settledNodeIds } = await refreshMeshFromDaemon(ctx);
|
|
2484
|
+
const refreshed = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
|
|
2485
|
+
if (refreshed) return refreshed;
|
|
2486
|
+
if (settledNodeIds.has(nodeId)) {
|
|
2487
|
+
throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
|
|
2488
|
+
}
|
|
2489
|
+
const owned = await resolveNodeFromOwningDaemons(ctx, nodeId);
|
|
2490
|
+
if (owned.node) return owned.node;
|
|
2491
|
+
if (owned.ownerUnreachable) {
|
|
2492
|
+
const err = new Error(
|
|
2493
|
+
`Node '${nodeId}' could not be resolved: the daemon that owns it is unreachable. This is NOT proof of non-membership \u2014 retry once the owning daemon is online.`
|
|
2494
|
+
);
|
|
2495
|
+
err.code = "mesh_node_owner_unreachable";
|
|
2496
|
+
throw err;
|
|
2497
|
+
}
|
|
2498
|
+
throw new Error(`Node '${nodeId}' is not a member of mesh '${ctx.mesh.name}'`);
|
|
2411
2499
|
}
|
|
2412
2500
|
async function findOptionalNodeWithRefresh(ctx, nodeId) {
|
|
2413
|
-
const hit = ctx.mesh.nodes.find((n) => (0,
|
|
2501
|
+
const hit = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
|
|
2414
2502
|
if (hit && !hit.isLocalWorktree) return hit;
|
|
2415
|
-
await refreshMeshFromDaemon(ctx);
|
|
2416
|
-
|
|
2503
|
+
const { settledNodeIds } = await refreshMeshFromDaemon(ctx);
|
|
2504
|
+
const refreshed = ctx.mesh.nodes.find((n) => (0, import_daemon_core4.meshNodeIdMatches)(n, nodeId));
|
|
2505
|
+
if (refreshed) return refreshed;
|
|
2506
|
+
if (settledNodeIds.has(nodeId)) return null;
|
|
2507
|
+
const owned = await resolveNodeFromOwningDaemons(ctx, nodeId);
|
|
2508
|
+
return owned.node;
|
|
2417
2509
|
}
|
|
2418
2510
|
function hasRecentDuplicateDispatch(ctx, args) {
|
|
2419
2511
|
const now = Date.now();
|
|
2420
2512
|
const normalizedMessage = args.message.trim();
|
|
2421
|
-
for (const task of (0,
|
|
2513
|
+
for (const task of (0, import_daemon_core4.getQueue)(ctx.mesh.id)) {
|
|
2422
2514
|
const timestamp = new Date(task.updatedAt || task.createdAt).getTime();
|
|
2423
2515
|
if (!Number.isFinite(timestamp) || now - timestamp > DUPLICATE_DISPATCH_WINDOW_MS) continue;
|
|
2424
2516
|
if (task.targetNodeId && task.targetNodeId !== args.node_id) continue;
|
|
@@ -2428,7 +2520,7 @@ function hasRecentDuplicateDispatch(ctx, args) {
|
|
|
2428
2520
|
return { duplicate: true, entry: task, source: "queue" };
|
|
2429
2521
|
}
|
|
2430
2522
|
}
|
|
2431
|
-
const entries = (0,
|
|
2523
|
+
const entries = (0, import_daemon_core4.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
|
|
2432
2524
|
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
2433
2525
|
const entry = entries[i];
|
|
2434
2526
|
const timestamp = new Date(entry.timestamp).getTime();
|
|
@@ -2445,7 +2537,7 @@ function hasRecentDuplicateDispatch(ctx, args) {
|
|
|
2445
2537
|
}
|
|
2446
2538
|
function buildMissionInactiveWarning(ctx, missionId) {
|
|
2447
2539
|
if (!missionId) return void 0;
|
|
2448
|
-
const mission = (0,
|
|
2540
|
+
const mission = (0, import_daemon_core4.getMeshMission)(ctx.mesh.id, missionId);
|
|
2449
2541
|
if (!mission || mission.status === "active") return void 0;
|
|
2450
2542
|
const hintByStatus = {
|
|
2451
2543
|
paused: `Mission '${missionId}' (${mission.title}) is paused \u2014 a new task was just attached to it anyway. Mission status is never auto-transitioned; if this mission should be active again, call mesh_mission_upsert(mission_id: '${missionId}', status: 'active').`,
|
|
@@ -2459,7 +2551,7 @@ function buildMissionInactiveWarning(ctx, missionId) {
|
|
|
2459
2551
|
};
|
|
2460
2552
|
}
|
|
2461
2553
|
function buildMissingNodeReadChatRecovery(ctx, args) {
|
|
2462
|
-
const entries = (0,
|
|
2554
|
+
const entries = (0, import_daemon_core4.readLedgerEntries)(ctx.mesh.id, { tail: 300 });
|
|
2463
2555
|
const relatedEntries = entries.filter((entry) => entry.nodeId === args.node_id || entry.sessionId === args.session_id);
|
|
2464
2556
|
const completedEntries = relatedEntries.filter((entry) => entry.kind === "task_completed");
|
|
2465
2557
|
const lastDispatch = [...relatedEntries].reverse().find((entry) => entry.kind === "task_dispatched");
|
|
@@ -2583,7 +2675,7 @@ function readFinalAssistantTranscriptEvidence(payload) {
|
|
|
2583
2675
|
}
|
|
2584
2676
|
function findNodeSession(nodes, nodeId, sessionId) {
|
|
2585
2677
|
if (!nodeId || !sessionId) return {};
|
|
2586
|
-
const node = nodes.find((candidate) => (0,
|
|
2678
|
+
const node = nodes.find((candidate) => (0, import_daemon_core4.meshNodeIdMatches)(candidate, nodeId));
|
|
2587
2679
|
if (!node) return {};
|
|
2588
2680
|
const sessions = Array.isArray(node.sessions) ? node.sessions : [];
|
|
2589
2681
|
const session = sessions.find((candidate) => readSessionRecordId(candidate) === sessionId);
|
|
@@ -2652,10 +2744,10 @@ async function reconcileDirectDispatchesFromTranscriptEvidence(ctx, liveNodes, d
|
|
|
2652
2744
|
});
|
|
2653
2745
|
const payload = unwrapCommandPayload(readResult);
|
|
2654
2746
|
if (payload?.success === false) continue;
|
|
2655
|
-
if ((0,
|
|
2747
|
+
if ((0, import_daemon_core4.hasTrailingToolActivityAfterFinalAssistant)(Array.isArray(payload?.messages) ? payload.messages : [])) continue;
|
|
2656
2748
|
const evidence = readFinalAssistantTranscriptEvidence(payload);
|
|
2657
2749
|
if (!evidence.finalSummary) continue;
|
|
2658
|
-
const result = (0,
|
|
2750
|
+
const result = (0, import_daemon_core4.reconcileDirectDispatchCompletionFromTranscript)({
|
|
2659
2751
|
meshId: ctx.mesh.id,
|
|
2660
2752
|
nodeId,
|
|
2661
2753
|
sessionId,
|
|
@@ -2831,8 +2923,8 @@ function assignFullGitSnapshot(entry, status) {
|
|
|
2831
2923
|
if (!status || typeof status !== "object" || Array.isArray(status)) return;
|
|
2832
2924
|
entry.git = status;
|
|
2833
2925
|
}
|
|
2834
|
-
var COMPACT_DETAILED_NODES_BYTE_BUDGET =
|
|
2835
|
-
var COMPACT_NODES_TOTAL_BYTE_BUDGET =
|
|
2926
|
+
var COMPACT_DETAILED_NODES_BYTE_BUDGET = 32e3;
|
|
2927
|
+
var COMPACT_NODES_TOTAL_BYTE_BUDGET = 4e4;
|
|
2836
2928
|
var COMPACT_MISSIONS_BYTE_BUDGET = 6e3;
|
|
2837
2929
|
function extractLaunchPayload(value) {
|
|
2838
2930
|
return findNestedPayload(value, (payload) => Boolean(payload?.sessionId || payload?.id || payload?.runtimeSessionId));
|
|
@@ -2840,7 +2932,7 @@ function extractLaunchPayload(value) {
|
|
|
2840
2932
|
function classifyMeshLaunchFailure(error) {
|
|
2841
2933
|
const message = error instanceof Error ? error.message : String(error || "launch failed");
|
|
2842
2934
|
const lower = message.toLowerCase();
|
|
2843
|
-
const p2pClassification = (0,
|
|
2935
|
+
const p2pClassification = (0, import_daemon_core4.classifyP2pRelayFailure)(error, { command: "launch_cli" });
|
|
2844
2936
|
if (p2pClassification.recoverable) {
|
|
2845
2937
|
return p2pClassification;
|
|
2846
2938
|
}
|
|
@@ -2915,7 +3007,7 @@ function buildRecoverableLaunchFailure(ctx, node, providerType, error) {
|
|
|
2915
3007
|
function recordRecoverableLaunchFailure(ctx, node, providerType, error) {
|
|
2916
3008
|
const failure = buildRecoverableLaunchFailure(ctx, node, providerType, error);
|
|
2917
3009
|
try {
|
|
2918
|
-
(0,
|
|
3010
|
+
(0, import_daemon_core4.appendLedgerEntry)(ctx.mesh.id, {
|
|
2919
3011
|
kind: "recovery_attempted",
|
|
2920
3012
|
nodeId: node.id,
|
|
2921
3013
|
providerType,
|
|
@@ -2929,7 +3021,7 @@ function recordRecoverableLaunchFailure(ctx, node, providerType, error) {
|
|
|
2929
3021
|
return failure;
|
|
2930
3022
|
}
|
|
2931
3023
|
function getLatestActiveLaunchFailure(meshId, nodeId) {
|
|
2932
|
-
const entries = (0,
|
|
3024
|
+
const entries = (0, import_daemon_core4.readLedgerEntries)(meshId, { tail: 200 });
|
|
2933
3025
|
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
2934
3026
|
const entry = entries[i];
|
|
2935
3027
|
if (entry.nodeId !== nodeId) continue;
|
|
@@ -2941,7 +3033,7 @@ function getLatestActiveLaunchFailure(meshId, nodeId) {
|
|
|
2941
3033
|
return null;
|
|
2942
3034
|
}
|
|
2943
3035
|
function buildCoordinatorP2pRelayFailure(error, context) {
|
|
2944
|
-
const payload = (0,
|
|
3036
|
+
const payload = (0, import_daemon_core4.buildP2pRelayFailurePayload)(error, {
|
|
2945
3037
|
command: context.command,
|
|
2946
3038
|
targetDaemonId: context.targetDaemonId
|
|
2947
3039
|
});
|
|
@@ -3122,7 +3214,7 @@ function rememberMeshSessionProviderMetadataFromEvent(event) {
|
|
|
3122
3214
|
});
|
|
3123
3215
|
}
|
|
3124
3216
|
function resolveMeshSessionProviderMetadataFromLedger(ctx, nodeId, runtimeSessionId) {
|
|
3125
|
-
const entries = (0,
|
|
3217
|
+
const entries = (0, import_daemon_core4.readLedgerEntries)(ctx.mesh.id, { tail: 50 });
|
|
3126
3218
|
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3127
3219
|
const entry = entries[i];
|
|
3128
3220
|
const payload = entry.payload && typeof entry.payload === "object" && !Array.isArray(entry.payload) ? entry.payload : {};
|
|
@@ -3258,12 +3350,12 @@ function readNodeSupportedProviders(policy) {
|
|
|
3258
3350
|
}
|
|
3259
3351
|
function buildNodeCapabilityExposure(node) {
|
|
3260
3352
|
const providers = readNodeSupportedProviders(node.policy);
|
|
3261
|
-
const capabilityTags = (0,
|
|
3353
|
+
const capabilityTags = (0, import_daemon_core4.buildMeshNodeCapabilityTags)(node);
|
|
3262
3354
|
const exposure = { capabilityTags };
|
|
3263
3355
|
if (providers.length) {
|
|
3264
3356
|
const byProvider = {};
|
|
3265
3357
|
for (const provider of providers) {
|
|
3266
|
-
byProvider[provider] = (0,
|
|
3358
|
+
byProvider[provider] = (0, import_daemon_core4.buildMeshNodeCapabilityTags)(node, provider);
|
|
3267
3359
|
}
|
|
3268
3360
|
exposure.capabilityTagsByProvider = byProvider;
|
|
3269
3361
|
}
|
|
@@ -3347,12 +3439,35 @@ async function collectLiveStatusProbe(ctx, node) {
|
|
|
3347
3439
|
const statusResult = await commandForNode(ctx, node, "get_status_metadata", {}, { statusProbe: true });
|
|
3348
3440
|
return {
|
|
3349
3441
|
sessions: extractStatusMetadataSessions(statusResult),
|
|
3350
|
-
daemonBuild: extractDaemonBuildInfo(statusResult)
|
|
3442
|
+
daemonBuild: extractDaemonBuildInfo(statusResult),
|
|
3443
|
+
upgradeFailure: extractUpgradeFailureSummary(statusResult)
|
|
3351
3444
|
};
|
|
3352
3445
|
} catch {
|
|
3353
3446
|
return { sessions: [] };
|
|
3354
3447
|
}
|
|
3355
3448
|
}
|
|
3449
|
+
var UPGRADE_FAILURE_SUMMARY_MAX_CHARS = 200;
|
|
3450
|
+
function extractUpgradeFailureSummary(value) {
|
|
3451
|
+
const payload = unwrapCommandPayload(value);
|
|
3452
|
+
const raw = payload?.upgradeFailure && typeof payload.upgradeFailure === "object" ? payload.upgradeFailure : value?.upgradeFailure && typeof value.upgradeFailure === "object" ? value.upgradeFailure : void 0;
|
|
3453
|
+
if (!raw) return void 0;
|
|
3454
|
+
const notice = readString(raw.notice) || "";
|
|
3455
|
+
const noticePath = readString(raw.noticePath) || "";
|
|
3456
|
+
if (!notice && !noticePath) return void 0;
|
|
3457
|
+
const bodyLine = notice.split(/\r?\n/).map((line) => line.trim()).find((line) => line && !/^\[[^\]\n]+\]$/.test(line)) || "";
|
|
3458
|
+
const summary = bodyLine.length > UPGRADE_FAILURE_SUMMARY_MAX_CHARS ? `${bodyLine.slice(0, UPGRADE_FAILURE_SUMMARY_MAX_CHARS)}\u2026` : bodyLine;
|
|
3459
|
+
const recordedAt = readString(raw.recordedAt);
|
|
3460
|
+
const ageLabel = readString(raw.ageLabel);
|
|
3461
|
+
const targetVersion = readString(raw.targetVersion);
|
|
3462
|
+
return {
|
|
3463
|
+
summary,
|
|
3464
|
+
...recordedAt ? { recordedAt } : {},
|
|
3465
|
+
...ageLabel ? { ageLabel } : {},
|
|
3466
|
+
...targetVersion ? { targetVersion } : {},
|
|
3467
|
+
noticePath,
|
|
3468
|
+
logPath: readString(raw.logPath) || ""
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3356
3471
|
function extractDaemonBuildInfo(value) {
|
|
3357
3472
|
const payload = unwrapCommandPayload(value);
|
|
3358
3473
|
const build = payload?.daemonBuild && typeof payload.daemonBuild === "object" ? payload.daemonBuild : value?.daemonBuild && typeof value.daemonBuild === "object" ? value.daemonBuild : void 0;
|
|
@@ -3572,7 +3687,7 @@ function buildMeshForwardPayloadFromPendingEvent(event) {
|
|
|
3572
3687
|
// eventId (idempotency) and unicast routing intact, matching the reconcile-loop
|
|
3573
3688
|
// relay path (buildForwardPayloadFromPending). Spread LAST so the authoritative
|
|
3574
3689
|
// envelope always wins. Empty for a v1 event (version-skew safe).
|
|
3575
|
-
...(0,
|
|
3690
|
+
...(0, import_daemon_core4.serializeV2EnvelopeToWire)(event)
|
|
3576
3691
|
};
|
|
3577
3692
|
}
|
|
3578
3693
|
async function drainCoordinatorPendingEvents(ctx, opts) {
|
|
@@ -3642,11 +3757,11 @@ async function drainCoordinatorPendingEvents(ctx, opts) {
|
|
|
3642
3757
|
}
|
|
3643
3758
|
return surfacedEvents;
|
|
3644
3759
|
}
|
|
3645
|
-
const drainerIdentity = (0,
|
|
3760
|
+
const drainerIdentity = (0, import_daemon_core4.coordinatorIdentityFromEmitFields)({
|
|
3646
3761
|
daemonId: ctx.localDaemonId,
|
|
3647
3762
|
sessionId: ctx.coordinatorSessionId
|
|
3648
3763
|
});
|
|
3649
|
-
const events = (0,
|
|
3764
|
+
const events = (0, import_daemon_core4.drainPendingMeshCoordinatorEvents)(
|
|
3650
3765
|
ctx.mesh.id,
|
|
3651
3766
|
ctx.localDaemonId,
|
|
3652
3767
|
drainerIdentity ? { drainerIdentity } : void 0
|
|
@@ -3655,7 +3770,7 @@ async function drainCoordinatorPendingEvents(ctx, opts) {
|
|
|
3655
3770
|
return events;
|
|
3656
3771
|
}
|
|
3657
3772
|
function isP2pTransportUnavailableError(error) {
|
|
3658
|
-
return (0,
|
|
3773
|
+
return (0, import_daemon_core4.isP2pRelayTransportFailure)(error);
|
|
3659
3774
|
}
|
|
3660
3775
|
function buildRemoveNodeArgs(ctx, nodeId, sessionCleanupMode, force) {
|
|
3661
3776
|
return {
|
|
@@ -3674,7 +3789,7 @@ function classifyReadChatTransportCause(error) {
|
|
|
3674
3789
|
return "saturated";
|
|
3675
3790
|
}
|
|
3676
3791
|
function resolveCachedMeshSessionPreviewFromLedger(ctx, nodeId, sessionId) {
|
|
3677
|
-
const entries = (0,
|
|
3792
|
+
const entries = (0, import_daemon_core4.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
|
|
3678
3793
|
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
3679
3794
|
const entry = entries[i];
|
|
3680
3795
|
const payload = entry.payload && typeof entry.payload === "object" && !Array.isArray(entry.payload) ? entry.payload : {};
|
|
@@ -3683,7 +3798,7 @@ function resolveCachedMeshSessionPreviewFromLedger(ctx, nodeId, sessionId) {
|
|
|
3683
3798
|
const entrySessionId = readString(entry.sessionId) || readString(payload.targetSessionId) || readString(payload.sessionId) || readString(payload.instanceId);
|
|
3684
3799
|
if (entrySessionId !== sessionId) continue;
|
|
3685
3800
|
const metadataEvent = payload.metadataEvent && typeof payload.metadataEvent === "object" && !Array.isArray(payload.metadataEvent) ? payload.metadataEvent : payload;
|
|
3686
|
-
const preview = (0,
|
|
3801
|
+
const preview = (0, import_daemon_core4.resolveMeshSurfacedSessionPreview)(metadataEvent);
|
|
3687
3802
|
if (preview) {
|
|
3688
3803
|
return { ...preview, ledgerKind: entry.kind, timestamp: entry.timestamp };
|
|
3689
3804
|
}
|
|
@@ -3691,7 +3806,7 @@ function resolveCachedMeshSessionPreviewFromLedger(ctx, nodeId, sessionId) {
|
|
|
3691
3806
|
return void 0;
|
|
3692
3807
|
}
|
|
3693
3808
|
function buildMeshReadChatCacheFallback(ctx, args, node, error) {
|
|
3694
|
-
const classification = (0,
|
|
3809
|
+
const classification = (0, import_daemon_core4.classifyP2pRelayFailure)(error, { command: "read_chat", targetDaemonId: node.daemonId });
|
|
3695
3810
|
const cause = classifyReadChatTransportCause(error);
|
|
3696
3811
|
const errorMessage = error instanceof Error ? error.message : String(error ?? "");
|
|
3697
3812
|
const causeNote = cause === "not_connected" ? "the worker daemon is not currently connected over P2P (no live channel)" : "the worker daemon is connected but saturated \u2014 it acknowledged the request but did not return the transcript within the deadline";
|
|
@@ -3772,12 +3887,12 @@ function summarizePendingEventProtocolMetrics(pendingEvents) {
|
|
|
3772
3887
|
};
|
|
3773
3888
|
}
|
|
3774
3889
|
async function meshStatus(ctx, args = {}) {
|
|
3775
|
-
const rateResult = (0,
|
|
3890
|
+
const rateResult = (0, import_daemon_core5.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_status" });
|
|
3776
3891
|
const compact = args.verbose === true ? false : args.compact ?? true;
|
|
3777
3892
|
await refreshMeshFromDaemon(ctx);
|
|
3778
3893
|
const { mesh, transport } = ctx;
|
|
3779
|
-
let ledgerSummary = (0,
|
|
3780
|
-
const schedulingRuntime = (0,
|
|
3894
|
+
let ledgerSummary = (0, import_daemon_core5.getLedgerSummary)(mesh.id);
|
|
3895
|
+
const schedulingRuntime = (0, import_daemon_core5.buildMeshSchedulingRuntime)(mesh, (0, import_daemon_core5.getQueue)(mesh.id));
|
|
3781
3896
|
const schedulingByNode = new Map(schedulingRuntime.nodes.map((n) => [n.nodeId, n]));
|
|
3782
3897
|
const results = await Promise.all(mesh.nodes.map(async (node) => {
|
|
3783
3898
|
const entry = {
|
|
@@ -3786,6 +3901,10 @@ async function meshStatus(ctx, args = {}) {
|
|
|
3786
3901
|
machine: buildNodeMachineIdentity(ctx, node),
|
|
3787
3902
|
daemonId: readNodeDaemonId(node),
|
|
3788
3903
|
machineId: readNodeMachineId(node),
|
|
3904
|
+
// Needed by the compact fold to distinguish a machine (repo-root) node
|
|
3905
|
+
// from a worktree node: the per-daemon representative pin keeps machine
|
|
3906
|
+
// nodes out of the fold so a deploy roster can never lose a machine.
|
|
3907
|
+
isLocalWorktree: node.isLocalWorktree === true,
|
|
3789
3908
|
...getNodeLaunchReadiness(node),
|
|
3790
3909
|
...buildNodeCapabilityExposure(node)
|
|
3791
3910
|
};
|
|
@@ -3841,14 +3960,14 @@ async function meshStatus(ctx, args = {}) {
|
|
|
3841
3960
|
noFallbackReason: failure.noFallbackReason
|
|
3842
3961
|
});
|
|
3843
3962
|
}
|
|
3844
|
-
entry.dataFreshness = (0,
|
|
3963
|
+
entry.dataFreshness = (0, import_daemon_core5.buildMeshNodeProbeFreshness)({
|
|
3845
3964
|
git: entry.git,
|
|
3846
3965
|
liveTruthProbed,
|
|
3847
3966
|
isSelfNode: entry.machine?.sameMachine === true,
|
|
3848
3967
|
daemonId: readNodeDaemonId(node),
|
|
3849
3968
|
node
|
|
3850
3969
|
});
|
|
3851
|
-
const recoveryContext = (0,
|
|
3970
|
+
const recoveryContext = (0, import_daemon_core5.getSessionRecoveryContext)(mesh.id, { nodeId: node.id });
|
|
3852
3971
|
if (recoveryContext.consecutiveNodeFailures > 0) {
|
|
3853
3972
|
entry.recoveryHints = {
|
|
3854
3973
|
consecutiveFailures: recoveryContext.consecutiveNodeFailures,
|
|
@@ -3895,6 +4014,7 @@ async function meshStatus(ctx, args = {}) {
|
|
|
3895
4014
|
const statusProbe = await collectLiveStatusProbe(ctx, node);
|
|
3896
4015
|
const liveSessions = statusProbe.sessions;
|
|
3897
4016
|
if (statusProbe.daemonBuild) entry.daemonBuild = statusProbe.daemonBuild;
|
|
4017
|
+
if (statusProbe.upgradeFailure) entry.upgradeFailure = statusProbe.upgradeFailure;
|
|
3898
4018
|
if (liveSessions.length > 0) {
|
|
3899
4019
|
entry.sessions = liveSessions.map((s) => {
|
|
3900
4020
|
const coordinatorMeshId = typeof s.coordinator?.meshId === "string" ? s.coordinator.meshId : void 0;
|
|
@@ -3937,23 +4057,23 @@ async function meshStatus(ctx, args = {}) {
|
|
|
3937
4057
|
}
|
|
3938
4058
|
return entry;
|
|
3939
4059
|
}));
|
|
3940
|
-
let ledgerEntries = (0,
|
|
3941
|
-
let directDispatches = (0,
|
|
4060
|
+
let ledgerEntries = (0, import_daemon_core5.readLedgerEntries)(mesh.id, { tail: 200 });
|
|
4061
|
+
let directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(mesh.id);
|
|
3942
4062
|
const directReconciliation = await reconcileDirectDispatchesFromTranscriptEvidence(ctx, results, directDispatches, ledgerEntries);
|
|
3943
4063
|
if (directReconciliation.reconciled > 0) {
|
|
3944
|
-
ledgerEntries = (0,
|
|
3945
|
-
directDispatches = (0,
|
|
3946
|
-
ledgerSummary = (0,
|
|
4064
|
+
ledgerEntries = (0, import_daemon_core5.readLedgerEntries)(mesh.id, { tail: 200 });
|
|
4065
|
+
directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(mesh.id);
|
|
4066
|
+
ledgerSummary = (0, import_daemon_core5.getLedgerSummary)(mesh.id);
|
|
3947
4067
|
}
|
|
3948
|
-
const activeWorkEvidence = (0,
|
|
4068
|
+
const activeWorkEvidence = (0, import_daemon_core5.buildMeshActiveWork)({
|
|
3949
4069
|
meshId: mesh.id,
|
|
3950
|
-
queue: (0,
|
|
4070
|
+
queue: (0, import_daemon_core5.getQueue)(mesh.id),
|
|
3951
4071
|
ledgerEntries,
|
|
3952
4072
|
directDispatches,
|
|
3953
4073
|
nodes: results
|
|
3954
4074
|
});
|
|
3955
4075
|
const pollingGuidance = buildActiveWorkPollingGuidance(activeWorkEvidence.summary);
|
|
3956
|
-
const staleDirectWorkSummary = (0,
|
|
4076
|
+
const staleDirectWorkSummary = (0, import_daemon_core5.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
|
|
3957
4077
|
note: activeWorkEvidence.staleDirectWorkNote,
|
|
3958
4078
|
detailHint: "Full stale direct entries are omitted from mesh_status by default. Call mesh_status with includeStaleDirectWorkDetails=true or inspect mesh_task_history for ledger detail."
|
|
3959
4079
|
});
|
|
@@ -3992,6 +4112,21 @@ async function meshStatus(ctx, args = {}) {
|
|
|
3992
4112
|
daemonBuilds[daemonId] = entry.daemonBuild;
|
|
3993
4113
|
}
|
|
3994
4114
|
}
|
|
4115
|
+
const daemonMachines = {};
|
|
4116
|
+
const daemonQuotas = {};
|
|
4117
|
+
for (const entry of results) {
|
|
4118
|
+
const daemonId = typeof entry?.daemonId === "string" && entry.daemonId ? entry.daemonId : "";
|
|
4119
|
+
if (!daemonId) continue;
|
|
4120
|
+
if (entry?.machine && !(daemonId in daemonMachines)) daemonMachines[daemonId] = entry.machine;
|
|
4121
|
+
if (entry?.quota && !(daemonId in daemonQuotas)) daemonQuotas[daemonId] = entry.quota;
|
|
4122
|
+
}
|
|
4123
|
+
const daemonUpgradeFailures = {};
|
|
4124
|
+
for (const entry of results) {
|
|
4125
|
+
const daemonId = typeof entry?.daemonId === "string" && entry.daemonId ? entry.daemonId : "";
|
|
4126
|
+
if (daemonId && entry?.upgradeFailure && !(daemonId in daemonUpgradeFailures)) {
|
|
4127
|
+
daemonUpgradeFailures[daemonId] = entry.upgradeFailure;
|
|
4128
|
+
}
|
|
4129
|
+
}
|
|
3995
4130
|
const staleDaemonBuilds = [];
|
|
3996
4131
|
const seenStale = /* @__PURE__ */ new Set();
|
|
3997
4132
|
for (const entry of results) {
|
|
@@ -4054,20 +4189,36 @@ async function meshStatus(ctx, args = {}) {
|
|
|
4054
4189
|
if (!includeSessions) delete next.sessions;
|
|
4055
4190
|
}
|
|
4056
4191
|
if (next.daemonBuild !== void 0) delete next.daemonBuild;
|
|
4192
|
+
if (next.machine && typeof next.machine === "object") {
|
|
4193
|
+
const m = next.machine;
|
|
4194
|
+
next.machine = {
|
|
4195
|
+
daemonId: m.daemonId,
|
|
4196
|
+
displayName: m.displayName,
|
|
4197
|
+
sameMachine: m.sameMachine,
|
|
4198
|
+
seeDaemonMachines: true
|
|
4199
|
+
};
|
|
4200
|
+
}
|
|
4201
|
+
if (next.upgradeFailure !== void 0) delete next.upgradeFailure;
|
|
4057
4202
|
return next;
|
|
4058
4203
|
});
|
|
4204
|
+
const pinnedIds = pinnedRepresentativeNodeIds(compacted);
|
|
4059
4205
|
const noteworthy = compacted.filter((n) => n && typeof n === "object" && isNoteworthyCompactNode(n));
|
|
4060
|
-
const
|
|
4206
|
+
const bySeverityDesc = (a, b) => compactNodeSeverity(b) - compactNodeSeverity(a);
|
|
4207
|
+
const isPinned = (n) => pinnedIds.has(String(n?.nodeId));
|
|
4208
|
+
const ranked = [
|
|
4209
|
+
...compacted.filter((n) => n && typeof n === "object" && isPinned(n)).sort(bySeverityDesc),
|
|
4210
|
+
...noteworthy.filter((n) => !isPinned(n)).sort(bySeverityDesc)
|
|
4211
|
+
];
|
|
4061
4212
|
const detailedIds = /* @__PURE__ */ new Set();
|
|
4062
4213
|
let detailSpent = 0;
|
|
4063
4214
|
for (const n of ranked) {
|
|
4064
4215
|
const cost = JSON.stringify(n).length + 1;
|
|
4065
|
-
if (detailedIds.size === 0 || detailSpent + cost <= COMPACT_DETAILED_NODES_BYTE_BUDGET) {
|
|
4216
|
+
if (detailedIds.size === 0 || isPinned(n) || detailSpent + cost <= COMPACT_DETAILED_NODES_BYTE_BUDGET) {
|
|
4066
4217
|
detailedIds.add(String(n.nodeId));
|
|
4067
4218
|
detailSpent += cost;
|
|
4068
4219
|
}
|
|
4069
4220
|
}
|
|
4070
|
-
const stubOrder = [...compacted].filter((n) => n && typeof n === "object").sort(
|
|
4221
|
+
const stubOrder = [...compacted].filter((n) => n && typeof n === "object").sort(bySeverityDesc);
|
|
4071
4222
|
const keptIds = new Set(detailedIds);
|
|
4072
4223
|
let totalSpent = detailSpent;
|
|
4073
4224
|
for (const n of stubOrder) {
|
|
@@ -4140,6 +4291,14 @@ async function meshStatus(ctx, args = {}) {
|
|
|
4140
4291
|
...compact && foldedNodesSummary ? { foldedNodes: foldedNodesSummary } : {},
|
|
4141
4292
|
...compact && Object.keys(daemonSessions).length > 0 ? { daemonSessions } : {},
|
|
4142
4293
|
...Object.keys(daemonBuilds).length > 0 ? { daemonBuilds } : {},
|
|
4294
|
+
// Per-daemon machine identity / provider quota, recorded once per daemonId
|
|
4295
|
+
// instead of repeated on every node sharing that daemon. Both modes.
|
|
4296
|
+
...Object.keys(daemonMachines).length > 0 ? { daemonMachines } : {},
|
|
4297
|
+
...Object.keys(daemonQuotas).length > 0 ? { daemonQuotas } : {},
|
|
4298
|
+
...Object.keys(daemonUpgradeFailures).length > 0 ? {
|
|
4299
|
+
daemonUpgradeFailures,
|
|
4300
|
+
daemonUpgradeFailureWarning: `One or more daemons have a failed-upgrade notice on record: that daemon's LAST upgrade failed and rolled back, so it is still on the PREVIOUS version. An upgrade/restart response only reports "scheduled", never success \u2014 do not read a prior success as proof the version changed. The notice persists until a later upgrade succeeds, so check targetVersion/recordedAt: a target other than the running version is a stale earlier attempt. Full body at noticePath, trace at logPath.`
|
|
4301
|
+
} : {},
|
|
4143
4302
|
...staleDaemonBuilds.length > 0 ? { staleDaemonBuilds } : {},
|
|
4144
4303
|
...daemonAffectingStaleBuilds.length > 0 ? {
|
|
4145
4304
|
staleDaemonBuildWarning: "One or more live daemons were built from a commit behind the workspace HEAD with daemon-runtime package changes. Merged refinery/mesh-tool fixes are NOT live on those daemons until they are rebuilt/redeployed and restarted \u2014 a local daemon-core dist rebuild does not update a cloud daemon. Do not assume a just-merged fix is active."
|
|
@@ -4178,13 +4337,13 @@ async function meshStatus(ctx, args = {}) {
|
|
|
4178
4337
|
}
|
|
4179
4338
|
if (args.includeUsage === true) {
|
|
4180
4339
|
try {
|
|
4181
|
-
response.usage = (0,
|
|
4340
|
+
response.usage = (0, import_daemon_core5.summarizeMeshUsage)(mesh.id);
|
|
4182
4341
|
} catch {
|
|
4183
4342
|
}
|
|
4184
4343
|
}
|
|
4185
4344
|
try {
|
|
4186
4345
|
if (compact) {
|
|
4187
|
-
const { live, historyFold } = (0,
|
|
4346
|
+
const { live, historyFold } = (0, import_daemon_core5.getMeshStatusMissionsCompact)(mesh.id);
|
|
4188
4347
|
const ranked = [...live].sort((a, b) => String(b.tasks?.lastActivityAt ?? "").localeCompare(String(a.tasks?.lastActivityAt ?? "")));
|
|
4189
4348
|
const kept = [];
|
|
4190
4349
|
const overflow = [];
|
|
@@ -4211,11 +4370,11 @@ async function meshStatus(ctx, args = {}) {
|
|
|
4211
4370
|
}
|
|
4212
4371
|
if (historyFold) response.missionsHistory = historyFold;
|
|
4213
4372
|
} else {
|
|
4214
|
-
const missions = (0,
|
|
4373
|
+
const missions = (0, import_daemon_core5.getMeshStatusMissionSummaries)(mesh.id, { verbose: true });
|
|
4215
4374
|
if (missions.length > 0) {
|
|
4216
4375
|
response.missions = missions.map((mission) => {
|
|
4217
4376
|
try {
|
|
4218
|
-
return { ...mission, stats: (0,
|
|
4377
|
+
return { ...mission, stats: (0, import_daemon_core5.computeMeshMissionStats)(mesh.id, mission.id) };
|
|
4219
4378
|
} catch {
|
|
4220
4379
|
return mission;
|
|
4221
4380
|
}
|
|
@@ -4226,14 +4385,14 @@ async function meshStatus(ctx, args = {}) {
|
|
|
4226
4385
|
}
|
|
4227
4386
|
try {
|
|
4228
4387
|
const pendingEvents = await drainCoordinatorPendingEvents(ctx);
|
|
4229
|
-
const asyncRefineJobs = (0,
|
|
4388
|
+
const asyncRefineJobs = (0, import_daemon_core5.buildMeshAsyncRefineJobs)({
|
|
4230
4389
|
meshId: mesh.id,
|
|
4231
4390
|
ledgerEntries,
|
|
4232
4391
|
pendingEvents
|
|
4233
4392
|
});
|
|
4234
4393
|
if (asyncRefineJobs.length > 0) {
|
|
4235
4394
|
if (compact) {
|
|
4236
|
-
const summary = (0,
|
|
4395
|
+
const summary = (0, import_daemon_core5.summarizeMeshAsyncRefineJobs)(asyncRefineJobs);
|
|
4237
4396
|
if (summary.activeJobs.length > 0) response.asyncRefineJobs = summary.activeJobs;
|
|
4238
4397
|
response.asyncRefineJobsSummary = {
|
|
4239
4398
|
total: summary.total,
|
|
@@ -4244,9 +4403,9 @@ async function meshStatus(ctx, args = {}) {
|
|
|
4244
4403
|
response.asyncRefineJobs = asyncRefineJobs;
|
|
4245
4404
|
}
|
|
4246
4405
|
}
|
|
4247
|
-
const magiActivity = (0,
|
|
4406
|
+
const magiActivity = (0, import_daemon_core5.buildMeshMagiActivity)({ meshId: mesh.id, ledgerEntries });
|
|
4248
4407
|
if (magiActivity.length > 0) {
|
|
4249
|
-
const fold = (0,
|
|
4408
|
+
const fold = (0, import_daemon_core5.summarizeMeshMagiActivity)(magiActivity);
|
|
4250
4409
|
if (compact) {
|
|
4251
4410
|
if (fold.groups.length > 0) response.magiActivity = fold.groups;
|
|
4252
4411
|
response.magiActivitySummary = {
|
|
@@ -4270,7 +4429,7 @@ async function meshStatus(ctx, args = {}) {
|
|
|
4270
4429
|
}
|
|
4271
4430
|
} catch {
|
|
4272
4431
|
}
|
|
4273
|
-
return JSON.stringify(response
|
|
4432
|
+
return JSON.stringify(response);
|
|
4274
4433
|
}
|
|
4275
4434
|
async function meshListNodes(ctx) {
|
|
4276
4435
|
await refreshMeshFromDaemon(ctx);
|
|
@@ -4302,12 +4461,12 @@ function normalizeDedupMessage(message) {
|
|
|
4302
4461
|
function findInFlightDuplicate(ctx, message, targetNodeId) {
|
|
4303
4462
|
const fingerprint = normalizeDedupMessage(message);
|
|
4304
4463
|
if (!fingerprint) return null;
|
|
4305
|
-
for (const task of (0,
|
|
4464
|
+
for (const task of (0, import_daemon_core5.getQueue)(ctx.mesh.id)) {
|
|
4306
4465
|
if (task.status !== "pending" && task.status !== "assigned") continue;
|
|
4307
4466
|
if (normalizeDedupMessage(task.message) !== fingerprint) continue;
|
|
4308
4467
|
if (targetNodeId) {
|
|
4309
4468
|
const existingTarget = task.targetNodeId || task.assignedNodeId;
|
|
4310
|
-
if (!existingTarget || !(0,
|
|
4469
|
+
if (!existingTarget || !(0, import_daemon_core5.meshNodeIdMatches)({ id: existingTarget }, targetNodeId)) continue;
|
|
4311
4470
|
}
|
|
4312
4471
|
return { id: task.id, status: task.status, assignedNodeId: task.assignedNodeId, targetNodeId: task.targetNodeId };
|
|
4313
4472
|
}
|
|
@@ -4324,15 +4483,15 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4324
4483
|
}
|
|
4325
4484
|
const taskMode = readString(args.task_mode) || readString(args.taskMode);
|
|
4326
4485
|
const readonly = args.readonly === true || args.read_only === true;
|
|
4327
|
-
const requiredTags = (0,
|
|
4486
|
+
const requiredTags = (0, import_daemon_core5.normalizeMeshCapabilityTags)(Array.isArray(args.requiredTags) ? args.requiredTags : args.required_tags);
|
|
4328
4487
|
const dependsOn = Array.isArray(args.dependsOn) ? args.dependsOn : Array.isArray(args.depends_on) ? args.depends_on : void 0;
|
|
4329
4488
|
const missionId = readString(args.missionId) || readString(args.mission_id) || void 0;
|
|
4330
|
-
const priority = (0,
|
|
4489
|
+
const priority = (0, import_daemon_core5.normalizeMeshTaskPriority)(readString(args.priority)) || void 0;
|
|
4331
4490
|
const model = readString(args.model) || void 0;
|
|
4332
4491
|
const thinkingLevel = readString(args.thinkingLevel) || void 0;
|
|
4333
4492
|
const difficulty = readString(args.difficulty) || void 0;
|
|
4334
4493
|
const notBeforeRaw = args.notBefore !== void 0 ? args.notBefore : args.not_before;
|
|
4335
|
-
const notBefore = (0,
|
|
4494
|
+
const notBefore = (0, import_daemon_core5.resolveNotBefore)(notBeforeRaw);
|
|
4336
4495
|
const maxRetriesRaw = typeof args.maxRetries === "number" ? args.maxRetries : typeof args.max_retries === "number" ? args.max_retries : void 0;
|
|
4337
4496
|
const maxRetries = typeof maxRetriesRaw === "number" && Number.isFinite(maxRetriesRaw) && maxRetriesRaw >= 0 ? Math.floor(maxRetriesRaw) : void 0;
|
|
4338
4497
|
const allowDuplicate = args.allowDuplicate === true || args.allow_duplicate === true;
|
|
@@ -4341,7 +4500,7 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4341
4500
|
const preferWorktree = args.preferWorktree === true || args.prefer_worktree === true;
|
|
4342
4501
|
let targetNodeId;
|
|
4343
4502
|
if (explicitTargetRaw) {
|
|
4344
|
-
const matched = ctx.mesh.nodes.find((n) => (0,
|
|
4503
|
+
const matched = ctx.mesh.nodes.find((n) => (0, import_daemon_core5.meshNodeIdMatches)(n, explicitTargetRaw));
|
|
4345
4504
|
if (!matched) {
|
|
4346
4505
|
return JSON.stringify({
|
|
4347
4506
|
success: false,
|
|
@@ -4365,7 +4524,7 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4365
4524
|
});
|
|
4366
4525
|
}
|
|
4367
4526
|
try {
|
|
4368
|
-
const task = (0,
|
|
4527
|
+
const task = (0, import_daemon_core5.enqueueTask)(ctx.mesh.id, message, {
|
|
4369
4528
|
taskMode,
|
|
4370
4529
|
...readonly ? { readonly: true } : {},
|
|
4371
4530
|
requiredTags,
|
|
@@ -4408,9 +4567,9 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4408
4567
|
{
|
|
4409
4568
|
const queueTrigger = await triggerMeshQueueAndReport(ctx);
|
|
4410
4569
|
const dependencyStatusById = new Map(
|
|
4411
|
-
(0,
|
|
4570
|
+
(0, import_daemon_core5.getQueue)(ctx.mesh.id).map((t) => [t.id, t.status])
|
|
4412
4571
|
);
|
|
4413
|
-
const eagerPushDeferred = !(0,
|
|
4572
|
+
const eagerPushDeferred = !(0, import_daemon_core5.taskDependenciesSatisfied)(task, dependencyStatusById);
|
|
4414
4573
|
const coordinatorDaemonId = resolveCoordinatorDaemonId(ctx);
|
|
4415
4574
|
const dispatchPromises = [];
|
|
4416
4575
|
const eagerPushTargets = eagerPushDeferred ? [] : ctx.mesh.nodes;
|
|
@@ -4418,7 +4577,7 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4418
4577
|
const isLocalNode = isLocalControlPlaneNode(ctx, node);
|
|
4419
4578
|
if (isLocalNode || !node.daemonId) continue;
|
|
4420
4579
|
if (targetNodeId && node.id !== targetNodeId) continue;
|
|
4421
|
-
if (!(0,
|
|
4580
|
+
if (!(0, import_daemon_core5.nodeSatisfiesRequiredTags)(requiredTags, (0, import_daemon_core5.buildMeshNodeCapabilityTags)(node))) continue;
|
|
4422
4581
|
dispatchPromises.push(
|
|
4423
4582
|
ipcDispatchToRemoteAgent(ctx, node, {
|
|
4424
4583
|
message,
|
|
@@ -4433,7 +4592,7 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4433
4592
|
try {
|
|
4434
4593
|
const providerType = result.providerType;
|
|
4435
4594
|
const descriptor = summarizeTaskMessage(message);
|
|
4436
|
-
(0,
|
|
4595
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
4437
4596
|
kind: "task_dispatched",
|
|
4438
4597
|
nodeId: node.id,
|
|
4439
4598
|
sessionId: result.sessionId,
|
|
@@ -4455,7 +4614,7 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4455
4614
|
}
|
|
4456
4615
|
}).catch((err) => {
|
|
4457
4616
|
try {
|
|
4458
|
-
(0,
|
|
4617
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
4459
4618
|
kind: "p2p_dispatch_failed",
|
|
4460
4619
|
nodeId: node.id,
|
|
4461
4620
|
payload: {
|
|
@@ -4502,17 +4661,17 @@ async function meshEnqueueTask(ctx, args) {
|
|
|
4502
4661
|
}
|
|
4503
4662
|
}
|
|
4504
4663
|
async function meshViewQueue(ctx, args) {
|
|
4505
|
-
const rateResult = (0,
|
|
4664
|
+
const rateResult = (0, import_daemon_core5.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_view_queue" });
|
|
4506
4665
|
const compact = args.verbose === true ? false : args.compact ?? true;
|
|
4507
4666
|
try {
|
|
4508
4667
|
await refreshMeshFromDaemon(ctx);
|
|
4509
4668
|
const statusFilter = sanitizeQueueStatusFilter(args.status);
|
|
4510
4669
|
const view = normalizeQueueViewMode(args.view);
|
|
4511
|
-
const rawQueue = (0,
|
|
4670
|
+
const rawQueue = (0, import_daemon_core5.getQueue)(ctx.mesh.id);
|
|
4512
4671
|
const statusById = new Map(rawQueue.map((task) => [task.id, task.status]));
|
|
4513
4672
|
const withDependencies = rawQueue.map((task) => {
|
|
4514
4673
|
if (!Array.isArray(task.dependsOn) || task.dependsOn.length === 0) return task;
|
|
4515
|
-
const depState = (0,
|
|
4674
|
+
const depState = (0, import_daemon_core5.describeTaskDependencyState)(task, statusById);
|
|
4516
4675
|
return { ...task, ...depState };
|
|
4517
4676
|
});
|
|
4518
4677
|
const liveNodes = await collectMeshViewQueueNodesWithLiveSessionsVerified(ctx);
|
|
@@ -4521,16 +4680,16 @@ async function meshViewQueue(ctx, args) {
|
|
|
4521
4680
|
const summary = buildQueueStatusSummary(fullQueue);
|
|
4522
4681
|
const visibleSummary = buildQueueStatusSummary(queue);
|
|
4523
4682
|
const maintenance = buildQueueMaintenanceReport(fullQueue);
|
|
4524
|
-
let ledgerEntries = (0,
|
|
4525
|
-
let directDispatches = (0,
|
|
4683
|
+
let ledgerEntries = (0, import_daemon_core5.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
|
|
4684
|
+
let directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id);
|
|
4526
4685
|
const directReconciliation = await reconcileDirectDispatchesFromTranscriptEvidence(ctx, liveNodes, directDispatches, ledgerEntries);
|
|
4527
4686
|
if (directReconciliation.reconciled > 0) {
|
|
4528
|
-
ledgerEntries = (0,
|
|
4529
|
-
directDispatches = (0,
|
|
4687
|
+
ledgerEntries = (0, import_daemon_core5.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
|
|
4688
|
+
directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id);
|
|
4530
4689
|
}
|
|
4531
|
-
(0,
|
|
4532
|
-
directDispatches = (0,
|
|
4533
|
-
const activeWorkEvidence = (0,
|
|
4690
|
+
(0, import_daemon_core5.markStaleDirectDispatches)(ctx.mesh.id);
|
|
4691
|
+
directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id);
|
|
4692
|
+
const activeWorkEvidence = (0, import_daemon_core5.buildMeshActiveWork)({
|
|
4534
4693
|
meshId: ctx.mesh.id,
|
|
4535
4694
|
queue: fullQueue,
|
|
4536
4695
|
ledgerEntries,
|
|
@@ -4555,7 +4714,7 @@ async function meshViewQueue(ctx, args) {
|
|
|
4555
4714
|
const wantActiveQueueArray = view === "active" || statusFilter?.some((status) => ACTIVE_QUEUE_STATUSES.has(status));
|
|
4556
4715
|
const wantHistoricalQueueArray = !compact && (view === "historical" || requestedHistoricalRows);
|
|
4557
4716
|
const activeWorkResult = compact ? compactActiveWorkRecords(activeWorkEvidence.activeWork) : { records: activeWorkEvidence.activeWork, omitted: 0 };
|
|
4558
|
-
const staleDirectWorkSummary = (0,
|
|
4717
|
+
const staleDirectWorkSummary = (0, import_daemon_core5.buildCompactStaleDirectWorkSummary)(activeWorkEvidence.staleDirectWork, {
|
|
4559
4718
|
note: activeWorkEvidence.staleDirectWorkNote,
|
|
4560
4719
|
detailHint: "Full stale direct entries are omitted from mesh_view_queue in compact mode. Call mesh_view_queue with verbose=true, or inspect mesh_task_history for ledger detail."
|
|
4561
4720
|
});
|
|
@@ -4630,12 +4789,12 @@ async function meshQueueCancel(ctx, args) {
|
|
|
4630
4789
|
try {
|
|
4631
4790
|
const taskId = (args.task_id || args.taskId || "").trim();
|
|
4632
4791
|
if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
|
|
4633
|
-
const preCancel = (0,
|
|
4792
|
+
const preCancel = (0, import_daemon_core5.getQueue)(ctx.mesh.id).find((t) => t?.id === taskId);
|
|
4634
4793
|
const wasAssigned = preCancel?.status === "assigned";
|
|
4635
4794
|
const assignedSessionId = readString(preCancel?.assignedSessionId) || void 0;
|
|
4636
4795
|
const assignedNodeId = readString(preCancel?.assignedNodeId) || void 0;
|
|
4637
4796
|
const assignedProviderType = readString(preCancel?.assignedProviderType) || void 0;
|
|
4638
|
-
const task = (0,
|
|
4797
|
+
const task = (0, import_daemon_core5.cancelTask)(ctx.mesh.id, taskId, { reason: args.reason });
|
|
4639
4798
|
if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
|
|
4640
4799
|
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
4641
4800
|
});
|
|
@@ -4711,7 +4870,7 @@ async function meshQueueRequeue(ctx, args) {
|
|
|
4711
4870
|
});
|
|
4712
4871
|
return JSON.stringify({ success: true, task: task2 }, null, 2);
|
|
4713
4872
|
}
|
|
4714
|
-
const task = (0,
|
|
4873
|
+
const task = (0, import_daemon_core5.requeueTask)(ctx.mesh.id, taskId, {
|
|
4715
4874
|
reason: args.reason,
|
|
4716
4875
|
targetNodeId,
|
|
4717
4876
|
targetSessionId,
|
|
@@ -4750,17 +4909,17 @@ async function meshTaskHistory(ctx, args) {
|
|
|
4750
4909
|
const compactCap = requestedTail > 50 ? 20 : 30;
|
|
4751
4910
|
const tail = compact ? Math.min(requestedTail, compactCap) : Math.min(requestedTail, 200);
|
|
4752
4911
|
const kind = typeof args.kind === "string" && args.kind.trim() ? [args.kind.trim()] : void 0;
|
|
4753
|
-
const rawEntries = (0,
|
|
4912
|
+
const rawEntries = (0, import_daemon_core5.readLedgerEntries)(mesh.id, { tail, kind });
|
|
4754
4913
|
const entries = compact ? rawEntries.map((e) => ({
|
|
4755
4914
|
...e,
|
|
4756
4915
|
payload: e.payload ? slimLedgerPayload(e.payload) : e.payload
|
|
4757
4916
|
})) : rawEntries;
|
|
4758
|
-
const summary = (0,
|
|
4917
|
+
const summary = (0, import_daemon_core5.getLedgerSummary)(mesh.id);
|
|
4759
4918
|
let taskStats;
|
|
4760
4919
|
try {
|
|
4761
4920
|
const taskIds = [...new Set(rawEntries.map((e) => typeof e.payload?.taskId === "string" ? e.payload.taskId : "").filter(Boolean))];
|
|
4762
4921
|
if (taskIds.length > 0) {
|
|
4763
|
-
const stats = (0,
|
|
4922
|
+
const stats = (0, import_daemon_core5.computeMeshTaskStats)(mesh.id, { taskIds });
|
|
4764
4923
|
if (stats.length > 0) taskStats = stats;
|
|
4765
4924
|
}
|
|
4766
4925
|
} catch {
|
|
@@ -4782,8 +4941,8 @@ async function meshLedgerQuery(ctx, args) {
|
|
|
4782
4941
|
const node = typeof args.node === "string" && args.node.trim() ? args.node.trim() : void 0;
|
|
4783
4942
|
const requestedTail = typeof args.tail === "number" && args.tail > 0 ? Math.floor(args.tail) : 50;
|
|
4784
4943
|
const tail = Math.min(requestedTail, 500);
|
|
4785
|
-
const entries = (0,
|
|
4786
|
-
const summary = (0,
|
|
4944
|
+
const entries = (0, import_daemon_core5.readLedgerEntries)(mesh.id, { tail, kind, since, node });
|
|
4945
|
+
const summary = (0, import_daemon_core5.getLedgerSummary)(mesh.id);
|
|
4787
4946
|
return JSON.stringify({
|
|
4788
4947
|
meshId: mesh.id,
|
|
4789
4948
|
query: {
|
|
@@ -4816,7 +4975,7 @@ async function meshRecordNote(ctx, args) {
|
|
|
4816
4975
|
const supersedes = typeof args.supersedes === "string" && args.supersedes.trim() ? args.supersedes.trim() : void 0;
|
|
4817
4976
|
const subjectKey = typeof args.subject_key === "string" && args.subject_key.trim() ? args.subject_key.trim() : void 0;
|
|
4818
4977
|
const sourceCoordinator = ctx.coordinatorSessionId || ctx.localDaemonId || ctx.coordinatorHostname || void 0;
|
|
4819
|
-
const entry = (0,
|
|
4978
|
+
const entry = (0, import_daemon_core5.appendLedgerEntry)(mesh.id, {
|
|
4820
4979
|
kind: "coordinator_operating_note",
|
|
4821
4980
|
...sourceCoordinator ? { sessionId: sourceCoordinator } : {},
|
|
4822
4981
|
payload: {
|
|
@@ -4854,7 +5013,7 @@ async function meshForgetNote(ctx, args) {
|
|
|
4854
5013
|
return JSON.stringify({ success: false, error: "note_id or text required" }, null, 2);
|
|
4855
5014
|
}
|
|
4856
5015
|
try {
|
|
4857
|
-
const { tombstone, matched } = (0,
|
|
5016
|
+
const { tombstone, matched } = (0, import_daemon_core5.tombstoneOperatingNote)(mesh.id, {
|
|
4858
5017
|
...noteId ? { noteId } : {},
|
|
4859
5018
|
...text ? { text } : {},
|
|
4860
5019
|
...typeof args.reason === "string" && args.reason.trim() ? { reason: args.reason.trim() } : {}
|
|
@@ -4885,8 +5044,8 @@ async function meshReconcileLedger(ctx, args) {
|
|
|
4885
5044
|
const reconcileNode = async (node) => {
|
|
4886
5045
|
try {
|
|
4887
5046
|
if (isLocalControlPlaneNode(ctx, node) || !node.daemonId) {
|
|
4888
|
-
const slice2 = (0,
|
|
4889
|
-
return (0,
|
|
5047
|
+
const slice2 = (0, import_daemon_core5.readLedgerSliceFromStore)(ctx.mesh.id, queryArgs);
|
|
5048
|
+
return (0, import_daemon_core5.buildMeshLedgerReplicaEvidence)({
|
|
4890
5049
|
nodeId: node.id,
|
|
4891
5050
|
daemonId: node.daemonId,
|
|
4892
5051
|
transport: "local",
|
|
@@ -4903,9 +5062,9 @@ async function meshReconcileLedger(ctx, args) {
|
|
|
4903
5062
|
if (slice?.protocol !== "adhdev.mesh.ledger.slice.v1" || !Array.isArray(slice.entries)) {
|
|
4904
5063
|
throw new Error("remote daemon returned an invalid ledger slice payload");
|
|
4905
5064
|
}
|
|
4906
|
-
const importResult = shouldImport ? (0,
|
|
5065
|
+
const importResult = shouldImport ? (0, import_daemon_core5.appendRemoteLedgerEntries)(ctx.mesh.id, slice.entries) : { accepted: 0, skippedDuplicate: 0, rejectedInvalid: 0, entries: [] };
|
|
4907
5066
|
if (shouldImport && importResult.accepted > 0) {
|
|
4908
|
-
(0,
|
|
5067
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
4909
5068
|
kind: "ledger_replicated",
|
|
4910
5069
|
nodeId: node.id,
|
|
4911
5070
|
payload: {
|
|
@@ -4918,7 +5077,7 @@ async function meshReconcileLedger(ctx, args) {
|
|
|
4918
5077
|
}
|
|
4919
5078
|
});
|
|
4920
5079
|
}
|
|
4921
|
-
return (0,
|
|
5080
|
+
return (0, import_daemon_core5.buildMeshLedgerReplicaEvidence)({
|
|
4922
5081
|
nodeId: node.id,
|
|
4923
5082
|
daemonId: node.daemonId,
|
|
4924
5083
|
transport: "p2p_datachannel",
|
|
@@ -4926,7 +5085,7 @@ async function meshReconcileLedger(ctx, args) {
|
|
|
4926
5085
|
importResult
|
|
4927
5086
|
});
|
|
4928
5087
|
} catch (e) {
|
|
4929
|
-
return (0,
|
|
5088
|
+
return (0, import_daemon_core5.buildMeshLedgerReplicaEvidence)({
|
|
4930
5089
|
nodeId: node.id,
|
|
4931
5090
|
daemonId: node.daemonId,
|
|
4932
5091
|
transport: node.daemonId ? "p2p_datachannel" : "local",
|
|
@@ -4941,7 +5100,7 @@ async function meshReconcileLedger(ctx, args) {
|
|
|
4941
5100
|
replicas.push(outcome.value);
|
|
4942
5101
|
} else {
|
|
4943
5102
|
const node = nodes[idx];
|
|
4944
|
-
replicas.push((0,
|
|
5103
|
+
replicas.push((0, import_daemon_core5.buildMeshLedgerReplicaEvidence)({
|
|
4945
5104
|
nodeId: node.id,
|
|
4946
5105
|
daemonId: node.daemonId,
|
|
4947
5106
|
transport: node.daemonId ? "p2p_datachannel" : "local",
|
|
@@ -4950,8 +5109,8 @@ async function meshReconcileLedger(ctx, args) {
|
|
|
4950
5109
|
}));
|
|
4951
5110
|
}
|
|
4952
5111
|
});
|
|
4953
|
-
const evidence = (0,
|
|
4954
|
-
(0,
|
|
5112
|
+
const evidence = (0, import_daemon_core5.buildMeshLedgerReconciliationEvidence)(ctx.mesh.id, replicas);
|
|
5113
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
4955
5114
|
kind: "ledger_reconciled",
|
|
4956
5115
|
payload: {
|
|
4957
5116
|
protocol: evidence.protocol,
|
|
@@ -4972,7 +5131,7 @@ async function meshRequeueHeldEvents(ctx, args) {
|
|
|
4972
5131
|
...readString(raw.reason) ? { reason: readString(raw.reason) } : {},
|
|
4973
5132
|
...readString(raw.since) ? { since: readString(raw.since) } : {}
|
|
4974
5133
|
} : void 0;
|
|
4975
|
-
const result = (0,
|
|
5134
|
+
const result = (0, import_daemon_core5.requeueHeldMeshCoordinatorEvents)(mesh.id, filter && Object.keys(filter).length > 0 ? filter : void 0);
|
|
4976
5135
|
const note = result.matched === 0 ? "No recoverable held events matched. Nothing to requeue." : `${result.requeued} held event(s) restored to the pending queue` + (result.dedupSuppressed > 0 ? ` (${result.dedupSuppressed} collapsed onto still-live duplicates)` : "") + (result.alreadyRequeued > 0 ? `; ${result.alreadyRequeued} already recovered by a prior pass` : "") + (result.unrecoverable > 0 ? `; ${result.unrecoverable} had no restorable original event` : "") + ". A coordinator will drain them on its next poll.";
|
|
4977
5136
|
return JSON.stringify({ success: true, ...result, note }, null, 2);
|
|
4978
5137
|
}
|
|
@@ -4990,7 +5149,7 @@ async function meshMissionUpsert(ctx, args) {
|
|
|
4990
5149
|
error: "mission_title_required: single-mission upsert needs a non-empty title. For a bulk status transition pass mission_ids (array) + status instead."
|
|
4991
5150
|
});
|
|
4992
5151
|
}
|
|
4993
|
-
const mission = (0,
|
|
5152
|
+
const mission = (0, import_daemon_core5.upsertMeshMission)(ctx.mesh.id, {
|
|
4994
5153
|
id: readString(args.mission_id) || readString(args.missionId) || void 0,
|
|
4995
5154
|
title,
|
|
4996
5155
|
goal: typeof args.goal === "string" ? args.goal : void 0,
|
|
@@ -5026,9 +5185,9 @@ async function meshMissionUpsertBulk(ctx, missionIds, status) {
|
|
|
5026
5185
|
}
|
|
5027
5186
|
const results = missionIds.map((id) => {
|
|
5028
5187
|
try {
|
|
5029
|
-
const existing = (0,
|
|
5188
|
+
const existing = (0, import_daemon_core5.getMeshMission)(ctx.mesh.id, id);
|
|
5030
5189
|
if (!existing) return { id, ok: false, error: "mission_not_found" };
|
|
5031
|
-
const updated = (0,
|
|
5190
|
+
const updated = (0, import_daemon_core5.upsertMeshMission)(ctx.mesh.id, {
|
|
5032
5191
|
id,
|
|
5033
5192
|
title: existing.title,
|
|
5034
5193
|
status
|
|
@@ -5055,12 +5214,12 @@ async function meshMissionUpsertBulk(ctx, missionIds, status) {
|
|
|
5055
5214
|
async function meshMissionList(ctx, args = {}) {
|
|
5056
5215
|
try {
|
|
5057
5216
|
const rawStatuses = Array.isArray(args.status) ? args.status : typeof args.status === "string" && args.status.trim() ? [args.status] : [];
|
|
5058
|
-
const invalid = rawStatuses.filter((s) => !
|
|
5217
|
+
const invalid = rawStatuses.filter((s) => !import_daemon_core5.MESH_MISSION_STATUSES.includes(s));
|
|
5059
5218
|
if (invalid.length > 0) {
|
|
5060
5219
|
return JSON.stringify({
|
|
5061
5220
|
success: false,
|
|
5062
5221
|
code: "invalid_mission_status",
|
|
5063
|
-
error: `invalid status filter: ${invalid.join(", ")} (valid: ${
|
|
5222
|
+
error: `invalid status filter: ${invalid.join(", ")} (valid: ${import_daemon_core5.MESH_MISSION_STATUSES.join(", ")})`
|
|
5064
5223
|
});
|
|
5065
5224
|
}
|
|
5066
5225
|
const statuses = rawStatuses.length > 0 ? rawStatuses : void 0;
|
|
@@ -5068,7 +5227,7 @@ async function meshMissionList(ctx, args = {}) {
|
|
|
5068
5227
|
const verbose = args.verbose === true;
|
|
5069
5228
|
const withStats = verbose || (args.include_stats ?? args.includeStats) === true;
|
|
5070
5229
|
const limit = typeof args.limit === "number" && Number.isFinite(args.limit) && args.limit > 0 ? Math.floor(args.limit) : void 0;
|
|
5071
|
-
const result = (0,
|
|
5230
|
+
const result = (0, import_daemon_core5.listMeshMissionsForTool)(ctx.mesh.id, {
|
|
5072
5231
|
statuses,
|
|
5073
5232
|
verbose,
|
|
5074
5233
|
includeMagi,
|
|
@@ -5101,7 +5260,7 @@ async function meshReviewInbox(ctx, args = {}) {
|
|
|
5101
5260
|
}
|
|
5102
5261
|
|
|
5103
5262
|
// src/tools/mesh-tools-magi.ts
|
|
5104
|
-
var
|
|
5263
|
+
var import_daemon_core6 = require("@adhdev/daemon-core");
|
|
5105
5264
|
var MAGI_MAX_REPLICAS = 12;
|
|
5106
5265
|
var MAGI_MIN_TARGETS = 2;
|
|
5107
5266
|
var MAGI_CLUSTER_JACCARD = 0.4;
|
|
@@ -5585,19 +5744,19 @@ function buildMagiFanoutPlan(slots, nodes, opts = {}) {
|
|
|
5585
5744
|
slotList.forEach((slot, slotIndex) => {
|
|
5586
5745
|
const provider = slot.provider;
|
|
5587
5746
|
const model = typeof slot.model === "string" && slot.model.trim() ? slot.model.trim() : void 0;
|
|
5588
|
-
const capabilityTags = (0,
|
|
5589
|
-
const requiredTags = (0,
|
|
5747
|
+
const capabilityTags = (0, import_daemon_core5.normalizeMeshCapabilityTags)(slot.capabilityTags);
|
|
5748
|
+
const requiredTags = (0, import_daemon_core5.normalizeMeshCapabilityTags)([`provider=${provider}`, ...capabilityTags]);
|
|
5590
5749
|
const count = replicaCountFor(slot, defaultN, opts.n);
|
|
5591
5750
|
let targetNodeId;
|
|
5592
5751
|
let candidateNodes = [];
|
|
5593
5752
|
if (slot.nodeId) {
|
|
5594
|
-
const node = nodes.find((n) => (0,
|
|
5753
|
+
const node = nodes.find((n) => (0, import_daemon_core5.meshNodeIdMatches)(n, slot.nodeId));
|
|
5595
5754
|
if (node) {
|
|
5596
5755
|
targetNodeId = node.id;
|
|
5597
5756
|
candidateNodes = [node];
|
|
5598
5757
|
}
|
|
5599
5758
|
} else {
|
|
5600
|
-
candidateNodes = nodes.filter((n) => (0,
|
|
5759
|
+
candidateNodes = nodes.filter((n) => (0, import_daemon_core5.nodeSatisfiesRequiredTags)(requiredTags, (0, import_daemon_core5.buildMeshNodeCapabilityTags)(n)));
|
|
5601
5760
|
}
|
|
5602
5761
|
const available = candidateNodes.length > 0;
|
|
5603
5762
|
if (!available) {
|
|
@@ -5611,9 +5770,9 @@ function buildMagiFanoutPlan(slots, nodes, opts = {}) {
|
|
|
5611
5770
|
slotResolutions.push({ slotIndex, provider, nodeId: slot.nodeId, capabilityTags, available: false, gitStale: false, unhealthy: false, excluded: true, reason: "unavailable" });
|
|
5612
5771
|
return;
|
|
5613
5772
|
}
|
|
5614
|
-
const launchableCandidates = candidateNodes.filter((n) => (0,
|
|
5773
|
+
const launchableCandidates = candidateNodes.filter((n) => (0, import_daemon_core5.isMeshNodeHealthLaunchable)(n));
|
|
5615
5774
|
if (launchableCandidates.length === 0) {
|
|
5616
|
-
const health = (0,
|
|
5775
|
+
const health = (0, import_daemon_core5.resolveEffectiveMeshNodeHealth)(candidateNodes[0]);
|
|
5617
5776
|
unhealthySlots.push({
|
|
5618
5777
|
slotIndex,
|
|
5619
5778
|
provider,
|
|
@@ -5678,7 +5837,7 @@ function buildMagiFanoutPlan(slots, nodes, opts = {}) {
|
|
|
5678
5837
|
// Candidate pool was already narrowed to launch-ready nodes above, so an
|
|
5679
5838
|
// included slot is health-launchable by construction.
|
|
5680
5839
|
unhealthy: false,
|
|
5681
|
-
health: (0,
|
|
5840
|
+
health: (0, import_daemon_core5.resolveEffectiveMeshNodeHealth)(candidateNodes[0]),
|
|
5682
5841
|
excluded: false
|
|
5683
5842
|
};
|
|
5684
5843
|
if (gitStale && !includeStale) {
|
|
@@ -5851,13 +6010,13 @@ function collectMagiCandidateTexts(payload) {
|
|
|
5851
6010
|
}
|
|
5852
6011
|
function replicaCompletionIsWeak(meshId, taskId) {
|
|
5853
6012
|
try {
|
|
5854
|
-
const entries = (0,
|
|
6013
|
+
const entries = (0, import_daemon_core5.readLedgerEntries)(meshId, { kind: ["task_completed"], tail: 200 });
|
|
5855
6014
|
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
5856
6015
|
const entry = entries[i];
|
|
5857
6016
|
const payload = entry?.payload && typeof entry.payload === "object" ? entry.payload : void 0;
|
|
5858
6017
|
const entryTaskId = readString(payload?.taskId) || readString(entry?.taskId);
|
|
5859
6018
|
if (!entryTaskId || entryTaskId !== taskId) continue;
|
|
5860
|
-
if ((0,
|
|
6019
|
+
if ((0, import_daemon_core5.isWeakCompletionEvidence)(payload)) return true;
|
|
5861
6020
|
const diag = payload?.completionDiagnostic;
|
|
5862
6021
|
if (diag && typeof diag === "object" && !Array.isArray(diag) && readString(diag.reason) === "short_generating_suppressed") {
|
|
5863
6022
|
return true;
|
|
@@ -5884,9 +6043,9 @@ async function meshMagiKindPanelSet(ctx, args) {
|
|
|
5884
6043
|
const meshId = ctx.mesh.id;
|
|
5885
6044
|
const scope = magiPanelScope(meshId, ctx.mesh.name);
|
|
5886
6045
|
try {
|
|
5887
|
-
const current = (0,
|
|
6046
|
+
const current = (0, import_daemon_core5.getMagiKindPanel)(kind, meshId) ?? [];
|
|
5888
6047
|
if (!write) {
|
|
5889
|
-
const preview = (0,
|
|
6048
|
+
const preview = (0, import_daemon_core5.normalizeMagiSlots)(args.slots, ctx.mesh.nodes.map((n) => n.id));
|
|
5890
6049
|
return JSON.stringify({
|
|
5891
6050
|
success: true,
|
|
5892
6051
|
dryRun: true,
|
|
@@ -5898,7 +6057,7 @@ async function meshMagiKindPanelSet(ctx, args) {
|
|
|
5898
6057
|
note: `Dry-run only \u2014 no file written. This is a WHOLESALE replacement of the kind's slot list for mesh '${meshId}' (machine-local ~/.adhdev/meshes.json); the currentSlots would be fully replaced. Other meshes on this machine are unaffected. Re-run with write=true after explicit user approval.`
|
|
5899
6058
|
}, null, 2);
|
|
5900
6059
|
}
|
|
5901
|
-
const slots = (0,
|
|
6060
|
+
const slots = (0, import_daemon_core5.setMagiKindPanel)(kind, args.slots, meshId);
|
|
5902
6061
|
return JSON.stringify({
|
|
5903
6062
|
success: true,
|
|
5904
6063
|
written: true,
|
|
@@ -5919,9 +6078,9 @@ async function meshMagiKindPanelList(ctx, args = {}) {
|
|
|
5919
6078
|
const only = readString(args.task_kind) || readString(args.kind);
|
|
5920
6079
|
const meshId = ctx.mesh.id;
|
|
5921
6080
|
const scope = magiPanelScope(meshId, ctx.mesh.name);
|
|
5922
|
-
const all = (0,
|
|
6081
|
+
const all = (0, import_daemon_core5.listMagiKindPanels)(meshId);
|
|
5923
6082
|
if (only) {
|
|
5924
|
-
const slots = (0,
|
|
6083
|
+
const slots = (0, import_daemon_core5.getMagiKindPanel)(only, meshId);
|
|
5925
6084
|
if (slots === void 0) {
|
|
5926
6085
|
return JSON.stringify({
|
|
5927
6086
|
success: false,
|
|
@@ -5954,7 +6113,7 @@ async function meshMagiReview(ctx, args) {
|
|
|
5954
6113
|
const referenceSubmoduleKey = resolveMagiReferenceSubmoduleKey(ctx);
|
|
5955
6114
|
const taskKind = normalizeMagiTaskKind(explicitTaskKind);
|
|
5956
6115
|
const panelName = `(kind:${taskKind})`;
|
|
5957
|
-
const slots = (0,
|
|
6116
|
+
const slots = (0, import_daemon_core5.getMagiKindPanel)(taskKind, ctx.mesh.id);
|
|
5958
6117
|
if (!slots || slots.length === 0) {
|
|
5959
6118
|
return JSON.stringify({
|
|
5960
6119
|
success: false,
|
|
@@ -5962,13 +6121,13 @@ async function meshMagiReview(ctx, args) {
|
|
|
5962
6121
|
error: `No panel slots are configured for this task_kind in mesh '${ctx.mesh.id}' settings. Add at least one (machine + provider + model) slot in settings \u2014 task_kind '${taskKind}' has no configured kind-panel.`,
|
|
5963
6122
|
taskKind,
|
|
5964
6123
|
meshId: ctx.mesh.id,
|
|
5965
|
-
configuredKinds: Object.keys((0,
|
|
6124
|
+
configuredKinds: Object.keys((0, import_daemon_core5.listMagiKindPanels)(ctx.mesh.id)),
|
|
5966
6125
|
hint: "Configure this kind in mesh settings (MagiKindPanelEditor), or set it with mesh_magi_kind_panel_set, then retry."
|
|
5967
6126
|
}, null, 2);
|
|
5968
6127
|
}
|
|
5969
6128
|
let planSlots;
|
|
5970
6129
|
try {
|
|
5971
|
-
planSlots = (0,
|
|
6130
|
+
planSlots = (0, import_daemon_core5.normalizeMagiSlots)(slots);
|
|
5972
6131
|
} catch (e) {
|
|
5973
6132
|
return JSON.stringify({
|
|
5974
6133
|
success: false,
|
|
@@ -6024,7 +6183,7 @@ async function meshMagiReview(ctx, args) {
|
|
|
6024
6183
|
const waitTimeoutMs = Math.min(MAGI_MAX_WAIT_MS, Math.max(MAGI_POLL_INTERVAL_MS, Number(args.wait_timeout_ms ?? args.waitTimeoutMs) || MAGI_DEFAULT_WAIT_MS));
|
|
6025
6184
|
const consensusGroupId = `magi_${(0, import_node_crypto.randomUUID)().replace(/-/g, "")}`;
|
|
6026
6185
|
const titleQ = question.length > 80 ? `${question.slice(0, 77)}...` : question;
|
|
6027
|
-
const mission = (0,
|
|
6186
|
+
const mission = (0, import_daemon_core5.upsertMeshMission)(ctx.mesh.id, {
|
|
6028
6187
|
title: `MAGI: ${titleQ}`,
|
|
6029
6188
|
goal: `Cross-verify (read-only) across panel '${panelName}': ${question}${args.target ? `
|
|
6030
6189
|
Target: ${args.target}` : ""}`,
|
|
@@ -6036,7 +6195,7 @@ Target: ${args.target}` : ""}`,
|
|
|
6036
6195
|
const replicaRecords = [];
|
|
6037
6196
|
for (const replica of plan.replicas) {
|
|
6038
6197
|
try {
|
|
6039
|
-
const task = (0,
|
|
6198
|
+
const task = (0, import_daemon_core5.enqueueTask)(ctx.mesh.id, prompt, {
|
|
6040
6199
|
readonly: true,
|
|
6041
6200
|
taskMode: "live_debug_readonly",
|
|
6042
6201
|
requiredTags: replica.requiredTags,
|
|
@@ -6049,7 +6208,7 @@ Target: ${args.target}` : ""}`,
|
|
|
6049
6208
|
replicaRecords.push({ taskId: task.id, provider: replica.provider, targetNodeId: replica.targetNodeId, requiredTags: replica.requiredTags });
|
|
6050
6209
|
} catch (e) {
|
|
6051
6210
|
try {
|
|
6052
|
-
(0,
|
|
6211
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
6053
6212
|
kind: "magi_replica_enqueue_failed",
|
|
6054
6213
|
payload: { consensusGroupId, missionId: mission.id, provider: replica.provider, error: e?.message || String(e) }
|
|
6055
6214
|
});
|
|
@@ -6139,7 +6298,7 @@ Target: ${args.target}` : ""}`,
|
|
|
6139
6298
|
});
|
|
6140
6299
|
closeMagiMissionIfTerminal(ctx, mission.id, collected.terminal);
|
|
6141
6300
|
const cleanupMode = resolveMagiAutoCleanupMode(ctx, args.auto_cleanup ?? args.autoCleanup);
|
|
6142
|
-
const cleanupReplicaTasks = findMagiReplicaTasks((0,
|
|
6301
|
+
const cleanupReplicaTasks = findMagiReplicaTasks((0, import_daemon_core5.getQueue)(ctx.mesh.id), consensusGroupId);
|
|
6143
6302
|
const cleanup = await cleanupMagiAutoLaunchedSessions(ctx, {
|
|
6144
6303
|
replicaTasks: cleanupReplicaTasks,
|
|
6145
6304
|
terminal: collected.terminal,
|
|
@@ -6169,7 +6328,7 @@ async function meshMagiCollect(ctx, args) {
|
|
|
6169
6328
|
await refreshMeshFromDaemon(ctx);
|
|
6170
6329
|
const explicitKind = args.task_kind ?? args.taskKind;
|
|
6171
6330
|
const taskKind = explicitKind !== void 0 ? normalizeMagiTaskKind(explicitKind) : recoverMagiTaskKind(ctx, consensusGroupId);
|
|
6172
|
-
const replicaTasks = findMagiReplicaTasks((0,
|
|
6331
|
+
const replicaTasks = findMagiReplicaTasks((0, import_daemon_core5.getQueue)(ctx.mesh.id), consensusGroupId);
|
|
6173
6332
|
if (replicaTasks.length === 0) {
|
|
6174
6333
|
return JSON.stringify({
|
|
6175
6334
|
success: false,
|
|
@@ -6273,7 +6432,7 @@ function computeMagiCleanupTargets(replicaTasks) {
|
|
|
6273
6432
|
function resolveMagiAutoCleanupMode(ctx, perCallOverride) {
|
|
6274
6433
|
if (perCallOverride === true) return "stop_and_delete";
|
|
6275
6434
|
if (perCallOverride === false) return "preserve";
|
|
6276
|
-
return (0,
|
|
6435
|
+
return (0, import_daemon_core6.resolveMagiSessionCleanupMode)(ctx.mesh?.policy?.magiSessionCleanup);
|
|
6277
6436
|
}
|
|
6278
6437
|
async function cleanupMagiAutoLaunchedSessions(ctx, args) {
|
|
6279
6438
|
if (args.mode === "preserve") return null;
|
|
@@ -6352,7 +6511,7 @@ function classifyStaleReplicas(annotatedTasks, terminal = MAGI_TERMINAL_STATUSES
|
|
|
6352
6511
|
}
|
|
6353
6512
|
function persistMagiDispatched(ctx, args) {
|
|
6354
6513
|
try {
|
|
6355
|
-
(0,
|
|
6514
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
6356
6515
|
kind: "magi_dispatched",
|
|
6357
6516
|
payload: {
|
|
6358
6517
|
source: "magi",
|
|
@@ -6372,7 +6531,7 @@ function persistMagiDispatched(ctx, args) {
|
|
|
6372
6531
|
}
|
|
6373
6532
|
function recoverMagiTaskKind(ctx, consensusGroupId) {
|
|
6374
6533
|
try {
|
|
6375
|
-
const entries = (0,
|
|
6534
|
+
const entries = (0, import_daemon_core5.readLedgerEntries)(ctx.mesh.id, { kind: ["magi_dispatched"], tail: 200 });
|
|
6376
6535
|
for (let i = entries.length - 1; i >= 0; i -= 1) {
|
|
6377
6536
|
const payload = entries[i]?.payload;
|
|
6378
6537
|
if (!payload || typeof payload !== "object") continue;
|
|
@@ -6396,7 +6555,7 @@ function stripRawAnswers(synthesis) {
|
|
|
6396
6555
|
}
|
|
6397
6556
|
function persistMagiSynthesis(ctx, args) {
|
|
6398
6557
|
try {
|
|
6399
|
-
(0,
|
|
6558
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
6400
6559
|
kind: "magi_synthesis",
|
|
6401
6560
|
payload: {
|
|
6402
6561
|
source: "magi",
|
|
@@ -6416,9 +6575,9 @@ function closeMagiMissionIfTerminal(ctx, missionId, terminal) {
|
|
|
6416
6575
|
const id = readString(missionId);
|
|
6417
6576
|
if (!id) return;
|
|
6418
6577
|
try {
|
|
6419
|
-
const mission = (0,
|
|
6578
|
+
const mission = (0, import_daemon_core5.getMeshMission)(ctx.mesh.id, id);
|
|
6420
6579
|
if (!mission || mission.status !== "active") return;
|
|
6421
|
-
(0,
|
|
6580
|
+
(0, import_daemon_core5.upsertMeshMission)(ctx.mesh.id, {
|
|
6422
6581
|
id,
|
|
6423
6582
|
title: mission.title,
|
|
6424
6583
|
// Preserve goal: upsert defaults goal to the existing value when omitted.
|
|
@@ -6453,8 +6612,8 @@ async function collectMagiResponses(ctx, args) {
|
|
|
6453
6612
|
const candidates = collectMagiCandidateTexts(payload);
|
|
6454
6613
|
const raw = candidates.find((c) => c.trim().length > 0);
|
|
6455
6614
|
if (!raw) return;
|
|
6456
|
-
if (raw.length >
|
|
6457
|
-
source.rawAnswer = raw.slice(0,
|
|
6615
|
+
if (raw.length > import_daemon_core5.MAGI_RAW_ANSWER_CAP) {
|
|
6616
|
+
source.rawAnswer = raw.slice(0, import_daemon_core5.MAGI_RAW_ANSWER_CAP);
|
|
6458
6617
|
source.rawAnswerTruncated = true;
|
|
6459
6618
|
} else {
|
|
6460
6619
|
source.rawAnswer = raw;
|
|
@@ -6464,7 +6623,7 @@ async function collectMagiResponses(ctx, args) {
|
|
|
6464
6623
|
};
|
|
6465
6624
|
const buildSource = (task) => {
|
|
6466
6625
|
const sourceNodeId = task.assignedNodeId || task.targetNodeId || void 0;
|
|
6467
|
-
const gitRef = extractNodeGitRef(sourceNodeId ? ctx.mesh.nodes.find((n) => (0,
|
|
6626
|
+
const gitRef = extractNodeGitRef(sourceNodeId ? ctx.mesh.nodes.find((n) => (0, import_daemon_core5.meshNodeIdMatches)(n, sourceNodeId)) : void 0);
|
|
6468
6627
|
return {
|
|
6469
6628
|
taskId: task.id,
|
|
6470
6629
|
nodeId: sourceNodeId,
|
|
@@ -6474,7 +6633,7 @@ async function collectMagiResponses(ctx, args) {
|
|
|
6474
6633
|
};
|
|
6475
6634
|
};
|
|
6476
6635
|
const sendKindRetry = async (task, failReason) => {
|
|
6477
|
-
const node = ctx.mesh.nodes.find((n) => (0,
|
|
6636
|
+
const node = ctx.mesh.nodes.find((n) => (0, import_daemon_core5.meshNodeIdMatches)(n, task.assignedNodeId));
|
|
6478
6637
|
if (!node || !task.assignedSessionId) return false;
|
|
6479
6638
|
const why = failReason === "empty_evidence" ? "your previous answer had an empty evidence array" : failReason === "missing_required_fields" ? "your previous answer was missing required fields" : "your previous answer did not parse as the required JSON";
|
|
6480
6639
|
const message = `Your previous MAGI answer could not be accepted (${why}). Respond NOW with ONLY a single JSON object (no prose, no code fence) matching EXACTLY this schema, with non-empty evidence:
|
|
@@ -6498,7 +6657,7 @@ ${magiOutputContractFor(kind)}`;
|
|
|
6498
6657
|
}
|
|
6499
6658
|
});
|
|
6500
6659
|
try {
|
|
6501
|
-
(0,
|
|
6660
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
6502
6661
|
kind: "magi_replica_retry",
|
|
6503
6662
|
payload: { taskId: task.id, kind, failReason }
|
|
6504
6663
|
});
|
|
@@ -6510,7 +6669,7 @@ ${magiOutputContractFor(kind)}`;
|
|
|
6510
6669
|
}
|
|
6511
6670
|
};
|
|
6512
6671
|
const nudgeWedgedReplica = async (task) => {
|
|
6513
|
-
const node = ctx.mesh.nodes.find((n) => (0,
|
|
6672
|
+
const node = ctx.mesh.nodes.find((n) => (0, import_daemon_core5.meshNodeIdMatches)(n, task.assignedNodeId));
|
|
6514
6673
|
if (!node || !task.assignedSessionId) return;
|
|
6515
6674
|
try {
|
|
6516
6675
|
const read = await commandForNode(ctx, node, "read_chat", {
|
|
@@ -6532,7 +6691,7 @@ ${magiOutputContractFor(kind)}`;
|
|
|
6532
6691
|
action: "approve"
|
|
6533
6692
|
});
|
|
6534
6693
|
try {
|
|
6535
|
-
(0,
|
|
6694
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
6536
6695
|
kind: "magi_replica_auto_approved",
|
|
6537
6696
|
payload: { taskId: task.id, nodeId: task.assignedNodeId, status }
|
|
6538
6697
|
});
|
|
@@ -6576,7 +6735,7 @@ ${magiOutputContractFor(kind)}`;
|
|
|
6576
6735
|
}
|
|
6577
6736
|
let kindResult;
|
|
6578
6737
|
try {
|
|
6579
|
-
const node = ctx.mesh.nodes.find((n) => (0,
|
|
6738
|
+
const node = ctx.mesh.nodes.find((n) => (0, import_daemon_core5.meshNodeIdMatches)(n, task.assignedNodeId));
|
|
6580
6739
|
if (!node) throw new Error("assigned node not in mesh");
|
|
6581
6740
|
const result = await commandForNode(ctx, node, "read_chat", {
|
|
6582
6741
|
sessionId: task.assignedSessionId,
|
|
@@ -6629,7 +6788,7 @@ ${magiOutputContractFor(kind)}`;
|
|
|
6629
6788
|
return false;
|
|
6630
6789
|
};
|
|
6631
6790
|
for (; ; ) {
|
|
6632
|
-
const tasks = annotateQueueStaleness((0,
|
|
6791
|
+
const tasks = annotateQueueStaleness((0, import_daemon_core5.getQueue)(ctx.mesh.id).filter((t) => ids.has(t.id)), ctx.mesh);
|
|
6633
6792
|
const allPresent = tasks.length === ids.size;
|
|
6634
6793
|
const { staleTaskIds: staleTaskIds2, staleReasons: staleReasons2 } = classifyStaleReplicas(tasks, TERMINAL);
|
|
6635
6794
|
const pastDeadline = Date.now() >= deadline;
|
|
@@ -6643,7 +6802,7 @@ ${magiOutputContractFor(kind)}`;
|
|
|
6643
6802
|
if (allPresent && outstanding.length > 0 && outstanding.every((t) => staleTaskIds2.has(t.id))) break;
|
|
6644
6803
|
await sleep(Math.min(MAGI_POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
|
|
6645
6804
|
}
|
|
6646
|
-
const finalTasks = annotateQueueStaleness((0,
|
|
6805
|
+
const finalTasks = annotateQueueStaleness((0, import_daemon_core5.getQueue)(ctx.mesh.id).filter((t) => ids.has(t.id)), ctx.mesh);
|
|
6647
6806
|
const { staleTaskIds, staleReasons } = classifyStaleReplicas(finalTasks, TERMINAL);
|
|
6648
6807
|
const presentIds = new Set(finalTasks.map((t) => t.id));
|
|
6649
6808
|
for (const task of finalTasks) {
|
|
@@ -6851,11 +7010,11 @@ async function meshPruneStaleDirect(ctx, args = {}) {
|
|
|
6851
7010
|
const execute = args.execute === true && args.dry_run !== true;
|
|
6852
7011
|
const includeTerminal = args.include_terminal === true;
|
|
6853
7012
|
const liveNodes = await collectMeshViewQueueNodesWithLiveSessions(ctx);
|
|
6854
|
-
const ledgerEntries = (0,
|
|
6855
|
-
const directDispatches = (0,
|
|
6856
|
-
const result = (0,
|
|
7013
|
+
const ledgerEntries = (0, import_daemon_core5.readLedgerEntries)(ctx.mesh.id, { tail: 500 });
|
|
7014
|
+
const directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id);
|
|
7015
|
+
const result = (0, import_daemon_core5.pruneStaleDirectDispatches)({
|
|
6857
7016
|
meshId: ctx.mesh.id,
|
|
6858
|
-
queue: (0,
|
|
7017
|
+
queue: (0, import_daemon_core5.getQueue)(ctx.mesh.id),
|
|
6859
7018
|
ledgerEntries,
|
|
6860
7019
|
directDispatches,
|
|
6861
7020
|
nodes: liveNodes,
|
|
@@ -6906,7 +7065,7 @@ async function meshSendTask(ctx, args) {
|
|
|
6906
7065
|
const requestedTaskMode = readString(args.task_mode) || readString(args.taskMode);
|
|
6907
7066
|
const readonly = args.readonly === true || args.read_only === true;
|
|
6908
7067
|
const missionId = readString(args.missionId) || readString(args.mission_id) || void 0;
|
|
6909
|
-
const modeValidation = (0,
|
|
7068
|
+
const modeValidation = (0, import_daemon_core5.validateMeshTaskModeRequest)(requestedTaskMode, message, readonly);
|
|
6910
7069
|
if (!modeValidation.valid) {
|
|
6911
7070
|
return JSON.stringify({
|
|
6912
7071
|
success: false,
|
|
@@ -7018,7 +7177,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7018
7177
|
const dispatchedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7019
7178
|
try {
|
|
7020
7179
|
const providerType = result2.providerType || cached?.providerType;
|
|
7021
|
-
(0,
|
|
7180
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
7022
7181
|
kind: "task_dispatched",
|
|
7023
7182
|
nodeId: args.node_id,
|
|
7024
7183
|
sessionId: dispatchedSessionId,
|
|
@@ -7036,7 +7195,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7036
7195
|
...coordinatorDaemonId ? { coordinatorDaemonId } : {}
|
|
7037
7196
|
})
|
|
7038
7197
|
});
|
|
7039
|
-
(0,
|
|
7198
|
+
(0, import_daemon_core5.insertDirectDispatch)(ctx.mesh.id, {
|
|
7040
7199
|
taskId,
|
|
7041
7200
|
nodeId: args.node_id,
|
|
7042
7201
|
sessionId: dispatchedSessionId,
|
|
@@ -7046,7 +7205,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7046
7205
|
via: "p2p_direct",
|
|
7047
7206
|
dispatchedAt
|
|
7048
7207
|
});
|
|
7049
|
-
(0,
|
|
7208
|
+
(0, import_daemon_core5.recordDirectDispatchTask)(ctx.mesh.id, message, {
|
|
7050
7209
|
id: taskId,
|
|
7051
7210
|
...missionId ? { missionId } : {},
|
|
7052
7211
|
assignedNodeId: args.node_id,
|
|
@@ -7150,7 +7309,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7150
7309
|
const { resolveDeliveryDecision } = await import("@adhdev/daemon-core");
|
|
7151
7310
|
const policyResult = resolveDeliveryDecision(sessionStatus, { kind: "task" });
|
|
7152
7311
|
if (policyResult.decision === "queued") {
|
|
7153
|
-
const queuedTask = (0,
|
|
7312
|
+
const queuedTask = (0, import_daemon_core5.enqueueTask)(ctx.mesh.id, message, {
|
|
7154
7313
|
targetNodeId: args.node_id,
|
|
7155
7314
|
targetSessionId: args.session_id,
|
|
7156
7315
|
taskMode,
|
|
@@ -7179,7 +7338,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7179
7338
|
const dispatchedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7180
7339
|
const coordinatorDaemonId = resolveCoordinatorDaemonId(ctx);
|
|
7181
7340
|
try {
|
|
7182
|
-
(0,
|
|
7341
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
7183
7342
|
kind: "task_dispatched",
|
|
7184
7343
|
nodeId: args.node_id,
|
|
7185
7344
|
sessionId: args.session_id,
|
|
@@ -7200,7 +7359,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7200
7359
|
});
|
|
7201
7360
|
} catch {
|
|
7202
7361
|
}
|
|
7203
|
-
(0,
|
|
7362
|
+
(0, import_daemon_core5.insertDirectDispatch)(ctx.mesh.id, {
|
|
7204
7363
|
taskId,
|
|
7205
7364
|
nodeId: args.node_id,
|
|
7206
7365
|
sessionId: args.session_id,
|
|
@@ -7213,7 +7372,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7213
7372
|
});
|
|
7214
7373
|
let dispatchPreRecorded = false;
|
|
7215
7374
|
try {
|
|
7216
|
-
dispatchPreRecorded = (0,
|
|
7375
|
+
dispatchPreRecorded = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id).some((d) => d.taskId === taskId);
|
|
7217
7376
|
} catch {
|
|
7218
7377
|
}
|
|
7219
7378
|
const dispatchResult = await commandForNode(ctx, node, "agent_command", {
|
|
@@ -7235,7 +7394,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7235
7394
|
const dispatchPayload = unwrapCommandPayload(dispatchResult);
|
|
7236
7395
|
if (dispatchPayload?.success === false || dispatchResult?.success === false) {
|
|
7237
7396
|
try {
|
|
7238
|
-
(0,
|
|
7397
|
+
(0, import_daemon_core5.deleteDirectDispatchesByTaskId)(ctx.mesh.id, [taskId]);
|
|
7239
7398
|
} catch {
|
|
7240
7399
|
}
|
|
7241
7400
|
dispatchPreRecorded = false;
|
|
@@ -7249,7 +7408,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7249
7408
|
});
|
|
7250
7409
|
}
|
|
7251
7410
|
try {
|
|
7252
|
-
(0,
|
|
7411
|
+
(0, import_daemon_core5.recordDirectDispatchTask)(ctx.mesh.id, message, {
|
|
7253
7412
|
id: taskId,
|
|
7254
7413
|
...missionId ? { missionId } : {},
|
|
7255
7414
|
assignedNodeId: args.node_id,
|
|
@@ -7294,7 +7453,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7294
7453
|
...buildMissionInactiveWarning(ctx, missionId) ?? {}
|
|
7295
7454
|
});
|
|
7296
7455
|
}
|
|
7297
|
-
const task = (0,
|
|
7456
|
+
const task = (0, import_daemon_core5.enqueueTask)(ctx.mesh.id, message, {
|
|
7298
7457
|
targetNodeId: args.node_id,
|
|
7299
7458
|
targetSessionId: args.session_id,
|
|
7300
7459
|
taskMode,
|
|
@@ -7303,7 +7462,7 @@ async function meshSendTask(ctx, args) {
|
|
|
7303
7462
|
...ctx.coordinatorSessionId ? { sourceCoordinatorSessionId: ctx.coordinatorSessionId } : {}
|
|
7304
7463
|
});
|
|
7305
7464
|
const queueTrigger = await triggerMeshQueueAndReport(ctx);
|
|
7306
|
-
const pendingEvents = (0,
|
|
7465
|
+
const pendingEvents = (0, import_daemon_core5.drainPendingMeshCoordinatorEvents)(ctx.mesh.id, ctx.localDaemonId);
|
|
7307
7466
|
const result = {
|
|
7308
7467
|
success: true,
|
|
7309
7468
|
source: "queue",
|
|
@@ -7349,7 +7508,7 @@ async function meshReadChat(ctx, args) {
|
|
|
7349
7508
|
tailLimit: args.tail ?? 10
|
|
7350
7509
|
});
|
|
7351
7510
|
} catch (e) {
|
|
7352
|
-
if (isLocalNode || !(0,
|
|
7511
|
+
if (isLocalNode || !(0, import_daemon_core5.isP2pRelayTransportFailure)(e)) throw e;
|
|
7353
7512
|
return buildMeshReadChatCacheFallback(ctx, args, node, e);
|
|
7354
7513
|
}
|
|
7355
7514
|
const payload = annotateRapidReadChatAdvisory(unwrapCommandPayload(result), {
|
|
@@ -7438,7 +7597,7 @@ async function meshSendKeys(ctx, args) {
|
|
|
7438
7597
|
const auditKeys = requestedKeys.slice(0, 64);
|
|
7439
7598
|
const recordAudit = (result2, extra = {}) => {
|
|
7440
7599
|
try {
|
|
7441
|
-
(0,
|
|
7600
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
7442
7601
|
kind: "key_injection",
|
|
7443
7602
|
nodeId: args.node_id,
|
|
7444
7603
|
sessionId: args.session_id,
|
|
@@ -7455,7 +7614,7 @@ async function meshSendKeys(ctx, args) {
|
|
|
7455
7614
|
}
|
|
7456
7615
|
};
|
|
7457
7616
|
if (hasDestructive) {
|
|
7458
|
-
const policyAllows = (0,
|
|
7617
|
+
const policyAllows = (0, import_daemon_core5.resolveAllowSendKeysDestructive)(ctx.mesh.policy, node.policy);
|
|
7459
7618
|
if (args.confirm_destructive !== true || !policyAllows) {
|
|
7460
7619
|
recordAudit("refused", { refused: "destructive_gate", policyAllows });
|
|
7461
7620
|
return JSON.stringify({
|
|
@@ -7537,14 +7696,14 @@ async function meshLaunchSession(ctx, args) {
|
|
|
7537
7696
|
const coordinatorNode = resolveCoordinatorNode(ctx);
|
|
7538
7697
|
const coordinatorDaemonId = resolveCoordinatorDaemonId(ctx);
|
|
7539
7698
|
const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
|
|
7540
|
-
const delegatedWorkerAutoApprove = (0,
|
|
7699
|
+
const delegatedWorkerAutoApprove = (0, import_daemon_core5.resolveDelegatedWorkerAutoApprove)(ctx.mesh.policy, node.policy);
|
|
7541
7700
|
let requestedAutoApproveMode;
|
|
7542
|
-
const delegatedWorkerDangerousModeAllow = (0,
|
|
7701
|
+
const delegatedWorkerDangerousModeAllow = (0, import_daemon_core5.resolveDelegatedWorkerDangerousModeAllow)(ctx.mesh.policy, node.policy);
|
|
7543
7702
|
if (delegatedWorkerAutoApprove !== false) {
|
|
7544
7703
|
try {
|
|
7545
7704
|
const ws = typeof node.workspace === "string" && node.workspace.trim() ? node.workspace.trim() : "";
|
|
7546
7705
|
if (ws) {
|
|
7547
|
-
const repo = (0,
|
|
7706
|
+
const repo = (0, import_daemon_core5.loadRepoMeshJsonConfig)(ws);
|
|
7548
7707
|
const repoMode = repo.sourceType === "repo_file" ? repo.config?.providerDefaults?.autoApproveModes?.[resolvedProviderType] : void 0;
|
|
7549
7708
|
if (typeof repoMode === "string" && repoMode.trim()) requestedAutoApproveMode = repoMode.trim();
|
|
7550
7709
|
}
|
|
@@ -7641,7 +7800,7 @@ async function meshLaunchSession(ctx, args) {
|
|
|
7641
7800
|
});
|
|
7642
7801
|
}
|
|
7643
7802
|
try {
|
|
7644
|
-
(0,
|
|
7803
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
7645
7804
|
kind: "session_launched",
|
|
7646
7805
|
nodeId: args.node_id,
|
|
7647
7806
|
sessionId: runtimeSessionId || void 0,
|
|
@@ -7694,26 +7853,26 @@ async function meshAnswerQuestion(ctx, args) {
|
|
|
7694
7853
|
return JSON.stringify(result, null, 2);
|
|
7695
7854
|
}
|
|
7696
7855
|
async function meshListPendingApprovals(ctx, _args = {}) {
|
|
7697
|
-
(0,
|
|
7856
|
+
(0, import_daemon_core5.recordMeshToolCall)({ meshId: ctx.mesh.id, tool: "mesh_list_pending_approvals" });
|
|
7698
7857
|
await refreshMeshFromDaemon(ctx);
|
|
7699
7858
|
const liveNodes = await collectMeshViewQueueNodesWithLiveSessions(ctx);
|
|
7700
|
-
let ledgerEntries = (0,
|
|
7701
|
-
let directDispatches = (0,
|
|
7859
|
+
let ledgerEntries = (0, import_daemon_core5.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
|
|
7860
|
+
let directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id);
|
|
7702
7861
|
const directReconciliation = await reconcileDirectDispatchesFromTranscriptEvidence(ctx, liveNodes, directDispatches, ledgerEntries);
|
|
7703
7862
|
if (directReconciliation.reconciled > 0) {
|
|
7704
|
-
ledgerEntries = (0,
|
|
7705
|
-
directDispatches = (0,
|
|
7863
|
+
ledgerEntries = (0, import_daemon_core5.readLedgerEntries)(ctx.mesh.id, { tail: 200 });
|
|
7864
|
+
directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id);
|
|
7706
7865
|
}
|
|
7707
|
-
(0,
|
|
7708
|
-
directDispatches = (0,
|
|
7709
|
-
const activeWorkEvidence = (0,
|
|
7866
|
+
(0, import_daemon_core5.markStaleDirectDispatches)(ctx.mesh.id);
|
|
7867
|
+
directDispatches = (0, import_daemon_core5.getActiveDirectDispatches)(ctx.mesh.id);
|
|
7868
|
+
const activeWorkEvidence = (0, import_daemon_core5.buildMeshActiveWork)({
|
|
7710
7869
|
meshId: ctx.mesh.id,
|
|
7711
|
-
queue: (0,
|
|
7870
|
+
queue: (0, import_daemon_core5.getQueue)(ctx.mesh.id),
|
|
7712
7871
|
ledgerEntries,
|
|
7713
7872
|
directDispatches,
|
|
7714
7873
|
nodes: liveNodes
|
|
7715
7874
|
});
|
|
7716
|
-
const approvals = (0,
|
|
7875
|
+
const approvals = (0, import_daemon_core5.collectPendingApprovals)(activeWorkEvidence.activeWork);
|
|
7717
7876
|
return JSON.stringify({
|
|
7718
7877
|
count: approvals.length,
|
|
7719
7878
|
approvals,
|
|
@@ -7875,7 +8034,7 @@ async function meshCheckpoint(ctx, args) {
|
|
|
7875
8034
|
includeUntracked: true
|
|
7876
8035
|
});
|
|
7877
8036
|
try {
|
|
7878
|
-
(0,
|
|
8037
|
+
(0, import_daemon_core5.appendLedgerEntry)(ctx.mesh.id, {
|
|
7879
8038
|
kind: "checkpoint_created",
|
|
7880
8039
|
nodeId: args.node_id,
|
|
7881
8040
|
payload: {
|