@adhdev/daemon-core 0.9.77-rc.9 → 0.9.78

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.
Files changed (50) hide show
  1. package/dist/boot/daemon-lifecycle.d.ts +3 -0
  2. package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -0
  3. package/dist/commands/mesh-coordinator.d.ts +10 -0
  4. package/dist/commands/router.d.ts +4 -1
  5. package/dist/config/mesh-config.d.ts +1 -0
  6. package/dist/git/git-worktree.d.ts +15 -2
  7. package/dist/index.d.ts +11 -6
  8. package/dist/index.js +2117 -300
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +2102 -300
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/mesh/mesh-events.d.ts +14 -7
  13. package/dist/mesh/mesh-ledger-reconciliation.d.ts +55 -0
  14. package/dist/mesh/mesh-ledger.d.ts +84 -4
  15. package/dist/mesh/mesh-sync.d.ts +4 -12
  16. package/dist/mesh/mesh-visualization.d.ts +70 -0
  17. package/dist/mesh/mesh-work-queue.d.ts +58 -1
  18. package/dist/mesh/p2p-relay-failure.d.ts +35 -0
  19. package/dist/providers/chat-message-normalization.d.ts +1 -0
  20. package/dist/providers/cli-provider-instance.d.ts +6 -0
  21. package/dist/repo-mesh-types.d.ts +2 -0
  22. package/dist/shared-types.d.ts +38 -0
  23. package/package.json +1 -1
  24. package/src/boot/daemon-lifecycle.ts +5 -0
  25. package/src/cli-adapters/provider-cli-adapter.ts +30 -5
  26. package/src/commands/cli-manager.ts +0 -4
  27. package/src/commands/mesh-coordinator.ts +55 -7
  28. package/src/commands/router.ts +964 -26
  29. package/src/commands/stream-commands.ts +8 -1
  30. package/src/config/config.ts +2 -1
  31. package/src/config/mesh-config.ts +2 -0
  32. package/src/config/workspaces.ts +1 -1
  33. package/src/git/git-worktree.ts +56 -4
  34. package/src/index.d.ts +3 -0
  35. package/src/index.ts +30 -6
  36. package/src/mesh/coordinator-prompt.ts +21 -10
  37. package/src/mesh/mesh-events.ts +532 -22
  38. package/src/mesh/mesh-ledger-reconciliation.ts +115 -0
  39. package/src/mesh/mesh-ledger.ts +209 -8
  40. package/src/mesh/mesh-sync.ts +4 -34
  41. package/src/mesh/mesh-visualization.ts +341 -0
  42. package/src/mesh/mesh-work-queue.ts +183 -17
  43. package/src/mesh/p2p-relay-failure.ts +152 -0
  44. package/src/providers/acp-provider-instance.ts +2 -1
  45. package/src/providers/chat-message-normalization.ts +33 -1
  46. package/src/providers/cli-provider-instance.ts +155 -31
  47. package/src/providers/extension-provider-instance.ts +2 -1
  48. package/src/providers/ide-provider-instance.ts +2 -2
  49. package/src/repo-mesh-types.ts +2 -0
  50. package/src/shared-types.ts +38 -0
@@ -8,20 +8,27 @@ export interface PendingMeshCoordinatorEvent {
8
8
  }
9
9
  /** Drain and return all pending coordinator events, clearing the queue. */
10
10
  export declare function drainPendingMeshCoordinatorEvents(): PendingMeshCoordinatorEvent[];
11
- export declare function tryAssignQueueTask(components: {
12
- cliManager: any;
13
- }, meshId: string, nodeId: string, sessionId: string, providerType: string): boolean;
11
+ /** Peek at pending coordinator events without draining (non-destructive). */
12
+ export declare function getPendingMeshCoordinatorEvents(): readonly PendingMeshCoordinatorEvent[];
13
+ /** Explicitly clear all pending coordinator events. */
14
+ export declare function clearPendingMeshCoordinatorEvents(): void;
15
+ export declare function tryAssignQueueTask(components: DaemonComponents, meshId: string, nodeId: string, sessionId: string, providerType: string): boolean;
14
16
  /**
15
17
  * Triggers a queue check for all nodes in the mesh.
16
18
  * Called when a new task is enqueued, in case nodes are already idle.
17
19
  */
18
- export declare function triggerMeshQueue(components: {
19
- instanceManager: any;
20
- cliManager: any;
21
- }, meshId: string): void;
20
+ export declare function triggerMeshQueue(components: DaemonComponents, meshId: string): Promise<void>;
22
21
  export declare function handleMeshForwardEvent(components: DaemonComponents, payload: Record<string, unknown>): {
23
22
  success: boolean;
24
23
  forwarded: number;
24
+ suppressed: boolean;
25
+ intentionalCleanupStop: boolean;
26
+ error?: undefined;
27
+ } | {
28
+ success: boolean;
29
+ forwarded: number;
30
+ suppressed?: undefined;
31
+ intentionalCleanupStop?: undefined;
25
32
  error?: undefined;
26
33
  } | {
27
34
  success: boolean;
@@ -0,0 +1,55 @@
1
+ import type { AppendRemoteLedgerResult, MeshLedgerSlice, MeshLedgerSummary } from './mesh-ledger.js';
2
+ export type MeshLedgerReplicaStatus = 'local' | 'queried' | 'imported' | 'failed';
3
+ export interface MeshLedgerReplicaEvidence {
4
+ nodeId: string;
5
+ daemonId?: string;
6
+ status: MeshLedgerReplicaStatus;
7
+ transport: 'local' | 'p2p_datachannel';
8
+ protocol: 'adhdev.mesh.ledger.slice.v1';
9
+ entriesReceived: number;
10
+ entriesImported: number;
11
+ skippedDuplicate: number;
12
+ rejectedInvalid: number;
13
+ hasMore: boolean;
14
+ nextAfterId: string | null;
15
+ lastTimestamp: string | null;
16
+ summary?: MeshLedgerSummary;
17
+ error?: string;
18
+ noFallbackReason?: string;
19
+ }
20
+ export interface MeshLedgerReconciliationEvidence {
21
+ protocol: 'adhdev.mesh.ledger.reconciliation.v1';
22
+ meshId: string;
23
+ generatedAt: string;
24
+ sourceOfTruth: {
25
+ kind: 'coordinator_local_jsonl';
26
+ p2pOnly: true;
27
+ cloudD1LedgerSync: false;
28
+ notes: string;
29
+ };
30
+ replicas: MeshLedgerReplicaEvidence[];
31
+ totals: {
32
+ replicas: number;
33
+ queried: number;
34
+ failed: number;
35
+ entriesReceived: number;
36
+ entriesImported: number;
37
+ skippedDuplicate: number;
38
+ rejectedInvalid: number;
39
+ };
40
+ convergence: {
41
+ complete: boolean;
42
+ pendingNodes: string[];
43
+ failedNodes: string[];
44
+ };
45
+ }
46
+ export declare function buildMeshLedgerReplicaEvidence(args: {
47
+ nodeId: string;
48
+ daemonId?: string;
49
+ transport: 'local' | 'p2p_datachannel';
50
+ slice?: MeshLedgerSlice;
51
+ importResult?: AppendRemoteLedgerResult;
52
+ status?: MeshLedgerReplicaStatus;
53
+ error?: string;
54
+ }): MeshLedgerReplicaEvidence;
55
+ export declare function buildMeshLedgerReconciliationEvidence(meshId: string, replicas: MeshLedgerReplicaEvidence[]): MeshLedgerReconciliationEvidence;
@@ -13,7 +13,7 @@
13
13
  * Safety: mode 0o600, atomic append via appendFileSync
14
14
  */
15
15
  import { EventEmitter } from 'events';
16
- export type MeshLedgerKind = 'task_dispatched' | 'task_completed' | 'task_failed' | 'task_stalled' | 'task_approval_needed' | 'session_launched' | 'session_stopped' | 'checkpoint_created' | 'node_cloned' | 'node_removed' | 'coordinator_started' | 'recovery_attempted';
16
+ export type MeshLedgerKind = 'task_dispatched' | 'task_completed' | 'task_failed' | 'task_stalled' | 'task_approval_needed' | 'session_launched' | 'session_auto_launch' | 'session_stopped' | 'checkpoint_created' | 'node_cloned' | 'node_removed' | 'coordinator_started' | 'recovery_attempted' | 'ledger_replicated' | 'ledger_reconciled';
17
17
  export interface MeshLedgerEntry {
18
18
  id: string;
19
19
  meshId: string;
@@ -24,6 +24,43 @@ export interface MeshLedgerEntry {
24
24
  providerType?: string;
25
25
  payload: Record<string, unknown>;
26
26
  }
27
+ export declare function isIntentionalCleanupStopEntry(entry: Pick<MeshLedgerEntry, 'kind' | 'payload'>): boolean;
28
+ export interface MeshTaskCompletionEvidence {
29
+ source: 'agent_status_event';
30
+ event: 'agent:generating_completed' | 'agent:ready';
31
+ nodeId: string;
32
+ sessionId: string;
33
+ providerType?: string;
34
+ completedAt: string;
35
+ transcriptHandle: {
36
+ kind: 'provider_session' | 'runtime_session';
37
+ sessionId: string;
38
+ providerSessionId?: string;
39
+ finalSummaryAvailable: boolean;
40
+ };
41
+ git: {
42
+ status: 'deferred';
43
+ reason: string;
44
+ };
45
+ validation: {
46
+ status: 'deferred';
47
+ commandsRun: string[];
48
+ reason: string;
49
+ };
50
+ checkpoint: {
51
+ attempted: false;
52
+ reason: 'not_attempted_for_ordinary_completion';
53
+ };
54
+ }
55
+ export interface BuildTaskCompletionEvidenceOptions {
56
+ event: MeshTaskCompletionEvidence['event'];
57
+ nodeId: string;
58
+ sessionId: string;
59
+ providerType?: string;
60
+ providerSessionId?: string;
61
+ finalSummary?: string;
62
+ completedAt?: string;
63
+ }
27
64
  export interface MeshLedgerSummary {
28
65
  meshId: string;
29
66
  totalEntries: number;
@@ -41,7 +78,44 @@ export interface ReadLedgerOptions {
41
78
  since?: string;
42
79
  kind?: MeshLedgerKind[];
43
80
  }
81
+ export interface ReadLedgerSliceOptions {
82
+ /** Return entries strictly after this entry id. If not found, starts from the beginning of the filtered set. */
83
+ afterId?: string;
84
+ /** Return entries at or after this timestamp. */
85
+ since?: string;
86
+ /** Optional event kind filter. */
87
+ kind?: MeshLedgerKind[];
88
+ /** Maximum entries to return. Clamped to a bounded protocol maximum. */
89
+ limit?: number;
90
+ }
91
+ export interface MeshLedgerCursor {
92
+ afterId: string | null;
93
+ nextAfterId: string | null;
94
+ limit: number;
95
+ hasMore: boolean;
96
+ }
97
+ export interface MeshLedgerSlice {
98
+ protocol: 'adhdev.mesh.ledger.slice.v1';
99
+ meshId: string;
100
+ entries: MeshLedgerEntry[];
101
+ cursor: MeshLedgerCursor;
102
+ summary: MeshLedgerSummary;
103
+ sourceOfTruth: {
104
+ kind: 'local_jsonl';
105
+ path: string;
106
+ bounded: true;
107
+ maxLimit: number;
108
+ };
109
+ }
110
+ export interface AppendRemoteLedgerResult {
111
+ accepted: number;
112
+ skippedDuplicate: number;
113
+ rejectedInvalid: number;
114
+ entries: MeshLedgerEntry[];
115
+ }
116
+ export declare const MAX_LEDGER_SLICE_LIMIT = 500;
44
117
  export declare function getLedgerDir(): string;
118
+ export declare function buildTaskCompletionEvidence(opts: BuildTaskCompletionEvidenceOptions): MeshTaskCompletionEvidence;
45
119
  /**
46
120
  * Append a new entry to the mesh ledger.
47
121
  * Handles file creation, rotation on size overflow, and atomic writes.
@@ -49,14 +123,20 @@ export declare function getLedgerDir(): string;
49
123
  export declare const meshLedgerEvents: EventEmitter<[never]>;
50
124
  export declare function appendLedgerEntry(meshId: string, partial: Omit<MeshLedgerEntry, 'id' | 'meshId' | 'timestamp'>): MeshLedgerEntry;
51
125
  /**
52
- * Append entries received from the cloud to the local ledger.
53
- * This skips deduplicated entries and just writes new ones.
126
+ * Append entries received over local-first/P2P ledger replication to the local ledger.
127
+ * This skips deduplicated entries and rejects malformed/cross-mesh entries.
54
128
  */
55
- export declare function appendRemoteLedgerEntries(meshId: string, entries: MeshLedgerEntry[]): void;
129
+ export declare function appendRemoteLedgerEntries(meshId: string, entries: MeshLedgerEntry[]): AppendRemoteLedgerResult;
56
130
  /**
57
131
  * Read ledger entries with optional filtering.
58
132
  */
59
133
  export declare function readLedgerEntries(meshId: string, opts?: ReadLedgerOptions): MeshLedgerEntry[];
134
+ /**
135
+ * Read a bounded, cursor-addressable ledger slice for local-first/P2P replication.
136
+ * The result is intentionally small and self-describing so coordinators can query
137
+ * remote daemons on demand without Cloud/D1 becoming a ledger data-plane.
138
+ */
139
+ export declare function readLedgerSlice(meshId: string, opts?: ReadLedgerSliceOptions): MeshLedgerSlice;
60
140
  /**
61
141
  * Get a summary of mesh activity from the ledger.
62
142
  */
@@ -1,10 +1,12 @@
1
1
  /**
2
- * Mesh Sync — Sync local mesh config to/from cloud D1
2
+ * Mesh Sync — Sync local mesh metadata to/from cloud D1
3
3
  *
4
4
  * When cloud is available, this module pushes local mesh config
5
5
  * to the server and pulls remote meshes that were created from
6
6
  * other machines. The local ~/.adhdev/meshes.json remains the
7
- * canonical source; cloud is a persistence/relay layer.
7
+ * canonical source; cloud is a membership/metadata layer only.
8
+ * Task/chat/ledger evidence remains local-first and must not be
9
+ * synchronized through Cloud/D1.
8
10
  *
9
11
  * This is called lazily (not on daemon startup) — only when the
10
12
  * user explicitly opens the mesh page or runs `adhdev mesh sync`.
@@ -26,12 +28,6 @@ export interface MeshSyncTransport {
26
28
  }>;
27
29
  /** DELETE /api/v1/repo-meshes/:id */
28
30
  deleteRemoteMesh(meshId: string): Promise<void>;
29
- /** POST /api/v1/repo-meshes/:id/ledger/sync */
30
- syncMeshLedger?(meshId: string, data: {
31
- newEntries: any[];
32
- }): Promise<{
33
- missingEntries: any[];
34
- }>;
35
31
  }
36
32
  export interface RemoteMeshRecord {
37
33
  id: string;
@@ -55,7 +51,3 @@ export interface MeshSyncResult {
55
51
  * Pull remote meshes that don't exist locally.
56
52
  */
57
53
  export declare function syncMeshes(transport: MeshSyncTransport): Promise<MeshSyncResult>;
58
- /**
59
- * Sync the task ledger for a specific mesh.
60
- */
61
- export declare function syncMeshLedger(meshId: string, transport: MeshSyncTransport): Promise<void>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Mesh Visualization — Transform RepoMeshStatus into a graph structure
3
+ * for SVG/Canvas rendering without external dependencies.
4
+ */
5
+ import type { RepoMeshStatus, RepoMeshNodeStatus, RepoMeshNodeHealth } from '../repo-mesh-types.js';
6
+ export type MeshGraphNodeType = 'defaultBranchNode' | 'worktreeNode' | 'orphanNode';
7
+ export type MeshGraphEdgeType = 'parentBranch' | 'worktreeLink' | 'sessionLink';
8
+ export interface MeshGraphNode {
9
+ id: string;
10
+ type: MeshGraphNodeType;
11
+ label: string;
12
+ workspace: string;
13
+ branch: string | null;
14
+ health: RepoMeshNodeHealth;
15
+ ahead: number;
16
+ behind: number;
17
+ dirty: boolean;
18
+ dirtyFiles: number;
19
+ hasConflicts: boolean;
20
+ activeSessionCount: number;
21
+ activeSessions: string[];
22
+ providers: string[];
23
+ isOrphan: boolean;
24
+ orphanReasons: string[];
25
+ /** Next-step hint from convergence analysis */
26
+ nextStepHint?: string;
27
+ /** Original node status for drill-down */
28
+ source: RepoMeshNodeStatus;
29
+ }
30
+ export interface MeshGraphEdge {
31
+ id: string;
32
+ source: string;
33
+ target: string;
34
+ type: MeshGraphEdgeType;
35
+ label?: string;
36
+ }
37
+ export interface MeshGraph {
38
+ meshId: string;
39
+ meshName: string;
40
+ repoIdentity: string;
41
+ refreshedAt: string;
42
+ nodes: MeshGraphNode[];
43
+ edges: MeshGraphEdge[];
44
+ /** Summary statistics */
45
+ stats: {
46
+ totalNodes: number;
47
+ onlineNodes: number;
48
+ dirtyNodes: number;
49
+ orphanNodes: number;
50
+ errorNodes: number;
51
+ offlineNodes: number;
52
+ totalActiveSessions: number;
53
+ };
54
+ /** Global orphan / stale warnings */
55
+ warnings: string[];
56
+ }
57
+ /**
58
+ * Build a visualization graph from RepoMeshStatus.
59
+ *
60
+ * Nodes:
61
+ * - defaultBranchNode: the mesh's default branch (aggregated from nodes on that branch)
62
+ * - worktreeNode: a node on a feature / worktree branch
63
+ * - orphanNode: a node with orphanReasons (upstream missing, detached HEAD, etc.)
64
+ *
65
+ * Edges:
66
+ * - parentBranch: default branch → worktree branch (when branch name differs)
67
+ * - worktreeLink: links nodes that share the same branch (clustering hint)
68
+ * - sessionLink: node → session (lightweight, optional; not rendered as primary edge)
69
+ */
70
+ export declare function buildMeshGraph(status: RepoMeshStatus): MeshGraph;
@@ -1,4 +1,8 @@
1
- export type MeshTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed';
1
+ export type MeshTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed' | 'cancelled';
2
+ export type MeshActiveTaskStatus = Extract<MeshTaskStatus, 'pending' | 'assigned'>;
3
+ export type MeshHistoricalTaskStatus = Extract<MeshTaskStatus, 'completed' | 'failed' | 'cancelled'>;
4
+ export declare const ACTIVE_MESH_QUEUE_STATUSES: MeshActiveTaskStatus[];
5
+ export declare const HISTORICAL_MESH_QUEUE_STATUSES: MeshHistoricalTaskStatus[];
2
6
  export interface MeshWorkQueueEntry {
3
7
  id: string;
4
8
  meshId: string;
@@ -6,10 +10,30 @@ export interface MeshWorkQueueEntry {
6
10
  status: MeshTaskStatus;
7
11
  /** If specified, only this node can claim the task (used by legacy mesh_send_task) */
8
12
  targetNodeId?: string;
13
+ /** If specified, only this runtime session can claim the task */
14
+ targetSessionId?: string;
9
15
  /** The node that actually claimed and is executing the task */
10
16
  assignedNodeId?: string;
11
17
  /** The session currently executing the task */
12
18
  assignedSessionId?: string;
19
+ /** Human/operator reason for terminal cancellation. */
20
+ cancelReason?: string;
21
+ cancelledAt?: string;
22
+ /** Human/operator reason for manually requeueing a task. */
23
+ requeueReason?: string;
24
+ requeuedAt?: string;
25
+ requeueCount?: number;
26
+ /** Last automatic queue session spin-up attempt, for mesh_view_queue/debug visibility. */
27
+ autoLaunch?: {
28
+ status: 'skipped' | 'started' | 'failed' | 'completed';
29
+ reason?: string;
30
+ nodeId?: string;
31
+ providerType?: string;
32
+ sessionId?: string;
33
+ updatedAt: string;
34
+ };
35
+ /** ISO timestamp when the task was dispatched (assigned) to a node/session. Used for precise matching on completion. */
36
+ dispatchTimestamp?: string;
13
37
  createdAt: string;
14
38
  updatedAt: string;
15
39
  }
@@ -18,6 +42,7 @@ export interface MeshWorkQueueEntry {
18
42
  */
19
43
  export declare function enqueueTask(meshId: string, message: string, opts?: {
20
44
  targetNodeId?: string;
45
+ targetSessionId?: string;
21
46
  }): MeshWorkQueueEntry;
22
47
  /**
23
48
  * Get all tasks in the queue, optionally filtered by status.
@@ -34,15 +59,47 @@ export declare function claimNextTask(meshId: string, nodeId: string, sessionId:
34
59
  * Used when a session completes, fails, or stalls.
35
60
  */
36
61
  export declare function updateTaskStatus(meshId: string, taskId: string, status: MeshTaskStatus): MeshWorkQueueEntry | null;
62
+ export declare function recordTaskAutoLaunch(meshId: string, taskId: string, autoLaunch: Omit<NonNullable<MeshWorkQueueEntry['autoLaunch']>, 'updatedAt'>): MeshWorkQueueEntry | null;
63
+ /**
64
+ * Mark a queue task as manually cancelled without deleting audit history.
65
+ */
66
+ export declare function cancelTask(meshId: string, taskId: string, opts?: {
67
+ reason?: string;
68
+ }): MeshWorkQueueEntry | null;
69
+ /**
70
+ * Return a queue task to pending for retry. By default, dead session targeting
71
+ * and assigned ownership are cleared so stale assignments do not strand again.
72
+ */
73
+ export declare function requeueTask(meshId: string, taskId: string, opts?: {
74
+ reason?: string;
75
+ targetNodeId?: string;
76
+ targetSessionId?: string;
77
+ clearTargetNode?: boolean;
78
+ clearTargetSession?: boolean;
79
+ }): MeshWorkQueueEntry | null;
37
80
  /**
38
81
  * Update the status of the task currently assigned to a specific session.
39
82
  */
40
83
  export declare function updateSessionTaskStatus(meshId: string, sessionId: string, status: MeshTaskStatus): MeshWorkQueueEntry | null;
41
84
  export interface MeshWorkQueueStats {
85
+ total: number;
86
+ active: number;
87
+ historical: number;
42
88
  pending: number;
43
89
  assigned: number;
44
90
  completed: number;
45
91
  failed: number;
92
+ cancelled: number;
93
+ /** Source-of-truth active queue counters; only pending/assigned are live work. */
94
+ activeCounts: Record<MeshActiveTaskStatus, number>;
95
+ /** Terminal ledger records kept for audit/history; never count as active work. */
96
+ historicalCounts: Record<MeshHistoricalTaskStatus, number>;
97
+ activeAssignments: Array<{
98
+ id: string;
99
+ nodeId?: string;
100
+ sessionId?: string;
101
+ message: string;
102
+ }>;
46
103
  }
47
104
  /**
48
105
  * Return aggregate queue statistics for the given mesh.
@@ -0,0 +1,35 @@
1
+ export type P2pRelayFailureCode = 'p2p_unavailable' | 'p2p_timeout' | 'p2p_not_connected' | 'p2p_datachannel_closed' | 'p2p_no_route' | 'p2p_daemon_offline' | 'mesh_logic_or_provider_failure';
2
+ export interface P2pRelayFailureContext {
3
+ command?: string;
4
+ targetDaemonId?: string;
5
+ }
6
+ export interface P2pRelayFailureClassification {
7
+ code: P2pRelayFailureCode;
8
+ reason: string;
9
+ transport: 'p2p' | 'unknown';
10
+ recoverable: boolean;
11
+ retryRecommended: boolean;
12
+ nextAction: string;
13
+ noFallbackReason: string;
14
+ }
15
+ export interface P2pRelayFailurePayload extends P2pRelayFailureClassification {
16
+ success: false;
17
+ error: string;
18
+ command?: string;
19
+ targetDaemonId?: string;
20
+ }
21
+ export declare function classifyP2pRelayFailure(error: unknown, _context?: P2pRelayFailureContext): P2pRelayFailureClassification;
22
+ export declare function isP2pRelayTransportFailure(error: unknown): boolean;
23
+ export declare function buildP2pRelayFailurePayload(error: unknown, context?: P2pRelayFailureContext): P2pRelayFailurePayload;
24
+ export declare class P2pRelayFailureError extends Error {
25
+ code: P2pRelayFailureCode;
26
+ reason: string;
27
+ transport: 'p2p' | 'unknown';
28
+ recoverable: boolean;
29
+ retryRecommended: boolean;
30
+ nextAction: string;
31
+ noFallbackReason: string;
32
+ command?: string;
33
+ targetDaemonId?: string;
34
+ constructor(message: string, context?: P2pRelayFailureContext);
35
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ChatMessage } from '../types.js';
2
+ export declare function extractFinalSummaryFromMessages(messages: ChatMessage[] | null | undefined, maxChars?: number): string;
2
3
  export declare const BUILTIN_CHAT_MESSAGE_KINDS: readonly ["standard", "thought", "tool", "terminal", "system"];
3
4
  export type BuiltinChatMessageKind = typeof BUILTIN_CHAT_MESSAGE_KINDS[number];
4
5
  export type ChatMessageKind = BuiltinChatMessageKind | (string & {});
@@ -100,6 +100,12 @@ export declare class CliProviderInstance implements ProviderInstance {
100
100
  private completedDebounceTimer;
101
101
  private completedDebouncePending;
102
102
  private enforceFreshSessionLaunchIfNeeded;
103
+ private completionHasFinalAssistantMessage;
104
+ private hasAdapterPendingResponse;
105
+ private shouldSuppressStaleParsedBusyStatus;
106
+ private getCompletedFinalizationBlockReason;
107
+ private scheduleCompletedDebounceFlush;
108
+ private flushCompletedDebounceIfFinalized;
103
109
  private maybeAutoApproveStatus;
104
110
  private detectStatusTransition;
105
111
  private pushEvent;
@@ -179,6 +179,8 @@ export interface LocalMeshNodeEntry {
179
179
  workspace: string;
180
180
  repoRoot?: string;
181
181
  daemonId?: string;
182
+ /** Machine registry ID that owns this workspace, when known. */
183
+ machineId?: string;
182
184
  userOverrides: Partial<RepoMeshNodeCapabilities>;
183
185
  policy: RepoMeshNodePolicy;
184
186
  /** For single-machine mesh: same daemon, different worktree */
@@ -293,10 +293,29 @@ export interface SessionEntry {
293
293
  surfaceHidden?: boolean;
294
294
  settings?: Record<string, any>;
295
295
  meshQueueStats?: {
296
+ total?: number;
297
+ active?: number;
298
+ historical?: number;
296
299
  pending: number;
297
300
  assigned: number;
298
301
  completed: number;
299
302
  failed: number;
303
+ cancelled?: number;
304
+ activeCounts?: {
305
+ pending: number;
306
+ assigned: number;
307
+ };
308
+ historicalCounts?: {
309
+ completed: number;
310
+ failed: number;
311
+ cancelled: number;
312
+ };
313
+ activeAssignments?: Array<{
314
+ id: string;
315
+ nodeId?: string;
316
+ sessionId?: string;
317
+ message: string;
318
+ }>;
300
319
  };
301
320
  }
302
321
  /**
@@ -337,10 +356,29 @@ export interface CompactSessionEntry {
337
356
  summaryMetadata?: ProviderSummaryMetadata;
338
357
  settings?: Record<string, any>;
339
358
  meshQueueStats?: {
359
+ total?: number;
360
+ active?: number;
361
+ historical?: number;
340
362
  pending: number;
341
363
  assigned: number;
342
364
  completed: number;
343
365
  failed: number;
366
+ cancelled?: number;
367
+ activeCounts?: {
368
+ pending: number;
369
+ assigned: number;
370
+ };
371
+ historicalCounts?: {
372
+ completed: number;
373
+ failed: number;
374
+ cancelled: number;
375
+ };
376
+ activeAssignments?: Array<{
377
+ id: string;
378
+ nodeId?: string;
379
+ sessionId?: string;
380
+ message: string;
381
+ }>;
344
382
  };
345
383
  }
346
384
  export type VersionUpdateReason = 'force_update_below' | 'major_minor_mismatch' | 'patch_mismatch' | 'daemon_ahead';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.77-rc.9",
3
+ "version": "0.9.78",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -83,6 +83,9 @@ export interface DaemonInitConfig {
83
83
 
84
84
  /** Fired before send_chat is dispatched — used for turn snapshot hooks */
85
85
  onBeforeSendChat?: (params: { workspace: string; sessionId: string }) => void;
86
+
87
+ /** Relays a command to a remote mesh node daemon */
88
+ dispatchMeshCommand?: (daemonId: string, command: string, args: Record<string, unknown>) => Promise<any>;
86
89
  }
87
90
 
88
91
  // ─── Result ───
@@ -100,6 +103,7 @@ export interface DaemonComponents {
100
103
  sessionRegistry: SessionRegistry;
101
104
  detectedIdes: { value: IDEInfo[] };
102
105
  refreshProviderAvailability: (providerType?: string) => Promise<void>;
106
+ dispatchMeshCommand?: (daemonId: string, command: string, args: Record<string, unknown>) => Promise<any>;
103
107
  }
104
108
 
105
109
  export interface DaemonDevSupportOptions {
@@ -331,6 +335,7 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
331
335
  sessionRegistry,
332
336
  detectedIdes: detectedIdesRef,
333
337
  refreshProviderAvailability,
338
+ dispatchMeshCommand: config.dispatchMeshCommand,
334
339
  };
335
340
 
336
341
  // 11. Setup Mesh Event Forwarding