import type { LLMProvider } from './types.js'; export type AgentType = 'general' | 'explore' | 'plan'; /** * Tool subsets per agent type. The unified capability filters its built * tool suite against this set when an agent is spawned. * * - general — full toolset (excluding the spawning tools themselves to * avoid runaway recursion) * - explore — read-only investigation: grep, glob, read_file, list, * file_exists, web_fetch, git (status/diff/log only) * - plan — same as explore (no writes); used for "design this" tasks * where the parent wants a plan back, not edits */ export declare const TOOL_SUBSETS: Record | null>; /** Tools sub-agents NEVER get — would risk infinite recursion. */ export declare const FORBIDDEN_FOR_SUBAGENTS: ReadonlySet; export declare function filterToolsForType(toolNames: readonly string[], _type: AgentType): string[]; export type AgentStatus = 'queued' | 'running' | 'completed' | 'failed' | 'stopped'; export interface AgentSpawnRequest { /** Sub-agent type — controls available tools. */ subagent_type?: AgentType; /** 3-5 word label shown in lists. */ description: string; /** Full instructions sent to the sub-agent as its user prompt. */ prompt: string; /** Per-agent model override; undefined inherits parent. */ model?: string; /** "worktree" creates a fresh `git worktree` for the agent. */ isolation?: 'worktree' | 'none'; /** When true, returns immediately with an id; caller polls for output. */ run_in_background?: boolean; } export interface AgentHandle { id: string; type: AgentType; description: string; status: AgentStatus; startedAt: number; endedAt?: number; /** Working directory the agent was spawned into. */ workingDir: string; /** Worktree path + branch when isolation: "worktree" was used and * changes were left behind for the user. */ worktreePath?: string; worktreeBranch?: string; /** Most recent partial output (foreground completes synchronously and * fills `output` directly). */ output?: string; error?: string; /** Conversation continuation point — see sendMessage(). */ continuation?: AgentContinuation; } /** * Captures whatever's needed to resume an agent with a follow-up message. * For now: the underlying LeanAgent reference (kept alive in the registry * even after `completed`) plus the original spawn options so we can * reconstruct the right tool subset for the follow-up. */ export interface AgentContinuation { agentObject: unknown; spawnOptions: AgentSpawnRequest; } export interface AgentSpawnerDeps { provider: LLMProvider; workingDir: string; providerId?: string; modelId?: string; } /** * Function that actually creates and runs a sub-agent. Injected by the * capability layer so this module doesn't depend on LeanAgent (avoids a * circular dep with unifiedCodingCapability). * * The function should: * - Honor `req.subagent_type` (filter tools) * - Honor `req.model` (override modelId) * - Run the prompt to completion * - Mutate the handle with output / error / status / endedAt */ export type AgentSpawnerFn = (req: AgentSpawnRequest, handle: AgentHandle, deps: AgentSpawnerDeps) => Promise; export declare class AgentRegistry { private readonly deps; private readonly spawner; private agents; private runs; private cancellers; constructor(deps: AgentSpawnerDeps, spawner: AgentSpawnerFn); /** * Spawn an agent. Returns the handle immediately — callers can choose * to await `runs.get(id)` for completion (foreground) or poll * `getStatus(id)` (background). */ spawn(req: AgentSpawnRequest): AgentHandle; /** Block until the agent finishes. */ wait(id: string): Promise; get(id: string): AgentHandle | undefined; list(): AgentHandle[]; /** Best-effort stop. We can't actually halt an in-flight LLM call, but * we can mark the handle and signal via canceller if the spawner * registered one. */ stop(id: string): boolean; registerCanceller(id: string, fn: () => void): void; /** Continue an existing agent with a follow-up message. */ sendMessage(id: string, message: string): Promise; private resolveWorkingDir; private createWorktree; /** If the agent left no changes behind, prune the worktree to keep * /tmp tidy. Otherwise leave it so the user can inspect / merge. */ private cleanupWorktreeIfUnchanged; } //# sourceMappingURL=agentRegistry.d.ts.map