/**
 * 0.13.98 Batch B — bounded LLM-based conversation compaction.
 *
 * Replaces auto-compact's truncation-only strategy with a bounded
 * LLM-summary-first / truncation-fallback-always pipeline.
 *
 * Design contract (locked after user review of /tmp/owl-bounded-compact-design.md):
 *
 *   1. Bounded input — compactor never sees raw oversized conversation.
 *      buildCompactionRequest() composes a 7-segment prompt capped at
 *      `compactionInputMaxTokens` (default 8000). Sections are dropped
 *      in priority order when over cap; system + latest_user_goal are
 *      load-bearing and never dropped.
 *
 *   2. ONE attempt per trigger — tryCompact() does NOT retry. Failure
 *      → fallback to truncation. Callers (threshold / hard_limit /
 *      context_exceeded) call tryCompact ONCE, never twice.
 *
 *   3. Heap-pressure path NEVER calls LLM — V8 heap at 75% means we're
 *      already memory-constrained; allocating buffers / Promises for an
 *      LLM round-trip risks OOM. heap-pressure stays sync truncation.
 *
 *   4. 3-strike session disable — tracked on
 *      `conversation.options.llmCompactFailureCount`. After 3
 *      consecutive failures, this session goes straight to truncation.
 *      A successful compact resets the counter to 0 (not a permanent
 *      penalty — just protection against persistent provider trouble).
 *
 *   5. Output validation — LLM output MUST contain all 4 structured
 *      headers (Current goal / Preserved evidence / Recent actions /
 *      Open risks), be 50-8000 chars, and contain no tool_use markers.
 *      Any validation failure → treated as compact failure → fallback.
 *
 *   6. No transcript pollution — failure surfaces only via onAutoCompact
 *      callback (footer notice path) and `conversation.options.compactionLog`
 *      telemetry ring buffer. Never appendTranscript, never retry, never
 *      block the main turn.
 *
 *   7. Compactor model call has hard limits:
 *      max_tokens=1500, temperature=0, tools=undefined, stream=false,
 *      AbortSignal.timeout=15s. Prevents the compactor itself from
 *      becoming a long task.
 *
 * Slice scope (B1 only). Slice B2 (evidence ledger) and B3 (batch
 * synthesis) are explicitly out — see /tmp/owl-preflight-research.md §5.
 */
import { type GateEvent } from './gate-telemetry.js';
import type { Conversation, ConversationTurn } from './protocol/types.js';
/** Default token budget for the compactor's INPUT. The compactor itself
 *  emits ≤ 1500 max_tokens. Total compactor round-trip token cost is
 *  bounded at ~9.5K — well under any model's context window. */
export declare const DEFAULT_COMPACTION_INPUT_MAX_TOKENS = 8000;
/** Number of most-recent turns kept verbatim in BOTH the compactor input
 *  AND the post-compact conversation. Deliberate redundancy: the LLM
 *  summary references these turns; they survive in keptTurns so the
 *  reference is stable. */
declare const RECENT_TURNS_VERBATIM_COUNT = 4;
/** Per-section token caps. Sum to 7800; leave 200 for prompt scaffold. */
declare const SECTION_CAPS: {
    readonly system: 2000;
    readonly latestUserGoal: 1500;
    readonly recentTurnsVerbatim: 2500;
    readonly toolCallSummary: 1000;
    readonly errorEvidence: 500;
    readonly filePathsTouched: 300;
};
/** Find the most recent NON-meta user text turn. Skips:
 *   - "继续" / "continue" / pure punctuation (recovery-shape inputs)
 *   - `[Runtime ...]` framed system-injected user turns
 *   - tool_result-only user turns (no plain text content)
 *  Returns null when no eligible turn found. */
export declare function findLatestNonMetaUserText(turns: readonly ConversationTurn[]): string | null;
/** Serialize a list of turns for verbatim inclusion. Format:
 *    [user] text...
 *    [assistant] text... (tool_use: name) (tool_use: name)
 *    [tool_result] (id=abc) ok: first 200 chars
 *  Caps total at maxTokens. When over, drops oldest turns first. */
export declare function serializeTurnsForCompactor(turns: readonly ConversationTurn[], maxTokens: number): string;
/** Extract per-tool-call summary lines from "dropped" turns:
 *    `Read({"path":"src/foo.ts"}) → ok: 1024 chars`
 *    `Bash({"cmd":"npm test"}) → err: timeout after 30s`
 *  Each line ≤ ~150 chars. Caps at TOOL_CALL_SUMMARY_MAX_LINES (50).
 *  When over the line cap, keeps the MOST RECENT 50 (most-recent-N tail). */
export declare function extractToolCallSummary(turns: readonly ConversationTurn[], maxLines?: number): string;
/** Extract error evidence: is_error tool_results, [Runtime ...] warnings,
 *  timeout / failure messages from text. Each line ≤ ~120 chars. */
export declare function extractErrorEvidence(turns: readonly ConversationTurn[], maxLines?: number): string;
/** Extract file paths from tool_use inputs across the dropped turns.
 *  Heuristic: any string input value containing `/`, no whitespace, no
 *  shell metachars. Dedup; cap to FILE_PATHS_MAX (80). */
export declare function extractFilePaths(turns: readonly ConversationTurn[], maxPaths?: number): string[];
export interface CompactionRequest {
    prompt: string;
    estimatedTokens: number;
    droppedTurns: ConversationTurn[];
    keptTurns: ConversationTurn[];
}
export interface BuildCompactionRequestOptions {
    inputMaxTokens?: number;
    recentTurnsCount?: number;
}
/** Build the bounded compactor input. Returns null if there's nothing to
 *  compact (≤ recentTurnsCount turns total → all are kept verbatim, no
 *  drop, no summary needed). */
export declare function buildCompactionRequest(conv: Conversation, options?: BuildCompactionRequestOptions): CompactionRequest | null;
declare const REQUIRED_HEADERS: readonly ["Current goal", "Preserved evidence", "Recent actions", "Open risks"];
export interface ValidationResult {
    ok: boolean;
    reason?: 'too_short' | 'too_long' | 'missing_header' | 'tool_use_marker' | 'empty';
}
/** Validate compactor LLM output against locked contract:
 *   - 50 ≤ length ≤ 8000 chars
 *   - all 4 required headers present (case-insensitive substring match)
 *   - no `<tool_use>` or `"type":"tool_use"` markers (compactor must not
 *     hallucinate tool calls — they'd cascade into the post-compact turn) */
export declare function validateCompactionOutput(text: string): ValidationResult;
export interface BuildCompactionFidelityEventsOptions {
    summary: string;
    conversationId: string;
    iteration: number;
    lastToolSignatures?: string[];
    model?: string;
    maxFacts?: number;
}
/** Build shadow-only exact-match facts for compaction fidelity audits.
 *  This intentionally prefers precision over recall: it only asks whether
 *  concrete path strings present in dropped tool inputs survived verbatim in
 *  the LLM summary. No semantic inference, no gating, no authority changes. */
export declare function buildCompactionFidelityEvents(droppedTurns: readonly ConversationTurn[], opts: BuildCompactionFidelityEventsOptions): GateEvent[];
declare const COMPACTION_TIMEOUT_MS = 15000;
declare const COMPACTION_MAX_OUTPUT_TOKENS = 1500;
declare const COMPACTOR_SYSTEM_PROMPT = "You are a conversation compressor for an in-progress coding session.\nOutput a structured summary preserving essential context for continuing the conversation.\nBe factual and dense. Skip pleasantries and meta-commentary.\n\nRequired output structure (use these exact section headers):\n\nCurrent goal:\n<one or two sentences stating what the user is trying to do RIGHT NOW>\n\nPreserved evidence:\n<bulleted facts: key file paths, decisions, numbers, configuration choices, derived results>\n\nRecent actions:\n<bulleted recent tool calls and their material outcomes; one line each>\n\nOpen risks:\n<bulleted unresolved errors, blocked paths, expired assumptions, things still pending>\n\nOutput ONLY the summary. No XML tags, no code blocks, no preface.\nMaximum 1500 tokens.";
export interface ConversationLoopOptionsLike {
    apiBaseUrl: string;
    apiKey?: string;
}
export interface CompactViaLLMResult {
    ok: boolean;
    summary?: string;
    error?: string;
    validationReason?: ValidationResult['reason'];
    ms: number;
}
export interface CompactViaLLMOptions extends ConversationLoopOptionsLike {
    model: string;
    /** Override the system prompt. Default is COMPACTOR_SYSTEM_PROMPT. Tests
     *  use this to verify the prompt contract; production should not set it. */
    compactorSystemPrompt?: string;
    /** Optional fetch override for tests. */
    fetchImpl?: typeof fetch;
}
export declare function compactViaLLM(request: CompactionRequest, opts: CompactViaLLMOptions): Promise<CompactViaLLMResult>;
/** The reasons surfaced to onAutoCompact callback. Subset extends the
 *  pre-0.13.98 reason enum. */
export type CompactReason = 'threshold' | 'hard_limit' | 'context_exceeded' | 'heap_pressure';
export type CompactMethod = 'llm_summary' | 'truncation' | 'no_op';
export interface CompactResult {
    method: CompactMethod;
    reason: CompactReason;
    /** Why we ended up at truncation if LLM was attempted. Omitted when
     *  method='llm_summary' or when LLM was never tried. */
    fallbackReason?: 'llm_compact_failed' | 'llm_compact_disabled_3strikes' | 'heap_pressure_skip_llm' | 'no_llm_opts';
    before: number;
    after: number;
    beforeTokens: number;
    afterTokens: number;
    /** ms taken by the LLM attempt (when attempted). 0 otherwise. */
    llmMs?: number;
}
/** Maximum consecutive LLM-compact failures before this session disables
 *  LLM and goes straight to truncation. Reset to 0 on first success. */
export declare const MAX_CONSECUTIVE_LLM_COMPACT_FAILURES = 3;
/** Ring buffer cap for compactionLog telemetry on conversation.options. */
export declare const COMPACTION_LOG_MAX_ENTRIES = 5;
export interface TryCompactOptions {
    reason: CompactReason;
    /** Conversation context — must be the same Conversation that runs in the
     *  loop. tryCompact mutates conv.turns AND conv.options. */
    apiBaseUrl?: string;
    apiKey?: string;
    /** Compactor model override. Defaults to conv.model when undefined.
     *  Resolved from middleware.compactionModel by the caller. */
    compactionModel?: string;
    /** Bounded input cap override. Defaults to
     *  DEFAULT_COMPACTION_INPUT_MAX_TOKENS. */
    inputMaxTokens?: number;
    /** Truncation keep-count (turns to retain after fallback). Caller
     *  computes from contextWindow. */
    truncationKeepCount: number;
    /** Optional shadow telemetry for evidence-ledger fidelity audits. */
    fidelityTelemetry?: Omit<BuildCompactionFidelityEventsOptions, 'summary'>;
    /** Test override for fetch. */
    fetchImpl?: typeof fetch;
}
/** Single attempt to compact. Returns a fully-populated CompactResult.
 *  Never throws — all errors converted to truncation-path results.
 *
 *  Mutates:
 *   - conv.turns (replaces with [summary turn, ...keptTurns] on success or
 *     truncated tail on fallback)
 *   - conv.options.llmCompactFailureCount (incremented on failure, reset
 *     to 0 on success)
 *   - conv.options.compactionLog (ring buffer telemetry, up to 5 entries) */
export declare function tryCompact(conv: Conversation, opts: TryCompactOptions): Promise<CompactResult>;
export { RECENT_TURNS_VERBATIM_COUNT, SECTION_CAPS, COMPACTION_TIMEOUT_MS, COMPACTION_MAX_OUTPUT_TOKENS, COMPACTOR_SYSTEM_PROMPT, REQUIRED_HEADERS, };
