/** * Agent Event Handler — coordinates listeners on pi-agent events. * * Previously a single god-handler with ten manager fields and one `switch`. Now a * thin façade around {@link SessionEventBus}: each concern (lifecycle * hooks, tool-chain recording, error tracking, self-verify, etc.) registers its * own listener at construction time, and external code can add new listeners via * {@link AgentEventHandler.registerListener} without modifying this file (OCP). * * Ordering note: a few listeners are order-sensitive (notably the * `tool_execution_end` chain — `SystemReminder` mutates `event.result` in place * and downstream listeners read the mutated value). The `installX` calls below * preserve the exact order from the previous implementation. */ import type { AgentEvent } from '@earendil-works/pi-agent-core'; import type { SessionContext } from '../session/session-context.js'; import type { ToolErrorTracker } from '../tools/error-tracker.js'; import type { RequestLimiter } from '../models/request-limiter.js'; import type { LifecycleManager } from '../lifecycle/index.js'; import type { ToolChainTracker } from '../tools/chain-tracker.js'; import type { SelfVerifyMiddleware } from '../middleware/index.js'; import type { SystemReminder } from '../prompt/system-reminder.js'; import type { ToolUsageAnalyzer } from '../tools/usage-analyzer.js'; import type { ErrorPatternMatcher } from '../tools/error-pattern-matcher.js'; import type { TurnDiffTracker } from '../coding/index.js'; export type SessionEventListener = (event: AgentEvent, context: SessionContext) => void; export type SessionEventTypeFilter = AgentEvent['type'] | 'all'; /** * Typed pub/sub for agent events. Listeners run in registration order; the bus * itself is synchronous — listeners that need async work must dispatch their own * promises (typically by awaiting and logging on error, like the lifecycle hooks). */ export declare class SessionEventBus { private readonly listeners; on(type: SessionEventTypeFilter, listener: SessionEventListener): () => void; dispatch(event: AgentEvent, context: SessionContext | null): void; } export declare function readChangedPathsFromToolEnd(toolName: string, args: unknown, result: unknown): string[]; export interface AgentEventHandlerConfig { errorTracker: ToolErrorTracker; requestLimiter: RequestLimiter; lifecycleManager: LifecycleManager; toolChainTracker: ToolChainTracker; selfVerifyMiddleware: SelfVerifyMiddleware; systemReminder: SystemReminder; toolUsageAnalyzer: ToolUsageAnalyzer; errorPatternMatcher: ErrorPatternMatcher; turnDiffTracker?: TurnDiffTracker; } /** * Thin façade over {@link SessionEventBus} that pre-registers all built-in * listeners in their required order. `handle(event, ctx)` is the entry point * used by `AgentService.handleSessionEvent`; extensions can hook in via * {@link registerListener} without touching this class. */ export declare class AgentEventHandler { private readonly bus; constructor(config: AgentEventHandlerConfig); /** Dispatch a pi-agent event to all registered listeners. */ handle(event: AgentEvent, context: SessionContext | null): void; /** * Register an additional listener (e.g. from an extension). Returns an * unsubscribe function. Listeners run after the built-ins in registration * order; if you need to run before a built-in, you must create your own * {@link SessionEventBus} instance. */ registerListener(type: SessionEventTypeFilter, listener: SessionEventListener): () => void; }