@adhdev/daemon-core 0.9.77-rc.4 → 0.9.77-rc.41
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 +4 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +14 -4
- package/dist/commands/mesh-coordinator.d.ts +10 -0
- package/dist/commands/router.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +424 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +421 -45
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events.d.ts +2 -7
- package/dist/mesh/mesh-work-queue.d.ts +35 -1
- package/dist/shared-types.d.ts +14 -0
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +5 -0
- package/src/cli-adapters/provider-cli-adapter.ts +34 -4
- package/src/cli-adapters/provider-cli-shared.ts +14 -4
- package/src/commands/cli-manager.ts +0 -4
- package/src/commands/mesh-coordinator.ts +55 -7
- package/src/commands/router.ts +193 -4
- package/src/commands/stream-commands.ts +8 -1
- package/src/index.ts +2 -2
- package/src/mesh/mesh-events.ts +147 -20
- package/src/mesh/mesh-work-queue.ts +103 -6
- package/src/providers/cli-provider-instance.ts +2 -0
- package/src/shared-types.ts +14 -0
|
@@ -3,7 +3,7 @@ import { join } from 'path';
|
|
|
3
3
|
import { randomUUID } from 'crypto';
|
|
4
4
|
import { getLedgerDir } from './mesh-ledger.js';
|
|
5
5
|
|
|
6
|
-
export type MeshTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed';
|
|
6
|
+
export type MeshTaskStatus = 'pending' | 'assigned' | 'completed' | 'failed' | 'cancelled';
|
|
7
7
|
|
|
8
8
|
export interface MeshWorkQueueEntry {
|
|
9
9
|
id: string;
|
|
@@ -12,10 +12,19 @@ export interface MeshWorkQueueEntry {
|
|
|
12
12
|
status: MeshTaskStatus;
|
|
13
13
|
/** If specified, only this node can claim the task (used by legacy mesh_send_task) */
|
|
14
14
|
targetNodeId?: string;
|
|
15
|
+
/** If specified, only this runtime session can claim the task */
|
|
16
|
+
targetSessionId?: string;
|
|
15
17
|
/** The node that actually claimed and is executing the task */
|
|
16
18
|
assignedNodeId?: string;
|
|
17
19
|
/** The session currently executing the task */
|
|
18
20
|
assignedSessionId?: string;
|
|
21
|
+
/** Human/operator reason for terminal cancellation. */
|
|
22
|
+
cancelReason?: string;
|
|
23
|
+
cancelledAt?: string;
|
|
24
|
+
/** Human/operator reason for manually requeueing a task. */
|
|
25
|
+
requeueReason?: string;
|
|
26
|
+
requeuedAt?: string;
|
|
27
|
+
requeueCount?: number;
|
|
19
28
|
createdAt: string;
|
|
20
29
|
updatedAt: string;
|
|
21
30
|
}
|
|
@@ -47,7 +56,7 @@ function writeQueue(meshId: string, queue: MeshWorkQueueEntry[]): void {
|
|
|
47
56
|
export function enqueueTask(
|
|
48
57
|
meshId: string,
|
|
49
58
|
message: string,
|
|
50
|
-
opts?: { targetNodeId?: string }
|
|
59
|
+
opts?: { targetNodeId?: string; targetSessionId?: string }
|
|
51
60
|
): MeshWorkQueueEntry {
|
|
52
61
|
const queue = readQueue(meshId);
|
|
53
62
|
const entry: MeshWorkQueueEntry = {
|
|
@@ -56,6 +65,7 @@ export function enqueueTask(
|
|
|
56
65
|
message,
|
|
57
66
|
status: 'pending',
|
|
58
67
|
targetNodeId: opts?.targetNodeId,
|
|
68
|
+
targetSessionId: opts?.targetSessionId,
|
|
59
69
|
createdAt: new Date().toISOString(),
|
|
60
70
|
updatedAt: new Date().toISOString(),
|
|
61
71
|
};
|
|
@@ -81,13 +91,25 @@ export function getQueue(meshId: string, opts?: { status?: MeshTaskStatus[] }):
|
|
|
81
91
|
*/
|
|
82
92
|
export function claimNextTask(meshId: string, nodeId: string, sessionId: string): MeshWorkQueueEntry | null {
|
|
83
93
|
const queue = readQueue(meshId);
|
|
94
|
+
|
|
95
|
+
// A worker must finish or fail its current queued assignment before it can
|
|
96
|
+
// claim another one. maxParallelTasks limits total mesh concurrency; it is
|
|
97
|
+
// not permission for one node/session to accumulate multiple assigned items.
|
|
98
|
+
const hasActiveAssignment = queue.some(q => q.status === 'assigned' && (
|
|
99
|
+
q.assignedSessionId === sessionId || q.assignedNodeId === nodeId
|
|
100
|
+
));
|
|
101
|
+
if (hasActiveAssignment) return null;
|
|
84
102
|
|
|
85
103
|
// Find highest priority task:
|
|
86
|
-
// 1. Pending tasks explicitly targeted at this
|
|
87
|
-
// 2. Pending tasks
|
|
88
|
-
|
|
104
|
+
// 1. Pending tasks explicitly targeted at this runtime session
|
|
105
|
+
// 2. Pending tasks explicitly targeted at this node (but not another session)
|
|
106
|
+
// 3. Pending tasks with no target node/session
|
|
107
|
+
let targetIdx = queue.findIndex(q => q.status === 'pending' && q.targetSessionId === sessionId);
|
|
108
|
+
if (targetIdx === -1) {
|
|
109
|
+
targetIdx = queue.findIndex(q => q.status === 'pending' && q.targetNodeId === nodeId && !q.targetSessionId);
|
|
110
|
+
}
|
|
89
111
|
if (targetIdx === -1) {
|
|
90
|
-
targetIdx = queue.findIndex(q => q.status === 'pending' && !q.targetNodeId);
|
|
112
|
+
targetIdx = queue.findIndex(q => q.status === 'pending' && !q.targetNodeId && !q.targetSessionId);
|
|
91
113
|
}
|
|
92
114
|
|
|
93
115
|
if (targetIdx === -1) return null;
|
|
@@ -121,6 +143,65 @@ export function updateTaskStatus(
|
|
|
121
143
|
return queue[idx];
|
|
122
144
|
}
|
|
123
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Mark a queue task as manually cancelled without deleting audit history.
|
|
148
|
+
*/
|
|
149
|
+
export function cancelTask(
|
|
150
|
+
meshId: string,
|
|
151
|
+
taskId: string,
|
|
152
|
+
opts?: { reason?: string },
|
|
153
|
+
): MeshWorkQueueEntry | null {
|
|
154
|
+
const queue = readQueue(meshId);
|
|
155
|
+
const idx = queue.findIndex(q => q.id === taskId);
|
|
156
|
+
if (idx === -1) return null;
|
|
157
|
+
|
|
158
|
+
const now = new Date().toISOString();
|
|
159
|
+
queue[idx].status = 'cancelled';
|
|
160
|
+
queue[idx].updatedAt = now;
|
|
161
|
+
queue[idx].cancelledAt = now;
|
|
162
|
+
if (opts?.reason) queue[idx].cancelReason = opts.reason;
|
|
163
|
+
writeQueue(meshId, queue);
|
|
164
|
+
return queue[idx];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Return a queue task to pending for retry. By default, dead session targeting
|
|
169
|
+
* and assigned ownership are cleared so stale assignments do not strand again.
|
|
170
|
+
*/
|
|
171
|
+
export function requeueTask(
|
|
172
|
+
meshId: string,
|
|
173
|
+
taskId: string,
|
|
174
|
+
opts?: {
|
|
175
|
+
reason?: string;
|
|
176
|
+
targetNodeId?: string;
|
|
177
|
+
targetSessionId?: string;
|
|
178
|
+
clearTargetNode?: boolean;
|
|
179
|
+
clearTargetSession?: boolean;
|
|
180
|
+
},
|
|
181
|
+
): MeshWorkQueueEntry | null {
|
|
182
|
+
const queue = readQueue(meshId);
|
|
183
|
+
const idx = queue.findIndex(q => q.id === taskId);
|
|
184
|
+
if (idx === -1) return null;
|
|
185
|
+
|
|
186
|
+
const entry = queue[idx];
|
|
187
|
+
const now = new Date().toISOString();
|
|
188
|
+
entry.status = 'pending';
|
|
189
|
+
delete entry.assignedNodeId;
|
|
190
|
+
delete entry.assignedSessionId;
|
|
191
|
+
delete entry.cancelledAt;
|
|
192
|
+
delete entry.cancelReason;
|
|
193
|
+
if (opts?.clearTargetNode) delete entry.targetNodeId;
|
|
194
|
+
if (typeof opts?.targetNodeId === 'string') entry.targetNodeId = opts.targetNodeId;
|
|
195
|
+
if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
|
|
196
|
+
if (typeof opts?.targetSessionId === 'string') entry.targetSessionId = opts.targetSessionId;
|
|
197
|
+
entry.updatedAt = now;
|
|
198
|
+
entry.requeuedAt = now;
|
|
199
|
+
entry.requeueCount = (entry.requeueCount || 0) + 1;
|
|
200
|
+
if (opts?.reason) entry.requeueReason = opts.reason;
|
|
201
|
+
writeQueue(meshId, queue);
|
|
202
|
+
return entry;
|
|
203
|
+
}
|
|
204
|
+
|
|
124
205
|
/**
|
|
125
206
|
* Update the status of the task currently assigned to a specific session.
|
|
126
207
|
*/
|
|
@@ -148,6 +229,13 @@ export interface MeshWorkQueueStats {
|
|
|
148
229
|
assigned: number;
|
|
149
230
|
completed: number;
|
|
150
231
|
failed: number;
|
|
232
|
+
cancelled: number;
|
|
233
|
+
activeAssignments: Array<{
|
|
234
|
+
id: string;
|
|
235
|
+
nodeId?: string;
|
|
236
|
+
sessionId?: string;
|
|
237
|
+
message: string;
|
|
238
|
+
}>;
|
|
151
239
|
}
|
|
152
240
|
|
|
153
241
|
/**
|
|
@@ -160,5 +248,14 @@ export function getMeshQueueStats(meshId: string): MeshWorkQueueStats {
|
|
|
160
248
|
assigned: queue.filter(q => q.status === 'assigned').length,
|
|
161
249
|
completed: queue.filter(q => q.status === 'completed').length,
|
|
162
250
|
failed: queue.filter(q => q.status === 'failed').length,
|
|
251
|
+
cancelled: queue.filter(q => q.status === 'cancelled').length,
|
|
252
|
+
activeAssignments: queue
|
|
253
|
+
.filter(q => q.status === 'assigned')
|
|
254
|
+
.map(q => ({
|
|
255
|
+
id: q.id,
|
|
256
|
+
nodeId: q.assignedNodeId,
|
|
257
|
+
sessionId: q.assignedSessionId,
|
|
258
|
+
message: q.message,
|
|
259
|
+
})),
|
|
163
260
|
};
|
|
164
261
|
}
|
|
@@ -833,6 +833,8 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
833
833
|
this.completedDebounceTimer = null;
|
|
834
834
|
}, 3000);
|
|
835
835
|
}
|
|
836
|
+
} else if (newStatus === 'idle' && this.lastStatus === 'starting') {
|
|
837
|
+
this.pushEvent({ event: 'agent:ready', chatTitle, timestamp: now });
|
|
836
838
|
} else if (newStatus === 'stopped') {
|
|
837
839
|
// Cancel any pending debounce
|
|
838
840
|
if (this.generatingDebounceTimer) { clearTimeout(this.generatingDebounceTimer); this.generatingDebounceTimer = null; }
|
package/src/shared-types.ts
CHANGED
|
@@ -394,6 +394,13 @@ export interface SessionEntry {
|
|
|
394
394
|
assigned: number;
|
|
395
395
|
completed: number;
|
|
396
396
|
failed: number;
|
|
397
|
+
cancelled?: number;
|
|
398
|
+
activeAssignments?: Array<{
|
|
399
|
+
id: string;
|
|
400
|
+
nodeId?: string;
|
|
401
|
+
sessionId?: string;
|
|
402
|
+
message: string;
|
|
403
|
+
}>;
|
|
397
404
|
};
|
|
398
405
|
}
|
|
399
406
|
|
|
@@ -439,6 +446,13 @@ export interface CompactSessionEntry {
|
|
|
439
446
|
assigned: number;
|
|
440
447
|
completed: number;
|
|
441
448
|
failed: number;
|
|
449
|
+
cancelled?: number;
|
|
450
|
+
activeAssignments?: Array<{
|
|
451
|
+
id: string;
|
|
452
|
+
nodeId?: string;
|
|
453
|
+
sessionId?: string;
|
|
454
|
+
message: string;
|
|
455
|
+
}>;
|
|
442
456
|
};
|
|
443
457
|
}
|
|
444
458
|
|