import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
import { type SecretObfuscator } from "../secrets/obfuscator.js";
/**
 * Minimal slice of `Agent` the runtime drives — satisfied by pi-agent-core
 * `Agent`. `state.error` mirrors `Agent.state.error`: provider/stream failures
 * the loop catches internally never reject `prompt()`, so the runtime reads
 * this field after every prompt to detect a failed turn.
 */
export interface AdvisorAgent {
    prompt(input: string): Promise<void>;
    abort(reason?: unknown): void;
    reset(): void;
    /**
     * Drop messages appended past `count`. Called after a failed `prompt()` so a
     * retry doesn't replay the failed user batch + synthetic assistant-error
     * turn `Agent.#runLoop` records on its internal state.
     */
    rollbackTo?(count: number): void;
    readonly state: {
        messages: AgentMessage[];
        error?: string;
    };
}
export interface AdvisorRuntimeHost {
    /** Live primary transcript (use `agent.state.messages`). */
    snapshotMessages(): AgentMessage[];
    /** Surface one advice note to the primary (enqueues into the session YieldQueue). */
    enqueueAdvice(note: string, severity?: "nit" | "concern" | "blocker"): void;
    /** Redact primary transcript bytes before they reach the advisor model. */
    obfuscator?: SecretObfuscator;
    /**
     * Pre-prompt context maintenance for the advisor's own append-only context.
     * Promotes the advisor model to a larger sibling when its context nears the
     * window (mirroring the primary's promote-first policy) and resolves `true`
     * when the advisor should re-prime — reset and replay the current
     * primary-bounded transcript — because promotion did not free enough room.
     * Optional: hosts that omit it get no maintenance (context only shrinks when
     * the primary's next compaction triggers {@link AdvisorRuntime.reset}).
     */
    maintainContext?(incomingTokens: number): Promise<boolean>;
    /**
     * Called immediately before each `agent.prompt(batch)` cycle. Lets the host
     * clear per-update advisor state — currently the one-advise-per-update gate
     * in {@link AdvisorEmissionGuard}, which the host owns because it is the
     * one that routes `advise()` results back to the primary.
     */
    beginAdvisorUpdate?(): void;
    /**
     * Called with the error of every failed advisor turn, before the retry sleep
     * or the dropped-after-3 path. Lets the host apply credential-level remedies
     * the advisor loop lacks: the in-stream a/b/c auth retry rotates through
     * sibling credentials within one request but never blocks the LAST failing
     * one — the primary agent's retry pipeline does that via
     * `markUsageLimitReached`, so without this hook the advisor re-picks the
     * same usage-limited account on every retry. Errors thrown here are logged
     * and swallowed.
     */
    onTurnError?(error: unknown): Promise<void> | void;
    /** Surface a non-recovering advisor failure to the host UI without adding model-visible context. */
    notifyFailure?(error: unknown): void;
}
export declare class AdvisorRuntime {
    #private;
    private readonly agent;
    private readonly host;
    private readonly retryDelayMs;
    disposed: boolean;
    constructor(agent: AdvisorAgent, host: AdvisorRuntimeHost, retryDelayMs?: number);
    get backlog(): number;
    onTurnEnd(messages?: AgentMessage[]): void;
    waitForCatchup(maxMs: number, threshold: number, signal?: AbortSignal): Promise<void>;
    dispose(): void;
    /**
     * Re-prime the advisor after a history rewrite (compaction, session
     * switch/resume, branch). Clears the advisor's own (non-persisted) context
     * and rewinds the cursor to 0 so the NEXT turn replays the full current —
     * post-compaction — transcript, giving the advisor fresh context instead of
     * leaving it blind to everything before the rewrite.
     */
    reset(): void;
    /**
     * Seed the cursor to the current transcript length when the advisor is enabled
     * mid-session. Prevents the next turn from replaying the entire history to the
     * advisor (which would be expensive and likely stale).
     */
    seedTo(count: number): void;
}
