@yemi33/minions 0.1.2229 → 0.1.2230
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/dashboard.js +20 -1
- package/engine/dispatch-events.js +40 -0
- package/package.json +1 -1
package/dashboard.js
CHANGED
|
@@ -6965,9 +6965,28 @@ const server = http.createServer(async (req, res) => {
|
|
|
6965
6965
|
// Replay-on-connect: if a terminal event for this agent landed within
|
|
6966
6966
|
// the ring's TTL, push it immediately so a viewer who opens the live
|
|
6967
6967
|
// view AFTER completion still sees the verdict.
|
|
6968
|
+
//
|
|
6969
|
+
// W-mqprx2px00076668 — but a STALE terminal failure must not be replayed
|
|
6970
|
+
// as the active blocking banner when the agent has since started a newer
|
|
6971
|
+
// dispatch (e.g. a successful retry of the same work item). Gate the
|
|
6972
|
+
// replay on the agent's live dispatch state: suppress the failure banner
|
|
6973
|
+
// when the agent is actively working a different (newer) dispatch than the
|
|
6974
|
+
// one that produced the event. History is preserved — the raw event still
|
|
6975
|
+
// lives in the JSONL ring and the WI/event history; only the prominent
|
|
6976
|
+
// active-agent banner is gated.
|
|
6968
6977
|
try {
|
|
6969
6978
|
const recent = dispatchEvents.getLastTerminalForAgent(agentId);
|
|
6970
|
-
if (recent)
|
|
6979
|
+
if (recent) {
|
|
6980
|
+
let agentStatus = null;
|
|
6981
|
+
try { agentStatus = queries.getAgentStatus(agentId); } catch { agentStatus = null; }
|
|
6982
|
+
if (dispatchEvents.isStaleTerminalForActiveDispatch(recent, agentStatus)) {
|
|
6983
|
+
// Mark as already-handled so a later file-rotation rewind in the
|
|
6984
|
+
// terminal watcher cannot re-broadcast this suppressed stale banner.
|
|
6985
|
+
if (recent.dispatchId) _sentTerminalDispatchIds.add(recent.dispatchId);
|
|
6986
|
+
} else {
|
|
6987
|
+
sendTerminalEvent(recent);
|
|
6988
|
+
}
|
|
6989
|
+
}
|
|
6971
6990
|
} catch { /* best-effort replay */ }
|
|
6972
6991
|
|
|
6973
6992
|
const eventsFile = dispatchEvents._eventsFile();
|
|
@@ -141,6 +141,45 @@ function getLastTerminalForAgent(agentId) {
|
|
|
141
141
|
return null;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* W-mqprx2px00076668 — gate a terminal-FAILURE banner against the agent's
|
|
146
|
+
* live dispatch state. A stale terminal failure (result !== 'success', e.g.
|
|
147
|
+
* `error` / `timeout`) MUST NOT be surfaced as the active blocking banner
|
|
148
|
+
* once the SAME agent is actively working a NEWER dispatch than the one that
|
|
149
|
+
* produced the event. The active-dispatch state wins over any older terminal
|
|
150
|
+
* error whose `dispatchId` is not the agent's current dispatch.
|
|
151
|
+
*
|
|
152
|
+
* This is a GENERIC rule across all failureClasses — keyed solely on "does
|
|
153
|
+
* this terminal event belong to the agent's CURRENT dispatch?" — not a
|
|
154
|
+
* special-case for any one failureClass. Pure (no I/O): the caller passes the
|
|
155
|
+
* agent's status snapshot so the predicate stays unit-testable and reusable
|
|
156
|
+
* by both the dashboard replay-on-connect path and the client renderer.
|
|
157
|
+
*
|
|
158
|
+
* Returns true when the event should be suppressed as the active banner.
|
|
159
|
+
* Does NOT delete history — the raw event still lives in the JSONL ring and
|
|
160
|
+
* the WI/event history; only the prominent active-agent banner is gated.
|
|
161
|
+
*
|
|
162
|
+
* @param {object} event - dispatch.terminal event ({ result, dispatchId, ... }).
|
|
163
|
+
* @param {object} agentStatus - agent status snapshot, e.g. the
|
|
164
|
+
* `{ status, dispatch_id }` shape returned by queries.getAgentStatus().
|
|
165
|
+
* @returns {boolean}
|
|
166
|
+
*/
|
|
167
|
+
function isStaleTerminalForActiveDispatch(event, agentStatus) {
|
|
168
|
+
if (!event || !event.dispatchId) return false;
|
|
169
|
+
// Success banners never imply the run is blocked — leave them to the
|
|
170
|
+
// dispatch.started clear path. Only failure/timeout banners are gated.
|
|
171
|
+
if (event.result === 'success') return false;
|
|
172
|
+
// No active work → keep the failure banner. An agent that is genuinely
|
|
173
|
+
// idle (or in the post-completion `error`/`done` window) after a terminal
|
|
174
|
+
// failure STILL shows its banner; don't over-suppress.
|
|
175
|
+
if (!agentStatus || agentStatus.status !== 'working') return false;
|
|
176
|
+
const current = agentStatus.dispatch_id || null;
|
|
177
|
+
if (!current) return false;
|
|
178
|
+
// Agent is actively working a DIFFERENT (newer) dispatch than the one that
|
|
179
|
+
// produced this terminal failure → suppress it as the active banner.
|
|
180
|
+
return current !== event.dispatchId;
|
|
181
|
+
}
|
|
182
|
+
|
|
144
183
|
|
|
145
184
|
/**
|
|
146
185
|
* Build the terminal event payload from a freshly-completed dispatch entry +
|
|
@@ -237,6 +276,7 @@ module.exports = {
|
|
|
237
276
|
onDispatchTerminal,
|
|
238
277
|
readRecentEvents,
|
|
239
278
|
getLastTerminalForAgent,
|
|
279
|
+
isStaleTerminalForActiveDispatch,
|
|
240
280
|
buildTerminalEvent,
|
|
241
281
|
// dispatch.started (W-mq1m1wo5000nd78d)
|
|
242
282
|
emitDispatchStarted,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2230",
|
|
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"
|