@adhdev/daemon-core 0.9.77-rc.50 → 0.9.77-rc.52

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.d.ts CHANGED
@@ -37,7 +37,10 @@ export { buildMeshLedgerReconciliationEvidence, buildMeshLedgerReplicaEvidence }
37
37
  export type { MeshLedgerReconciliationEvidence, MeshLedgerReplicaEvidence, MeshLedgerReplicaStatus } from './mesh/mesh-ledger-reconciliation.js';
38
38
  export { enqueueTask, getQueue, claimNextTask, updateTaskStatus, updateSessionTaskStatus, cancelTask, requeueTask, getMeshQueueStats } from './mesh/mesh-work-queue.js';
39
39
  export type { MeshWorkQueueEntry, MeshTaskStatus, MeshWorkQueueStats } from './mesh/mesh-work-queue.js';
40
- export { triggerMeshQueue } from './mesh/mesh-events.js';
40
+ export { buildMeshGraph } from './mesh/mesh-visualization.js';
41
+ export type { MeshGraph, MeshGraphNode, MeshGraphEdge, MeshGraphNodeType, MeshGraphEdgeType } from './mesh/mesh-visualization.js';
42
+ export { triggerMeshQueue, drainPendingMeshCoordinatorEvents, getPendingMeshCoordinatorEvents, clearPendingMeshCoordinatorEvents } from './mesh/mesh-events.js';
43
+ export type { PendingMeshCoordinatorEvent } from './mesh/mesh-events.js';
41
44
  export { P2pRelayFailureError, buildP2pRelayFailurePayload, classifyP2pRelayFailure, isP2pRelayTransportFailure, } from './mesh/p2p-relay-failure.js';
42
45
  export type { P2pRelayFailureClassification, P2pRelayFailureCode, P2pRelayFailureContext, P2pRelayFailurePayload, } from './mesh/p2p-relay-failure.js';
43
46
  export { loadState, saveState, resetState } from './config/state-store.js';
package/dist/index.js CHANGED
@@ -1209,6 +1209,7 @@ function claimNextTask(meshId, nodeId, sessionId) {
1209
1209
  entry.status = "assigned";
1210
1210
  entry.assignedNodeId = nodeId;
1211
1211
  entry.assignedSessionId = sessionId;
1212
+ entry.dispatchTimestamp = (/* @__PURE__ */ new Date()).toISOString();
1212
1213
  entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1213
1214
  writeQueue(meshId, queue);
1214
1215
  return entry;
@@ -1271,15 +1272,22 @@ function requeueTask(meshId, taskId, opts) {
1271
1272
  }
1272
1273
  function updateSessionTaskStatus(meshId, sessionId, status) {
1273
1274
  const queue = readQueue(meshId);
1275
+ let bestIdx = -1;
1276
+ let bestTime = 0;
1274
1277
  for (let i = queue.length - 1; i >= 0; i--) {
1275
1278
  if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
1276
- queue[i].status = status;
1277
- queue[i].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1278
- writeQueue(meshId, queue);
1279
- return queue[i];
1279
+ const time = new Date(queue[i].dispatchTimestamp || queue[i].updatedAt).getTime();
1280
+ if (time > bestTime) {
1281
+ bestTime = time;
1282
+ bestIdx = i;
1283
+ }
1280
1284
  }
1281
1285
  }
1282
- return null;
1286
+ if (bestIdx === -1) return null;
1287
+ queue[bestIdx].status = status;
1288
+ queue[bestIdx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1289
+ writeQueue(meshId, queue);
1290
+ return queue[bestIdx];
1283
1291
  }
1284
1292
  function getMeshQueueStats(meshId) {
1285
1293
  const queue = readQueue(meshId);
@@ -1679,7 +1687,9 @@ var init_logger = __esm({
1679
1687
  // src/mesh/mesh-events.ts
1680
1688
  var mesh_events_exports = {};
1681
1689
  __export(mesh_events_exports, {
1690
+ clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
1682
1691
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
1692
+ getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
1683
1693
  handleMeshForwardEvent: () => handleMeshForwardEvent,
1684
1694
  setupMeshEventForwarding: () => setupMeshEventForwarding,
1685
1695
  triggerMeshQueue: () => triggerMeshQueue,
@@ -1688,6 +1698,12 @@ __export(mesh_events_exports, {
1688
1698
  function drainPendingMeshCoordinatorEvents() {
1689
1699
  return pendingMeshCoordinatorEvents.splice(0);
1690
1700
  }
1701
+ function getPendingMeshCoordinatorEvents() {
1702
+ return pendingMeshCoordinatorEvents.slice();
1703
+ }
1704
+ function clearPendingMeshCoordinatorEvents() {
1705
+ pendingMeshCoordinatorEvents.splice(0);
1706
+ }
1691
1707
  function readNonEmptyString(value) {
1692
1708
  return typeof value === "string" && value.trim() ? value.trim() : "";
1693
1709
  }
@@ -5514,6 +5530,7 @@ __export(index_exports, {
5514
5530
  buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
5515
5531
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
5516
5532
  buildMachineInfo: () => buildMachineInfo,
5533
+ buildMeshGraph: () => buildMeshGraph,
5517
5534
  buildMeshLedgerReconciliationEvidence: () => buildMeshLedgerReconciliationEvidence,
5518
5535
  buildMeshLedgerReplicaEvidence: () => buildMeshLedgerReplicaEvidence,
5519
5536
  buildP2pRelayFailurePayload: () => buildP2pRelayFailurePayload,
@@ -5533,6 +5550,7 @@ __export(index_exports, {
5533
5550
  classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
5534
5551
  classifyP2pRelayFailure: () => classifyP2pRelayFailure,
5535
5552
  clearDebugTrace: () => clearDebugTrace,
5553
+ clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
5536
5554
  compareGitSnapshots: () => compareGitSnapshots,
5537
5555
  configureDebugTraceStore: () => configureDebugTraceStore,
5538
5556
  connectCdpManager: () => connectCdpManager,
@@ -5548,6 +5566,7 @@ __export(index_exports, {
5548
5566
  detectAllVersions: () => detectAllVersions,
5549
5567
  detectCLIs: () => detectCLIs,
5550
5568
  detectIDEs: () => detectIDEs,
5569
+ drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
5551
5570
  enqueueTask: () => enqueueTask,
5552
5571
  ensureSessionHostReady: () => ensureSessionHostReady,
5553
5572
  execNpmCommandSync: () => execNpmCommandSync,
@@ -5574,6 +5593,7 @@ __export(index_exports, {
5574
5593
  getMeshByRepo: () => getMeshByRepo,
5575
5594
  getMeshQueueStats: () => getMeshQueueStats,
5576
5595
  getNpmExecOptions: () => getNpmExecOptions,
5596
+ getPendingMeshCoordinatorEvents: () => getPendingMeshCoordinatorEvents,
5577
5597
  getQueue: () => getQueue,
5578
5598
  getRecentActivity: () => getRecentActivity,
5579
5599
  getRecentCommands: () => getRecentCommands,
@@ -7606,6 +7626,231 @@ function buildMeshLedgerReconciliationEvidence(meshId, replicas) {
7606
7626
 
7607
7627
  // src/index.ts
7608
7628
  init_mesh_work_queue();
7629
+
7630
+ // src/mesh/mesh-visualization.ts
7631
+ function isDirty(git) {
7632
+ if (!git) return false;
7633
+ return git.staged + git.modified + git.untracked + git.deleted + git.renamed > 0;
7634
+ }
7635
+ function dirtyFileCount(git) {
7636
+ if (!git) return 0;
7637
+ return git.staged + git.modified + git.untracked + git.deleted + git.renamed;
7638
+ }
7639
+ function detectOrphanReasons(node, defaultBranch) {
7640
+ const reasons = [];
7641
+ const git = node.git;
7642
+ if (!git) {
7643
+ reasons.push("No git status available");
7644
+ return reasons;
7645
+ }
7646
+ if (!git.isGitRepo) {
7647
+ reasons.push("Not a git repository");
7648
+ return reasons;
7649
+ }
7650
+ if (git.branch === null && git.headCommit) {
7651
+ reasons.push("Detached HEAD");
7652
+ }
7653
+ if (git.branch && !git.upstream) {
7654
+ if (defaultBranch && git.branch !== defaultBranch) {
7655
+ reasons.push(`No upstream: ${git.branch}`);
7656
+ }
7657
+ }
7658
+ if (git.branch && git.upstream === null && defaultBranch && git.branch !== defaultBranch) {
7659
+ if (!reasons.includes(`No upstream: ${git.branch}`)) {
7660
+ reasons.push(`No upstream: ${git.branch}`);
7661
+ }
7662
+ }
7663
+ if (node.error) {
7664
+ reasons.push(`Error: ${node.error}`);
7665
+ }
7666
+ return reasons;
7667
+ }
7668
+ function nodeHealthPriority(health) {
7669
+ switch (health) {
7670
+ case "online":
7671
+ return 0;
7672
+ case "dirty":
7673
+ return 1;
7674
+ case "degraded":
7675
+ return 2;
7676
+ case "wrong_branch":
7677
+ return 3;
7678
+ case "offline":
7679
+ return 4;
7680
+ case "unknown":
7681
+ return 5;
7682
+ default:
7683
+ return 5;
7684
+ }
7685
+ }
7686
+ function pickDominantHealth(healths) {
7687
+ if (healths.length === 0) return "unknown";
7688
+ return healths.reduce(
7689
+ (best, h) => nodeHealthPriority(h) > nodeHealthPriority(best) ? h : best
7690
+ );
7691
+ }
7692
+ function buildMeshGraph(status) {
7693
+ const nodes = [];
7694
+ const edges = [];
7695
+ const warnings = [];
7696
+ const branchToNodeIds = /* @__PURE__ */ new Map();
7697
+ for (const nodeStatus of status.nodes) {
7698
+ const git = nodeStatus.git;
7699
+ const branch = git?.branch || null;
7700
+ const orphanReasons = detectOrphanReasons(nodeStatus, null);
7701
+ const dirty = isDirty(git);
7702
+ const dfc = dirtyFileCount(git);
7703
+ let type = "worktreeNode";
7704
+ if (orphanReasons.length > 0) {
7705
+ type = "orphanNode";
7706
+ }
7707
+ const graphNode = {
7708
+ id: nodeStatus.nodeId,
7709
+ type,
7710
+ label: nodeStatus.machineLabel || nodeStatus.nodeId.slice(0, 8),
7711
+ workspace: nodeStatus.workspace,
7712
+ branch,
7713
+ health: nodeStatus.health,
7714
+ ahead: git?.ahead ?? 0,
7715
+ behind: git?.behind ?? 0,
7716
+ dirty,
7717
+ dirtyFiles: dfc,
7718
+ hasConflicts: git?.hasConflicts ?? false,
7719
+ activeSessionCount: nodeStatus.activeSessions?.length ?? 0,
7720
+ activeSessions: nodeStatus.activeSessions ?? [],
7721
+ providers: nodeStatus.providers ?? [],
7722
+ isOrphan: orphanReasons.length > 0,
7723
+ orphanReasons,
7724
+ source: nodeStatus
7725
+ };
7726
+ nodes.push(graphNode);
7727
+ if (branch) {
7728
+ const list = branchToNodeIds.get(branch) ?? [];
7729
+ list.push(graphNode.id);
7730
+ branchToNodeIds.set(branch, list);
7731
+ }
7732
+ }
7733
+ const branchUpstreamCounts = /* @__PURE__ */ new Map();
7734
+ for (const n of status.nodes) {
7735
+ const b = n.git?.branch;
7736
+ const upstream = n.git?.upstream;
7737
+ if (b && upstream) {
7738
+ branchUpstreamCounts.set(b, (branchUpstreamCounts.get(b) ?? 0) + 1);
7739
+ }
7740
+ }
7741
+ let inferredDefaultBranch = null;
7742
+ let bestCount = 0;
7743
+ for (const [b, count] of branchUpstreamCounts) {
7744
+ if (count > bestCount) {
7745
+ bestCount = count;
7746
+ inferredDefaultBranch = b;
7747
+ }
7748
+ }
7749
+ const defaultBranchNodeId = inferredDefaultBranch ? `__branch_${inferredDefaultBranch}` : null;
7750
+ if (defaultBranchNodeId && inferredDefaultBranch) {
7751
+ const branchNodes = branchToNodeIds.get(inferredDefaultBranch) ?? [];
7752
+ const branchHealths = branchNodes.map(
7753
+ (id) => nodes.find((n) => n.id === id).health
7754
+ );
7755
+ const defaultNode = {
7756
+ id: defaultBranchNodeId,
7757
+ type: "defaultBranchNode",
7758
+ label: inferredDefaultBranch,
7759
+ workspace: "",
7760
+ branch: inferredDefaultBranch,
7761
+ health: pickDominantHealth(branchHealths),
7762
+ ahead: 0,
7763
+ behind: 0,
7764
+ dirty: false,
7765
+ dirtyFiles: 0,
7766
+ hasConflicts: false,
7767
+ activeSessionCount: 0,
7768
+ activeSessions: [],
7769
+ providers: [],
7770
+ isOrphan: false,
7771
+ orphanReasons: [],
7772
+ nextStepHint: branchNodes.length > 0 ? `${branchNodes.length} node(s) on default branch` : void 0,
7773
+ source: {
7774
+ nodeId: defaultBranchNodeId,
7775
+ machineLabel: inferredDefaultBranch,
7776
+ workspace: "",
7777
+ health: "online",
7778
+ providers: [],
7779
+ activeSessions: []
7780
+ }
7781
+ };
7782
+ nodes.push(defaultNode);
7783
+ const seenBranches = /* @__PURE__ */ new Set();
7784
+ for (const n of nodes) {
7785
+ if (n.type === "defaultBranchNode") continue;
7786
+ if (!n.branch) continue;
7787
+ if (n.branch === inferredDefaultBranch) {
7788
+ edges.push({
7789
+ id: `${defaultBranchNodeId}--${n.id}`,
7790
+ source: defaultBranchNodeId,
7791
+ target: n.id,
7792
+ type: "parentBranch",
7793
+ label: "default"
7794
+ });
7795
+ continue;
7796
+ }
7797
+ if (seenBranches.has(n.branch)) continue;
7798
+ seenBranches.add(n.branch);
7799
+ edges.push({
7800
+ id: `${defaultBranchNodeId}--branch_${n.branch}`,
7801
+ source: defaultBranchNodeId,
7802
+ target: n.branch,
7803
+ type: "parentBranch",
7804
+ label: n.branch
7805
+ });
7806
+ }
7807
+ }
7808
+ for (const [branch, ids] of branchToNodeIds) {
7809
+ if (ids.length < 2) continue;
7810
+ for (let i = 1; i < ids.length; i++) {
7811
+ edges.push({
7812
+ id: `wt_${ids[0]}--${ids[i]}`,
7813
+ source: ids[0],
7814
+ target: ids[i],
7815
+ type: "worktreeLink",
7816
+ label: branch
7817
+ });
7818
+ }
7819
+ }
7820
+ const orphanCount = nodes.filter((n) => n.isOrphan).length;
7821
+ if (orphanCount > 0) {
7822
+ warnings.push(`${orphanCount} orphan node(s) detected`);
7823
+ }
7824
+ const conflictCount = nodes.filter((n) => n.hasConflicts).length;
7825
+ if (conflictCount > 0) {
7826
+ warnings.push(`${conflictCount} node(s) with merge conflicts`);
7827
+ }
7828
+ const offlineCount = nodes.filter((n) => n.health === "offline").length;
7829
+ if (offlineCount > 0) {
7830
+ warnings.push(`${offlineCount} node(s) offline`);
7831
+ }
7832
+ const stats = {
7833
+ totalNodes: status.nodes.length,
7834
+ onlineNodes: status.nodes.filter((n) => n.health === "online").length,
7835
+ dirtyNodes: nodes.filter((n) => n.dirty).length,
7836
+ orphanNodes: orphanCount,
7837
+ errorNodes: status.nodes.filter((n) => !!n.error).length,
7838
+ offlineNodes: offlineCount,
7839
+ totalActiveSessions: status.nodes.reduce((sum, n) => sum + (n.activeSessions?.length ?? 0), 0)
7840
+ };
7841
+ return {
7842
+ meshId: status.meshId,
7843
+ meshName: status.meshName,
7844
+ repoIdentity: status.repoIdentity,
7845
+ refreshedAt: status.refreshedAt,
7846
+ nodes,
7847
+ edges,
7848
+ stats,
7849
+ warnings
7850
+ };
7851
+ }
7852
+
7853
+ // src/index.ts
7609
7854
  init_mesh_events();
7610
7855
 
7611
7856
  // src/mesh/p2p-relay-failure.ts
@@ -9767,6 +10012,28 @@ var StatusMonitor = class {
9767
10012
  };
9768
10013
 
9769
10014
  // src/providers/chat-message-normalization.ts
10015
+ function extractFinalSummaryFromMessages(messages, maxChars = 500) {
10016
+ if (!Array.isArray(messages) || messages.length === 0) return "";
10017
+ for (let i = messages.length - 1; i >= 0; i--) {
10018
+ const msg = messages[i];
10019
+ if (!msg) continue;
10020
+ const classification = classifyChatMessageVisibility(msg);
10021
+ if (classification.isUserFacing && (msg.role === "assistant" || msg.role === "model")) {
10022
+ const text = flattenContent(msg.content).trim();
10023
+ if (text) return text.slice(0, maxChars);
10024
+ }
10025
+ }
10026
+ for (let i = messages.length - 1; i >= 0; i--) {
10027
+ const msg = messages[i];
10028
+ if (!msg) continue;
10029
+ const classification = classifyChatMessageVisibility(msg);
10030
+ if (classification.isUserFacing) {
10031
+ const text = flattenContent(msg.content).trim();
10032
+ if (text) return text.slice(0, maxChars);
10033
+ }
10034
+ }
10035
+ return "";
10036
+ }
9770
10037
  var BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
9771
10038
  var CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
9772
10039
  var CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
@@ -11778,7 +12045,8 @@ var ExtensionProviderInstance = class {
11778
12045
  ideType: this.ideType || this.type,
11779
12046
  agentType: this.type,
11780
12047
  agentName: this.agentName || this.provider.name,
11781
- extensionId: this.extensionId || this.type
12048
+ extensionId: this.extensionId || this.type,
12049
+ finalSummary: extractFinalSummaryFromMessages(data?.messages)
11782
12050
  });
11783
12051
  this.generatingStartedAt = 0;
11784
12052
  }
@@ -12546,7 +12814,7 @@ var IdeProviderInstance = class {
12546
12814
  } else if (agentStatus === "idle" && (lastStatus === "generating" || lastStatus === "waiting_approval")) {
12547
12815
  const startedAt = this.generatingStartedAt.get(agentKey);
12548
12816
  const duration = startedAt ? Math.round((now - startedAt) / 1e3) : 0;
12549
- this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now, ideType: this.type });
12817
+ this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now, ideType: this.type, finalSummary: extractFinalSummaryFromMessages(chatData?.messages) });
12550
12818
  this.generatingStartedAt.delete(agentKey);
12551
12819
  }
12552
12820
  this.lastAgentStatuses.set(agentKey, agentStatus);
@@ -17663,7 +17931,8 @@ var CliProviderInstance = class {
17663
17931
  event: "agent:generating_completed",
17664
17932
  chatTitle: pending.chatTitle,
17665
17933
  duration: pending.duration,
17666
- timestamp: pending.timestamp
17934
+ timestamp: pending.timestamp,
17935
+ finalSummary: extractFinalSummaryFromMessages(this.adapter?.getScriptParsedStatus()?.messages)
17667
17936
  });
17668
17937
  this.completedDebouncePending = null;
17669
17938
  this.completedDebounceTimer = null;
@@ -19406,7 +19675,7 @@ ${rawInput}` : rawInput;
19406
19675
  });
19407
19676
  } else if (newStatus === "idle" && (this.lastStatus === "generating" || this.lastStatus === "waiting_approval")) {
19408
19677
  const duration = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1e3) : 0;
19409
- this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now });
19678
+ this.pushEvent({ event: "agent:generating_completed", chatTitle, duration, timestamp: now, finalSummary: extractFinalSummaryFromMessages(this.messages) });
19410
19679
  this.generatingStartedAt = 0;
19411
19680
  } else if (newStatus === "stopped") {
19412
19681
  this.pushEvent({ event: "agent:stopped", chatTitle, timestamp: now });
@@ -33992,6 +34261,7 @@ async function shutdownDaemonComponents(components) {
33992
34261
  buildChatTailDeliverySignature,
33993
34262
  buildCoordinatorSystemPrompt,
33994
34263
  buildMachineInfo,
34264
+ buildMeshGraph,
33995
34265
  buildMeshLedgerReconciliationEvidence,
33996
34266
  buildMeshLedgerReplicaEvidence,
33997
34267
  buildP2pRelayFailurePayload,
@@ -34011,6 +34281,7 @@ async function shutdownDaemonComponents(components) {
34011
34281
  classifyHotChatSessionsForSubscriptionFlush,
34012
34282
  classifyP2pRelayFailure,
34013
34283
  clearDebugTrace,
34284
+ clearPendingMeshCoordinatorEvents,
34014
34285
  compareGitSnapshots,
34015
34286
  configureDebugTraceStore,
34016
34287
  connectCdpManager,
@@ -34026,6 +34297,7 @@ async function shutdownDaemonComponents(components) {
34026
34297
  detectAllVersions,
34027
34298
  detectCLIs,
34028
34299
  detectIDEs,
34300
+ drainPendingMeshCoordinatorEvents,
34029
34301
  enqueueTask,
34030
34302
  ensureSessionHostReady,
34031
34303
  execNpmCommandSync,
@@ -34052,6 +34324,7 @@ async function shutdownDaemonComponents(components) {
34052
34324
  getMeshByRepo,
34053
34325
  getMeshQueueStats,
34054
34326
  getNpmExecOptions,
34327
+ getPendingMeshCoordinatorEvents,
34055
34328
  getQueue,
34056
34329
  getRecentActivity,
34057
34330
  getRecentCommands,