@adhdev/daemon-core 0.9.82-rc.372 → 0.9.82-rc.374
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/router.d.ts +28 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +211 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +214 -69
- package/dist/index.mjs.map +1 -1
- package/dist/logging/log-tail-reader.d.ts +40 -5
- package/dist/mesh/mesh-events-stale.d.ts +12 -0
- package/dist/providers/chat-message-normalization.d.ts +1 -1
- package/package.json +2 -2
- package/src/commands/low-family/mesh-node-logs.ts +6 -0
- package/src/commands/med-family/mesh-crud.ts +12 -2
- package/src/commands/router.ts +45 -0
- package/src/index.ts +1 -1
- package/src/logging/log-tail-reader.ts +187 -66
- package/src/mesh/mesh-events-coordinator.ts +19 -0
- package/src/mesh/mesh-events-stale.ts +23 -0
- package/src/mesh/mesh-events-utils.ts +1 -1
- package/src/mesh/mesh-reconcile-loop.ts +31 -9
- package/src/providers/chat-message-normalization.ts +1 -1
|
@@ -58,10 +58,10 @@ import {
|
|
|
58
58
|
import { readNonEmptyString, readMeshCompletionSummary } from './mesh-events-utils.js';
|
|
59
59
|
import { traceMeshEventStage, traceMeshEventDrop } from './mesh-event-trace.js';
|
|
60
60
|
import { expandDaemonIdForms, daemonIdsEquivalent } from '@adhdev/mesh-shared';
|
|
61
|
-
import { getActiveDirectDispatches, getQueue, reclaimStrandedAssignedTask } from './mesh-work-queue.js';
|
|
61
|
+
import { getActiveDirectDispatches, getQueue, reclaimStrandedAssignedTask, updateTaskStatus } from './mesh-work-queue.js';
|
|
62
62
|
import { readLedgerEntries } from './mesh-ledger.js';
|
|
63
63
|
import { pruneStaleDirectDispatches } from './mesh-active-work.js';
|
|
64
|
-
import { reconcileDirectDispatchCompletionFromTranscript } from './mesh-events-stale.js';
|
|
64
|
+
import { findTerminalLedgerEvidenceForTask, reconcileDirectDispatchCompletionFromTranscript } from './mesh-events-stale.js';
|
|
65
65
|
import { extractFinalAssistantSummaryEvidence } from '../providers/chat-message-normalization.js';
|
|
66
66
|
import type { ChatMessage } from '../types.js';
|
|
67
67
|
|
|
@@ -164,7 +164,12 @@ function daemonHostsMesh(mesh: LocalMeshEntry, daemonIds: string[]): boolean {
|
|
|
164
164
|
const hostDaemonId = readNonEmptyString(host.hostDaemonId);
|
|
165
165
|
// Host role but no pinned hostDaemonId → treat as host (single-daemon / legacy).
|
|
166
166
|
if (!hostDaemonId) return true;
|
|
167
|
-
return daemonIds
|
|
167
|
+
return daemonIdListIncludes(daemonIds, hostDaemonId);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function daemonIdListIncludes(ids: readonly string[], id: string | undefined): boolean {
|
|
171
|
+
if (!id) return false;
|
|
172
|
+
return ids.some(candidate => candidate === id || daemonIdsEquivalent(candidate, id));
|
|
168
173
|
}
|
|
169
174
|
|
|
170
175
|
// Resolve EVERY id-form this daemon answers to FOR A GIVEN MESH: the runtime drain
|
|
@@ -183,8 +188,8 @@ function resolveCoordinatorSelfIds(mesh: LocalMeshEntry, drainDaemonIds: string[
|
|
|
183
188
|
for (const node of mesh.nodes) {
|
|
184
189
|
const nodeDaemonId = readNonEmptyString(node.daemonId);
|
|
185
190
|
const nodeMachineId = readNonEmptyString(node.machineId);
|
|
186
|
-
const isSelf = (nodeDaemonId && drainDaemonIds
|
|
187
|
-
|| (nodeMachineId && drainDaemonIds
|
|
191
|
+
const isSelf = (nodeDaemonId && daemonIdListIncludes(drainDaemonIds, nodeDaemonId))
|
|
192
|
+
|| (nodeMachineId && daemonIdListIncludes(drainDaemonIds, nodeMachineId));
|
|
188
193
|
if (!isSelf) continue;
|
|
189
194
|
if (nodeDaemonId) ids.add(nodeDaemonId);
|
|
190
195
|
if (nodeMachineId) ids.add(nodeMachineId);
|
|
@@ -196,7 +201,7 @@ function resolveCoordinatorSelfIds(mesh: LocalMeshEntry, drainDaemonIds: string[
|
|
|
196
201
|
// this daemon does not make this daemon the host; daemonHostsMesh still honours a
|
|
197
202
|
// foreign hostDaemonId and rejects ownership.
|
|
198
203
|
const hostDaemonId = readNonEmptyString(mesh.meshHost?.hostDaemonId);
|
|
199
|
-
if (hostDaemonId && ids
|
|
204
|
+
if (hostDaemonId && daemonIdListIncludes([...ids], hostDaemonId)) ids.add(hostDaemonId);
|
|
200
205
|
return [...ids];
|
|
201
206
|
}
|
|
202
207
|
|
|
@@ -358,6 +363,23 @@ function recoverStrandedAssignedDispatches(meshId: string, store: MeshRuntimeSto
|
|
|
358
363
|
const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? '');
|
|
359
364
|
if (!Number.isFinite(dispatchedAtMs)) continue; // no dispatch ts → can't age it
|
|
360
365
|
if (nowMs - dispatchedAtMs < ASSIGNED_STRANDED_DEADLINE_MS) continue; // still in confirm window
|
|
366
|
+
const terminal = findTerminalLedgerEvidenceForTask({
|
|
367
|
+
meshId,
|
|
368
|
+
taskId: row.id,
|
|
369
|
+
});
|
|
370
|
+
if (terminal) {
|
|
371
|
+
const status = terminal.kind === 'task_completed' ? 'completed' : 'failed';
|
|
372
|
+
updateTaskStatus(meshId, row.id, status);
|
|
373
|
+
LOG.warn('MeshReconcile', `Skipped stranded reclaim redispatch for terminal task ${row.id} on mesh ${meshId}; ${terminal.kind} ledger evidence already exists`);
|
|
374
|
+
traceMeshEventDrop('assigned_stranded_terminal_ledger', {
|
|
375
|
+
taskId: row.id,
|
|
376
|
+
sessionId: row.assignedSessionId,
|
|
377
|
+
nodeId: row.assignedNodeId,
|
|
378
|
+
meshId,
|
|
379
|
+
event: 'agent:generating_completed',
|
|
380
|
+
}, terminal.kind);
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
361
383
|
if (store.taskHasConfirmedDelivery(meshId, row.id)) continue; // dispatched → PHASE 4's job
|
|
362
384
|
const reclaimed = reclaimStrandedAssignedTask(meshId, row.id, {
|
|
363
385
|
reason: 'assigned_stranded_dispatch_unconfirmed',
|
|
@@ -896,7 +918,7 @@ async function pullRemoteNodeQueues(
|
|
|
896
918
|
// from ourselves over P2P is both wasteful and a self-dispatch hazard.
|
|
897
919
|
if (!nodeDaemonId) continue;
|
|
898
920
|
if (daemonIdsEquivalent(nodeDaemonId, localDaemonId)) continue;
|
|
899
|
-
if (candidateDaemonIds
|
|
921
|
+
if (daemonIdListIncludes(candidateDaemonIds, nodeDaemonId)) continue;
|
|
900
922
|
|
|
901
923
|
for (const pendingEventArgs of pulls) {
|
|
902
924
|
let events: unknown;
|
|
@@ -972,7 +994,7 @@ async function reconcileUnterminatedDirectDispatches(
|
|
|
972
994
|
// A node is local when it has no daemonId, names this daemon, or actually
|
|
973
995
|
// has a live instance here. Anything else is reached over P2P.
|
|
974
996
|
const isLocalNode = !nodeDaemonId
|
|
975
|
-
|| selfIds
|
|
997
|
+
|| daemonIdListIncludes(selfIds, nodeDaemonId)
|
|
976
998
|
|| daemonIdsEquivalent(nodeDaemonId, localDaemonId)
|
|
977
999
|
|| !!components.instanceManager.getInstance(sessionId);
|
|
978
1000
|
|
|
@@ -1092,7 +1114,7 @@ async function collectLiveNodesWithSessions(
|
|
|
1092
1114
|
return Promise.all(mesh.nodes.map(async (node) => {
|
|
1093
1115
|
const nodeDaemonId = readNonEmptyString(node.daemonId);
|
|
1094
1116
|
const isLocalNode = !nodeDaemonId
|
|
1095
|
-
|| selfIds
|
|
1117
|
+
|| daemonIdListIncludes(selfIds, nodeDaemonId)
|
|
1096
1118
|
|| daemonIdsEquivalent(nodeDaemonId, localDaemonId);
|
|
1097
1119
|
let statusResult: unknown;
|
|
1098
1120
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChatMessage } from '../types.js';
|
|
2
2
|
import { flattenContent } from './contracts.js';
|
|
3
3
|
|
|
4
|
-
export const DEFAULT_FINAL_SUMMARY_MAX_CHARS =
|
|
4
|
+
export const DEFAULT_FINAL_SUMMARY_MAX_CHARS = 16_000;
|
|
5
5
|
|
|
6
6
|
export function extractFinalSummaryFromMessages(
|
|
7
7
|
messages: ChatMessage[] | null | undefined,
|