/** * Every `tool_use.id` and `tool_result.tool_use_id` already present in the REQUEST conversation. * * Pure: it reads the already-parsed request body the caller holds, so it adds no disk read and no * network call to the request path. Compute it lazily — a response with no tool call at all never * needs it. */ export declare function knownToolUseIds(reqJson: unknown): Set; /** * `id` when nothing has claimed it, else the smallest free `_relay`. * * Pure and deterministic — it does not record the answer. `ToolUseIdMinter` is what marks a * result as taken, because "is this id free?" and "claim this id" are different decisions and a * caller inspecting one candidate must not mutate the set. */ export declare function uniqueToolUseId(id: string, taken: ReadonlySet): string; /** * Per-RESPONSE minting state: the conversation's ids plus everything this response has emitted. * * Claiming each emitted id — the unchanged ones too — is what makes two identical ids inside ONE * response diverge, which is the shape kimi produces when a turn calls the same tool twice. */ export declare class ToolUseIdMinter { private readonly taken; private count; constructor(taken: Iterable); /** The id this response should carry for `id`, claiming it against later blocks. */ mint(id: string): string; /** How many ids this response had to change. A count, never an id. */ get rewritten(): number; } export interface ToolUseIdRewrite { /** The content array with unique `tool_use` ids. The same array instance when nothing changed. */ content: unknown[]; /** How many blocks changed id. */ rewritten: number; /** original id -> minted id, for the blocks that changed. Diagnostics only; nothing consults it. */ map: Map; } /** * Rewrite the `tool_use` ids of one buffered Anthropic content array. * * Non-`tool_use` blocks are returned untouched and by reference: this is an identifier fix, not a * re-serialization of the model's answer. */ export declare function rewriteToolUseIds(content: unknown, taken: ReadonlySet): ToolUseIdRewrite; /** * Wrap a translated Anthropic SSE stream so a colliding `tool_use` id is minted afresh. * * Applied AFTER dialect recovery so a recovered call is covered too, and BEFORE anything that * watches for the first `tool_use` — validation, repair and `guardReshaped`'s structural * conservation check all see the final ids, which is what makes the repaired message the same * message the client received. * * Every event this does not rewrite is forwarded byte-identical, including a truncated tail and an * event whose data is not JSON: any doubt releases the original bytes. `takenIds` is a thunk so a * response with no tool call never pays for walking the conversation, and `onRewrite` reports the * running count for the metadata-only log field (headers are long gone by then). */ export declare function rewriteToolUseIdsInStream(upstream: ReadableStream, takenIds: () => Iterable, onRewrite?: (count: number) => void): ReadableStream;