/** * v2.6 โ€” AgentPool (Phase 0 scaffold). * * Lazy get-or-create registry of `AgentBackend` instances keyed by * `${sessionId}:${agent}`. Phase 0 ships the skeleton only: an in-memory Map, * lookup / register / health, and clean disposal wired to the server's onClose. * Spawning lands in Phase 1/2; nothing populates the map yet. * * Spec: openspec/changes/v2-6-persistent-agent-sessions/design.md ยง2. */ import type { AgentBackend } from './agent-backend.js'; export class AgentPool { private readonly backends = new Map(); private key(sessionId: string, agent: string): string { return `${sessionId}:${agent}`; } /** Map lookup only. Spawning is Phase 1/2 โ€” never creates here. */ get(sessionId: string, agent: string): AgentBackend | undefined { return this.backends.get(this.key(sessionId, agent)); } /** Store a backend instance for this (session, agent). */ register(sessionId: string, agent: string, backend: AgentBackend): void { this.backends.set(this.key(sessionId, agent), backend); } /** Summary for the health endpoint. */ health(): { size: number } { return { size: this.backends.size }; } /** Dispose every backend and clear the map. Tolerates throwing backends. */ async dispose(): Promise { const entries = [...this.backends.values()]; this.backends.clear(); await Promise.allSettled(entries.map((b) => b.dispose())); } } /** Single shared instance โ€” referenced only by the server's onClose hook in Phase 0. */ export const agentPool = new AgentPool();