agent-working-memory 0.5.5 → 0.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/README.md +428 -399
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +60 -5
- package/dist/api/routes.js.map +1 -1
- package/dist/cli.js +468 -68
- package/dist/cli.js.map +1 -1
- package/dist/coordination/index.d.ts +11 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +39 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/mcp-tools.d.ts +8 -0
- package/dist/coordination/mcp-tools.d.ts.map +1 -0
- package/dist/coordination/mcp-tools.js +221 -0
- package/dist/coordination/mcp-tools.js.map +1 -0
- package/dist/coordination/routes.d.ts +9 -0
- package/dist/coordination/routes.d.ts.map +1 -0
- package/dist/coordination/routes.js +573 -0
- package/dist/coordination/routes.js.map +1 -0
- package/dist/coordination/schema.d.ts +12 -0
- package/dist/coordination/schema.d.ts.map +1 -0
- package/dist/coordination/schema.js +125 -0
- package/dist/coordination/schema.js.map +1 -0
- package/dist/coordination/schemas.d.ts +227 -0
- package/dist/coordination/schemas.d.ts.map +1 -0
- package/dist/coordination/schemas.js +125 -0
- package/dist/coordination/schemas.js.map +1 -0
- package/dist/coordination/stale.d.ts +27 -0
- package/dist/coordination/stale.d.ts.map +1 -0
- package/dist/coordination/stale.js +58 -0
- package/dist/coordination/stale.js.map +1 -0
- package/dist/engine/activation.d.ts.map +1 -1
- package/dist/engine/activation.js +119 -23
- package/dist/engine/activation.js.map +1 -1
- package/dist/engine/consolidation.d.ts.map +1 -1
- package/dist/engine/consolidation.js +27 -6
- package/dist/engine/consolidation.js.map +1 -1
- package/dist/index.js +100 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +149 -80
- package/dist/mcp.js.map +1 -1
- package/dist/storage/sqlite.d.ts +21 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +331 -282
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/types/engram.d.ts +24 -0
- package/dist/types/engram.d.ts.map +1 -1
- package/dist/types/engram.js.map +1 -1
- package/package.json +57 -55
- package/src/api/index.ts +3 -3
- package/src/api/routes.ts +600 -536
- package/src/cli.ts +850 -397
- package/src/coordination/index.ts +47 -0
- package/src/coordination/mcp-tools.ts +318 -0
- package/src/coordination/routes.ts +846 -0
- package/src/coordination/schema.ts +120 -0
- package/src/coordination/schemas.ts +155 -0
- package/src/coordination/stale.ts +97 -0
- package/src/core/decay.ts +63 -63
- package/src/core/embeddings.ts +88 -88
- package/src/core/hebbian.ts +93 -93
- package/src/core/index.ts +5 -5
- package/src/core/logger.ts +36 -36
- package/src/core/query-expander.ts +66 -66
- package/src/core/reranker.ts +101 -101
- package/src/engine/activation.ts +758 -656
- package/src/engine/connections.ts +103 -103
- package/src/engine/consolidation-scheduler.ts +125 -125
- package/src/engine/consolidation.ts +29 -6
- package/src/engine/eval.ts +102 -102
- package/src/engine/eviction.ts +101 -101
- package/src/engine/index.ts +8 -8
- package/src/engine/retraction.ts +100 -100
- package/src/engine/staging.ts +74 -74
- package/src/index.ts +208 -121
- package/src/mcp.ts +1093 -1013
- package/src/storage/index.ts +3 -3
- package/src/storage/sqlite.ts +1017 -963
- package/src/types/agent.ts +67 -67
- package/src/types/checkpoint.ts +46 -46
- package/src/types/engram.ts +245 -217
- package/src/types/eval.ts +100 -100
- package/src/types/index.ts +6 -6
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
// Copyright 2026 Robert Winter / Complete Ideas
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* HTTP routes for the coordination module.
|
|
5
|
+
* Ported from AgentSynapse packages/coordinator/src/routes/*.ts into a single file.
|
|
6
|
+
* All tables use coord_ prefix to avoid collision with AWM core tables.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from 'node:crypto';
|
|
9
|
+
import { checkinSchema, checkoutSchema, pulseSchema, nextSchema, assignCreateSchema, assignmentQuerySchema, assignmentClaimSchema, assignmentUpdateSchema, assignmentIdParamSchema, lockAcquireSchema, lockReleaseSchema, commandCreateSchema, commandWaitQuerySchema, findingCreateSchema, findingsQuerySchema, findingIdParamSchema, decisionsQuerySchema, eventsQuerySchema, staleQuerySchema, workersQuerySchema, } from './schemas.js';
|
|
10
|
+
import { detectStale, cleanupStale } from './stale.js';
|
|
11
|
+
/** Pretty timestamp for coordination logs. */
|
|
12
|
+
function ts() {
|
|
13
|
+
return new Date().toLocaleTimeString('en-GB', { hour12: false });
|
|
14
|
+
}
|
|
15
|
+
/** Log a coordination event in human-readable format. */
|
|
16
|
+
function coordLog(msg) {
|
|
17
|
+
console.log(`${ts()} [coord] ${msg}`);
|
|
18
|
+
}
|
|
19
|
+
export function registerCoordinationRoutes(app, db) {
|
|
20
|
+
// Log errors and non-200 responses
|
|
21
|
+
app.addHook('onResponse', async (request, reply) => {
|
|
22
|
+
if (reply.statusCode >= 400) {
|
|
23
|
+
coordLog(`${request.method} ${request.url} → ${reply.statusCode}`);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
// ─── Checkin ────────────────────────────────────────────────────
|
|
27
|
+
app.post('/checkin', async (req, reply) => {
|
|
28
|
+
const parsed = checkinSchema.safeParse(req.body);
|
|
29
|
+
if (!parsed.success)
|
|
30
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
31
|
+
const { name, role, pid, metadata, capabilities, workspace } = parsed.data;
|
|
32
|
+
const capsJson = capabilities ? JSON.stringify(capabilities) : null;
|
|
33
|
+
// Look up ANY existing agent with same name+workspace — including dead ones (upsert)
|
|
34
|
+
const existing = workspace
|
|
35
|
+
? db.prepare(`SELECT id, status FROM coord_agents WHERE name = ? AND workspace = ? ORDER BY last_seen DESC LIMIT 1`).get(name, workspace)
|
|
36
|
+
: db.prepare(`SELECT id, status FROM coord_agents WHERE name = ? AND workspace IS NULL ORDER BY last_seen DESC LIMIT 1`).get(name);
|
|
37
|
+
if (existing) {
|
|
38
|
+
const wasDead = existing.status === 'dead';
|
|
39
|
+
db.prepare(`UPDATE coord_agents SET last_seen = datetime('now'), status = CASE WHEN status = 'dead' THEN 'idle' ELSE status END, pid = COALESCE(?, pid), capabilities = COALESCE(?, capabilities) WHERE id = ?`).run(pid ?? null, capsJson, existing.id);
|
|
40
|
+
const eventType = wasDead ? 'reconnected' : 'heartbeat';
|
|
41
|
+
const detail = wasDead ? `${name} reconnected (was dead)` : `heartbeat from ${name}`;
|
|
42
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, ?, ?)`).run(existing.id, eventType, detail);
|
|
43
|
+
if (wasDead)
|
|
44
|
+
coordLog(`${name} reconnected (reusing UUID ${existing.id.slice(0, 8)})`);
|
|
45
|
+
const action = wasDead ? 'reconnected' : 'heartbeat';
|
|
46
|
+
const status = wasDead ? 'idle' : existing.status;
|
|
47
|
+
return reply.send({ agentId: existing.id, action, status, workspace });
|
|
48
|
+
}
|
|
49
|
+
const id = randomUUID();
|
|
50
|
+
db.prepare(`INSERT INTO coord_agents (id, name, role, pid, status, metadata, capabilities, workspace) VALUES (?, ?, ?, ?, 'idle', ?, ?, ?)`).run(id, name, role ?? 'worker', pid ?? null, metadata ? JSON.stringify(metadata) : null, capsJson, workspace ?? null);
|
|
51
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'registered', ?)`).run(id, `${name} joined as ${role ?? 'worker'}${workspace ? ' [' + workspace + ']' : ''}${capabilities ? ' [' + capabilities.join(', ') + ']' : ''}`);
|
|
52
|
+
coordLog(`${name} registered (${role ?? 'worker'})${capabilities ? ' [' + capabilities.join(', ') + ']' : ''}`);
|
|
53
|
+
return reply.code(201).send({ agentId: id, action: 'registered', status: 'idle', workspace });
|
|
54
|
+
});
|
|
55
|
+
app.post('/checkout', async (req, reply) => {
|
|
56
|
+
const parsed = checkoutSchema.safeParse(req.body);
|
|
57
|
+
if (!parsed.success)
|
|
58
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
59
|
+
const { agentId } = parsed.data;
|
|
60
|
+
db.prepare(`DELETE FROM coord_locks WHERE agent_id = ?`).run(agentId);
|
|
61
|
+
db.prepare(`UPDATE coord_agents SET status = 'dead', last_seen = datetime('now') WHERE id = ?`).run(agentId);
|
|
62
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'checkout', 'agent signed off')`).run(agentId);
|
|
63
|
+
// Look up agent name for logging
|
|
64
|
+
const agent = db.prepare(`SELECT name FROM coord_agents WHERE id = ?`).get(agentId);
|
|
65
|
+
coordLog(`${agent?.name ?? agentId} checked out`);
|
|
66
|
+
return reply.send({ ok: true });
|
|
67
|
+
});
|
|
68
|
+
// ─── Pulse (lightweight heartbeat — no event row) ──────────────
|
|
69
|
+
app.patch('/pulse', async (req, reply) => {
|
|
70
|
+
const parsed = pulseSchema.safeParse(req.body);
|
|
71
|
+
if (!parsed.success)
|
|
72
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
73
|
+
const { agentId } = parsed.data;
|
|
74
|
+
db.prepare(`UPDATE coord_agents SET last_seen = datetime('now') WHERE id = ?`).run(agentId);
|
|
75
|
+
return reply.send({ ok: true });
|
|
76
|
+
});
|
|
77
|
+
// ─── Next (combined checkin + commands + assignment poll) ───────
|
|
78
|
+
app.post('/next', async (req, reply) => {
|
|
79
|
+
const parsed = nextSchema.safeParse(req.body);
|
|
80
|
+
if (!parsed.success)
|
|
81
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
82
|
+
const { name, workspace, role, capabilities } = parsed.data;
|
|
83
|
+
const capsJson = capabilities ? JSON.stringify(capabilities) : null;
|
|
84
|
+
// Step 1: Upsert agent (checkin / heartbeat) — including dead agents (reuse UUID)
|
|
85
|
+
const existing = workspace
|
|
86
|
+
? db.prepare(`SELECT id, status FROM coord_agents WHERE name = ? AND workspace = ? ORDER BY last_seen DESC LIMIT 1`).get(name, workspace)
|
|
87
|
+
: db.prepare(`SELECT id, status FROM coord_agents WHERE name = ? AND workspace IS NULL ORDER BY last_seen DESC LIMIT 1`).get(name);
|
|
88
|
+
let agentId;
|
|
89
|
+
if (existing) {
|
|
90
|
+
agentId = existing.id;
|
|
91
|
+
const wasDead = existing.status === 'dead';
|
|
92
|
+
db.prepare(`UPDATE coord_agents SET last_seen = datetime('now'), status = CASE WHEN status = 'dead' THEN 'idle' ELSE status END, capabilities = COALESCE(?, capabilities) WHERE id = ?`).run(capsJson, agentId);
|
|
93
|
+
const eventType = wasDead ? 'reconnected' : 'heartbeat';
|
|
94
|
+
const detail = wasDead ? `${name} reconnected via /next` : `heartbeat from ${name}`;
|
|
95
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, ?, ?)`).run(agentId, eventType, detail);
|
|
96
|
+
if (wasDead)
|
|
97
|
+
coordLog(`${name} reconnected via /next (reusing UUID ${agentId.slice(0, 8)})`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
agentId = randomUUID();
|
|
101
|
+
db.prepare(`INSERT INTO coord_agents (id, name, role, pid, status, metadata, capabilities, workspace) VALUES (?, ?, ?, NULL, 'idle', NULL, ?, ?)`).run(agentId, name, role ?? 'worker', capsJson, workspace ?? null);
|
|
102
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'registered', ?)`).run(agentId, `${name} joined as ${role ?? 'worker'} via /next`);
|
|
103
|
+
coordLog(`${name} registered via /next (${role ?? 'worker'})${capabilities ? ' [' + capabilities.join(', ') + ']' : ''}`);
|
|
104
|
+
}
|
|
105
|
+
// Step 2: Get active commands
|
|
106
|
+
const activeCommands = workspace
|
|
107
|
+
? db.prepare(`SELECT id, command, reason, issued_by, issued_at, workspace
|
|
108
|
+
FROM coord_commands WHERE cleared_at IS NULL AND (workspace = ? OR workspace IS NULL)
|
|
109
|
+
ORDER BY issued_at DESC`).all(workspace)
|
|
110
|
+
: db.prepare(`SELECT id, command, reason, issued_by, issued_at, workspace
|
|
111
|
+
FROM coord_commands WHERE cleared_at IS NULL
|
|
112
|
+
ORDER BY issued_at DESC`).all();
|
|
113
|
+
// Step 3: Get or auto-claim assignment
|
|
114
|
+
let assignment = db.prepare(`SELECT * FROM coord_assignments WHERE agent_id = ? AND status IN ('assigned', 'in_progress') ORDER BY created_at DESC LIMIT 1`).get(agentId);
|
|
115
|
+
if (!assignment) {
|
|
116
|
+
const agentWorkspace = workspace ?? null;
|
|
117
|
+
// Priority-ordered dispatch: higher priority first, then FIFO.
|
|
118
|
+
// Skip assignments blocked by incomplete dependencies.
|
|
119
|
+
const blockedFilter = `AND (blocked_by IS NULL OR blocked_by IN (SELECT id FROM coord_assignments WHERE status = 'completed'))`;
|
|
120
|
+
const pending = agentWorkspace
|
|
121
|
+
? db.prepare(`SELECT * FROM coord_assignments WHERE status = 'pending' AND (workspace = ? OR workspace IS NULL) ${blockedFilter} ORDER BY priority DESC, created_at ASC LIMIT 1`).get(agentWorkspace)
|
|
122
|
+
: db.prepare(`SELECT * FROM coord_assignments WHERE status = 'pending' ${blockedFilter} ORDER BY priority DESC, created_at ASC LIMIT 1`).get();
|
|
123
|
+
if (pending) {
|
|
124
|
+
const claimed = db.prepare(`UPDATE coord_assignments SET agent_id = ?, status = 'assigned', started_at = datetime('now') WHERE id = ? AND status = 'pending'`).run(agentId, pending.id);
|
|
125
|
+
if (claimed.changes > 0) {
|
|
126
|
+
db.prepare(`UPDATE coord_agents SET status = 'working', current_task = ? WHERE id = ?`).run(pending.id, agentId);
|
|
127
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'assignment_claimed', ?)`).run(agentId, `auto-claimed assignment ${pending.id} via /next`);
|
|
128
|
+
assignment = db.prepare(`SELECT * FROM coord_assignments WHERE id = ?`).get(pending.id);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Read current agent status after all mutations
|
|
133
|
+
const agentRow = db.prepare(`SELECT status FROM coord_agents WHERE id = ?`).get(agentId);
|
|
134
|
+
return reply.send({
|
|
135
|
+
agentId,
|
|
136
|
+
status: agentRow.status,
|
|
137
|
+
assignment: assignment ?? null,
|
|
138
|
+
commands: activeCommands,
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
// ─── Assignments ────────────────────────────────────────────────
|
|
142
|
+
app.post('/assign', async (req, reply) => {
|
|
143
|
+
const parsed = assignCreateSchema.safeParse(req.body);
|
|
144
|
+
if (!parsed.success)
|
|
145
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
146
|
+
const { agentId, task, description, workspace, priority, blocked_by } = parsed.data;
|
|
147
|
+
const id = randomUUID();
|
|
148
|
+
db.prepare(`INSERT INTO coord_assignments (id, agent_id, task, description, status, priority, blocked_by, workspace) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(id, agentId ?? null, task, description ?? null, agentId ? 'assigned' : 'pending', priority, blocked_by ?? null, workspace ?? null);
|
|
149
|
+
if (agentId) {
|
|
150
|
+
db.prepare(`UPDATE coord_agents SET status = 'working', current_task = ? WHERE id = ?`).run(id, agentId);
|
|
151
|
+
}
|
|
152
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'assignment_created', ?)`).run(agentId ?? null, `task: ${task}`);
|
|
153
|
+
// Log assignment with agent name
|
|
154
|
+
if (agentId) {
|
|
155
|
+
const agent = db.prepare(`SELECT name FROM coord_agents WHERE id = ?`).get(agentId);
|
|
156
|
+
coordLog(`assigned → ${agent?.name ?? 'unknown'}: ${task.slice(0, 80)}`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
coordLog(`assignment queued (pending): ${task.slice(0, 80)}`);
|
|
160
|
+
}
|
|
161
|
+
return reply.code(201).send({ assignmentId: id, status: agentId ? 'assigned' : 'pending' });
|
|
162
|
+
});
|
|
163
|
+
app.get('/assignment', async (req, reply) => {
|
|
164
|
+
const q = assignmentQuerySchema.parse(req.query);
|
|
165
|
+
let agentId = req.headers['x-agent-id'] ?? q.agentId;
|
|
166
|
+
// Fallback: resolve agentId from name + workspace
|
|
167
|
+
if (!agentId && q.name) {
|
|
168
|
+
const found = q.workspace
|
|
169
|
+
? db.prepare(`SELECT id FROM coord_agents WHERE name = ? AND workspace = ? AND status != 'dead'`).get(q.name, q.workspace)
|
|
170
|
+
: db.prepare(`SELECT id FROM coord_agents WHERE name = ? AND workspace IS NULL AND status != 'dead'`).get(q.name);
|
|
171
|
+
agentId = found?.id;
|
|
172
|
+
}
|
|
173
|
+
if (!agentId) {
|
|
174
|
+
return reply.send({ assignment: null });
|
|
175
|
+
}
|
|
176
|
+
const active = db.prepare(`SELECT * FROM coord_assignments WHERE agent_id = ? AND status IN ('assigned', 'in_progress') ORDER BY created_at DESC LIMIT 1`).get(agentId);
|
|
177
|
+
if (active)
|
|
178
|
+
return reply.send({ assignment: active });
|
|
179
|
+
const agentRow = db.prepare(`SELECT workspace FROM coord_agents WHERE id = ?`).get(agentId);
|
|
180
|
+
const agentWorkspace = agentRow?.workspace;
|
|
181
|
+
const blockedFilter = `AND (blocked_by IS NULL OR blocked_by IN (SELECT id FROM coord_assignments WHERE status = 'completed'))`;
|
|
182
|
+
const pending = agentWorkspace
|
|
183
|
+
? db.prepare(`SELECT * FROM coord_assignments WHERE status = 'pending' AND (workspace = ? OR workspace IS NULL) ${blockedFilter} ORDER BY priority DESC, created_at ASC LIMIT 1`).get(agentWorkspace)
|
|
184
|
+
: db.prepare(`SELECT * FROM coord_assignments WHERE status = 'pending' ${blockedFilter} ORDER BY priority DESC, created_at ASC LIMIT 1`).get();
|
|
185
|
+
if (pending) {
|
|
186
|
+
const claimed = db.prepare(`UPDATE coord_assignments SET agent_id = ?, status = 'assigned', started_at = datetime('now') WHERE id = ? AND status = 'pending'`).run(agentId, pending.id);
|
|
187
|
+
if (claimed.changes > 0) {
|
|
188
|
+
db.prepare(`UPDATE coord_agents SET status = 'working', current_task = ? WHERE id = ?`).run(pending.id, agentId);
|
|
189
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'assignment_claimed', ?)`).run(agentId, `auto-claimed assignment ${pending.id}`);
|
|
190
|
+
const assignment = db.prepare(`SELECT * FROM coord_assignments WHERE id = ?`).get(pending.id);
|
|
191
|
+
return reply.send({ assignment });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const busyCount = db.prepare(`SELECT COUNT(*) as c FROM coord_agents WHERE status = 'working' AND last_seen > datetime('now', '-120 seconds')`).get().c;
|
|
195
|
+
const retryAfter = busyCount > 0 ? 30 : 300;
|
|
196
|
+
return reply.send({ assignment: null, retry_after_seconds: retryAfter });
|
|
197
|
+
});
|
|
198
|
+
app.post('/assignment/:id/claim', async (req, reply) => {
|
|
199
|
+
const { id } = assignmentIdParamSchema.parse(req.params);
|
|
200
|
+
const parsed = assignmentClaimSchema.safeParse(req.body);
|
|
201
|
+
if (!parsed.success)
|
|
202
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
203
|
+
const { agentId } = parsed.data;
|
|
204
|
+
const result = db.prepare(`UPDATE coord_assignments SET agent_id = ?, status = 'assigned', started_at = datetime('now') WHERE id = ? AND status = 'pending'`).run(agentId, id);
|
|
205
|
+
if (result.changes === 0) {
|
|
206
|
+
return reply.code(409).send({ error: 'assignment not available (already claimed or missing)' });
|
|
207
|
+
}
|
|
208
|
+
db.prepare(`UPDATE coord_agents SET status = 'working', current_task = ? WHERE id = ?`).run(id, agentId);
|
|
209
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'assignment_claimed', ?)`).run(agentId, `claimed assignment ${id}`);
|
|
210
|
+
return reply.send({ ok: true, assignmentId: id });
|
|
211
|
+
});
|
|
212
|
+
function handleAssignmentUpdate(id, status, result, commitSha) {
|
|
213
|
+
// Verification gate: completed status requires structured proof of work
|
|
214
|
+
if (status === 'completed') {
|
|
215
|
+
if (!result || result.trim().length < 20) {
|
|
216
|
+
return { error: 'completion requires a result summary — minimum 20 characters describing what was done' };
|
|
217
|
+
}
|
|
218
|
+
// Must mention at least one of: commit/SHA, build, audit, test, verified, fix, created, updated, implemented
|
|
219
|
+
const actionWords = /\b(commit|sha|[0-9a-f]{7,40}|build|audit|test|verified|fix|created|updated|implemented|added|refactored|documented)\b/i;
|
|
220
|
+
if (!actionWords.test(result)) {
|
|
221
|
+
return { error: 'completion result must describe the work done — include what was committed, built, tested, or verified' };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (['completed', 'failed'].includes(status)) {
|
|
225
|
+
db.prepare(`UPDATE coord_assignments SET status = ?, result = ?, commit_sha = ?, completed_at = datetime('now') WHERE id = ?`).run(status, result ?? null, commitSha ?? null, id);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
db.prepare(`UPDATE coord_assignments SET status = ?, result = ? WHERE id = ?`).run(status, result ?? null, id);
|
|
229
|
+
}
|
|
230
|
+
if (['completed', 'failed'].includes(status)) {
|
|
231
|
+
const assignment = db.prepare(`SELECT agent_id FROM coord_assignments WHERE id = ?`).get(id);
|
|
232
|
+
if (assignment?.agent_id) {
|
|
233
|
+
db.prepare(`UPDATE coord_agents SET status = 'idle', current_task = NULL WHERE id = ?`).run(assignment.agent_id);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const eventDetail = ['completed', 'failed'].includes(status)
|
|
237
|
+
? `${id} → ${status}${commitSha ? ' [' + commitSha + ']' : ''}: ${(result ?? '').slice(0, 300)}`
|
|
238
|
+
: `${id} → ${status}`;
|
|
239
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES ((SELECT agent_id FROM coord_assignments WHERE id = ?), 'assignment_update', ?)`).run(id, eventDetail);
|
|
240
|
+
// Log completion/failure with agent name and task
|
|
241
|
+
if (['completed', 'failed'].includes(status)) {
|
|
242
|
+
const info = db.prepare(`SELECT a.task, g.name AS agent_name FROM coord_assignments a LEFT JOIN coord_agents g ON a.agent_id = g.id WHERE a.id = ?`).get(id);
|
|
243
|
+
coordLog(`${info?.agent_name ?? 'unknown'} ${status}: ${info?.task?.slice(0, 80) ?? id}`);
|
|
244
|
+
}
|
|
245
|
+
return {};
|
|
246
|
+
}
|
|
247
|
+
app.get('/assignment/:id', async (req, reply) => {
|
|
248
|
+
const { id } = assignmentIdParamSchema.parse(req.params);
|
|
249
|
+
const assignment = db.prepare(`SELECT a.*, g.name AS agent_name FROM coord_assignments a LEFT JOIN coord_agents g ON a.agent_id = g.id WHERE a.id = ?`).get(id);
|
|
250
|
+
if (!assignment)
|
|
251
|
+
return reply.code(404).send({ error: 'assignment not found' });
|
|
252
|
+
return reply.send({ assignment });
|
|
253
|
+
});
|
|
254
|
+
// List all non-completed assignments with priority and blocked_by status
|
|
255
|
+
app.get('/assignments', async (req, reply) => {
|
|
256
|
+
const assignments = db.prepare(`SELECT a.*, g.name AS agent_name,
|
|
257
|
+
CASE WHEN a.blocked_by IS NOT NULL AND a.blocked_by NOT IN (SELECT id FROM coord_assignments WHERE status = 'completed')
|
|
258
|
+
THEN 1 ELSE 0 END AS is_blocked
|
|
259
|
+
FROM coord_assignments a
|
|
260
|
+
LEFT JOIN coord_agents g ON a.agent_id = g.id
|
|
261
|
+
WHERE a.status NOT IN ('completed', 'failed')
|
|
262
|
+
ORDER BY a.priority DESC, a.created_at ASC`).all();
|
|
263
|
+
return reply.send({ assignments });
|
|
264
|
+
});
|
|
265
|
+
app.post('/assignment/:id/update', async (req, reply) => {
|
|
266
|
+
const { id } = assignmentIdParamSchema.parse(req.params);
|
|
267
|
+
const parsed = assignmentUpdateSchema.safeParse(req.body);
|
|
268
|
+
if (!parsed.success)
|
|
269
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
270
|
+
const gate = handleAssignmentUpdate(id, parsed.data.status, parsed.data.result, parsed.data.commit_sha);
|
|
271
|
+
if (gate.error)
|
|
272
|
+
return reply.code(400).send({ error: gate.error });
|
|
273
|
+
return reply.send({ ok: true });
|
|
274
|
+
});
|
|
275
|
+
app.patch('/assignment/:id', async (req, reply) => {
|
|
276
|
+
const { id } = assignmentIdParamSchema.parse(req.params);
|
|
277
|
+
const parsed = assignmentUpdateSchema.safeParse(req.body);
|
|
278
|
+
if (!parsed.success)
|
|
279
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
280
|
+
const gate = handleAssignmentUpdate(id, parsed.data.status, parsed.data.result, parsed.data.commit_sha);
|
|
281
|
+
if (gate.error)
|
|
282
|
+
return reply.code(400).send({ error: gate.error });
|
|
283
|
+
return reply.send({ ok: true });
|
|
284
|
+
});
|
|
285
|
+
app.put('/assignment/:id', async (req, reply) => {
|
|
286
|
+
const { id } = assignmentIdParamSchema.parse(req.params);
|
|
287
|
+
const parsed = assignmentUpdateSchema.safeParse(req.body);
|
|
288
|
+
if (!parsed.success)
|
|
289
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
290
|
+
const gate = handleAssignmentUpdate(id, parsed.data.status, parsed.data.result, parsed.data.commit_sha);
|
|
291
|
+
if (gate.error)
|
|
292
|
+
return reply.code(400).send({ error: gate.error });
|
|
293
|
+
return reply.send({ ok: true });
|
|
294
|
+
});
|
|
295
|
+
// ─── Locks ──────────────────────────────────────────────────────
|
|
296
|
+
app.post('/lock', async (req, reply) => {
|
|
297
|
+
const parsed = lockAcquireSchema.safeParse(req.body);
|
|
298
|
+
if (!parsed.success)
|
|
299
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
300
|
+
const { agentId, filePath, reason } = parsed.data;
|
|
301
|
+
const inserted = db.prepare(`INSERT OR IGNORE INTO coord_locks (file_path, agent_id, reason) VALUES (?, ?, ?)`).run(filePath, agentId, reason ?? null);
|
|
302
|
+
if (inserted.changes > 0) {
|
|
303
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'lock_acquired', ?)`).run(agentId, filePath);
|
|
304
|
+
return reply.send({ ok: true, action: 'acquired' });
|
|
305
|
+
}
|
|
306
|
+
const existing = db.prepare(`SELECT agent_id FROM coord_locks WHERE file_path = ?`).get(filePath);
|
|
307
|
+
if (existing?.agent_id === agentId) {
|
|
308
|
+
db.prepare(`UPDATE coord_locks SET locked_at = datetime('now') WHERE file_path = ?`).run(filePath);
|
|
309
|
+
return reply.send({ ok: true, action: 'refreshed' });
|
|
310
|
+
}
|
|
311
|
+
return reply.code(409).send({
|
|
312
|
+
error: 'file locked by another agent',
|
|
313
|
+
lockedBy: existing?.agent_id,
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
app.delete('/lock', async (req, reply) => {
|
|
317
|
+
const parsed = lockReleaseSchema.safeParse(req.body);
|
|
318
|
+
if (!parsed.success)
|
|
319
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
320
|
+
const { agentId, filePath } = parsed.data;
|
|
321
|
+
const result = db.prepare(`DELETE FROM coord_locks WHERE file_path = ? AND agent_id = ?`).run(filePath, agentId);
|
|
322
|
+
if (result.changes === 0) {
|
|
323
|
+
return reply.code(404).send({ error: 'lock not found or not owned by this agent' });
|
|
324
|
+
}
|
|
325
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'lock_released', ?)`).run(agentId, filePath);
|
|
326
|
+
return reply.send({ ok: true });
|
|
327
|
+
});
|
|
328
|
+
app.get('/locks', async (_req, reply) => {
|
|
329
|
+
const locks = db.prepare(`SELECT l.file_path, l.agent_id, a.name AS agent_name, l.locked_at, l.reason
|
|
330
|
+
FROM coord_locks l JOIN coord_agents a ON l.agent_id = a.id
|
|
331
|
+
ORDER BY l.locked_at DESC`).all();
|
|
332
|
+
return reply.send({ locks });
|
|
333
|
+
});
|
|
334
|
+
// ─── Commands ───────────────────────────────────────────────────
|
|
335
|
+
app.post('/command', async (req, reply) => {
|
|
336
|
+
const parsed = commandCreateSchema.safeParse(req.body);
|
|
337
|
+
if (!parsed.success)
|
|
338
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
339
|
+
const { command, reason, issuedBy, workspace } = parsed.data;
|
|
340
|
+
if (command === 'RESUME') {
|
|
341
|
+
if (workspace) {
|
|
342
|
+
db.prepare(`UPDATE coord_commands SET cleared_at = datetime('now') WHERE cleared_at IS NULL AND workspace = ?`).run(workspace);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
db.prepare(`UPDATE coord_commands SET cleared_at = datetime('now') WHERE cleared_at IS NULL`).run();
|
|
346
|
+
}
|
|
347
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'command', ?)`).run(issuedBy ?? null, `RESUME${workspace ? ' [' + workspace + ']' : ''} — commands cleared`);
|
|
348
|
+
return reply.send({ ok: true, command: 'RESUME', workspace, message: workspace ? `commands cleared for ${workspace}` : 'all active commands cleared' });
|
|
349
|
+
}
|
|
350
|
+
db.prepare(`INSERT INTO coord_commands (command, reason, issued_by, workspace) VALUES (?, ?, ?, ?)`).run(command, reason ?? null, issuedBy ?? null, workspace ?? null);
|
|
351
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'command', ?)`).run(issuedBy ?? null, `${command}${workspace ? ' [' + workspace + ']' : ''}: ${reason ?? 'no reason given'}`);
|
|
352
|
+
coordLog(`COMMAND: ${command}${reason ? ' — ' + reason : ''}`);
|
|
353
|
+
return reply.code(201).send({ ok: true, command, reason, workspace });
|
|
354
|
+
});
|
|
355
|
+
app.get('/command', async (req, reply) => {
|
|
356
|
+
const workspace = req.query.workspace;
|
|
357
|
+
const active = workspace
|
|
358
|
+
? db.prepare(`SELECT id, command, reason, issued_by, issued_at, workspace
|
|
359
|
+
FROM coord_commands WHERE cleared_at IS NULL AND (workspace = ? OR workspace IS NULL)
|
|
360
|
+
ORDER BY issued_at DESC`).all(workspace)
|
|
361
|
+
: db.prepare(`SELECT id, command, reason, issued_by, issued_at, workspace
|
|
362
|
+
FROM coord_commands WHERE cleared_at IS NULL
|
|
363
|
+
ORDER BY issued_at DESC`).all();
|
|
364
|
+
if (active.length === 0) {
|
|
365
|
+
return reply.send({ active: false, commands: [] });
|
|
366
|
+
}
|
|
367
|
+
const priority = { SHUTDOWN: 3, BUILD_FREEZE: 2, PAUSE: 1 };
|
|
368
|
+
active.sort((a, b) => (priority[b.command] ?? 0) - (priority[a.command] ?? 0));
|
|
369
|
+
return reply.send({
|
|
370
|
+
active: true,
|
|
371
|
+
command: active[0].command,
|
|
372
|
+
reason: active[0].reason,
|
|
373
|
+
issued_at: active[0].issued_at,
|
|
374
|
+
commands: active,
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
app.get('/command/wait', async (req, reply) => {
|
|
378
|
+
const q = commandWaitQuerySchema.safeParse(req.query);
|
|
379
|
+
const { status: targetStatus, workspace } = q.success ? q.data : { status: 'idle', workspace: undefined };
|
|
380
|
+
const agents = workspace
|
|
381
|
+
? db.prepare(`SELECT id, name, role, status, current_task, last_seen
|
|
382
|
+
FROM coord_agents WHERE status NOT IN ('dead') AND workspace = ?
|
|
383
|
+
ORDER BY name`).all(workspace)
|
|
384
|
+
: db.prepare(`SELECT id, name, role, status, current_task, last_seen
|
|
385
|
+
FROM coord_agents WHERE status NOT IN ('dead')
|
|
386
|
+
ORDER BY name`).all();
|
|
387
|
+
const ready = agents.filter(a => a.status === targetStatus || a.role === 'orchestrator');
|
|
388
|
+
const notReady = agents.filter(a => a.status !== targetStatus && a.role !== 'orchestrator');
|
|
389
|
+
return reply.send({
|
|
390
|
+
allReady: notReady.length === 0,
|
|
391
|
+
total: agents.length,
|
|
392
|
+
ready: ready.map(a => ({ name: a.name, status: a.status })),
|
|
393
|
+
waiting: notReady.map(a => ({ name: a.name, status: a.status, task: a.current_task })),
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
// ─── Findings ───────────────────────────────────────────────────
|
|
397
|
+
app.post('/finding', async (req, reply) => {
|
|
398
|
+
const parsed = findingCreateSchema.safeParse(req.body);
|
|
399
|
+
if (!parsed.success)
|
|
400
|
+
return reply.code(400).send({ error: parsed.error.issues[0].message });
|
|
401
|
+
const { agentId, category, severity, filePath, lineNumber, description, suggestion } = parsed.data;
|
|
402
|
+
db.prepare(`INSERT INTO coord_findings (agent_id, category, severity, file_path, line_number, description, suggestion)
|
|
403
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`).run(agentId, category, severity ?? 'info', filePath ?? null, lineNumber ?? null, description, suggestion ?? null);
|
|
404
|
+
db.prepare(`INSERT INTO coord_events (agent_id, event_type, detail) VALUES (?, 'finding', ?)`).run(agentId, `[${severity ?? 'info'}] ${category}: ${description.slice(0, 100)}`);
|
|
405
|
+
return reply.code(201).send({ ok: true });
|
|
406
|
+
});
|
|
407
|
+
app.get('/findings', async (req, reply) => {
|
|
408
|
+
const q = findingsQuerySchema.safeParse(req.query);
|
|
409
|
+
const { category, severity, status, limit } = q.success ? q.data : { category: undefined, severity: undefined, status: undefined, limit: 50 };
|
|
410
|
+
let sql = `
|
|
411
|
+
SELECT f.id, f.category, f.severity, f.file_path, f.line_number,
|
|
412
|
+
f.description, f.suggestion, f.status, f.created_at,
|
|
413
|
+
a.name AS agent_name
|
|
414
|
+
FROM coord_findings f JOIN coord_agents a ON f.agent_id = a.id
|
|
415
|
+
WHERE 1=1
|
|
416
|
+
`;
|
|
417
|
+
const params = [];
|
|
418
|
+
if (category) {
|
|
419
|
+
sql += ` AND f.category = ?`;
|
|
420
|
+
params.push(category);
|
|
421
|
+
}
|
|
422
|
+
if (severity) {
|
|
423
|
+
sql += ` AND f.severity = ?`;
|
|
424
|
+
params.push(severity);
|
|
425
|
+
}
|
|
426
|
+
if (status) {
|
|
427
|
+
sql += ` AND f.status = ?`;
|
|
428
|
+
params.push(status);
|
|
429
|
+
}
|
|
430
|
+
sql += ` ORDER BY
|
|
431
|
+
CASE f.severity WHEN 'critical' THEN 0 WHEN 'error' THEN 1 WHEN 'warn' THEN 2 ELSE 3 END,
|
|
432
|
+
f.created_at DESC
|
|
433
|
+
LIMIT ?`;
|
|
434
|
+
params.push(limit);
|
|
435
|
+
const findings = db.prepare(sql).all(...params);
|
|
436
|
+
const stats = db.prepare(`SELECT severity, COUNT(*) as count FROM coord_findings WHERE status = 'open' GROUP BY severity`).all();
|
|
437
|
+
return reply.send({ findings, stats });
|
|
438
|
+
});
|
|
439
|
+
app.post('/finding/:id/resolve', async (req, reply) => {
|
|
440
|
+
const { id } = findingIdParamSchema.parse(req.params);
|
|
441
|
+
db.prepare(`UPDATE coord_findings SET status = 'resolved', resolved_at = datetime('now') WHERE id = ?`).run(id);
|
|
442
|
+
return reply.send({ ok: true });
|
|
443
|
+
});
|
|
444
|
+
app.get('/findings/summary', async (_req, reply) => {
|
|
445
|
+
const bySeverity = db.prepare(`SELECT severity, COUNT(*) as count FROM coord_findings WHERE status = 'open' GROUP BY severity`).all();
|
|
446
|
+
const byCategory = db.prepare(`SELECT category, COUNT(*) as count FROM coord_findings WHERE status = 'open' GROUP BY category ORDER BY count DESC`).all();
|
|
447
|
+
const total = db.prepare(`SELECT COUNT(*) as total FROM coord_findings WHERE status = 'open'`).get();
|
|
448
|
+
return reply.send({ total: total.total, bySeverity, byCategory });
|
|
449
|
+
});
|
|
450
|
+
// ─── Decisions (cross-agent propagation) ────────────────────────
|
|
451
|
+
app.get('/decisions', async (req, reply) => {
|
|
452
|
+
const q = decisionsQuerySchema.safeParse(req.query);
|
|
453
|
+
const { since_id, assignment_id, limit } = q.success ? q.data : { since_id: 0, assignment_id: undefined, limit: 20 };
|
|
454
|
+
let sql = `
|
|
455
|
+
SELECT d.id, d.author_id, a.name AS author_name, d.assignment_id, d.tags, d.summary, d.created_at
|
|
456
|
+
FROM coord_decisions d JOIN coord_agents a ON d.author_id = a.id
|
|
457
|
+
WHERE d.id > ?
|
|
458
|
+
`;
|
|
459
|
+
const params = [since_id];
|
|
460
|
+
if (assignment_id) {
|
|
461
|
+
sql += ` AND d.assignment_id = ?`;
|
|
462
|
+
params.push(assignment_id);
|
|
463
|
+
}
|
|
464
|
+
sql += ` ORDER BY d.created_at ASC LIMIT ?`;
|
|
465
|
+
params.push(limit);
|
|
466
|
+
const decisions = db.prepare(sql).all(...params);
|
|
467
|
+
return reply.send({ decisions });
|
|
468
|
+
});
|
|
469
|
+
// ─── Status ─────────────────────────────────────────────────────
|
|
470
|
+
app.get('/status', async (_req, reply) => {
|
|
471
|
+
const agents = db.prepare(`SELECT id, name, role, status, current_task, last_seen,
|
|
472
|
+
ROUND((julianday('now') - julianday(last_seen)) * 86400) AS seconds_since_seen
|
|
473
|
+
FROM coord_agents WHERE status != 'dead'
|
|
474
|
+
ORDER BY role, name`).all();
|
|
475
|
+
const assignments = db.prepare(`SELECT a.id, a.task, a.description, a.status, a.agent_id, ag.name AS agent_name,
|
|
476
|
+
a.created_at, a.started_at, a.completed_at
|
|
477
|
+
FROM coord_assignments a LEFT JOIN coord_agents ag ON a.agent_id = ag.id
|
|
478
|
+
WHERE a.status NOT IN ('completed', 'failed')
|
|
479
|
+
ORDER BY a.created_at`).all();
|
|
480
|
+
const locks = db.prepare(`SELECT l.file_path, l.agent_id, a.name AS agent_name, l.locked_at, l.reason
|
|
481
|
+
FROM coord_locks l JOIN coord_agents a ON l.agent_id = a.id`).all();
|
|
482
|
+
const stats = db.prepare(`SELECT
|
|
483
|
+
(SELECT COUNT(*) FROM coord_agents WHERE status != 'dead') AS alive_agents,
|
|
484
|
+
(SELECT COUNT(*) FROM coord_agents WHERE status = 'working') AS busy_agents,
|
|
485
|
+
(SELECT COUNT(*) FROM coord_assignments WHERE status = 'pending') AS pending_tasks,
|
|
486
|
+
(SELECT COUNT(*) FROM coord_assignments WHERE status IN ('assigned', 'in_progress')) AS active_tasks,
|
|
487
|
+
(SELECT COUNT(*) FROM coord_locks) AS active_locks,
|
|
488
|
+
(SELECT COUNT(*) FROM coord_findings WHERE status = 'open') AS open_findings,
|
|
489
|
+
(SELECT COUNT(*) FROM coord_findings WHERE status = 'open' AND severity IN ('critical', 'error')) AS urgent_findings`).get();
|
|
490
|
+
const recentFindings = db.prepare(`SELECT f.id, f.category, f.severity, f.file_path, f.description, a.name AS agent_name, f.created_at
|
|
491
|
+
FROM coord_findings f JOIN coord_agents a ON f.agent_id = a.id
|
|
492
|
+
WHERE f.status = 'open'
|
|
493
|
+
ORDER BY CASE f.severity WHEN 'critical' THEN 0 WHEN 'error' THEN 1 WHEN 'warn' THEN 2 ELSE 3 END,
|
|
494
|
+
f.created_at DESC
|
|
495
|
+
LIMIT 10`).all();
|
|
496
|
+
return reply.send({ agents, assignments, locks, stats, recentFindings });
|
|
497
|
+
});
|
|
498
|
+
app.get('/workers', async (req, reply) => {
|
|
499
|
+
const q = workersQuerySchema.safeParse(req.query);
|
|
500
|
+
const { capability, status: filterStatus, workspace } = q.success ? q.data : { capability: undefined, status: undefined, workspace: undefined };
|
|
501
|
+
let workers = workspace
|
|
502
|
+
? db.prepare(`SELECT id, name, role, status, current_task, capabilities, workspace, last_seen,
|
|
503
|
+
ROUND((julianday('now') - julianday(last_seen)) * 86400) AS seconds_since_seen
|
|
504
|
+
FROM coord_agents
|
|
505
|
+
WHERE status != 'dead' AND role != 'orchestrator' AND workspace = ?
|
|
506
|
+
ORDER BY name`).all(workspace)
|
|
507
|
+
: db.prepare(`SELECT id, name, role, status, current_task, capabilities, workspace, last_seen,
|
|
508
|
+
ROUND((julianday('now') - julianday(last_seen)) * 86400) AS seconds_since_seen
|
|
509
|
+
FROM coord_agents
|
|
510
|
+
WHERE status != 'dead' AND role != 'orchestrator'
|
|
511
|
+
ORDER BY name`).all();
|
|
512
|
+
if (capability) {
|
|
513
|
+
workers = workers.filter(w => {
|
|
514
|
+
if (!w.capabilities)
|
|
515
|
+
return false;
|
|
516
|
+
try {
|
|
517
|
+
const caps = JSON.parse(w.capabilities);
|
|
518
|
+
return caps.includes(capability);
|
|
519
|
+
}
|
|
520
|
+
catch {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
if (filterStatus) {
|
|
526
|
+
workers = workers.filter(w => w.status === filterStatus);
|
|
527
|
+
}
|
|
528
|
+
const result = workers.map(w => ({
|
|
529
|
+
id: w.id,
|
|
530
|
+
name: w.name,
|
|
531
|
+
role: w.role,
|
|
532
|
+
status: w.status,
|
|
533
|
+
currentTask: w.current_task,
|
|
534
|
+
capabilities: w.capabilities ? JSON.parse(w.capabilities) : [],
|
|
535
|
+
workspace: w.workspace,
|
|
536
|
+
lastSeen: w.last_seen,
|
|
537
|
+
secondsSinceSeen: w.seconds_since_seen,
|
|
538
|
+
alive: w.seconds_since_seen < 120,
|
|
539
|
+
}));
|
|
540
|
+
return reply.send({
|
|
541
|
+
count: result.length,
|
|
542
|
+
idle: result.filter(w => w.status === 'idle').length,
|
|
543
|
+
working: result.filter(w => w.status === 'working').length,
|
|
544
|
+
workers: result,
|
|
545
|
+
});
|
|
546
|
+
});
|
|
547
|
+
app.get('/events', async (req, reply) => {
|
|
548
|
+
const q = eventsQuerySchema.safeParse(req.query);
|
|
549
|
+
const limit = q.success ? q.data.limit : 50;
|
|
550
|
+
const events = db.prepare(`SELECT e.id, e.agent_id, a.name AS agent_name, e.event_type, e.detail, e.created_at
|
|
551
|
+
FROM coord_events e LEFT JOIN coord_agents a ON e.agent_id = a.id
|
|
552
|
+
ORDER BY e.created_at DESC LIMIT ?`).all(limit);
|
|
553
|
+
return reply.send({ events });
|
|
554
|
+
});
|
|
555
|
+
app.get('/stale', async (req, reply) => {
|
|
556
|
+
const q = staleQuerySchema.safeParse(req.query);
|
|
557
|
+
const threshold = q.success ? q.data.seconds : 120;
|
|
558
|
+
const cleanup = q.success ? q.data.cleanup : undefined;
|
|
559
|
+
const stale = detectStale(db, threshold);
|
|
560
|
+
if (cleanup === '1' || cleanup === 'true') {
|
|
561
|
+
const { cleaned } = cleanupStale(db, threshold);
|
|
562
|
+
return reply.send({ stale, threshold_seconds: threshold, cleaned });
|
|
563
|
+
}
|
|
564
|
+
return reply.send({ stale, threshold_seconds: threshold });
|
|
565
|
+
});
|
|
566
|
+
app.post('/stale/cleanup', async (req, reply) => {
|
|
567
|
+
const q = staleQuerySchema.safeParse(req.query);
|
|
568
|
+
const threshold = q.success ? q.data.seconds : 120;
|
|
569
|
+
const { stale, cleaned } = cleanupStale(db, threshold);
|
|
570
|
+
return reply.send({ stale, threshold_seconds: threshold, cleaned });
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/coordination/routes.ts"],"names":[],"mappings":"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"}
|