import type { ContextBlock, InputAssemblyLayout, Message, ProviderRequest, Skill, TokenEstimate, ToolDefinition } from "./contracts.js"; import { type LoadedSkillSet, type SkillRenderContext, type SkillsDisclosure } from "./skill-disclosure.js"; /** * Host-supplied token estimator. Budget-only: it never reaches billing, provider * usage, or the wire — it decides what the assembler evicts and nothing else. */ export type TokenEstimator = (text: string) => number; /** Assembler-time input budget. At least one max required when present. */ export interface ContextBudget { readonly maxInputTokens?: number; readonly maxInputBytes?: number; readonly reportOmissions?: boolean; /** * Overrides the built-in UTF-16/4 heuristic for eviction accounting. Must return a * non-negative finite token count (a NaN/negative/absent return fails the assembly * closed with a `TypeError`). Byte caps are estimator-independent and always enforced. */ readonly tokenEstimator?: TokenEstimator; } export type ContextBudgetOmissionKind = "skills" | "skill_body" | "context" | "history" | "tool_results" | "summaries" | "attachments" | "tools"; export interface ContextBudgetOmission { readonly kind: ContextBudgetOmissionKind; readonly id?: string; readonly tokenEstimate: number; readonly byteLength: number; } export interface ContextBudgetReport { readonly omitted: readonly ContextBudgetOmission[]; readonly keptTokens: number; readonly keptBytes: number; readonly maxInputTokens?: number; readonly maxInputBytes?: number; readonly truncated: boolean; } export interface ContextBudgetMessageGroups { readonly instructions: readonly Message[]; readonly summaries: readonly Message[]; readonly history: readonly Message[]; readonly input: readonly Message[]; readonly attachments: readonly Message[]; readonly toolResults: readonly Message[]; } export declare const CONTEXT_BUDGET_REPORT_METADATA_KEY: "contextBudgetReport"; export declare const HARD_MAX_CONTEXT_BUDGET_TOKENS = 2000000; export declare const HARD_MAX_CONTEXT_BUDGET_BYTES: number; export declare const DEFAULT_MAX_CONTEXT_BUDGET_OMISSIONS = 256; export declare const HARD_MAX_CONTEXT_BUDGET_OMISSIONS = 1024; export declare const CONTEXT_BUDGET_ERROR_CODE: "context_budget_exceeded"; export declare class ContextBudgetError extends Error { readonly code: "context_budget_exceeded"; constructor(message?: string); } export declare function isContextBudgetError(error: unknown): error is ContextBudgetError; /** UTF-16 code units / 4. Estimate only — not billing. */ export declare function estimateTextTokens(text: string): number; export declare function estimateTextBytes(text: string): number; export declare function estimateMessageTokens(message: Message, estimateTokens?: TokenEstimator): number; export declare function estimateMessageTokens(messages: readonly Message[], modelFamily?: string): TokenEstimate; export declare function estimateMessageBytes(message: Message): number; export declare function estimateAssemblyTokens(messages: readonly Message[]): number; export declare function resolveContextBudget(budget: ContextBudget): Required> & ContextBudget; export declare function getContextBudgetReport(request: ProviderRequest): ContextBudgetReport | undefined; export declare function applyContextBudget(options: { readonly groups: ContextBudgetMessageGroups; readonly context?: readonly ContextBlock[]; readonly skills?: readonly Skill[]; readonly tools?: readonly ToolDefinition[]; readonly budget: ContextBudget; readonly layout?: InputAssemblyLayout; readonly skillsDisclosure?: SkillsDisclosure; readonly loadedSkills?: LoadedSkillSet; }): { readonly groups: ContextBudgetMessageGroups; readonly context: readonly ContextBlock[]; readonly skills: readonly Skill[]; readonly tools: readonly ToolDefinition[] | undefined; readonly demotedSkillBodies: readonly string[]; readonly report: ContextBudgetReport; }; /** Everything the assembler will send, in the order it will send it. */ export interface MeasureInputCostOptions { readonly groups: ContextBudgetMessageGroups; readonly context?: readonly ContextBlock[]; readonly skills?: readonly Skill[]; readonly tools?: readonly ToolDefinition[]; readonly skillContext?: SkillRenderContext; readonly demotedBodies?: ReadonlySet; readonly estimateTokens?: TokenEstimator; } /** * One O(n) cost measurement of the whole request (groups, context, skills, tool declarations). * Shared with the attention-compiler gate, which measures once per turn and then subtracts a * per-mutation delta instead of re-measuring — the same trick `applyContextBudget` uses. */ export declare function measureInputCost(options: MeasureInputCostOptions): { tokens: number; bytes: number; }; /** Plan 103 T6: the host's `contextBudget.tokenEstimator`, validated exactly like the budget pass * validates it (a non-function, or a non-finite/negative count, fails closed with `TypeError`). * `undefined` when no host estimator is configured, so callers can fall through to the built-in * heuristic. Exported for the usage seam (`provider-round.ts`) — deliberately not re-exported by * `src/index.ts`, so the public surface is unchanged. */ export declare function resolveHostTokenEstimator(budget: ContextBudget | undefined): TokenEstimator | undefined; /** Plan 103 T6: tool declarations and context blocks projected with the assembler's own * `measureAll` text shapes, so the usage-fallback estimate and the budget pass cannot drift * (never `JSON.stringify` of the raw schemas). Exported for the usage seam — deliberately not * re-exported by `src/index.ts`. */ export declare function estimateRequestExtrasTokens(tools: readonly ToolDefinition[] | undefined, context: readonly ContextBlock[] | undefined, estimateTokens: TokenEstimator): number;