/** Single subscriber that fans `AgentLoopEvent`s out to runtime side-effect handlers. */
import type { CustomMessage } from '../core/custom-messages.js';
import type { AgentController, AgentLoopEvent } from '../core/index.js';
import type { EmbeddedCompactionWiring } from './compaction-wiring.js';
import type { RunStatsAccumulator } from './run-stats.js';
import type { ShortcutXLSessionWriter } from './session-store.js';
export interface AgentEventFunnelOptions {
    agent: AgentController;
    sessionStore: ShortcutXLSessionWriter;
    runStatsAccumulator: RunStatsAccumulator;
    compactionWiring: EmbeddedCompactionWiring;
    onAgentStart?: () => void;
    /**
     * Fired once per successful (`agent_end` not preceded by an error)
     * turn. The composition root wires this to the suggestions runner +
     * extra-events emitter; the funnel itself stays oblivious to what
     * the hook does. Errors are swallowed by the caller.
     */
    onAgentEndSuccess?: () => void;
    /**
     * Fired once per `agent_end`, regardless of disposition (success,
     * error, abort). Used by the credit gate to update its disposition
     * after every run boundary. Errors are swallowed by the caller.
     *
     * Distinct from `onAgentEndSuccess`: a credit-fetch update should
     * fire even when the run errored or aborted, because the user's
     * credit state is independent of run outcome.
     */
    onAgentEnd?: () => void;
}
export interface AgentEventFunnel {
    handle(event: AgentLoopEvent): void;
    /** Per-message session-entry ids, lock-step with `agent.state.messages`. */
    getMessageEntryIds(): readonly string[];
    /** Drop the trailing K entry ids — used by edit-and-resubmit when messages are sliced. */
    truncateMessageEntryIds(keep: number): void;
    /** Replace the entire id list — used when hydrating from persisted entries. */
    seedMessageEntryIds(ids: readonly string[]): void;
    /** Append a runtime-owned custom boundary without treating it as part of a model run. */
    appendCustomBoundaryMessage(message: CustomMessage): string;
    /** Throws if `messageEntryIds.length !== expectedLength`. Used to enforce the funnel↔messages invariant. */
    assertAlignedWith(expectedLength: number): void;
}
/** Returns an `AgentLoopEvent` handler with a stable internal turn counter. */
export declare function createAgentEventFunnel(options: AgentEventFunnelOptions): AgentEventFunnel;
//# sourceMappingURL=agent-event-funnel.d.ts.map