@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.
- package/dist/boot/daemon-lifecycle.d.ts +3 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -0
- package/dist/commands/mesh-coordinator.d.ts +10 -0
- package/dist/commands/router.d.ts +4 -1
- package/dist/config/mesh-config.d.ts +1 -0
- package/dist/git/git-worktree.d.ts +15 -2
- package/dist/index.d.ts +11 -6
- package/dist/index.js +2117 -300
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2102 -300
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events.d.ts +14 -7
- package/dist/mesh/mesh-ledger-reconciliation.d.ts +55 -0
- package/dist/mesh/mesh-ledger.d.ts +84 -4
- package/dist/mesh/mesh-sync.d.ts +4 -12
- package/dist/mesh/mesh-visualization.d.ts +70 -0
- package/dist/mesh/mesh-work-queue.d.ts +58 -1
- package/dist/mesh/p2p-relay-failure.d.ts +35 -0
- package/dist/providers/chat-message-normalization.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +6 -0
- package/dist/repo-mesh-types.d.ts +2 -0
- package/dist/shared-types.d.ts +38 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +5 -0
- package/src/cli-adapters/provider-cli-adapter.ts +30 -5
- package/src/commands/cli-manager.ts +0 -4
- package/src/commands/mesh-coordinator.ts +55 -7
- package/src/commands/router.ts +964 -26
- package/src/commands/stream-commands.ts +8 -1
- package/src/config/config.ts +2 -1
- package/src/config/mesh-config.ts +2 -0
- package/src/config/workspaces.ts +1 -1
- package/src/git/git-worktree.ts +56 -4
- package/src/index.d.ts +3 -0
- package/src/index.ts +30 -6
- package/src/mesh/coordinator-prompt.ts +21 -10
- package/src/mesh/mesh-events.ts +532 -22
- package/src/mesh/mesh-ledger-reconciliation.ts +115 -0
- package/src/mesh/mesh-ledger.ts +209 -8
- package/src/mesh/mesh-sync.ts +4 -34
- package/src/mesh/mesh-visualization.ts +341 -0
- package/src/mesh/mesh-work-queue.ts +183 -17
- package/src/mesh/p2p-relay-failure.ts +152 -0
- package/src/providers/acp-provider-instance.ts +2 -1
- package/src/providers/chat-message-normalization.ts +33 -1
- package/src/providers/cli-provider-instance.ts +155 -31
- package/src/providers/extension-provider-instance.ts +2 -1
- package/src/providers/ide-provider-instance.ts +2 -2
- package/src/repo-mesh-types.ts +2 -0
- 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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
|
53
|
-
* This skips deduplicated entries and
|
|
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[]):
|
|
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
|
*/
|
package/dist/mesh/mesh-sync.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Mesh Sync — Sync local mesh
|
|
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
|
|
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 */
|
package/dist/shared-types.d.ts
CHANGED
|
@@ -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
|
@@ -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
|