import type { Message } from '../types/messages.js'; /** * Estimate tokens for a tool_use block input. * Caches the stringified result keyed by the stable string representation * to avoid repeated JSON.stringify calls during context window checks. */ export declare function estimateToolInputTokens(input: unknown): number; /** * Estimate tokens for a tool_result content. */ export declare function estimateToolResultTokens(content: string | unknown): number; /** * Estimate tokens for a text block. */ export declare function estimateTextTokens(text: string): number; /** * Compute and cache the token estimate for a single message. This is the * canonical per-message estimator — called once by ConversationState on * append/replace so the O(n·m) content-block walk happens at mutation time, * not on every context-pressure check. */ export declare function computeMessageTokens(msg: Message): number; /** * Estimate tokens for an array of messages (text + tool I/O), using the shared * 3.5 chars/token basis. This is the single canonical message-array estimator — * compactors, the context_manager tool, and the `/context` display all route * through it so the number a user sees matches the number compaction decides on. * * When a message carries a pre-computed `_estTokens` field (set by * ConversationState on append/replace), it is used directly instead of * re-walking the content blocks — turning the O(n·m) scan into an O(n) * sum for fully-cached arrays. */ export declare function estimateMessageTokens(messages: readonly Message[]): number; /** * Real-usage-anchored input-token count. Given the provider's authoritative * prompt-token count from the last response (`anchorTokens`, a REAL number) and * the `messages.length` of the request that produced it (`anchorMsgCount`), * returns `anchorTokens + estimate(messages appended since)` — so everything up * to the last turn is exact and only the newest, not-yet-sent messages are * estimated. This is deliberately NOT calibrated: the base is already real, and * on the next response the whole thing re-anchors to the new real count. * * Returns `null` when there is no usable anchor (no response yet, or the * message array shrank below the anchor — e.g. after compaction — in which case * the caller falls back to a full estimate until the next response re-anchors). */ export declare function realAnchoredInputTokens(messages: readonly Message[], anchorTokens: number | undefined, anchorMsgCount: number | undefined): number | null; /** * Rough estimate of tokens in a tool definition (name + description + schema). * Accounts for the JSON-serialized inputSchema which is sent to the API * but NOT included in roughEstimate(content). */ export declare function estimateToolDefTokens(tool: { name: string; description?: string | undefined; inputSchema: unknown; }): number; /** * Estimate the total API request token count: system prompt + tool definitions * + conversation messages. Use this for context-window bar calculations * instead of roughEstimate (which only counts messages). * * The overhead ratio (overhead / messages) varies by conversation length: * - Short conversations (< 10 messages): ~30-50% overhead (large system+tools) * - Medium (10-50 messages): ~15-30% * - Long (> 50 messages): ~5-15% * * Returns { messages, systemPrompt, tools, total } for debugging display. */ export interface RequestTokenBreakdown { messages: number; systemPrompt: number; tools: number; total: number; } export declare function estimateRequestTokens(messages: unknown, systemPrompt: unknown, tools: { name: string; description?: string | undefined; inputSchema: unknown; }[], calibrationKey?: string): RequestTokenBreakdown; /** * Record the actual API input token count after a provider call so * `estimateRequestTokensCalibrated` can self-correct on subsequent calls. * * Prefer passing `estimatedInputTokens` explicitly (the calibrated pre-flight * estimate from the middleware) — this avoids race conditions when other code * also calls `estimateRequestTokens` between the pre-flight and this call * (e.g. audit logging in agent.ts). * * When `estimatedInputTokens` is omitted, falls back to the keyed bucket's * `prevEst` for backward compatibility with callers that don't have the * pre-flight value. `calibrationKey` selects the per-(provider,model) bucket * (defaults to the shared global bucket). */ export declare function recordActualUsage(actualInputTokens: number, estimatedInputTokens?: number, calibrationKey?: string): void; /** * Returns the current calibration state for a bucket. Exposed for debugging * and tests — not needed by normal callers. */ export declare function getCalibrationState(calibrationKey?: string): { ratio: number; count: number; calibrated: boolean; }; /** * Like `estimateRequestTokens` but applies the rolling calibration factor * so context pressure readings converge on reality within a few iterations. * * Before any `recordActualUsage` samples are collected, returns the same * result as `estimateRequestTokens` (ratio = 1.0, no distortion). * After `MIN_SAMPLES_FOR_CALIBRATION` samples, applies the calibrated * multiplier capped to the range [0.5, 1.5] as a sanity bound. */ export declare function estimateRequestTokensCalibrated(messages: unknown, systemPrompt: unknown, tools: { name: string; description?: string | undefined; inputSchema: unknown; }[], calibrationKey?: string): RequestTokenBreakdown; /** * Never-undercount upper bound for the request token total, for the **send * guard** only. Takes the flat estimate and scales it up by the greater of the * content-density multiplier and the calibration ceiling, so the guarded value * satisfies `real ≤ upperBound`. The context bar and `/context` keep using the * calibrated estimate — this deliberately over-counts, which is only ever safe * for the "must this be trimmed before sending?" decision. */ export declare function estimateRequestTokensUpperBound(messages: unknown, systemPrompt: unknown, tools: { name: string; description?: string | undefined; inputSchema: unknown; }[], calibrationKey?: string): RequestTokenBreakdown; /** * Resets calibration state. Primarily for tests that run in the same * process and need a clean slate between suites. With no argument it clears * every bucket (including the global one); pass a key to reset just that bucket. */ export declare function resetCalibration(calibrationKey?: string): void; //# sourceMappingURL=token-estimate.d.ts.map