/**
 * Session compaction logic.
 *
 * Extracted from AgentSession to be independently testable.
 * Handles two compaction triggers:
 * 1. Overflow: LLM returned context overflow → compact → auto-retry
 * 2. Threshold: Context over threshold → compact → user continues manually
 *
 * The actual LLM summarization lives in compaction/index.ts.
 * This module owns the decision logic and orchestration.
 */
import type { AssistantMessage, Model } from '../../ai/types.js';
import type { HeartbeatWrapFn } from '../agent-engine.js';
import type { SessionEntry } from '../session-schema.js';
import { type CompactionCompleteFn, type CompactionPreparation, type CompactionResult } from './compaction/index.js';
export type CompactionEvent = {
    type: 'auto_compaction_start';
    reason: 'threshold' | 'overflow';
} | {
    type: 'auto_compaction_end';
    result: CompactionResult | undefined;
    aborted: boolean;
    willRetry: boolean;
    errorMessage?: string;
};
export type CompactionEventListener = (event: CompactionEvent) => void;
/**
 * Callback interface for actions that mutate agent/session/extension state.
 * Data inputs (model, apiKey, entries, settings) are passed directly to
 * runManual/runAuto to keep this interface lean — only mutation callbacks here.
 */
export interface CompactionActions {
    /** Try extension-provided compaction. Returns result if extension handled it. */
    tryExtensionCompaction(preparation: CompactionPreparation, branchEntries: SessionEntry[], customInstructions: string | undefined, signal: AbortSignal): Promise<{
        result?: CompactionResult;
        cancelled?: boolean;
    }>;
    /** Persist compaction to session and rebuild agent messages. */
    persistCompaction(result: CompactionResult, fromExtension: boolean): Promise<void>;
    /** Remove the last assistant error message from agent state. */
    removeLastAssistantMessage(): void;
    /** Kick the agent to continue after compaction. */
    continueAgent(): void;
    /** Check if the agent has queued steering/follow-up messages. */
    hasQueuedMessages(): boolean;
}
export interface CompactionCheckContext {
    currentModel: Model<any> | undefined;
    branchEntries: SessionEntry[];
    /**
     * Optional override for the effective context window. When set, this wins
     * over `currentModel.contextWindow`. Used by per-turn knobs like
     * `baseTokenLimit` and `contextSize=extended` so the compaction decision
     * matches the window the LLM call will actually use.
     */
    contextWindowOverride?: number;
}
export type CompactionDecision = {
    action: 'none';
} | {
    action: 'overflow';
} | {
    action: 'threshold';
};
export type SessionCompactionEntry = Extract<SessionEntry, {
    type: 'compaction';
}>;
export declare function findLatestCompactionEntry(entries: SessionEntry[]): SessionCompactionEntry | undefined;
/**
 * Decide whether compaction is needed based on the last assistant message.
 * Pure function — no side effects.
 */
export declare function checkCompactionNeeded(message: AssistantMessage, ctx: CompactionCheckContext, skipAbortedCheck: boolean): CompactionDecision;
export interface SessionCompactionOptions {
    /** Optional completion override used by extensions. */
    complete?: CompactionCompleteFn;
}
export declare class SessionCompaction {
    private readonly _complete;
    private _manualAbortController;
    private _autoAbortController;
    private _listener;
    private _consecutiveFailures;
    private static readonly MAX_CONSECUTIVE_FAILURES;
    /** Wall-clock ceiling for one auto-compaction attempt. */
    static readonly AUTO_COMPACTION_TIMEOUT_MS: number;
    constructor(options?: SessionCompactionOptions);
    get isCompacting(): boolean;
    /** Set the single event listener (the session facade). */
    onEvent(listener: CompactionEventListener): void;
    private _emit;
    abortAll(): void;
    /**
     * Run manual compaction. Caller is responsible for disconnecting/reconnecting the agent.
     */
    runManual(model: Model<any>, apiKey: string, branchEntries: SessionEntry[], customInstructions: string | undefined, actions: CompactionActions): Promise<CompactionResult>;
    /**
     * Run auto-compaction (triggered by overflow or threshold).
     *
     * `keepRecentTokens` defaults to `DEFAULT_COMPACTION_KEEP_RECENT_TOKENS`.
     * Error recovery passes a smaller value on retry to compact more aggressively.
     */
    runAuto(reason: 'overflow' | 'threshold', willRetry: boolean, model: Model<any> | undefined, apiKey: string | undefined, branchEntries: SessionEntry[], actions: CompactionActions, keepRecentTokens?: number, 
    /**
     * Per-call heartbeat wrap. Must be captured synchronously by the caller
     * (e.g. compaction-wiring.ts) BEFORE awaiting the agent loop's finally,
     * which clears the runtime's _activeWrap. Without this, _executeAndPersist
     * would read undefined and the actual LLM compaction would emit no
     * compaction_started/completed telemetry.
     */
    heartbeatWrap?: HeartbeatWrapFn): Promise<void>;
    /**
     * Run the LLM compaction + persist as one heartbeat-tracked op.
     *
     * This is the only span in the auto-compaction flow that emits
     * compaction_started/completed/failed/cancelled telemetry. Everything before
     * it (circuit-breaker check, model/preparation early returns) is bookkeeping
     * that should stay invisible to observability. Cancellation is represented
     * with `CompactionCancelledError` so callers do not infer control flow from
     * provider error text.
     */
    private _executeAndPersist;
    private _executeCompaction;
}
//# sourceMappingURL=session-compaction.d.ts.map