import type { AgentMessage } from "../internal/harness.js";
import type { Model } from "../internal/llm.js";
import { type ContextWindowOverlay } from "./context-settings.js";
/**
 * Last-resort, in-task context trim. Proper compaction (LLM summary) runs *between* tasks;
 * this prevents a single task whose internal tool-loop balloons from overflowing the window.
 *
 * Keeps all summary messages (compaction/branch) and the most recent messages that fit the
 * budget, dropping older regular messages at a safe boundary (never starting on an orphan
 * toolResult). Returns the original array when already within budget.
 *
 * design/123 D3 (= fable-M5) — anchored accounting: when `anchoredTotalTokens`
 * (= `estimateContextTokens(messages, charsPerToken).tokens` for the SAME array) is provided, the
 * trigger gate and the internal bookkeeping start from the usage-anchored value instead of the
 * structural sum (which underestimates code/CJK and lets over-window requests through). Dropping a
 * message AFTER the usage anchor reduces the accounted total by its structural estimate; dropping a
 * message AT/BEFORE the anchor reduces it by ZERO (the anchor usage was billed with that content —
 * a request-view drop only pays off on the NEXT request), so the trim keeps cutting deeper until
 * the anchored total meets the budget or only the minimal tail is left. Absent ⇒ legacy structural
 * behavior, byte-identical. `charsPerToken` (design/123 D2): structural coefficient, default 3 (design/374 slice 4).
 */
export declare function trimToBudget(messages: AgentMessage[], budgetTokens: number, anchoredTotalTokens?: number, charsPerToken?: number): AgentMessage[];
/**
 * In-band notice for a request view whose oldest messages were dropped by the guard trim. Every
 * other history-reducing pass in the pipeline announces itself to the model (compaction injects a
 * summary); a silent trim leaves the model unaware that earlier instructions or constraints are no
 * longer visible. MUST remain a single static string: the notice is re-inserted on every trimmed
 * request, and a byte-identical prefix keeps provider prefix caching effective.
 */
export declare const CONTEXT_TRIM_NOTICE: string;
/**
 * Insert the static trim notice ahead of the kept tail of a trimmed request view (after any
 * always-kept summary messages, which lead the rebuilt array). Call ONLY when the trim actually
 * dropped messages. Request-view only — the synthetic message is never persisted to the session
 * (fixed timestamp keeps it fully deterministic).
 */
export declare function insertTrimNotice(trimmed: AgentMessage[]): AgentMessage[];
/** R2-3 (falsification round 2) — does the message's ENGINE-AUTHORED region cover [start, start+len)?
 *  The carrier scan must never crown a counterfeit: a tool result or a user paste can reproduce the
 *  wrapped frame bytes verbatim, but only ENGINE metadata (engineMinted whole-message, the
 *  enginePrefixChars head, or an engineSegments range) proves the engine put them there. */
export declare function engineRegionCovers(m: AgentMessage, start: number, len: number): boolean;
/** Outcome of {@link protectGitFrame} — `over_budget` means the irreducible core (summaries + the
 *  protected frame carrier) exceeds the budget even after the one-shot degraded shrink: the caller
 *  must fail the request LOUDLY (`irreducible_core_over_budget`) instead of pretending the trim
 *  succeeded or looping compaction/re-assertion. */
export type GitFrameGuardOutcome = {
    messages: AgentMessage[];
    action: "kept" | "absent" | "reinserted" | "shrunk";
} | {
    action: "over_budget";
};
/**
 * env-tail migration — the git frame's UNCLIPPABLE-CORE protection over a trimmed request view.
 * The frame's "value unchanged ⇒ never re-sent" contract makes a request-only drop uniquely
 * dangerous for it: the commit receipt has already landed, so a trim that cuts the carrier makes
 * the announced hash suppress every future re-send while the model never saw the frame. Rules:
 *   - REPLACE-BY-KEY SLOT: exactly ONE carrier is protected — the newest message whose flat text CONTAINS
 *     `protectedText` (the ENGINE-HELD wrapped frame segment; set at delivery/re-assert AND
 *     re-seeded on value-unchanged legs, so the protection survives legs that send nothing).
 *     Older frames trim like ordinary history.
 *   - Re-insert a dropped carrier after the leading summaries/trim-notice (its original relative
 *     position is always ≥ there — the carrier predates every kept tail message).
 *   - IRREDUCIBLE-CORE arc: when the core (always-kept summaries + the carrier) alone exceeds the
 *     budget, substitute the carrier's frame segment with the deterministic DEGRADED rendering —
 *     exactly once per run (`alreadyShrunk` latch, request-view only; the run loop re-announces the
 *     shrunk view through its own receipt machinery). Still over after the shrink ⇒ `over_budget`.
 *   - A total overshoot whose core FITS is left alone (turn-alignment overshoot is a pre-existing,
 *     tolerated trade — validity beats budget; this guard must not convert it into a failure).
 */
export declare function protectGitFrame(before: AgentMessage[], trimmed: AgentMessage[], budgetTokens: number, frame: {
    protectedText: string;
    substitute?: {
        find: string;
        replace: string;
    };
}, // protectedText = the wrapped frame SEGMENT (see the carrier scan below)
charsPerToken?: number): GitFrameGuardOutcome;
/** Budget the in-task guard targets for a model — CC-aligned headroom numbers with a 0.85
 *  small-window floor, sema-owned drop-oldest action (see {@link GUARD_HEADROOM_TOKENS}); always
 *  above the compaction/clearStale frontier. Dual-window semantics: deliberately the PHYSICAL
 *  window (`contextTokens ?? contextWindow`), NOT `autoCompactTokens` — the guard protects the
 *  real request limit; a lowered autocompact window only moves the trigger-side geometry. */
export declare function guardBudget(model: Model, overlay?: ContextWindowOverlay): number;
