import type { ChatMessage, LlmClient } from "../llm/types.js";
import { type OptimizeOptions } from "../llm/message-optimizer.js";
import type { LiveToolResultGuardStats } from "../llm/live-tool-result-guard.js";
export interface ContextState {
    goals: string[];
    constraints: string[];
    facts: string[];
    decisions: string[];
    visitedUrls: string[];
    completedActions: string[];
    errors: string[];
    pending: string[];
    currentPage?: {
        title?: string;
        url?: string;
        note?: string;
    };
    rawRefs: string[];
}
export interface ContextManifest {
    cacheablePrefixHash: string;
    stateHash: string;
    transcriptFile?: string;
    messageCount: number;
    charCount: number;
    systemPromptChars: number;
    systemPromptStaticChars: number;
    systemPromptDynamicChars: number;
    stateChars: number;
    totalChars: number;
    rawRefCount: number;
    optimized: {
        inputMessageCount: number;
        outputMessageCount: number;
        inputChars: number;
        outputChars: number;
        liveToolResultGuard: LiveToolResultGuardStats;
    };
}
export interface BuiltLlmContext {
    messages: ChatMessage[];
    /**
     * Concatenated form (`systemPromptStatic + systemPromptDynamic`) — kept for
     * backwards-compatible callers that only need a single string.
     */
    systemPrompt: string;
    /**
     * Cacheable prefix: only the caller-supplied `baseSystemPrompt`. Designed to
     * be byte-identical across consecutive LLM requests within the same user
     * turn so that providers can hit their prompt-cache layer.
     */
    systemPromptStatic: string;
    /**
     * Per-turn appended section (currently the structured ContextState).
     * Empty string when there is no earlier-state to surface.
     */
    systemPromptDynamic: string;
    manifest: ContextManifest;
}
export interface CompactResult {
    messages: ChatMessage[];
    state: ContextState;
    changed: boolean;
    summarizedCount: number;
    retainedCount: number;
    reason?: string;
}
export declare const CONTEXT_BUDGETS: {
    readonly chat: {
        readonly softLimitChars: 60000;
        readonly hardLimitChars: 100000;
        readonly targetChars: 40000;
        readonly keepRatio: 0.6;
        readonly memoryIndexMaxEntries: 30;
        readonly memoryIndexMaxBytes: number;
        readonly installedSkillsMaxChars: number;
    };
    readonly task: {
        readonly compactionCharBudget: 80000;
        readonly keepRatio: 0.55;
        readonly memoryIndexMaxEntries: 20;
        readonly memoryIndexMaxBytes: number;
        readonly installedSkillsMaxChars: number;
        readonly relevantMemoryMaxFiles: 5;
        readonly relevantMemoryMaxTotalBytes: number;
        readonly relevantMemoryPerFileBytes: number;
    };
    readonly summaryInput: {
        readonly assistantContentPreviewChars: 800;
        readonly toolCallArgsPreviewChars: 300;
        readonly toolResultPreviewChars: 800;
        readonly messagePreviewChars: 1000;
        readonly snapshotPreviewChars: 1600;
    };
};
export declare function createEmptyContextState(): ContextState;
export declare function estimateMessagesChars(messages: ChatMessage[]): number;
export declare function truncateContextSection(text: string, maxChars: number, note: string): string;
export declare function limitContextState(state: ContextState): ContextState;
export declare function normalizeContextState(raw: unknown): ContextState | null;
/**
 * Merge two ContextState snapshots. Two distinct policies coexist here:
 *
 *   Accumulative fields (goals, constraints, facts, decisions, visitedUrls,
 *   completedActions, errors, rawRefs) — UNION with previous. These are
 *   "things we have learned / done so far", so the safety-net behaviour of
 *   keeping previous items even when the LLM forgot to repeat them is the
 *   one we want.
 *
 *   Mutable workflow fields (pending) — REPLACE with next. The summarizer
 *   prompt asks the LLM for the COMPLETE updated state; a unioning merge
 *   re-introduces items that the LLM legitimately removed (e.g. "log in"
 *   after the agent has actually logged in). That keeps stale TODOs alive
 *   in the system prompt across compactions and misleads later turns.
 *
 *   currentPage — field-level merge: each field (title/url/note) is taken
 *   from next if present, else from previous. See mergeCurrentPage.
 */
export declare function mergeContextState(previous: ContextState, next: ContextState): ContextState;
export declare function isContextStateEmpty(state: ContextState): boolean;
export declare function formatContextState(state: ContextState): string;
export declare function parseContextStateFromText(text: string): ContextState | null;
export declare class ContextTranscript {
    private seq;
    private filePath?;
    private refs;
    constructor(workspace: string, scope: string);
    append(message: ChatMessage, meta?: Record<string, unknown>): string;
    getRef(message: ChatMessage): string | undefined;
    getFilePath(): string | undefined;
}
export declare function compactMessagesWithState(opts: {
    messages: ChatMessage[];
    state: ContextState;
    llmClient: LlmClient;
    charBudget: number;
    keepRatio?: number;
    preserveFirst?: boolean;
    transcript?: ContextTranscript;
    /** Routed through to llmClient so summarization sticks to the same upstream account as the rest of the session. */
    sessionId?: string;
}): Promise<CompactResult>;
export declare function buildLlmContext(opts: {
    baseSystemPrompt: string;
    state: ContextState;
    messages: ChatMessage[];
    optimizeOptions?: OptimizeOptions;
    contextTitle: string;
    transcript?: ContextTranscript;
}): BuiltLlmContext;
