refactor(agents): remove terminated AgentState; collapse to paused/error
Drops "terminated" from AGENT_STATES. The agent lifecycle now runs through idle | active | running | paused | error. paused (carrying a pauseReason) absorbs every former terminated use case — manual stop, heartbeat run termination, spawned-child cleanup. Run status (agentRuns.status) is unchanged: "terminated" stays a valid run-status value. AGENT_VALID_TRANSITIONS allows direct any→idle transitions so resetAgent no longer needs the intermediate hop. Stack-wide: - core/agent-store: lastError clearing + resetAgent simplified. - engine/agent-heartbeat, executor, in-process-runtime: terminated state writes → paused; halt-state listener fires on paused/error. - dashboard: AgentsView/AgentListModal/AgentDetailView lose the Terminated badge/option/state-block; agent pickers no longer filter terminated; agentHealth drops the Terminated branch; routes/state cast widened to the new AgentState union. Tests across core and engine updated to assert paused for AgentState and left "terminated" intact for run-status assertions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1173,7 +1173,9 @@ export class AgentStore extends EventEmitter {
|
||||
state: newState,
|
||||
updatedAt: new Date().toISOString(),
|
||||
// Clear lastError when transitioning away from terminated
|
||||
...(currentState === "terminated" && newState !== "terminated" && { lastError: undefined }),
|
||||
// Clear lastError when an agent re-enters an actionable state so
|
||||
// a resumed agent does not carry stale "Error" badges.
|
||||
...((newState === "active" || newState === "running") && { lastError: undefined }),
|
||||
};
|
||||
|
||||
await this.writeAgent(updated);
|
||||
@@ -1432,11 +1434,9 @@ export class AgentStore extends EventEmitter {
|
||||
await this.endHeartbeatRun(activeRun.id, "terminated");
|
||||
}
|
||||
|
||||
// Normalize to terminated first when idle is not directly reachable.
|
||||
if (agent.state !== "idle" && agent.state !== "terminated") {
|
||||
agent = await this.updateAgentState(agentId, "terminated");
|
||||
}
|
||||
|
||||
// Any non-idle state can transition directly to idle in the new
|
||||
// lifecycle (see AGENT_VALID_TRANSITIONS in types.ts), so no
|
||||
// intermediate hop is required.
|
||||
if (agent.state !== "idle") {
|
||||
agent = await this.updateAgentState(agentId, "idle");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user