oh-my-claude-sisyphus 3.5.7 → 3.6.0
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/agents/executor-high.md +2 -0
- package/agents/executor-low.md +2 -0
- package/agents/executor.md +2 -0
- package/agents/templates/base-agent.md +9 -0
- package/commands/cancel.md +8 -8
- package/commands/swarm.md +350 -148
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts +7 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts.map +1 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js +374 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js.map +1 -0
- package/dist/__tests__/hooks/learner/bridge.test.d.ts +11 -0
- package/dist/__tests__/hooks/learner/bridge.test.d.ts.map +1 -0
- package/dist/__tests__/hooks/learner/bridge.test.js +199 -0
- package/dist/__tests__/hooks/learner/bridge.test.js.map +1 -0
- package/dist/__tests__/hooks.test.js +10 -9
- package/dist/__tests__/hooks.test.js.map +1 -1
- package/dist/__tests__/installer.test.js +1 -1
- package/dist/agents/codex-agents.d.ts +20 -0
- package/dist/agents/codex-agents.d.ts.map +1 -0
- package/dist/agents/codex-agents.js +36 -0
- package/dist/agents/codex-agents.js.map +1 -0
- package/dist/agents/preamble.d.ts +14 -0
- package/dist/agents/preamble.d.ts.map +1 -0
- package/dist/agents/preamble.js +26 -0
- package/dist/agents/preamble.js.map +1 -0
- package/dist/hooks/autopilot/__tests__/cancel.test.js +14 -4
- package/dist/hooks/autopilot/__tests__/cancel.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/state.test.js +1 -0
- package/dist/hooks/autopilot/__tests__/state.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/summary.test.js +38 -3
- package/dist/hooks/autopilot/__tests__/summary.test.js.map +1 -1
- package/dist/hooks/autopilot/state.d.ts +1 -1
- package/dist/hooks/autopilot/state.d.ts.map +1 -1
- package/dist/hooks/autopilot/state.js +15 -8
- package/dist/hooks/autopilot/state.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/learner/bridge.d.ts +71 -0
- package/dist/hooks/learner/bridge.d.ts.map +1 -0
- package/dist/hooks/learner/bridge.js +426 -0
- package/dist/hooks/learner/bridge.js.map +1 -0
- package/dist/hooks/mode-registry/index.d.ts +135 -0
- package/dist/hooks/mode-registry/index.d.ts.map +1 -0
- package/dist/hooks/mode-registry/index.js +445 -0
- package/dist/hooks/mode-registry/index.js.map +1 -0
- package/dist/hooks/mode-registry/types.d.ts +31 -0
- package/dist/hooks/mode-registry/types.d.ts.map +1 -0
- package/dist/hooks/mode-registry/types.js +7 -0
- package/dist/hooks/mode-registry/types.js.map +1 -0
- package/dist/hooks/ralph/loop.js +6 -6
- package/dist/hooks/ralph/loop.js.map +1 -1
- package/dist/hooks/skill-bridge.cjs +349 -0
- package/dist/hooks/swarm/__tests__/claiming.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/claiming.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/claiming.test.js +170 -0
- package/dist/hooks/swarm/__tests__/claiming.test.js.map +1 -0
- package/dist/hooks/swarm/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/index.test.js +157 -0
- package/dist/hooks/swarm/__tests__/index.test.js.map +1 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.js +177 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.js.map +1 -0
- package/dist/hooks/swarm/claiming.d.ts +101 -0
- package/dist/hooks/swarm/claiming.d.ts.map +1 -0
- package/dist/hooks/swarm/claiming.js +460 -0
- package/dist/hooks/swarm/claiming.js.map +1 -0
- package/dist/hooks/swarm/index.d.ts +221 -0
- package/dist/hooks/swarm/index.d.ts.map +1 -0
- package/dist/hooks/swarm/index.js +413 -0
- package/dist/hooks/swarm/index.js.map +1 -0
- package/dist/hooks/swarm/state.d.ts +94 -0
- package/dist/hooks/swarm/state.d.ts.map +1 -0
- package/dist/hooks/swarm/state.js +530 -0
- package/dist/hooks/swarm/state.js.map +1 -0
- package/dist/hooks/swarm/types.d.ts +116 -0
- package/dist/hooks/swarm/types.d.ts.map +1 -0
- package/dist/hooks/swarm/types.js +22 -0
- package/dist/hooks/swarm/types.js.map +1 -0
- package/dist/hooks/ultrapilot/decomposer.d.ts +141 -0
- package/dist/hooks/ultrapilot/decomposer.d.ts.map +1 -0
- package/dist/hooks/ultrapilot/decomposer.js +377 -0
- package/dist/hooks/ultrapilot/decomposer.js.map +1 -0
- package/dist/hooks/ultrapilot/index.d.ts +31 -0
- package/dist/hooks/ultrapilot/index.d.ts.map +1 -1
- package/dist/hooks/ultrapilot/index.js +43 -2
- package/dist/hooks/ultrapilot/index.js.map +1 -1
- package/dist/hooks/ultrapilot/state.d.ts +1 -1
- package/dist/hooks/ultrapilot/state.d.ts.map +1 -1
- package/dist/hooks/ultrapilot/state.js +7 -0
- package/dist/hooks/ultrapilot/state.js.map +1 -1
- package/dist/hooks/ultraqa/index.js +5 -5
- package/dist/hooks/ultraqa/index.js.map +1 -1
- package/dist/hooks/ultrawork/index.js +3 -3
- package/dist/hooks/ultrawork/index.js.map +1 -1
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.js +1 -1
- package/package.json +6 -2
- package/scripts/build-skill-bridge.mjs +32 -0
- package/scripts/skill-injector.mjs +77 -26
- package/skills/autopilot/SKILL.md +18 -0
- package/skills/cancel/SKILL.md +166 -141
- package/skills/ecomode/SKILL.md +14 -0
- package/skills/pipeline/SKILL.md +13 -0
- package/skills/ralph/SKILL.md +22 -1
- package/skills/swarm/SKILL.md +521 -197
- package/skills/ultrapilot/SKILL.md +82 -13
- package/skills/ultraqa/SKILL.md +13 -0
- package/skills/ultrawork/SKILL.md +14 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swarm Task Claiming
|
|
3
|
+
*
|
|
4
|
+
* Atomic task claiming with lease-based ownership.
|
|
5
|
+
* Uses SQLite transactions to ensure only one agent can claim a task.
|
|
6
|
+
* Implements 5-minute lease timeout and heartbeat monitoring.
|
|
7
|
+
*/
|
|
8
|
+
import { DEFAULT_SWARM_CONFIG } from './types.js';
|
|
9
|
+
import { getDb, recordHeartbeat } from './state.js';
|
|
10
|
+
/**
|
|
11
|
+
* Atomically claim the next available task
|
|
12
|
+
*
|
|
13
|
+
* Uses a transaction to ensure only one agent can claim a task.
|
|
14
|
+
* Claims are lease-based with a 5-minute timeout.
|
|
15
|
+
*
|
|
16
|
+
* @param agentId - Unique identifier for the claiming agent
|
|
17
|
+
* @returns ClaimResult indicating success/failure and task details
|
|
18
|
+
*/
|
|
19
|
+
export function claimTask(agentId) {
|
|
20
|
+
const db = getDb();
|
|
21
|
+
if (!db) {
|
|
22
|
+
return {
|
|
23
|
+
success: false,
|
|
24
|
+
taskId: null,
|
|
25
|
+
reason: 'Database not initialized'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
// Use a transaction for atomic claim
|
|
30
|
+
const claimTransaction = db.transaction(() => {
|
|
31
|
+
// Find the first pending task
|
|
32
|
+
const findStmt = db.prepare(`
|
|
33
|
+
SELECT id, description FROM tasks
|
|
34
|
+
WHERE status = 'pending'
|
|
35
|
+
ORDER BY id
|
|
36
|
+
LIMIT 1
|
|
37
|
+
`);
|
|
38
|
+
const task = findStmt.get();
|
|
39
|
+
if (!task) {
|
|
40
|
+
return {
|
|
41
|
+
success: false,
|
|
42
|
+
taskId: null,
|
|
43
|
+
reason: 'No pending tasks available'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Claim the task
|
|
47
|
+
const claimStmt = db.prepare(`
|
|
48
|
+
UPDATE tasks
|
|
49
|
+
SET status = 'claimed', claimed_by = ?, claimed_at = ?
|
|
50
|
+
WHERE id = ? AND status = 'pending'
|
|
51
|
+
`);
|
|
52
|
+
const result = claimStmt.run(agentId, Date.now(), task.id);
|
|
53
|
+
if (result.changes === 0) {
|
|
54
|
+
// Task was claimed by another agent between SELECT and UPDATE
|
|
55
|
+
return {
|
|
56
|
+
success: false,
|
|
57
|
+
taskId: null,
|
|
58
|
+
reason: 'Task was claimed by another agent'
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// Update heartbeat
|
|
62
|
+
const heartbeatStmt = db.prepare(`
|
|
63
|
+
INSERT OR REPLACE INTO heartbeats (agent_id, last_heartbeat, current_task_id)
|
|
64
|
+
VALUES (?, ?, ?)
|
|
65
|
+
`);
|
|
66
|
+
heartbeatStmt.run(agentId, Date.now(), task.id);
|
|
67
|
+
return {
|
|
68
|
+
success: true,
|
|
69
|
+
taskId: task.id,
|
|
70
|
+
description: task.description
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
return claimTransaction.immediate();
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
taskId: null,
|
|
79
|
+
reason: `Claim failed: ${error instanceof Error ? error.message : String(error)}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Release a claimed task back to the pending pool
|
|
85
|
+
*
|
|
86
|
+
* Used when an agent fails to complete a task or wants to give it up.
|
|
87
|
+
*
|
|
88
|
+
* @param agentId - Agent releasing the task
|
|
89
|
+
* @param taskId - Task to release
|
|
90
|
+
* @returns true if release was successful
|
|
91
|
+
*/
|
|
92
|
+
export function releaseTask(agentId, taskId) {
|
|
93
|
+
const db = getDb();
|
|
94
|
+
if (!db)
|
|
95
|
+
return false;
|
|
96
|
+
try {
|
|
97
|
+
const releaseTransaction = db.transaction(() => {
|
|
98
|
+
// Verify the agent owns this task
|
|
99
|
+
const verifyStmt = db.prepare(`
|
|
100
|
+
SELECT claimed_by FROM tasks WHERE id = ?
|
|
101
|
+
`);
|
|
102
|
+
const task = verifyStmt.get(taskId);
|
|
103
|
+
if (!task || task.claimed_by !== agentId) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
// Release the task
|
|
107
|
+
const releaseStmt = db.prepare(`
|
|
108
|
+
UPDATE tasks
|
|
109
|
+
SET status = 'pending', claimed_by = NULL, claimed_at = NULL
|
|
110
|
+
WHERE id = ? AND claimed_by = ?
|
|
111
|
+
`);
|
|
112
|
+
releaseStmt.run(taskId, agentId);
|
|
113
|
+
// Update heartbeat to show no current task
|
|
114
|
+
const heartbeatStmt = db.prepare(`
|
|
115
|
+
UPDATE heartbeats SET current_task_id = NULL WHERE agent_id = ?
|
|
116
|
+
`);
|
|
117
|
+
heartbeatStmt.run(agentId);
|
|
118
|
+
return true;
|
|
119
|
+
});
|
|
120
|
+
return releaseTransaction.immediate();
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
console.error('Failed to release task:', error);
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Mark a task as completed
|
|
129
|
+
*
|
|
130
|
+
* @param agentId - Agent that completed the task
|
|
131
|
+
* @param taskId - Completed task ID
|
|
132
|
+
* @param result - Optional result/output from the task
|
|
133
|
+
* @returns true if completion was recorded
|
|
134
|
+
*/
|
|
135
|
+
export function completeTask(agentId, taskId, result) {
|
|
136
|
+
const db = getDb();
|
|
137
|
+
if (!db)
|
|
138
|
+
return false;
|
|
139
|
+
try {
|
|
140
|
+
const completeTransaction = db.transaction(() => {
|
|
141
|
+
// Verify the agent owns this task
|
|
142
|
+
const verifyStmt = db.prepare(`
|
|
143
|
+
SELECT claimed_by FROM tasks WHERE id = ?
|
|
144
|
+
`);
|
|
145
|
+
const task = verifyStmt.get(taskId);
|
|
146
|
+
if (!task || task.claimed_by !== agentId) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
// Mark task as done
|
|
150
|
+
const completeStmt = db.prepare(`
|
|
151
|
+
UPDATE tasks
|
|
152
|
+
SET status = 'done', completed_at = ?, result = ?
|
|
153
|
+
WHERE id = ? AND claimed_by = ?
|
|
154
|
+
`);
|
|
155
|
+
completeStmt.run(Date.now(), result ?? null, taskId, agentId);
|
|
156
|
+
// Update heartbeat to show no current task
|
|
157
|
+
const heartbeatStmt = db.prepare(`
|
|
158
|
+
UPDATE heartbeats SET current_task_id = NULL WHERE agent_id = ?
|
|
159
|
+
`);
|
|
160
|
+
heartbeatStmt.run(agentId);
|
|
161
|
+
return true;
|
|
162
|
+
});
|
|
163
|
+
return completeTransaction.immediate();
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
console.error('Failed to complete task:', error);
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Mark a task as failed
|
|
172
|
+
*
|
|
173
|
+
* @param agentId - Agent that failed the task
|
|
174
|
+
* @param taskId - Failed task ID
|
|
175
|
+
* @param error - Error message/reason for failure
|
|
176
|
+
* @returns true if failure was recorded
|
|
177
|
+
*/
|
|
178
|
+
export function failTask(agentId, taskId, error) {
|
|
179
|
+
const db = getDb();
|
|
180
|
+
if (!db)
|
|
181
|
+
return false;
|
|
182
|
+
try {
|
|
183
|
+
const failTransaction = db.transaction(() => {
|
|
184
|
+
// Verify the agent owns this task
|
|
185
|
+
const verifyStmt = db.prepare(`
|
|
186
|
+
SELECT claimed_by FROM tasks WHERE id = ?
|
|
187
|
+
`);
|
|
188
|
+
const task = verifyStmt.get(taskId);
|
|
189
|
+
if (!task || task.claimed_by !== agentId) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
// Mark task as failed
|
|
193
|
+
const failStmt = db.prepare(`
|
|
194
|
+
UPDATE tasks
|
|
195
|
+
SET status = 'failed', completed_at = ?, error = ?
|
|
196
|
+
WHERE id = ? AND claimed_by = ?
|
|
197
|
+
`);
|
|
198
|
+
failStmt.run(Date.now(), error, taskId, agentId);
|
|
199
|
+
// Update heartbeat to show no current task
|
|
200
|
+
const heartbeatStmt = db.prepare(`
|
|
201
|
+
UPDATE heartbeats SET current_task_id = NULL WHERE agent_id = ?
|
|
202
|
+
`);
|
|
203
|
+
heartbeatStmt.run(agentId);
|
|
204
|
+
return true;
|
|
205
|
+
});
|
|
206
|
+
return failTransaction.immediate();
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
console.error('Failed to fail task:', error);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Record agent heartbeat
|
|
215
|
+
*
|
|
216
|
+
* Agents should call this every 60 seconds to indicate they're still alive.
|
|
217
|
+
* Used by cleanupStaleClaims to detect dead agents.
|
|
218
|
+
*
|
|
219
|
+
* @param agentId - Agent sending heartbeat
|
|
220
|
+
* @returns true if heartbeat was recorded
|
|
221
|
+
*/
|
|
222
|
+
export function heartbeat(agentId) {
|
|
223
|
+
const db = getDb();
|
|
224
|
+
if (!db)
|
|
225
|
+
return false;
|
|
226
|
+
try {
|
|
227
|
+
// Get current task for this agent
|
|
228
|
+
const taskStmt = db.prepare(`
|
|
229
|
+
SELECT id FROM tasks WHERE claimed_by = ? AND status = 'claimed'
|
|
230
|
+
`);
|
|
231
|
+
const task = taskStmt.get(agentId);
|
|
232
|
+
return recordHeartbeat(agentId, task?.id ?? null);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
console.error('Failed to record heartbeat:', error);
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Clean up stale claims from dead agents
|
|
241
|
+
*
|
|
242
|
+
* Releases tasks that have been claimed for longer than the lease timeout
|
|
243
|
+
* (default 5 minutes) by agents that haven't sent a heartbeat.
|
|
244
|
+
*
|
|
245
|
+
* @param leaseTimeout - Lease timeout in milliseconds (default: 5 minutes)
|
|
246
|
+
* @returns Number of tasks released
|
|
247
|
+
*/
|
|
248
|
+
export function cleanupStaleClaims(leaseTimeout = DEFAULT_SWARM_CONFIG.leaseTimeout) {
|
|
249
|
+
const db = getDb();
|
|
250
|
+
if (!db)
|
|
251
|
+
return 0;
|
|
252
|
+
try {
|
|
253
|
+
const cutoffTime = Date.now() - leaseTimeout;
|
|
254
|
+
const cleanupTransaction = db.transaction(() => {
|
|
255
|
+
// Find tasks claimed longer than the timeout
|
|
256
|
+
// Only release if the agent hasn't sent a heartbeat recently
|
|
257
|
+
const findStaleStmt = db.prepare(`
|
|
258
|
+
SELECT t.id, t.claimed_by
|
|
259
|
+
FROM tasks t
|
|
260
|
+
LEFT JOIN heartbeats h ON t.claimed_by = h.agent_id
|
|
261
|
+
WHERE t.status = 'claimed'
|
|
262
|
+
AND t.claimed_at < ?
|
|
263
|
+
AND (h.last_heartbeat IS NULL OR h.last_heartbeat < ?)
|
|
264
|
+
`);
|
|
265
|
+
const staleTasks = findStaleStmt.all(cutoffTime, cutoffTime);
|
|
266
|
+
if (staleTasks.length === 0) {
|
|
267
|
+
return 0;
|
|
268
|
+
}
|
|
269
|
+
// Release stale tasks
|
|
270
|
+
const releaseStmt = db.prepare(`
|
|
271
|
+
UPDATE tasks
|
|
272
|
+
SET status = 'pending', claimed_by = NULL, claimed_at = NULL
|
|
273
|
+
WHERE id = ?
|
|
274
|
+
`);
|
|
275
|
+
// Remove stale heartbeats
|
|
276
|
+
const removeHeartbeatStmt = db.prepare(`
|
|
277
|
+
DELETE FROM heartbeats WHERE agent_id = ?
|
|
278
|
+
`);
|
|
279
|
+
const staleAgents = new Set();
|
|
280
|
+
for (const task of staleTasks) {
|
|
281
|
+
releaseStmt.run(task.id);
|
|
282
|
+
if (task.claimed_by) {
|
|
283
|
+
staleAgents.add(task.claimed_by);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
for (const agentId of staleAgents) {
|
|
287
|
+
removeHeartbeatStmt.run(agentId);
|
|
288
|
+
}
|
|
289
|
+
return staleTasks.length;
|
|
290
|
+
});
|
|
291
|
+
return cleanupTransaction.immediate();
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
console.error('Failed to cleanup stale claims:', error);
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Get tasks claimed by a specific agent
|
|
300
|
+
*
|
|
301
|
+
* @param agentId - Agent to query
|
|
302
|
+
* @returns Array of tasks claimed by the agent
|
|
303
|
+
*/
|
|
304
|
+
export function getTasksClaimedBy(agentId) {
|
|
305
|
+
const db = getDb();
|
|
306
|
+
if (!db)
|
|
307
|
+
return [];
|
|
308
|
+
try {
|
|
309
|
+
const stmt = db.prepare(`
|
|
310
|
+
SELECT * FROM tasks WHERE claimed_by = ? AND status = 'claimed'
|
|
311
|
+
`);
|
|
312
|
+
const rows = stmt.all(agentId);
|
|
313
|
+
return rows.map(row => ({
|
|
314
|
+
id: row.id,
|
|
315
|
+
description: row.description,
|
|
316
|
+
status: row.status,
|
|
317
|
+
claimedBy: row.claimed_by,
|
|
318
|
+
claimedAt: row.claimed_at,
|
|
319
|
+
completedAt: row.completed_at,
|
|
320
|
+
error: row.error ?? undefined,
|
|
321
|
+
result: row.result ?? undefined
|
|
322
|
+
}));
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
console.error('Failed to get tasks claimed by agent:', error);
|
|
326
|
+
return [];
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Check if there are any pending tasks
|
|
331
|
+
*
|
|
332
|
+
* @returns true if there are pending tasks
|
|
333
|
+
*/
|
|
334
|
+
export function hasPendingTasks() {
|
|
335
|
+
const db = getDb();
|
|
336
|
+
if (!db)
|
|
337
|
+
return false;
|
|
338
|
+
try {
|
|
339
|
+
const stmt = db.prepare(`
|
|
340
|
+
SELECT COUNT(*) as count FROM tasks WHERE status = 'pending'
|
|
341
|
+
`);
|
|
342
|
+
const result = stmt.get();
|
|
343
|
+
return result.count > 0;
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
console.error('Failed to check pending tasks:', error);
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Check if all tasks are complete (done or failed)
|
|
352
|
+
*
|
|
353
|
+
* @returns true if all tasks are complete
|
|
354
|
+
*/
|
|
355
|
+
export function allTasksComplete() {
|
|
356
|
+
const db = getDb();
|
|
357
|
+
if (!db)
|
|
358
|
+
return false;
|
|
359
|
+
try {
|
|
360
|
+
const stmt = db.prepare(`
|
|
361
|
+
SELECT COUNT(*) as count FROM tasks WHERE status IN ('pending', 'claimed')
|
|
362
|
+
`);
|
|
363
|
+
const result = stmt.get();
|
|
364
|
+
return result.count === 0;
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
console.error('Failed to check if all tasks complete:', error);
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Get the number of active agents (with recent heartbeats)
|
|
373
|
+
*
|
|
374
|
+
* @param heartbeatTimeout - How old a heartbeat can be to still be considered active
|
|
375
|
+
* @returns Number of active agents
|
|
376
|
+
*/
|
|
377
|
+
export function getActiveAgentCount(heartbeatTimeout = DEFAULT_SWARM_CONFIG.leaseTimeout) {
|
|
378
|
+
const db = getDb();
|
|
379
|
+
if (!db)
|
|
380
|
+
return 0;
|
|
381
|
+
try {
|
|
382
|
+
const cutoffTime = Date.now() - heartbeatTimeout;
|
|
383
|
+
const stmt = db.prepare(`
|
|
384
|
+
SELECT COUNT(*) as count FROM heartbeats WHERE last_heartbeat > ?
|
|
385
|
+
`);
|
|
386
|
+
const result = stmt.get(cutoffTime);
|
|
387
|
+
return result.count;
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
console.error('Failed to get active agent count:', error);
|
|
391
|
+
return 0;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Attempt to reclaim a failed task
|
|
396
|
+
*
|
|
397
|
+
* @param agentId - Agent attempting to reclaim
|
|
398
|
+
* @param taskId - Task to reclaim
|
|
399
|
+
* @returns ClaimResult
|
|
400
|
+
*/
|
|
401
|
+
export function reclaimFailedTask(agentId, taskId) {
|
|
402
|
+
const db = getDb();
|
|
403
|
+
if (!db) {
|
|
404
|
+
return {
|
|
405
|
+
success: false,
|
|
406
|
+
taskId: null,
|
|
407
|
+
reason: 'Database not initialized'
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
try {
|
|
411
|
+
const reclaimTransaction = db.transaction(() => {
|
|
412
|
+
// Check if task is failed
|
|
413
|
+
const checkStmt = db.prepare(`
|
|
414
|
+
SELECT id, description, status FROM tasks WHERE id = ?
|
|
415
|
+
`);
|
|
416
|
+
const task = checkStmt.get(taskId);
|
|
417
|
+
if (!task) {
|
|
418
|
+
return {
|
|
419
|
+
success: false,
|
|
420
|
+
taskId: null,
|
|
421
|
+
reason: 'Task not found'
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
if (task.status !== 'failed') {
|
|
425
|
+
return {
|
|
426
|
+
success: false,
|
|
427
|
+
taskId: null,
|
|
428
|
+
reason: `Task is ${task.status}, not failed`
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
// Reclaim the task
|
|
432
|
+
const reclaimStmt = db.prepare(`
|
|
433
|
+
UPDATE tasks
|
|
434
|
+
SET status = 'claimed', claimed_by = ?, claimed_at = ?, error = NULL
|
|
435
|
+
WHERE id = ?
|
|
436
|
+
`);
|
|
437
|
+
reclaimStmt.run(agentId, Date.now(), taskId);
|
|
438
|
+
// Update heartbeat
|
|
439
|
+
const heartbeatStmt = db.prepare(`
|
|
440
|
+
INSERT OR REPLACE INTO heartbeats (agent_id, last_heartbeat, current_task_id)
|
|
441
|
+
VALUES (?, ?, ?)
|
|
442
|
+
`);
|
|
443
|
+
heartbeatStmt.run(agentId, Date.now(), taskId);
|
|
444
|
+
return {
|
|
445
|
+
success: true,
|
|
446
|
+
taskId: task.id,
|
|
447
|
+
description: task.description
|
|
448
|
+
};
|
|
449
|
+
});
|
|
450
|
+
return reclaimTransaction.immediate();
|
|
451
|
+
}
|
|
452
|
+
catch (error) {
|
|
453
|
+
return {
|
|
454
|
+
success: false,
|
|
455
|
+
taskId: null,
|
|
456
|
+
reason: `Reclaim failed: ${error instanceof Error ? error.message : String(error)}`
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
//# sourceMappingURL=claiming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claiming.js","sourceRoot":"","sources":["../../../src/hooks/swarm/claiming.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EACL,KAAK,EAIL,eAAe,EAIhB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,0BAA0B;SACnC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,qCAAqC;QACrC,MAAM,gBAAgB,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC3C,8BAA8B;YAC9B,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;OAK3B,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAqD,CAAC;YAE/E,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,4BAA4B;iBACtB,CAAC;YACnB,CAAC;YAED,iBAAiB;YACjB,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI5B,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAE3D,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;gBACzB,8DAA8D;gBAC9D,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,mCAAmC;iBAC7B,CAAC;YACnB,CAAC;YAED,mBAAmB;YACnB,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC;;;OAGhC,CAAC,CAAC;YACH,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAEhD,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,WAAW,EAAE,IAAI,CAAC,WAAW;aACf,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,iBAAiB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SAClF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,MAAc;IACzD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,kBAAkB,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC7C,kCAAkC;YAClC,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;OAE7B,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAA8C,CAAC;YAEjF,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACzC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,mBAAmB;YACnB,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI9B,CAAC,CAAC;YACH,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAEjC,2CAA2C;YAC3C,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC;;OAEhC,CAAC,CAAC;YACH,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAE3B,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,kBAAkB,CAAC,SAAS,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,MAAc,EAAE,MAAe;IAC3E,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,mBAAmB,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC9C,kCAAkC;YAClC,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;OAE7B,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAA8C,CAAC;YAEjF,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACzC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,oBAAoB;YACpB,MAAM,YAAY,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI/B,CAAC,CAAC;YACH,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,IAAI,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAE9D,2CAA2C;YAC3C,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC;;OAEhC,CAAC,CAAC;YACH,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAE3B,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,mBAAmB,CAAC,SAAS,EAAE,CAAC;IACzC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACjD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,MAAc,EAAE,KAAa;IACrE,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC1C,kCAAkC;YAClC,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;OAE7B,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAA8C,CAAC;YAEjF,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;gBACzC,OAAO,KAAK,CAAC;YACf,CAAC;YAED,sBAAsB;YACtB,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI3B,CAAC,CAAC;YACH,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;YAEjD,2CAA2C;YAC3C,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC;;OAEhC,CAAC,CAAC;YACH,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAE3B,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,eAAe,CAAC,SAAS,EAAE,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;QAC7C,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAEtB,IAAI,CAAC;QACH,kCAAkC;QAClC,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC;;KAE3B,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAA+B,CAAC;QAEjE,OAAO,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,eAAuB,oBAAoB,CAAC,YAAY;IACzF,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IAElB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;QAE7C,MAAM,kBAAkB,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC7C,6CAA6C;YAC7C,6DAA6D;YAC7D,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;;OAOhC,CAAC,CAAC;YACH,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAGzD,CAAC;YAEH,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO,CAAC,CAAC;YACX,CAAC;YAED,sBAAsB;YACtB,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI9B,CAAC,CAAC;YAEH,0BAA0B;YAC1B,MAAM,mBAAmB,GAAG,EAAE,CAAC,OAAO,CAAC;;OAEtC,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC9B,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACzB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACpB,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;gBAClC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;YAED,OAAO,UAAU,CAAC,MAAM,CAAC;QAC3B,CAAC,CAAC,CAAC;QAEH,OAAO,kBAAkB,CAAC,SAAS,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;IAEnB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;KAEvB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAS3B,CAAC;QAEH,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACtB,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,MAAM,EAAE,GAAG,CAAC,MAA6B;YACzC,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,WAAW,EAAE,GAAG,CAAC,YAAY;YAC7B,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,SAAS;YAC7B,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,SAAS;SAChC,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;QAC9D,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;KAEvB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAuB,CAAC;QAC/C,OAAO,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;KAEvB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAuB,CAAC;QAC/C,OAAO,MAAM,CAAC,KAAK,KAAK,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,mBAA2B,oBAAoB,CAAC,YAAY;IAC9F,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IAElB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,gBAAgB,CAAC;QACjD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;KAEvB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAsB,CAAC;QACzD,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;QAC1D,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,MAAc;IAC/D,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,0BAA0B;SACnC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,kBAAkB,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YAC7C,0BAA0B;YAC1B,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAAC;;OAE5B,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAoE,CAAC;YAEtG,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,gBAAgB;iBACV,CAAC;YACnB,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC7B,OAAO;oBACL,OAAO,EAAE,KAAK;oBACd,MAAM,EAAE,IAAI;oBACZ,MAAM,EAAE,WAAW,IAAI,CAAC,MAAM,cAAc;iBAC9B,CAAC;YACnB,CAAC;YAED,mBAAmB;YACnB,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC;;;;OAI9B,CAAC,CAAC;YACH,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;YAE7C,mBAAmB;YACnB,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC;;;OAGhC,CAAC,CAAC;YACH,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;YAE/C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,WAAW,EAAE,IAAI,CAAC,WAAW;aACf,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,OAAO,kBAAkB,CAAC,SAAS,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,mBAAmB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACpF,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swarm Coordination System
|
|
3
|
+
*
|
|
4
|
+
* SQLite-based multi-agent task coordination.
|
|
5
|
+
* Enables N agents to claim and work on tasks from a shared pool
|
|
6
|
+
* with atomic claiming, lease-based ownership, and heartbeat monitoring.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { startSwarm, claimTask, completeTask, stopSwarm } from './swarm';
|
|
11
|
+
*
|
|
12
|
+
* // Initialize swarm with tasks
|
|
13
|
+
* await startSwarm({
|
|
14
|
+
* agentCount: 5,
|
|
15
|
+
* tasks: ['fix error in auth.ts', 'add tests for api.ts', ...],
|
|
16
|
+
* cwd: process.cwd()
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Each agent claims and works on tasks
|
|
20
|
+
* const claim = claimTask('agent-1');
|
|
21
|
+
* if (claim.success) {
|
|
22
|
+
* // Do work...
|
|
23
|
+
* completeTask('agent-1', claim.taskId!, 'Fixed the bug');
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // Check status
|
|
27
|
+
* const status = getSwarmStatus();
|
|
28
|
+
*
|
|
29
|
+
* // Clean up when done
|
|
30
|
+
* stopSwarm();
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
import type { SwarmConfig, SwarmState, SwarmTask, SwarmStats, ClaimResult, AgentHeartbeat } from './types.js';
|
|
34
|
+
/**
|
|
35
|
+
* Start a new swarm session
|
|
36
|
+
*
|
|
37
|
+
* Initializes the SQLite database, creates the task pool,
|
|
38
|
+
* and starts the stale claim cleanup timer.
|
|
39
|
+
*
|
|
40
|
+
* @param config - Swarm configuration
|
|
41
|
+
* @returns true if swarm was started successfully
|
|
42
|
+
*/
|
|
43
|
+
export declare function startSwarm(config: SwarmConfig): Promise<boolean>;
|
|
44
|
+
/**
|
|
45
|
+
* Stop the swarm and clean up resources
|
|
46
|
+
*
|
|
47
|
+
* Stops the cleanup timer and optionally deletes the database.
|
|
48
|
+
*
|
|
49
|
+
* @param deleteDatabase - Whether to delete the database file (default: false)
|
|
50
|
+
* @returns true if swarm was stopped successfully
|
|
51
|
+
*/
|
|
52
|
+
export declare function stopSwarm(deleteDatabase?: boolean): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Get the current swarm status
|
|
55
|
+
*
|
|
56
|
+
* @returns SwarmState or null if swarm is not active
|
|
57
|
+
*/
|
|
58
|
+
export declare function getSwarmStatus(): SwarmState | null;
|
|
59
|
+
/**
|
|
60
|
+
* Get swarm statistics
|
|
61
|
+
*
|
|
62
|
+
* @returns SwarmStats with task counts and timing info
|
|
63
|
+
*/
|
|
64
|
+
export declare function getSwarmStats(): SwarmStats | null;
|
|
65
|
+
/**
|
|
66
|
+
* Claim the next available task
|
|
67
|
+
*
|
|
68
|
+
* @param agentId - Unique identifier for the claiming agent
|
|
69
|
+
* @returns ClaimResult with success status and task details
|
|
70
|
+
*/
|
|
71
|
+
export declare function claimTask(agentId: string): ClaimResult;
|
|
72
|
+
/**
|
|
73
|
+
* Release a claimed task back to the pool
|
|
74
|
+
*
|
|
75
|
+
* @param agentId - Agent releasing the task
|
|
76
|
+
* @param taskId - Task to release
|
|
77
|
+
* @returns true if release was successful
|
|
78
|
+
*/
|
|
79
|
+
export declare function releaseTask(agentId: string, taskId: string): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Mark a task as completed
|
|
82
|
+
*
|
|
83
|
+
* @param agentId - Agent that completed the task
|
|
84
|
+
* @param taskId - Completed task ID
|
|
85
|
+
* @param result - Optional result/output from the task
|
|
86
|
+
* @returns true if completion was recorded
|
|
87
|
+
*/
|
|
88
|
+
export declare function completeTask(agentId: string, taskId: string, result?: string): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Mark a task as failed
|
|
91
|
+
*
|
|
92
|
+
* @param agentId - Agent that failed the task
|
|
93
|
+
* @param taskId - Failed task ID
|
|
94
|
+
* @param error - Error message/reason for failure
|
|
95
|
+
* @returns true if failure was recorded
|
|
96
|
+
*/
|
|
97
|
+
export declare function failTask(agentId: string, taskId: string, error: string): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Send a heartbeat to indicate the agent is still alive
|
|
100
|
+
*
|
|
101
|
+
* Agents should call this every 60 seconds while working on tasks.
|
|
102
|
+
*
|
|
103
|
+
* @param agentId - Agent sending heartbeat
|
|
104
|
+
* @returns true if heartbeat was recorded
|
|
105
|
+
*/
|
|
106
|
+
export declare function heartbeat(agentId: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Clean up stale claims from dead agents
|
|
109
|
+
*
|
|
110
|
+
* Called automatically by the cleanup timer, but can also be called manually.
|
|
111
|
+
*
|
|
112
|
+
* @param leaseTimeout - Lease timeout in milliseconds (default: 5 minutes)
|
|
113
|
+
* @returns Number of tasks released
|
|
114
|
+
*/
|
|
115
|
+
export declare function cleanupStaleClaims(leaseTimeout?: number): number;
|
|
116
|
+
/**
|
|
117
|
+
* Check if there are pending tasks
|
|
118
|
+
*
|
|
119
|
+
* @returns true if there are tasks waiting to be claimed
|
|
120
|
+
*/
|
|
121
|
+
export declare function hasPendingWork(): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Check if all tasks are complete
|
|
124
|
+
*
|
|
125
|
+
* @returns true if all tasks are done or failed
|
|
126
|
+
*/
|
|
127
|
+
export declare function isSwarmComplete(): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Get the number of active agents
|
|
130
|
+
*
|
|
131
|
+
* @returns Number of agents with recent heartbeats
|
|
132
|
+
*/
|
|
133
|
+
export declare function getActiveAgents(): number;
|
|
134
|
+
/**
|
|
135
|
+
* Get all tasks
|
|
136
|
+
*
|
|
137
|
+
* @returns Array of all tasks in the swarm
|
|
138
|
+
*/
|
|
139
|
+
export declare function getAllTasks(): SwarmTask[];
|
|
140
|
+
/**
|
|
141
|
+
* Get tasks by status
|
|
142
|
+
*
|
|
143
|
+
* @param status - Task status to filter by
|
|
144
|
+
* @returns Array of tasks with the given status
|
|
145
|
+
*/
|
|
146
|
+
export declare function getTasksWithStatus(status: SwarmTask['status']): SwarmTask[];
|
|
147
|
+
/**
|
|
148
|
+
* Get a specific task
|
|
149
|
+
*
|
|
150
|
+
* @param taskId - Task ID to retrieve
|
|
151
|
+
* @returns Task or null if not found
|
|
152
|
+
*/
|
|
153
|
+
export declare function getTaskById(taskId: string): SwarmTask | null;
|
|
154
|
+
/**
|
|
155
|
+
* Get tasks claimed by a specific agent
|
|
156
|
+
*
|
|
157
|
+
* @param agentId - Agent to query
|
|
158
|
+
* @returns Array of tasks claimed by the agent
|
|
159
|
+
*/
|
|
160
|
+
export declare function getAgentTasks(agentId: string): SwarmTask[];
|
|
161
|
+
/**
|
|
162
|
+
* Get all agent heartbeats
|
|
163
|
+
*
|
|
164
|
+
* @returns Array of agent heartbeat records
|
|
165
|
+
*/
|
|
166
|
+
export declare function getAllHeartbeats(): AgentHeartbeat[];
|
|
167
|
+
/**
|
|
168
|
+
* Retry a failed task
|
|
169
|
+
*
|
|
170
|
+
* @param agentId - Agent attempting to retry
|
|
171
|
+
* @param taskId - Failed task to retry
|
|
172
|
+
* @returns ClaimResult
|
|
173
|
+
*/
|
|
174
|
+
export declare function retryTask(agentId: string, taskId: string): ClaimResult;
|
|
175
|
+
/**
|
|
176
|
+
* Check if swarm database is initialized
|
|
177
|
+
*
|
|
178
|
+
* @returns true if database is ready
|
|
179
|
+
*/
|
|
180
|
+
export declare function isSwarmReady(): boolean;
|
|
181
|
+
/**
|
|
182
|
+
* Initialize database without starting a swarm
|
|
183
|
+
*
|
|
184
|
+
* Useful for agents that join an existing swarm.
|
|
185
|
+
*
|
|
186
|
+
* @param cwd - Working directory
|
|
187
|
+
* @returns true if database was initialized
|
|
188
|
+
*/
|
|
189
|
+
export declare function connectToSwarm(cwd: string): Promise<boolean>;
|
|
190
|
+
/**
|
|
191
|
+
* Disconnect from swarm without stopping it
|
|
192
|
+
*
|
|
193
|
+
* @returns true if disconnected successfully
|
|
194
|
+
*/
|
|
195
|
+
export declare function disconnectFromSwarm(): boolean;
|
|
196
|
+
/**
|
|
197
|
+
* Check if swarm is currently active
|
|
198
|
+
*
|
|
199
|
+
* Used by cancel skill to detect active swarm.
|
|
200
|
+
* Checks if database exists and session is active.
|
|
201
|
+
*
|
|
202
|
+
* @param cwd - Working directory to check
|
|
203
|
+
* @returns true if swarm is active
|
|
204
|
+
*/
|
|
205
|
+
export declare function isSwarmActive(cwd: string): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Cancel active swarm
|
|
208
|
+
*
|
|
209
|
+
* Used by cancel skill to stop swarm cleanly.
|
|
210
|
+
*
|
|
211
|
+
* @param cwd - Working directory
|
|
212
|
+
* @returns CancelResult with success status and message
|
|
213
|
+
*/
|
|
214
|
+
export declare function cancelSwarm(cwd: string): Promise<{
|
|
215
|
+
success: boolean;
|
|
216
|
+
message: string;
|
|
217
|
+
stats?: SwarmStats | null;
|
|
218
|
+
}>;
|
|
219
|
+
export type { SwarmTask, SwarmState, SwarmConfig, SwarmStats, ClaimResult, AgentHeartbeat } from './types.js';
|
|
220
|
+
export { DEFAULT_SWARM_CONFIG } from './types.js';
|
|
221
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/swarm/index.ts"],"names":[],"mappings":"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"}
|