@adhdev/daemon-core 0.9.82-rc.24 → 0.9.82-rc.26

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 CHANGED
@@ -1514,18 +1514,20 @@ function requeueTask(meshId, taskId, opts) {
1514
1514
  return entry;
1515
1515
  });
1516
1516
  }
1517
- function updateSessionTaskStatus(meshId, sessionId, status) {
1517
+ function updateSessionTaskStatus(meshId, sessionId, status, opts) {
1518
1518
  return withQueueLock(meshId, () => {
1519
1519
  const queue = readQueue(meshId);
1520
+ const occurredAtTime = opts?.occurredAt ? new Date(opts.occurredAt).getTime() : Number.NaN;
1521
+ const hasOccurredAt = Number.isFinite(occurredAtTime);
1520
1522
  let bestIdx = -1;
1521
1523
  let bestTime = 0;
1522
1524
  for (let i = queue.length - 1; i >= 0; i--) {
1523
- if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
1524
- const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
1525
- if (time > bestTime) {
1526
- bestTime = time;
1527
- bestIdx = i;
1528
- }
1525
+ if (queue[i].assignedSessionId !== sessionId || queue[i].status !== "assigned") continue;
1526
+ const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
1527
+ if (hasOccurredAt && Number.isFinite(time) && time > occurredAtTime) continue;
1528
+ if (time > bestTime) {
1529
+ bestTime = time;
1530
+ bestIdx = i;
1529
1531
  }
1530
1532
  }
1531
1533
  if (bestIdx === -1) return null;
@@ -2051,6 +2053,38 @@ function shouldSuppressIntentionalCleanupStop(args) {
2051
2053
  if (isIntentionalCleanupStopMetadata(args.metadataEvent)) return true;
2052
2054
  return hasRecentIntentionalCleanupStop(args.meshId, args.sessionId, args.nodeId);
2053
2055
  }
2056
+ function readEventTimestamp(value) {
2057
+ if (typeof value === "number" && Number.isFinite(value)) return value;
2058
+ if (typeof value === "string" && value.trim()) {
2059
+ const numeric = Number(value);
2060
+ if (Number.isFinite(numeric)) return numeric;
2061
+ const parsed = Date.parse(value);
2062
+ if (Number.isFinite(parsed)) return parsed;
2063
+ }
2064
+ return null;
2065
+ }
2066
+ function buildMeshCompletionFingerprint(args) {
2067
+ const timestampPart = Number.isFinite(args.timestamp) ? String(args.timestamp) : readNonEmptyString(args.finalSummary).slice(0, 200);
2068
+ return [
2069
+ args.meshId,
2070
+ args.event,
2071
+ args.sessionId,
2072
+ args.providerType || "",
2073
+ args.providerSessionId || "",
2074
+ timestampPart
2075
+ ].join("::");
2076
+ }
2077
+ function isDuplicateMeshCompletionEvent(args) {
2078
+ const fingerprint = buildMeshCompletionFingerprint(args);
2079
+ if (!fingerprint) return false;
2080
+ const now = Date.now();
2081
+ for (const [key, seenAt] of recentCompletionFingerprints.entries()) {
2082
+ if (now - seenAt > RECENT_COMPLETION_FINGERPRINT_TTL_MS) recentCompletionFingerprints.delete(key);
2083
+ }
2084
+ if (recentCompletionFingerprints.has(fingerprint)) return true;
2085
+ recentCompletionFingerprints.set(fingerprint, now);
2086
+ return false;
2087
+ }
2054
2088
  function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
2055
2089
  const task = claimNextTask(meshId, nodeId, sessionId);
2056
2090
  if (!task) {
@@ -2412,13 +2446,31 @@ function injectMeshSystemMessage(components, args) {
2412
2446
  LOG.info("MeshEvents", `Suppressed ${args.event} for intentionally cleanup-stopped session ${eventSessionId || "(unknown session)"}`);
2413
2447
  return { success: true, forwarded: 0, suppressed: true, intentionalCleanupStop: true };
2414
2448
  }
2449
+ const eventTimestamp = readEventTimestamp(args.metadataEvent.timestamp);
2450
+ if (args.event === "agent:generating_completed" && eventSessionId) {
2451
+ const duplicateCompletion = isDuplicateMeshCompletionEvent({
2452
+ meshId: args.meshId,
2453
+ event: args.event,
2454
+ sessionId: eventSessionId,
2455
+ providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
2456
+ providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0,
2457
+ timestamp: eventTimestamp,
2458
+ finalSummary: readNonEmptyString(args.metadataEvent.finalSummary) || void 0
2459
+ });
2460
+ if (duplicateCompletion) {
2461
+ LOG.info("MeshEvents", `Suppressed duplicate completion for mesh ${args.meshId} session ${eventSessionId}`);
2462
+ return { success: true, forwarded: 0, suppressed: true, duplicateCompletion: true };
2463
+ }
2464
+ }
2415
2465
  let completedTaskForLedger = null;
2416
2466
  if (args.event === "agent:generating_completed") {
2417
2467
  const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
2418
2468
  const nodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
2419
2469
  const providerType = readNonEmptyString(args.metadataEvent.providerType);
2420
2470
  if (sessionId) {
2421
- const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed");
2471
+ const completedTask = updateSessionTaskStatus(args.meshId, sessionId, "completed", {
2472
+ occurredAt: eventTimestamp !== null ? new Date(eventTimestamp).toISOString() : void 0
2473
+ });
2422
2474
  completedTaskForLedger = completedTask ? { id: completedTask.id } : null;
2423
2475
  if (nodeId && providerType) {
2424
2476
  setImmediate(() => {
@@ -2632,6 +2684,7 @@ function handleMeshForwardEvent(components, payload) {
2632
2684
  providerType: readNonEmptyString(payload.providerType),
2633
2685
  providerSessionId: readNonEmptyString(payload.providerSessionId),
2634
2686
  finalSummary: readNonEmptyString(payload.finalSummary) || readNonEmptyString(payload.summary),
2687
+ ...payload.timestamp !== void 0 ? { timestamp: payload.timestamp } : {},
2635
2688
  intentional: payload.intentional === true,
2636
2689
  intentionalStop: payload.intentionalStop === true,
2637
2690
  operatorCleanup: payload.operatorCleanup === true,
@@ -2674,7 +2727,7 @@ function setupMeshEventForwarding(components) {
2674
2727
  });
2675
2728
  });
2676
2729
  }
2677
- var import_fs6, import_path5, REMOTE_IDLE_SESSION_TTL_MS, remoteIdleSessions, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
2730
+ var import_fs6, import_path5, REMOTE_IDLE_SESSION_TTL_MS, remoteIdleSessions, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, recentCompletionFingerprints, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS;
2678
2731
  var init_mesh_events = __esm({
2679
2732
  "src/mesh/mesh-events.ts"() {
2680
2733
  "use strict";
@@ -2703,6 +2756,8 @@ var init_mesh_events = __esm({
2703
2756
  "monitor:long_generating": "task_stalled"
2704
2757
  };
2705
2758
  INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS = 30 * 60 * 1e3;
2759
+ RECENT_COMPLETION_FINGERPRINT_TTL_MS = 10 * 60 * 1e3;
2760
+ recentCompletionFingerprints = /* @__PURE__ */ new Map();
2706
2761
  autoLaunchInProgress = /* @__PURE__ */ new Set();
2707
2762
  autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
2708
2763
  AUTO_LAUNCH_COOLDOWN_MS = 5e3;
@@ -24037,49 +24092,7 @@ function readGitSubmodules(value) {
24037
24092
  }).filter((entry) => entry !== null);
24038
24093
  return submodules.length > 0 ? submodules : void 0;
24039
24094
  }
24040
- function buildCachedInlineMeshGitStatus(node) {
24041
- const cachedStatus = readObjectRecord(node?.cachedStatus);
24042
- const cachedGit = readObjectRecord(cachedStatus.git);
24043
- if (Object.keys(cachedGit).length) {
24044
- const conflictFiles2 = Array.isArray(cachedGit.conflictFiles) ? cachedGit.conflictFiles.filter((value) => typeof value === "string") : [];
24045
- const conflictCount2 = readNumberValue(cachedGit.conflicts) ?? conflictFiles2.length;
24046
- const hasConflicts2 = readBooleanValue(cachedGit.hasConflicts) ?? conflictCount2 > 0;
24047
- const isGitRepo2 = readBooleanValue(cachedGit.isGitRepo);
24048
- if (isGitRepo2 !== void 0) {
24049
- const submodules2 = readGitSubmodules(cachedGit.submodules);
24050
- return {
24051
- workspace: readStringValue(cachedGit.workspace, node?.workspace) || "",
24052
- repoRoot: readStringValue(cachedGit.repoRoot, node?.repoRoot, node?.workspace) || null,
24053
- isGitRepo: isGitRepo2,
24054
- branch: readStringValue(cachedGit.branch) ?? null,
24055
- headCommit: readStringValue(cachedGit.headCommit) ?? null,
24056
- headMessage: readStringValue(cachedGit.headMessage) ?? null,
24057
- upstream: readStringValue(cachedGit.upstream) ?? null,
24058
- ahead: readNumberValue(cachedGit.ahead) ?? 0,
24059
- behind: readNumberValue(cachedGit.behind) ?? 0,
24060
- staged: readNumberValue(cachedGit.staged) ?? 0,
24061
- modified: readNumberValue(cachedGit.modified) ?? 0,
24062
- untracked: readNumberValue(cachedGit.untracked) ?? 0,
24063
- deleted: readNumberValue(cachedGit.deleted) ?? 0,
24064
- renamed: readNumberValue(cachedGit.renamed) ?? 0,
24065
- hasConflicts: hasConflicts2,
24066
- conflictFiles: conflictFiles2,
24067
- stashCount: readNumberValue(cachedGit.stashCount) ?? 0,
24068
- lastCheckedAt: readNumberValue(cachedGit.lastCheckedAt) ?? Date.now(),
24069
- ...submodules2 ? { submodules: submodules2 } : {}
24070
- };
24071
- }
24072
- }
24073
- const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
24074
- const gitResult = readObjectRecord(rawGit.result);
24075
- const directStatus = readObjectRecord(rawGit.status);
24076
- const nestedStatus = readObjectRecord(gitResult.status);
24077
- const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
24078
- const probeGit = readObjectRecord(rawProbe.git);
24079
- const probeGitResult = readObjectRecord(probeGit.result);
24080
- const probeDirectStatus = readObjectRecord(probeGit.status);
24081
- const probeNestedStatus = readObjectRecord(probeGitResult.status);
24082
- const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
24095
+ function normalizeInlineMeshGitStatus(status, node, options) {
24083
24096
  const isGitRepo = readBooleanValue(status.isGitRepo);
24084
24097
  if (!Object.keys(status).length || isGitRepo === void 0) return void 0;
24085
24098
  const conflictFiles = Array.isArray(status.conflictFiles) ? status.conflictFiles.filter((value) => typeof value === "string") : [];
@@ -24104,10 +24117,31 @@ function buildCachedInlineMeshGitStatus(node) {
24104
24117
  hasConflicts,
24105
24118
  conflictFiles,
24106
24119
  stashCount: readNumberValue(status.stashCount) ?? 0,
24107
- lastCheckedAt: Date.now(),
24120
+ lastCheckedAt: options?.lastCheckedAt ?? readNumberValue(status.lastCheckedAt) ?? Date.now(),
24108
24121
  ...submodules ? { submodules } : {}
24109
24122
  };
24110
24123
  }
24124
+ function buildInlineMeshTransitGitStatus(node) {
24125
+ const rawGit = readObjectRecord(node?.lastGit ?? node?.last_git);
24126
+ const gitResult = readObjectRecord(rawGit.result);
24127
+ const directStatus = readObjectRecord(rawGit.status);
24128
+ const nestedStatus = readObjectRecord(gitResult.status);
24129
+ const rawProbe = readObjectRecord(node?.lastProbe ?? node?.last_probe);
24130
+ const probeGit = readObjectRecord(rawProbe.git);
24131
+ const probeGitResult = readObjectRecord(probeGit.result);
24132
+ const probeDirectStatus = readObjectRecord(probeGit.status);
24133
+ const probeNestedStatus = readObjectRecord(probeGitResult.status);
24134
+ const status = Object.keys(directStatus).length ? directStatus : Object.keys(nestedStatus).length ? nestedStatus : Object.keys(probeDirectStatus).length ? probeDirectStatus : Object.keys(probeNestedStatus).length ? probeNestedStatus : {};
24135
+ return normalizeInlineMeshGitStatus(status, node, { lastCheckedAt: Date.now() });
24136
+ }
24137
+ function buildCachedInlineMeshGitStatus(node) {
24138
+ const liveGit = buildInlineMeshTransitGitStatus(node);
24139
+ if (liveGit) return liveGit;
24140
+ const cachedStatus = readObjectRecord(node?.cachedStatus);
24141
+ const cachedGit = readObjectRecord(cachedStatus.git);
24142
+ if (!Object.keys(cachedGit).length) return void 0;
24143
+ return normalizeInlineMeshGitStatus(cachedGit, node);
24144
+ }
24111
24145
  function shouldDiscardCachedInlineMeshStatus(node) {
24112
24146
  const cachedStatus = readObjectRecord(node?.cachedStatus);
24113
24147
  if (!Object.keys(cachedStatus).length) return false;
@@ -24336,9 +24370,10 @@ function collectLiveMeshSessionRecords(args) {
24336
24370
  }
24337
24371
  function applyCachedInlineMeshNodeStatus(status, node) {
24338
24372
  const cachedStatus = readObjectRecord(node?.cachedStatus);
24339
- const git = buildCachedInlineMeshGitStatus(node);
24340
- const error = readStringValue(cachedStatus.error, node?.error);
24341
- const health = readStringValue(cachedStatus.health, node?.health);
24373
+ const liveGit = buildInlineMeshTransitGitStatus(node);
24374
+ const git = liveGit ?? buildCachedInlineMeshGitStatus(node);
24375
+ const error = liveGit ? void 0 : readStringValue(cachedStatus.error, node?.error);
24376
+ const health = liveGit ? void 0 : readStringValue(cachedStatus.health, node?.health);
24342
24377
  const machineStatus = readStringValue(cachedStatus.machineStatus, node?.machineStatus);
24343
24378
  const lastSeenAt = toIsoTimestamp(cachedStatus.lastSeenAt ?? cachedStatus.last_seen_at ?? node?.lastSeenAt ?? node?.last_seen_at);
24344
24379
  const updatedAt = toIsoTimestamp(cachedStatus.updatedAt ?? cachedStatus.updated_at ?? node?.updatedAt ?? node?.updated_at);