Supervise several agents at once
One daemon already saw every session; the dashboard only ever showed one of them well. Under four parallel agents it failed in specific ways, each fixed here: - Sessions were identified by workspace basename, so two agents in one repo were indistinguishable. The daemon now hands out a small ordinal badge in arrival order and the web UI colours each agent by it — rows, timeline lines, and approval cards, which previously asked you to approve `rm -rf` "in remote-grok" without saying which one. - `currentTool` held a single call, so parallel tools overwrote each other. It is now a list; durations are matched FIFO per tool name, since hook payloads carry no call id. - One 400-event ring, evicted oldest-first, let a chatty agent blank everyone else's history. Eviction now takes from whichever session holds the most of the ring. - Sessions sorted by recency jumped under a moving thumb. They are ordered waiting -> error -> working -> idle -> ended, ties on badge, so an agent keeps its slot. - Events carry no workspace root, so a restart came back with a full timeline and an empty roster. The session map is persisted to sessions.json (debounced, flushed on shutdown, 12h cutoff on load). In-flight tools are dropped on the way out: they belonged to a process that no longer exists. - Snapshot pushes now back off to 1s once a snapshot exceeds 24KB, since full-snapshot SSE cost scales with agent count. - Pending approvals are ordered by which expires first, not by arrival. `glance status` and /local/status report the roster by state. e2e suite: 220 passed, 0 failed.
This commit is contained in:
+17
-1
@@ -59,6 +59,22 @@ async function api(pathname, { method = "GET", body, admin = false } = {}) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/** "3 (2 working, 1 waiting on you)" — a raw count says nothing when you watch several agents. */
|
||||
function sessionBreakdown(states) {
|
||||
if (!states || typeof states !== "object") return "";
|
||||
const order = [
|
||||
["waiting", "waiting on you"],
|
||||
["error", "error"],
|
||||
["working", "working"],
|
||||
["idle", "idle"],
|
||||
["ended", "ended"],
|
||||
];
|
||||
const parts = order
|
||||
.filter(([key]) => Number(states[key]) > 0)
|
||||
.map(([key, label]) => `${states[key]} ${label}`);
|
||||
return parts.length ? ` (${parts.join(", ")})` : "";
|
||||
}
|
||||
|
||||
function requireBuild() {
|
||||
if (!fs.existsSync(SERVER_ENTRY)) {
|
||||
console.error(`grok-glance is not built yet.\n\n cd ${PLUGIN_ROOT}\n npm install && npm run build\n`);
|
||||
@@ -122,7 +138,7 @@ switch (cmd) {
|
||||
console.log(` devices : ${s.devices}`);
|
||||
console.log(` approval mode : ${s.approval.mode}`);
|
||||
console.log(` watchers : ${s.watchers}`);
|
||||
console.log(` sessions : ${s.sessions}`);
|
||||
console.log(` sessions : ${s.sessions}${sessionBreakdown(s.sessionStates)}`);
|
||||
console.log(` events kept : ${s.events}`);
|
||||
if (s.hookAuthOk === false) {
|
||||
console.log(
|
||||
|
||||
Reference in New Issue
Block a user