fix(hub): dormant ≠ beschäftigt — arbeitende Agenten nicht mehr als tot melden
`dormantAgents` filterte auf `!inLoop`. `inLoop` ist aber immer false, solange
ein Agent einen Task AUSFÜHRT — dadurch meldete der Pulse jeden hart
arbeitenden Agenten als dormant. Live gesehen: codex mit 17 s altem Check-in
stand als dormant im Pulse. Genau das Signal, auf das sich der Architekt
verlassen soll, hätte ihn dazu gebracht, funktionierende Agenten anzustoßen.
Jetzt zwei getrennte Fälle:
- `loopExitReason` gesetzt → der Agent hat den Loop ausdrücklich verlassen
und hört nicht mehr zu: sofort melden (unverändert).
- kein Exit-Grund, aber Task in Arbeit → er führt aus; erst nach
DORMANT_AFTER_MS (5 min) ohne Check-in ist das mein Fall.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5fb2b6d6c6
commit
7a4ccaeb61
@ -22,6 +22,15 @@ import { VERSION } from '../../version.js';
|
||||
export const ACTIVE_WINDOW_MS = 2 * 60_000;
|
||||
/** Longer than this without any action ⇒ the agent is stale/offline. */
|
||||
export const STALE_WINDOW_MS = 10 * 60_000;
|
||||
/**
|
||||
* Ab wann gilt ein Agent als DORMANT (der Architekt muss eingreifen)?
|
||||
*
|
||||
* `inLoop` allein taugt dafür NICHT: es ist false, sobald ein Agent einen Task
|
||||
* ausführt — ein hart arbeitender Agent sähe damit genauso aus wie ein toter.
|
||||
* Entscheidend ist, wie lange der letzte Check-in her ist. Alles darunter ist
|
||||
* normale Arbeit und darf keinen Alarm auslösen.
|
||||
*/
|
||||
export const DORMANT_AFTER_MS = 5 * 60_000;
|
||||
|
||||
export type AgentLight = 'active' | 'busy' | 'idle' | 'stale';
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import { getStatus, updateStatus } from '../core/services/statusService.js';
|
||||
import { autoDelegate, suggestDelegation } from '../core/services/delegateService.js';
|
||||
import { computeBudget } from '../core/services/budgetService.js';
|
||||
import { getRoster } from '../core/services/rosterService.js';
|
||||
import { computeHealth, enterLoop, leaveLoop, stampSeen } from '../core/services/presenceService.js';
|
||||
import { computeHealth, enterLoop, leaveLoop, stampSeen, DORMANT_AFTER_MS } from '../core/services/presenceService.js';
|
||||
import { resolvePending, hasPending } from '../core/services/checkinService.js';
|
||||
import { loadConfig, saveConfig } from '../core/config.js';
|
||||
import { agentIdentity } from '../core/services/identityService.js';
|
||||
@ -96,8 +96,23 @@ export async function registerRoutes(app: FastifyInstance, cwd: string): Promise
|
||||
assignedTo: task.assignedTo,
|
||||
updatedAt: task.updatedAt,
|
||||
})),
|
||||
// Zwei verschiedene Zustände, die nicht gleich behandelt werden dürfen:
|
||||
//
|
||||
// a) `loopExitReason` gesetzt → der Agent hat den Loop AUSDRÜCKLICH
|
||||
// verlassen ("turn ended"). Er hört ab sofort nicht mehr zu; ein
|
||||
// Reopen erreicht ihn nie. Sofort melden, ohne Wartezeit.
|
||||
// b) kein Exit-Grund, aber ein Task in Arbeit → der Agent FÜHRT gerade
|
||||
// aus. `inLoop` ist dabei immer false; ohne Zeitbedingung wäre jeder
|
||||
// hart arbeitende Agent "dormant" und der Architekt würde Leute
|
||||
// anstoßen, die einwandfrei laufen. Erst nach DORMANT_AFTER_MS ohne
|
||||
// Check-in ist das ein Fall für mich.
|
||||
dormantAgents: health.agents
|
||||
.filter((agent) => !agent.inLoop && (agent.taskId || agent.loopExitReason))
|
||||
.filter((agent) => {
|
||||
if (agent.inLoop) return false;
|
||||
if (agent.loopExitReason) return true;
|
||||
if (!agent.taskId) return false;
|
||||
return agent.lastSeenAgoSec === undefined || agent.lastSeenAgoSec * 1000 >= DORMANT_AFTER_MS;
|
||||
})
|
||||
.map((agent) => ({
|
||||
name: agent.name,
|
||||
taskId: agent.taskId,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user