import type { Agent, AgentInput } from '../core/agent.js'; import type { EventBus } from '../kernel/events.js'; import type { SubagentConfig, SubagentRunner, TaskSpec } from '../types/multi-agent.js'; import type { FleetBus } from './fleet-bus.js'; /** * Caller-supplied factory that builds an isolated `Agent` for a subagent. * The factory MUST construct a fresh `Context` per call — sharing context * between subagents defeats isolation. Each Agent should also use either * its own `EventBus` or a forwarded view, so per-subagent metrics can be * attributed correctly. */ export type AgentFactory = (config: SubagentConfig, task?: TaskSpec) => Promise; /** * Wrap a factory to automatically filter out disabled tools from subagent * configurations. This provides mechanical enforcement of tool restrictions * (e.g., preventing delegation) in addition to the baseline prompt constraint. * * The wrapper reads `config.disabledTools` and removes those tools from the * agent's tool registry before returning. * * Usage: * const filteredFactory = withDisabledToolFiltering(originalFactory); * const runner = makeAgentSubagentRunner({ factory: filteredFactory }); */ export declare function withDisabledToolFiltering(factory: AgentFactory): AgentFactory; export interface AgentFactoryResult { agent: Agent; /** Event bus the factory wired to this agent — required for budget hookup. */ events: EventBus; /** * Optional cleanup hook invoked in the runner's `finally` block once * the task ends (success, failure, abort — same exit path). Factories * that own resources scoped to a single task (per-subagent JSONL * writers, transient providers, throwaway containers) implement this * to close them deterministically instead of relying on GC. Errors * thrown here are swallowed so a flaky cleanup can't mask the task's * real result. */ dispose?: ((() => Promise | void)) | undefined; } export interface AgentRunnerOptions { factory: AgentFactory; /** * Format a TaskSpec into the user input the agent will receive. Defaults * to `task.description ?? ''`. Override when subagents expect structured * input (e.g. JSON contracts, role-prefixed prompts). */ formatTaskInput?: (task: TaskSpec, config: SubagentConfig) => AgentInput; /** * When set, the runner attaches the subagent's EventBus to this FleetBus * on task start and detaches it when the task finishes. This is the * injection seam that lets the TUI fleet panel observe subagent activity * live — without it, FleetBus stays empty. */ fleetBus?: FleetBus | undefined; /** * Optional parent bus for task-correlated worker telemetry. The worker keeps * its own EventBus for isolation; this explicit bridge forwards only the * tool/file channels needed by host observability surfaces. */ hostEvents?: EventBus | undefined; } /** * Builds a `SubagentRunner` that drives a real `Agent` per task while honoring * the coordinator's budget and abort signal. This is the production adapter — * the coordinator's `runner` option in CLI/TUI assemblies points here. * * Lifecycle per task: * 1. factory(config) → fresh Agent + EventBus. * 2. Subscribe to events to feed the budget (tool calls, token usage). * 3. Call agent.run(input, { signal }) — the coordinator's signal cancels. * 4. Map RunResult.status onto a `SubagentRunOutcome` or throw on failure. * 5. Unsubscribe and let the factory's resources be GC'd. * * The budget is checked synchronously from event handlers — a runaway agent * that crosses its tool-call limit triggers `BudgetExceededError`, which the * coordinator surfaces as `status: 'failed'` on the task result. */ export declare function makeAgentSubagentRunner(opts: AgentRunnerOptions): SubagentRunner; //# sourceMappingURL=agent-subagent-runner.d.ts.map