@adhdev/daemon-core 0.9.82-rc.7 → 0.9.82-rc.70
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 +2 -0
- 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 +24 -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 +4619 -1143
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4582 -1128
- 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 +48 -0
- package/dist/mesh/mesh-events.d.ts +28 -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 +1 -0
- package/dist/repo-mesh-types.d.ts +160 -0
- package/dist/status/reporter.d.ts +2 -0
- package/package.json +3 -1
- package/src/boot/daemon-lifecycle.ts +4 -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/handler.ts +8 -1
- package/src/commands/mesh-coordinator.ts +13 -143
- package/src/commands/router.ts +2452 -409
- 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 +39 -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 +4 -2
- package/src/mesh/mesh-active-work.ts +205 -0
- package/src/mesh/mesh-events.ts +291 -38
- 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 +66 -1
- 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 +174 -0
- package/src/status/reporter.ts +15 -0
- package/src/system/host-memory.ts +29 -12
|
@@ -0,0 +1,205 @@
|
|
|
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
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface MeshActiveWorkSummary {
|
|
28
|
+
totalActiveCount: number;
|
|
29
|
+
queueActiveCount: number;
|
|
30
|
+
directActiveCount: number;
|
|
31
|
+
awaitingApprovalCount: number;
|
|
32
|
+
generatingCount: number;
|
|
33
|
+
failedCount: number;
|
|
34
|
+
idleCount: number;
|
|
35
|
+
sourceCounts: Record<MeshActiveWorkSource, number>;
|
|
36
|
+
statusCounts: Record<MeshActiveWorkStatus, number>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface BuildMeshActiveWorkOptions {
|
|
40
|
+
meshId: string;
|
|
41
|
+
queue?: MeshWorkQueueEntry[];
|
|
42
|
+
ledgerEntries?: MeshLedgerEntry[];
|
|
43
|
+
nodes?: any[];
|
|
44
|
+
now?: number;
|
|
45
|
+
/** Include terminal direct rows (idle/failed) for handoff/recent-work surfaces. Defaults false. */
|
|
46
|
+
includeTerminalDirect?: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const DIRECT_DISPATCH_VIA = new Set(['p2p_direct', 'local_direct', 'mesh_send_task']);
|
|
50
|
+
const TERMINAL_LEDGER_KINDS = new Set(['task_completed', 'task_failed', 'task_stalled']);
|
|
51
|
+
|
|
52
|
+
function readString(value: unknown): string | undefined {
|
|
53
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function summarizeMessage(message: string): { title: string; summary: string } {
|
|
57
|
+
const oneLine = message.replace(/\s+/g, ' ').trim();
|
|
58
|
+
const title = oneLine.length > 96 ? `${oneLine.slice(0, 93)}...` : oneLine;
|
|
59
|
+
return { title: title || '(untitled task)', summary: oneLine };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function elapsedSince(value: string | undefined, now: number): number {
|
|
63
|
+
const started = value ? new Date(value).getTime() : Number.NaN;
|
|
64
|
+
return Number.isFinite(started) ? Math.max(0, now - started) : 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function sessionStatusFromNodes(nodes: any[] | undefined, nodeId?: string, sessionId?: string): MeshActiveWorkStatus | undefined {
|
|
68
|
+
if (!nodeId || !sessionId || !Array.isArray(nodes)) return undefined;
|
|
69
|
+
const node = nodes.find(item => readString(item?.id) === nodeId || readString(item?.nodeId) === nodeId || readString(item?.node_id) === nodeId);
|
|
70
|
+
if (!node) return undefined;
|
|
71
|
+
const candidates: any[] = [];
|
|
72
|
+
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]) {
|
|
73
|
+
if (Array.isArray(value)) candidates.push(...value);
|
|
74
|
+
}
|
|
75
|
+
for (const value of [node.activeSession, node.active_session, node.currentSession, node.current_session, node.runtimeSession, node.runtime_session, node.session]) {
|
|
76
|
+
if (value && typeof value === 'object') candidates.push(value);
|
|
77
|
+
}
|
|
78
|
+
const session = candidates.find(item => {
|
|
79
|
+
const id = readString(item?.id) || readString(item?.sessionId) || readString(item?.session_id) || readString(item?.runtimeSessionId) || readString(item?.instanceId);
|
|
80
|
+
return id === sessionId;
|
|
81
|
+
});
|
|
82
|
+
if (!session) return undefined;
|
|
83
|
+
const raw = `${readString(session.status) || ''} ${readString(session.lifecycle) || ''} ${readString(session.state) || ''} ${readString(session.activeChat?.status) || ''}`.toLowerCase();
|
|
84
|
+
if (raw.includes('approval')) return 'awaiting_approval';
|
|
85
|
+
if (raw.includes('generating') || raw.includes('running') || raw.includes('busy')) return 'generating';
|
|
86
|
+
if (raw.includes('failed') || raw.includes('stopped') || raw.includes('terminated') || raw.includes('exited')) return 'failed';
|
|
87
|
+
if (raw.includes('idle') || raw.includes('waiting_input') || raw.includes('ready')) return 'idle';
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function isDirectDispatch(entry: MeshLedgerEntry): boolean {
|
|
92
|
+
if (entry.kind !== 'task_dispatched') return false;
|
|
93
|
+
const payload = entry.payload || {};
|
|
94
|
+
if (payload.source === 'direct') return true;
|
|
95
|
+
const via = readString(payload.via);
|
|
96
|
+
return Boolean(via && DIRECT_DISPATCH_VIA.has(via) && payload.source !== 'queue');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function directDispatchTaskId(entry: MeshLedgerEntry): string {
|
|
100
|
+
return readString(entry.payload?.taskId) || entry.id;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function terminalMatchesDispatch(terminal: MeshLedgerEntry, dispatch: MeshLedgerEntry, taskId: string): boolean {
|
|
104
|
+
const terminalTaskId = readString(terminal.payload?.taskId);
|
|
105
|
+
if (terminalTaskId && terminalTaskId === taskId) return true;
|
|
106
|
+
if (terminalTaskId && terminalTaskId !== taskId) return false;
|
|
107
|
+
if (dispatch.sessionId && terminal.sessionId === dispatch.sessionId) return true;
|
|
108
|
+
return Boolean(dispatch.nodeId && terminal.nodeId === dispatch.nodeId && !dispatch.sessionId);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function statusFromTerminal(entry: MeshLedgerEntry): MeshActiveWorkStatus {
|
|
112
|
+
if (entry.kind === 'task_approval_needed') return 'awaiting_approval';
|
|
113
|
+
if (entry.kind === 'task_completed') return 'idle';
|
|
114
|
+
return 'failed';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function buildMeshActiveWorkSummary(activeWork: MeshActiveWorkRecord[]): MeshActiveWorkSummary {
|
|
118
|
+
const statusCounts: Record<MeshActiveWorkStatus, number> = {
|
|
119
|
+
pending: 0,
|
|
120
|
+
assigned: 0,
|
|
121
|
+
generating: 0,
|
|
122
|
+
idle: 0,
|
|
123
|
+
failed: 0,
|
|
124
|
+
awaiting_approval: 0,
|
|
125
|
+
};
|
|
126
|
+
const sourceCounts: Record<MeshActiveWorkSource, number> = { queue: 0, direct: 0 };
|
|
127
|
+
for (const item of activeWork) {
|
|
128
|
+
sourceCounts[item.source] += 1;
|
|
129
|
+
statusCounts[item.status] += 1;
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
totalActiveCount: activeWork.length,
|
|
133
|
+
queueActiveCount: sourceCounts.queue,
|
|
134
|
+
directActiveCount: sourceCounts.direct,
|
|
135
|
+
awaitingApprovalCount: statusCounts.awaiting_approval,
|
|
136
|
+
generatingCount: statusCounts.generating,
|
|
137
|
+
failedCount: statusCounts.failed,
|
|
138
|
+
idleCount: statusCounts.idle,
|
|
139
|
+
sourceCounts,
|
|
140
|
+
statusCounts,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function buildMeshActiveWork(opts: BuildMeshActiveWorkOptions): { activeWork: MeshActiveWorkRecord[]; summary: MeshActiveWorkSummary } {
|
|
145
|
+
const now = opts.now ?? Date.now();
|
|
146
|
+
const records: MeshActiveWorkRecord[] = [];
|
|
147
|
+
|
|
148
|
+
for (const task of opts.queue || []) {
|
|
149
|
+
if (task.status !== 'pending' && task.status !== 'assigned') continue;
|
|
150
|
+
const { title, summary } = summarizeMessage(task.message || '');
|
|
151
|
+
records.push({
|
|
152
|
+
taskId: task.id,
|
|
153
|
+
source: 'queue',
|
|
154
|
+
status: task.status,
|
|
155
|
+
nodeId: task.assignedNodeId || task.targetNodeId,
|
|
156
|
+
sessionId: task.assignedSessionId || task.targetSessionId,
|
|
157
|
+
taskTitle: title,
|
|
158
|
+
taskSummary: summary,
|
|
159
|
+
message: task.message,
|
|
160
|
+
taskMode: task.taskMode,
|
|
161
|
+
createdAt: task.createdAt,
|
|
162
|
+
updatedAt: task.updatedAt,
|
|
163
|
+
dispatchedAt: task.dispatchTimestamp,
|
|
164
|
+
elapsedMs: elapsedSince(task.dispatchTimestamp || task.createdAt, now),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const ledgerEntries = (opts.ledgerEntries || []).slice().sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
169
|
+
const terminals = ledgerEntries.filter(entry => TERMINAL_LEDGER_KINDS.has(entry.kind) || entry.kind === 'task_approval_needed');
|
|
170
|
+
for (const dispatch of ledgerEntries.filter(isDirectDispatch)) {
|
|
171
|
+
const taskId = directDispatchTaskId(dispatch);
|
|
172
|
+
const terminal = terminals
|
|
173
|
+
.filter(entry => new Date(entry.timestamp).getTime() >= new Date(dispatch.timestamp).getTime())
|
|
174
|
+
.find(entry => terminalMatchesDispatch(entry, dispatch, taskId));
|
|
175
|
+
const terminalStatus = terminal ? statusFromTerminal(terminal) : undefined;
|
|
176
|
+
const liveStatus = sessionStatusFromNodes(opts.nodes, dispatch.nodeId, dispatch.sessionId);
|
|
177
|
+
const status = terminalStatus || liveStatus || 'assigned';
|
|
178
|
+
const terminalRow = Boolean(terminal && terminal.kind !== 'task_approval_needed');
|
|
179
|
+
if (terminalRow && opts.includeTerminalDirect !== true) continue;
|
|
180
|
+
const message = readString(dispatch.payload?.message) || readString(dispatch.payload?.summary) || '';
|
|
181
|
+
const { title, summary } = summarizeMessage(message);
|
|
182
|
+
records.push({
|
|
183
|
+
taskId,
|
|
184
|
+
source: 'direct',
|
|
185
|
+
status,
|
|
186
|
+
nodeId: dispatch.nodeId,
|
|
187
|
+
sessionId: dispatch.sessionId,
|
|
188
|
+
providerType: dispatch.providerType || readString(dispatch.payload?.providerType),
|
|
189
|
+
taskTitle: readString(dispatch.payload?.taskTitle) || title,
|
|
190
|
+
taskSummary: readString(dispatch.payload?.taskSummary) || summary,
|
|
191
|
+
message,
|
|
192
|
+
taskMode: readString(dispatch.payload?.taskMode),
|
|
193
|
+
createdAt: dispatch.timestamp,
|
|
194
|
+
updatedAt: terminal?.timestamp || dispatch.timestamp,
|
|
195
|
+
dispatchedAt: dispatch.timestamp,
|
|
196
|
+
elapsedMs: elapsedSince(dispatch.timestamp, now),
|
|
197
|
+
terminal: terminalRow,
|
|
198
|
+
terminalKind: terminal?.kind,
|
|
199
|
+
terminalAt: terminal?.timestamp,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
records.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
204
|
+
return { activeWork: records, summary: buildMeshActiveWorkSummary(records) };
|
|
205
|
+
}
|