/**
 * In-turn context guard for Gemini-shaped agent loops (native Vertex + AI
 * Studio + Gemini 3).
 *
 * These loops already had `createContextGuard`, but it is **stop-only**: once
 * the projected prompt crosses the threshold it breaks the loop and synthesizes
 * an answer from whatever it has. That avoids a provider rejection, but it also
 * ends the turn early — the model stops doing work it was mid-way through.
 *
 * This module brings them to parity with the other loops: reclaim budget and
 * CONTINUE, falling back to the existing stop only when reclaiming cannot get
 * back under the line. The reclaim policy is shared with every other provider
 * via `loopGuardCore`; this module owns only the Gemini shape mapping.
 *
 * Gemini history is `{ role, parts[] }`, where a part is a `functionCall`
 * (tool invocation) or `functionResponse` (its result). One model turn can
 * carry several `functionCall` parts and the following user turn carries the
 * matching `functionResponse` parts, so the CONTENT is the batch unit —
 * dropping a call turn together with its response turn can never orphan a part,
 * which Gemini rejects.
 */
import type { GeminiGuardContent, LoopGuardPlan } from "../types/index.js";
/** Marker left where dropped history used to be. */
export declare const GEMINI_ELISION_NOTE = "[Earlier tool exchanges were removed to fit the context window.]";
/** True when this content carries tool results worth previewing. */
export declare function isGeminiToolResponseContent(content: GeminiGuardContent): boolean;
/** Head/tail preview for an oversized tool response payload. */
export declare function previewGeminiToolResponseText(text: string): string;
/**
 * Decide what to reclaim from a Gemini agent loop.
 *
 * Returns `undefined` when the history still fits, in which case the caller
 * must leave it byte-identical — any rewrite invalidates the provider's cached
 * prefix, so "no change" has to mean no change.
 *
 * `observedPromptTokens` must be a count for the payload ABOUT TO BE SENT —
 * every Gemini-shaped loop plans only when its `createContextGuard` trips, and
 * that guard's `projectedNextPromptTokens` is exactly that: the provider's real
 * count for the last request plus the growth measured since. Dividing it by
 * this module's estimate of the current history therefore compares two views of
 * one payload, which is what makes the correction meaningful. A count for an
 * EARLIER request must not be passed here: the loop has appended a model turn
 * and its tool turn since, so the denominator would always be the larger of the
 * two, the ratio would read below 1 and the `Math.max(1, …)` floor would pin
 * calibration at 1 — silently disabling the correction. `planAnthropicLoopReclaim`
 * carries `previousSentEstimate` for callers in that other position.
 */
export declare function planGeminiLoopReclaim(args: {
    contents: readonly GeminiGuardContent[];
    availableInputTokens: number;
    fixedOverheadTokens?: number;
    provider?: string;
    observedPromptTokens?: number;
}): LoopGuardPlan | undefined;
