fix(agents): enforcer l'invariant « 1 session vivante par agent » (singleton)
Un agent ne peut tourner que dans une seule cellule à la fois. La garde dans LaunchAgent refuse le spawn si l'agent est déjà vivant dans un autre node (AGENT_ALREADY_RUNNING) ; idempotent sur le même node ; le chemin resume (agent mort) reste inchangé. Le node_id est désormais plombé jusqu'au use case. Corrige le reset asymétrique d'une cellule au changement d'onglet : deux leaves partageant le même agent id rendaient session_for_agent/is_agent_live/stop_agent ambigus (cible arbitraire). Le churn reset/reattach déclenchait aussi les accents mélangés (FIFO intact, non touché). - snapshot agentWasRunning calculé par node (is_node_live) et non par agent - commande list_live_agents + live_agents()/node_for_agent()/is_node_live() - UI : dropdown grise les agents déjà placés ailleurs ; 2e cellule en doublon affiche « disponible » au lieu d'une relance fantôme Tests : cargo test (application + app-tauri) vert ; tsc + vitest vert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -72,6 +72,12 @@ export interface ConversationDetails {
|
||||
export interface AgentGateway {
|
||||
/** Lists all agents belonging to the given project. */
|
||||
listAgents(projectId: string): Promise<Agent[]>;
|
||||
/**
|
||||
* Lists the agents that currently own a live session and the cell hosting
|
||||
* each. Used to disable an agent already running in another cell (it cannot be
|
||||
* launched a second time — one live session per agent).
|
||||
*/
|
||||
listLiveAgents(projectId: string): Promise<LiveAgent[]>;
|
||||
/** Creates a new agent from scratch; returns the created agent. */
|
||||
createAgent(projectId: string, input: CreateAgentInput): Promise<Agent>;
|
||||
/** Reads an agent's `.md` context by agent id. */
|
||||
@ -135,6 +141,21 @@ export interface OpenTerminalOptions {
|
||||
* meaningful for {@link AgentGateway.launchAgent}; ignored for plain terminals.
|
||||
*/
|
||||
conversationId?: string;
|
||||
/**
|
||||
* The layout leaf (node) hosting this launch. Drives the "one live session per
|
||||
* agent" invariant backend-side: launching an agent already running in a
|
||||
* *different* node is refused (`AGENT_ALREADY_RUNNING`); the same node is
|
||||
* idempotent. Only meaningful for {@link AgentGateway.launchAgent}.
|
||||
*/
|
||||
nodeId?: string;
|
||||
}
|
||||
|
||||
/** One currently-live agent and the cell hosting it (see {@link AgentGateway.listLiveAgents}). */
|
||||
export interface LiveAgent {
|
||||
/** The live agent's id. */
|
||||
agentId: string;
|
||||
/** The node (layout leaf) hosting the agent's live session. */
|
||||
nodeId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user