@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.
@@ -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.includes(hostDaemonId);
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.includes(nodeDaemonId))
187
- || (nodeMachineId && drainDaemonIds.includes(nodeMachineId));
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.has(hostDaemonId)) ids.add(hostDaemonId);
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.includes(nodeDaemonId)) continue;
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.includes(nodeDaemonId)
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.includes(nodeDaemonId)
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_000;
4
+ export const DEFAULT_FINAL_SUMMARY_MAX_CHARS = 16_000;
5
5
 
6
6
  export function extractFinalSummaryFromMessages(
7
7
  messages: ChatMessage[] | null | undefined,