@yemi33/minions 0.1.764 → 0.1.766
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/CHANGELOG.md +8 -0
- package/dashboard.js +61 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dashboard.js
CHANGED
|
@@ -1459,6 +1459,66 @@ const server = http.createServer(async (req, res) => {
|
|
|
1459
1459
|
} catch (e) { return jsonReply(res, 400, { error: e.message }); }
|
|
1460
1460
|
}
|
|
1461
1461
|
|
|
1462
|
+
async function handleAgentKill(req, res, match) {
|
|
1463
|
+
try {
|
|
1464
|
+
const agentId = match[1].replace(/[^a-zA-Z0-9_-]/g, '');
|
|
1465
|
+
if (!agentId) return jsonReply(res, 400, { error: 'agent id required' });
|
|
1466
|
+
|
|
1467
|
+
const agentDir = path.join(MINIONS_DIR, 'agents', agentId);
|
|
1468
|
+
if (!fs.existsSync(agentDir)) return jsonReply(res, 404, { error: 'Agent not found' });
|
|
1469
|
+
|
|
1470
|
+
// 1. Kill process via pid file
|
|
1471
|
+
const pidPath = path.join(agentDir, 'pid');
|
|
1472
|
+
try {
|
|
1473
|
+
const pid = parseInt(shared.safeRead(pidPath) || '', 10);
|
|
1474
|
+
if (pid) {
|
|
1475
|
+
shared.validatePid(pid); // throws if not numeric
|
|
1476
|
+
shared.killGracefully({ pid }, 3000);
|
|
1477
|
+
}
|
|
1478
|
+
} catch { /* process already dead or no pid file */ }
|
|
1479
|
+
try { fs.unlinkSync(pidPath); } catch { /* optional */ }
|
|
1480
|
+
|
|
1481
|
+
// 2. Clear session.json and steer.md so retry starts fresh
|
|
1482
|
+
try { fs.unlinkSync(path.join(agentDir, 'session.json')); } catch { /* optional */ }
|
|
1483
|
+
try { fs.unlinkSync(path.join(agentDir, 'steer.md')); } catch { /* optional */ }
|
|
1484
|
+
|
|
1485
|
+
// 3. Remove all active dispatch entries for this agent
|
|
1486
|
+
const dispatchPath = path.join(MINIONS_DIR, 'engine', 'dispatch.json');
|
|
1487
|
+
const removedIds = [];
|
|
1488
|
+
mutateJsonFileLocked(dispatchPath, (dp) => {
|
|
1489
|
+
const removed = (dp.active || []).filter(d => d.agent === agentId);
|
|
1490
|
+
removed.forEach(d => removedIds.push(d.id));
|
|
1491
|
+
dp.active = (dp.active || []).filter(d => d.agent !== agentId);
|
|
1492
|
+
return dp;
|
|
1493
|
+
}, { defaultValue: { pending: [], active: [], completed: [] } });
|
|
1494
|
+
|
|
1495
|
+
// 4. Reset work items from dispatched → pending so they can be retried
|
|
1496
|
+
const allWiPaths = [];
|
|
1497
|
+
for (const proj of PROJECTS) allWiPaths.push(shared.projectWorkItemsPath(proj));
|
|
1498
|
+
let resetCount = 0;
|
|
1499
|
+
for (const wiPath of allWiPaths) {
|
|
1500
|
+
try {
|
|
1501
|
+
mutateWorkItems(wiPath, items => {
|
|
1502
|
+
for (const item of items) {
|
|
1503
|
+
if (item.dispatched_to === agentId && item.status === WI_STATUS.DISPATCHED) {
|
|
1504
|
+
item.status = WI_STATUS.PENDING;
|
|
1505
|
+
item._retryCount = (item._retryCount || 0) + 1;
|
|
1506
|
+
delete item.dispatched_at;
|
|
1507
|
+
delete item.dispatched_to;
|
|
1508
|
+
delete item._pendingReason;
|
|
1509
|
+
resetCount++;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
return items;
|
|
1513
|
+
});
|
|
1514
|
+
} catch { /* optional */ }
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
invalidateStatusCache();
|
|
1518
|
+
return jsonReply(res, 200, { ok: true, agent: agentId, dispatchCleared: removedIds.length, workItemsReset: resetCount });
|
|
1519
|
+
} catch (e) { return jsonReply(res, 400, { error: e.message }); }
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1462
1522
|
async function handleAgentsCancel(req, res) {
|
|
1463
1523
|
try {
|
|
1464
1524
|
const body = await readBody(req);
|
|
@@ -4027,6 +4087,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
4027
4087
|
return jsonReply(res, 200, { ok: true, message: 'Steering message sent' });
|
|
4028
4088
|
}},
|
|
4029
4089
|
{ method: 'POST', path: '/api/agents/cancel', desc: 'Cancel an active agent by ID or task substring', params: 'agent?, task?', handler: handleAgentsCancel },
|
|
4090
|
+
{ method: 'POST', path: /^\/api\/agent\/([\w-]+)\/kill$/, desc: 'Kill a running agent: stop process, clear dispatch, reset work items to pending', handler: handleAgentKill },
|
|
4030
4091
|
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)\/live-stream(?:\?.*)?$/, desc: 'SSE real-time live output streaming', handler: handleAgentLiveStream },
|
|
4031
4092
|
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)\/live(?:\?.*)?$/, desc: 'Tail live output for a working agent', params: 'tail? (bytes, default 8192)', handler: handleAgentLive },
|
|
4032
4093
|
{ method: 'GET', path: /^\/api\/agent\/([\w-]+)\/output(?:\?.*)?$/, desc: 'Fetch final output.log for an agent', handler: handleAgentOutput },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.766",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|