@adhdev/daemon-core 0.9.82-rc.8 → 0.9.82-rc.80
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/cli-adapters/provider-cli-adapter.d.ts +2 -0
- package/dist/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +2 -0
- package/dist/commands/router.d.ts +22 -0
- package/dist/config/mesh-config.d.ts +66 -1
- package/dist/git/git-commands.d.ts +1 -0
- package/dist/git/git-status.d.ts +5 -0
- package/dist/git/git-types.d.ts +10 -0
- package/dist/index.d.ts +13 -6
- package/dist/index.js +4936 -1171
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4900 -1157
- package/dist/index.mjs.map +1 -1
- package/dist/installer.d.ts +1 -4
- package/dist/launch.d.ts +1 -1
- package/dist/logging/async-batch-writer.d.ts +10 -0
- package/dist/mesh/beads-db.d.ts +18 -0
- package/dist/mesh/mesh-active-work.d.ts +51 -0
- package/dist/mesh/mesh-events.d.ts +29 -5
- package/dist/mesh/mesh-fast-forward.d.ts +39 -0
- package/dist/mesh/mesh-host-ownership.d.ts +9 -0
- package/dist/mesh/mesh-ledger.d.ts +38 -1
- package/dist/mesh/mesh-work-queue.d.ts +27 -5
- package/dist/mesh/refine-config.d.ts +119 -0
- package/dist/providers/chat-message-normalization.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +2 -1
- package/dist/repo-mesh-types.d.ts +39 -0
- package/dist/status/reporter.d.ts +2 -0
- package/package.json +3 -1
- package/src/boot/daemon-lifecycle.ts +1 -0
- package/src/cli-adapters/provider-cli-adapter.ts +91 -3
- package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/src/cli-adapters/provider-cli-parse.ts +4 -0
- package/src/cli-adapters/provider-cli-runtime.ts +3 -1
- package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
- package/src/cli-adapters/provider-cli-shared.ts +20 -10
- package/src/commands/chat-commands.ts +242 -7
- package/src/commands/cli-manager.ts +63 -0
- package/src/commands/handler.ts +8 -1
- package/src/commands/mesh-coordinator.ts +13 -143
- package/src/commands/router.ts +2435 -414
- package/src/config/chat-history.ts +9 -7
- package/src/config/mesh-config.ts +244 -1
- package/src/daemon/dev-cli-debug.ts +10 -1
- package/src/detection/ide-detector.ts +26 -16
- package/src/git/git-commands.ts +3 -3
- package/src/git/git-status.ts +97 -6
- package/src/git/git-summary.ts +3 -0
- package/src/git/git-types.ts +11 -0
- package/src/index.ts +31 -5
- package/src/installer.d.ts +1 -1
- package/src/installer.ts +8 -6
- package/src/launch.d.ts +1 -1
- package/src/launch.ts +37 -28
- package/src/logging/async-batch-writer.ts +55 -0
- package/src/logging/logger.ts +2 -1
- package/src/mesh/beads-db.ts +176 -0
- package/src/mesh/coordinator-prompt.ts +27 -7
- package/src/mesh/mesh-active-work.ts +222 -0
- package/src/mesh/mesh-events.ts +342 -47
- package/src/mesh/mesh-fast-forward.ts +430 -0
- package/src/mesh/mesh-host-ownership.ts +73 -0
- package/src/mesh/mesh-ledger.ts +138 -1
- package/src/mesh/mesh-work-queue.ts +199 -137
- package/src/mesh/refine-config.ts +306 -0
- package/src/providers/chat-message-normalization.ts +3 -1
- package/src/providers/cli-provider-instance.ts +91 -13
- package/src/providers/ide-provider-instance.ts +17 -3
- package/src/providers/provider-loader.ts +10 -4
- package/src/providers/version-archive.ts +38 -20
- package/src/repo-mesh-types.ts +43 -0
- package/src/status/reporter.ts +15 -0
- package/src/system/host-memory.ts +29 -12
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import type { MeshLedgerEntry } from './mesh-ledger.js';
|
|
2
|
+
import type { MeshWorkQueueEntry } from './mesh-work-queue.js';
|
|
3
|
+
|
|
4
|
+
export type MeshActiveWorkSource = 'queue' | 'direct';
|
|
5
|
+
export type MeshActiveWorkStatus = 'pending' | 'assigned' | 'generating' | 'idle' | 'failed' | 'awaiting_approval';
|
|
6
|
+
|
|
7
|
+
export interface MeshActiveWorkRecord {
|
|
8
|
+
taskId: string;
|
|
9
|
+
source: MeshActiveWorkSource;
|
|
10
|
+
status: MeshActiveWorkStatus;
|
|
11
|
+
nodeId?: string;
|
|
12
|
+
sessionId?: string;
|
|
13
|
+
providerType?: string;
|
|
14
|
+
taskTitle: string;
|
|
15
|
+
taskSummary: string;
|
|
16
|
+
message?: string;
|
|
17
|
+
taskMode?: string;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
updatedAt: string;
|
|
20
|
+
dispatchedAt?: string;
|
|
21
|
+
elapsedMs: number;
|
|
22
|
+
terminal?: boolean;
|
|
23
|
+
terminalKind?: string;
|
|
24
|
+
terminalAt?: string;
|
|
25
|
+
staleReason?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface MeshActiveWorkSummary {
|
|
29
|
+
totalActiveCount: number;
|
|
30
|
+
queueActiveCount: number;
|
|
31
|
+
directActiveCount: number;
|
|
32
|
+
awaitingApprovalCount: number;
|
|
33
|
+
generatingCount: number;
|
|
34
|
+
failedCount: number;
|
|
35
|
+
idleCount: number;
|
|
36
|
+
sourceCounts: Record<MeshActiveWorkSource, number>;
|
|
37
|
+
statusCounts: Record<MeshActiveWorkStatus, number>;
|
|
38
|
+
staleDirectCount: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface BuildMeshActiveWorkOptions {
|
|
42
|
+
meshId: string;
|
|
43
|
+
queue?: MeshWorkQueueEntry[];
|
|
44
|
+
ledgerEntries?: MeshLedgerEntry[];
|
|
45
|
+
nodes?: any[];
|
|
46
|
+
now?: number;
|
|
47
|
+
/** Include terminal direct rows (idle/failed) for handoff/recent-work surfaces. Defaults false. */
|
|
48
|
+
includeTerminalDirect?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const DIRECT_DISPATCH_VIA = new Set(['p2p_direct', 'local_direct', 'mesh_send_task']);
|
|
52
|
+
const TERMINAL_LEDGER_KINDS = new Set(['task_completed', 'task_failed', 'task_stalled']);
|
|
53
|
+
|
|
54
|
+
function readString(value: unknown): string | undefined {
|
|
55
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function summarizeMessage(message: string): { title: string; summary: string } {
|
|
59
|
+
const oneLine = message.replace(/\s+/g, ' ').trim();
|
|
60
|
+
const title = oneLine.length > 96 ? `${oneLine.slice(0, 93)}...` : oneLine;
|
|
61
|
+
return { title: title || '(untitled task)', summary: oneLine };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function elapsedSince(value: string | undefined, now: number): number {
|
|
65
|
+
const started = value ? new Date(value).getTime() : Number.NaN;
|
|
66
|
+
return Number.isFinite(started) ? Math.max(0, now - started) : 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function sessionStatusFromNodes(nodes: any[] | undefined, nodeId?: string, sessionId?: string): { status?: MeshActiveWorkStatus; staleReason?: string } {
|
|
70
|
+
if (!Array.isArray(nodes)) return {};
|
|
71
|
+
if (!nodeId) return { staleReason: 'direct task has no node id' };
|
|
72
|
+
const node = nodes.find(item => readString(item?.id) === nodeId || readString(item?.nodeId) === nodeId || readString(item?.node_id) === nodeId);
|
|
73
|
+
if (!node) return { staleReason: 'direct task node is no longer in the live mesh' };
|
|
74
|
+
if (!sessionId) return {};
|
|
75
|
+
const candidates: any[] = [];
|
|
76
|
+
for (const value of [node.sessions, node.activeSessions, node.active_sessions, node.lastProbe?.sessions, node.last_probe?.sessions, node.lastProbe?.status?.sessions, node.last_probe?.status?.sessions]) {
|
|
77
|
+
if (Array.isArray(value)) candidates.push(...value);
|
|
78
|
+
}
|
|
79
|
+
for (const value of [node.activeSession, node.active_session, node.currentSession, node.current_session, node.runtimeSession, node.runtime_session, node.session]) {
|
|
80
|
+
if (value && typeof value === 'object') candidates.push(value);
|
|
81
|
+
}
|
|
82
|
+
const session = candidates.find(item => {
|
|
83
|
+
if (typeof item === 'string') return item === sessionId;
|
|
84
|
+
const id = readString(item?.id) || readString(item?.sessionId) || readString(item?.session_id) || readString(item?.runtimeSessionId) || readString(item?.instanceId);
|
|
85
|
+
return id === sessionId;
|
|
86
|
+
});
|
|
87
|
+
if (!session) return { staleReason: 'direct task session is not present in live session records' };
|
|
88
|
+
if (typeof session === 'string') return {};
|
|
89
|
+
const raw = `${readString(session.status) || ''} ${readString(session.lifecycle) || ''} ${readString(session.state) || ''} ${readString(session.activeChat?.status) || ''}`.toLowerCase();
|
|
90
|
+
if (raw.includes('approval')) return { status: 'awaiting_approval' };
|
|
91
|
+
if (raw.includes('generating') || raw.includes('running') || raw.includes('busy')) return { status: 'generating' };
|
|
92
|
+
if (raw.includes('failed') || raw.includes('stopped') || raw.includes('terminated') || raw.includes('exited')) return { status: 'failed' };
|
|
93
|
+
if (raw.includes('idle') || raw.includes('waiting_input') || raw.includes('ready')) return { status: 'idle' };
|
|
94
|
+
return {};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function isDirectDispatch(entry: MeshLedgerEntry): boolean {
|
|
98
|
+
if (entry.kind !== 'task_dispatched') return false;
|
|
99
|
+
const payload = entry.payload || {};
|
|
100
|
+
if (payload.source === 'direct') return true;
|
|
101
|
+
const via = readString(payload.via);
|
|
102
|
+
return Boolean(via && DIRECT_DISPATCH_VIA.has(via) && payload.source !== 'queue');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function directDispatchTaskId(entry: MeshLedgerEntry): string {
|
|
106
|
+
return readString(entry.payload?.taskId) || entry.id;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function terminalMatchesDispatch(terminal: MeshLedgerEntry, dispatch: MeshLedgerEntry, taskId: string): boolean {
|
|
110
|
+
const terminalTaskId = readString(terminal.payload?.taskId);
|
|
111
|
+
if (terminalTaskId && terminalTaskId === taskId) return true;
|
|
112
|
+
if (terminalTaskId && terminalTaskId !== taskId) return false;
|
|
113
|
+
if (dispatch.sessionId && terminal.sessionId === dispatch.sessionId) return true;
|
|
114
|
+
return Boolean(dispatch.nodeId && terminal.nodeId === dispatch.nodeId && !dispatch.sessionId);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function statusFromTerminal(entry: MeshLedgerEntry): MeshActiveWorkStatus {
|
|
118
|
+
if (entry.kind === 'task_approval_needed') return 'awaiting_approval';
|
|
119
|
+
if (entry.kind === 'task_completed') return 'idle';
|
|
120
|
+
return 'failed';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function buildMeshActiveWorkSummary(activeWork: MeshActiveWorkRecord[]): MeshActiveWorkSummary {
|
|
124
|
+
const statusCounts: Record<MeshActiveWorkStatus, number> = {
|
|
125
|
+
pending: 0,
|
|
126
|
+
assigned: 0,
|
|
127
|
+
generating: 0,
|
|
128
|
+
idle: 0,
|
|
129
|
+
failed: 0,
|
|
130
|
+
awaiting_approval: 0,
|
|
131
|
+
};
|
|
132
|
+
const sourceCounts: Record<MeshActiveWorkSource, number> = { queue: 0, direct: 0 };
|
|
133
|
+
for (const item of activeWork) {
|
|
134
|
+
sourceCounts[item.source] += 1;
|
|
135
|
+
statusCounts[item.status] += 1;
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
totalActiveCount: activeWork.length,
|
|
139
|
+
queueActiveCount: sourceCounts.queue,
|
|
140
|
+
directActiveCount: sourceCounts.direct,
|
|
141
|
+
awaitingApprovalCount: statusCounts.awaiting_approval,
|
|
142
|
+
generatingCount: statusCounts.generating,
|
|
143
|
+
failedCount: statusCounts.failed,
|
|
144
|
+
idleCount: statusCounts.idle,
|
|
145
|
+
sourceCounts,
|
|
146
|
+
statusCounts,
|
|
147
|
+
staleDirectCount: activeWork.filter(item => item.source === 'direct' && item.staleReason).length,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function buildMeshActiveWork(opts: BuildMeshActiveWorkOptions): { activeWork: MeshActiveWorkRecord[]; staleDirectWork: MeshActiveWorkRecord[]; summary: MeshActiveWorkSummary } {
|
|
152
|
+
const now = opts.now ?? Date.now();
|
|
153
|
+
const records: MeshActiveWorkRecord[] = [];
|
|
154
|
+
const staleDirectWork: MeshActiveWorkRecord[] = [];
|
|
155
|
+
|
|
156
|
+
for (const task of opts.queue || []) {
|
|
157
|
+
if (task.status !== 'pending' && task.status !== 'assigned') continue;
|
|
158
|
+
const { title, summary } = summarizeMessage(task.message || '');
|
|
159
|
+
records.push({
|
|
160
|
+
taskId: task.id,
|
|
161
|
+
source: 'queue',
|
|
162
|
+
status: task.status,
|
|
163
|
+
nodeId: task.assignedNodeId || task.targetNodeId,
|
|
164
|
+
sessionId: task.assignedSessionId || task.targetSessionId,
|
|
165
|
+
taskTitle: title,
|
|
166
|
+
taskSummary: summary,
|
|
167
|
+
message: task.message,
|
|
168
|
+
taskMode: task.taskMode,
|
|
169
|
+
createdAt: task.createdAt,
|
|
170
|
+
updatedAt: task.updatedAt,
|
|
171
|
+
dispatchedAt: task.dispatchTimestamp,
|
|
172
|
+
elapsedMs: elapsedSince(task.dispatchTimestamp || task.createdAt, now),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const ledgerEntries = (opts.ledgerEntries || []).slice().sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
177
|
+
const terminals = ledgerEntries.filter(entry => TERMINAL_LEDGER_KINDS.has(entry.kind) || entry.kind === 'task_approval_needed');
|
|
178
|
+
for (const dispatch of ledgerEntries.filter(isDirectDispatch)) {
|
|
179
|
+
const taskId = directDispatchTaskId(dispatch);
|
|
180
|
+
const terminal = terminals
|
|
181
|
+
.filter(entry => new Date(entry.timestamp).getTime() >= new Date(dispatch.timestamp).getTime())
|
|
182
|
+
.find(entry => terminalMatchesDispatch(entry, dispatch, taskId));
|
|
183
|
+
const terminalStatus = terminal ? statusFromTerminal(terminal) : undefined;
|
|
184
|
+
const live = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
|
|
185
|
+
const status = terminalStatus || live.status || 'assigned';
|
|
186
|
+
const terminalRow = Boolean(terminal && terminal.kind !== 'task_approval_needed');
|
|
187
|
+
if (terminalRow && opts.includeTerminalDirect !== true) continue;
|
|
188
|
+
const message = readString(dispatch.payload?.message) || readString(dispatch.payload?.summary) || '';
|
|
189
|
+
const { title, summary } = summarizeMessage(message);
|
|
190
|
+
const record: MeshActiveWorkRecord = {
|
|
191
|
+
taskId,
|
|
192
|
+
source: 'direct',
|
|
193
|
+
status,
|
|
194
|
+
nodeId: dispatch.nodeId,
|
|
195
|
+
sessionId: dispatch.sessionId,
|
|
196
|
+
providerType: dispatch.providerType || readString(dispatch.payload?.providerType),
|
|
197
|
+
taskTitle: readString(dispatch.payload?.taskTitle) || title,
|
|
198
|
+
taskSummary: readString(dispatch.payload?.taskSummary) || summary,
|
|
199
|
+
message,
|
|
200
|
+
taskMode: readString(dispatch.payload?.taskMode),
|
|
201
|
+
createdAt: dispatch.timestamp,
|
|
202
|
+
updatedAt: terminal?.timestamp || dispatch.timestamp,
|
|
203
|
+
dispatchedAt: dispatch.timestamp,
|
|
204
|
+
elapsedMs: elapsedSince(dispatch.timestamp, now),
|
|
205
|
+
terminal: terminalRow,
|
|
206
|
+
terminalKind: terminal?.kind,
|
|
207
|
+
terminalAt: terminal?.timestamp,
|
|
208
|
+
staleReason: live.staleReason,
|
|
209
|
+
};
|
|
210
|
+
if (live.staleReason && !terminalRow) {
|
|
211
|
+
staleDirectWork.push(record);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
records.push(record);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
records.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
218
|
+
staleDirectWork.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
219
|
+
const summary = buildMeshActiveWorkSummary(records);
|
|
220
|
+
summary.staleDirectCount = staleDirectWork.length;
|
|
221
|
+
return { activeWork: records, staleDirectWork, summary };
|
|
222
|
+
}
|