import { c as KvSnapshot, m as TokenLogprobs, n as Engine, o as GenerateOptions } from "./types-CBW7T_3s.js"; //#region src/chat/tokenizer.d.ts interface ChatMessage { role: 'system' | 'user' | 'assistant' | 'tool' | (string & {}); content: string; /** Tool calls made on a past assistant turn (the template renders them back as * blocks). Feed a turn's calls back verbatim from {@link ChatResult.toolCalls} when * continuing a tool round trip; a `tool` role message then carries each result. */ tool_calls?: { name: string; arguments: Record | string; }[]; } /** Incremental decoder for streaming generation: feed token ids as they arrive, get the newly * stable visible text each step. Re-decodes the running sequence and emits the delta, holding * back a trailing incomplete multi-byte character (which byte-level BPE decodes as U+FFFD) * until its remaining tokens arrive. */ interface DecoderStream { push(tokenId: number): string; flush(): string; } declare class ChatTokenizer { private readonly tok; private readonly template; private readonly templateContext; /** End-of-sequence token id (e.g. <|im_end|> for Qwen3-family models). */ readonly eosTokenId: number; /** The eos token's string form (used to reconstruct the template's turn terminator). */ readonly eosToken: string; constructor(tokenizerJson: unknown, tokenizerConfig: Record); /** Encode text to token ids. `addSpecialTokens` defaults to false: the chat template already * inserts the control tokens, so prompt/delta encoding must not add more. */ encode(text: string, addSpecialTokens?: boolean): number[]; /** Decode token ids to text. `skipSpecialTokens` defaults to true (never surface control tokens). */ decode(ids: number[], skipSpecialTokens?: boolean): string; /** The raw vocab string for a token id (byte-alias space for byte-level BPE). */ idToToken(id: number): string | undefined; /** The id of an exact vocab token (e.g. the marker); undefined when absent. */ tokenToId(token: string): number | undefined; /** Ids of all added tokens (ChatML markers, , etc.) - never plain content. */ addedTokenIds(): Set; get hasChatTemplate(): boolean; /** Render a message list to a prompt string via the model's own Jinja chat template * (matches transformers.js apply_chat_template byte-exactly). `tools` is passed to the * template verbatim (Qwen-family templates serialize each entry into the system block). */ applyChatTemplate(messages: ChatMessage[], opts?: { addGenerationPrompt?: boolean; enableThinking?: boolean; tools?: readonly unknown[]; }): string; createDecoderStream(skipSpecialTokens?: boolean): DecoderStream; } //#endregion //#region src/chat/json.d.ts /** The enforceable JSON Schema subset (see validateJsonSchema). */ interface JsonSchema { type?: 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null'; properties?: Record; required?: string[]; additionalProperties?: boolean; items?: JsonSchema; minItems?: number; maxItems?: number; enum?: string[]; /** DISCRIMINATED union only: every branch an object with additionalProperties: false, sharing * one required property whose single-value enum differs per branch (the discriminator), with * any other shared property schema identical across branches. General oneOf throws. */ oneOf?: JsonSchema[]; /** Integer range (type 'integer' only - float ranges are not incrementally enforceable). * Enforced with prefix feasibility: a digit is only permitted while SOME completion can still * land in range, so the machine can never get stuck mid-number. */ minimum?: number; maximum?: number; /** String length in code points (a \uXXXX escape counts as one); type 'string' only, and not * combinable with enum (the literals already fix the length). */ minLength?: number; maxLength?: number; /** Human-readable docs. Ignored by the enforcer, but the chat template renders the tools list * (parameters included) into the model's prompt, so a property `description` DOES reach the * model - the reason MCP/OpenAI tool schemas pass through unmodified. */ description?: string; title?: string; default?: unknown; examples?: unknown[]; deprecated?: boolean; readOnly?: boolean; writeOnly?: boolean; $comment?: string; $schema?: string; $id?: string; } /** Validate a schema against the enforceable subset; throws listing anything unsupported. */ declare function validateJsonSchema(schema: JsonSchema, path?: string, isRoot?: boolean): void; declare class JsonMachine { private readonly root; private stack; private phase; private uLeft; private utf8Left; private numSub; private numInt; private litWord; private litPos; private strKind; private strBuf; private strTracking; private enumCands; private strLenOn; private strCount; private strMin; private strMax; private numMin; private numMax; private numBuf; private pending; private wsRun; constructor(root?: JsonSchema | null); clone(): JsonMachine; get complete(): boolean; /** Feed bytes; false = the text stopped being a valid schema-conforming prefix (state is then undefined). */ feed(bytes: Uint8Array): boolean; private top; /** Byte-space form of a string literal (what strBuf accumulates). */ private static bytesOf; private openValue; /** A value just finished; land per the enclosing container and count array items. */ private closeValue; private closeContainer; /** Candidate property names for the key being typed (null = unconstrained). */ private keyCands; private startKey; /** Structural whitespace is never REQUIRED by JSON, so capping a run cannot make the grammar * unsatisfiable - but without a cap, a model denied prose can loop on whitespace forever (the * grammar permits it unboundedly) and burn the whole token budget producing "[ ". 16 bytes * allows generous pretty-printing indentation while forcing real progress. */ private ws; /** Integer bounds: can SOME digit-extension of the current number prefix (including "stop * here") land inside [min, max]? The attainable values from digit string D are * union over k >= 0 of sign * [D*10^k, (D+1)*10^k - 1]; leading-zero rules make 0 / -0 * terminal-only. Rejecting infeasible digits up front means the machine can never trap the * model in an unfinishable number. */ private intFeasible; /** May the current number END here (bounds permitting)? */ private intInRange; /** Accept a digit into the current number, bounds permitting. */ private numAppend; /** Count one code point of the current string, maxLength permitting. */ private strChar; private byte; /** In an enum/key-constrained string, the accumulated bytes must remain a prefix of some candidate. */ private enumOk; } interface TokenBytesSource { idToToken(id: number): string | undefined; addedTokenIds(): Set; } /** Precomputed id -> raw bytes lookup (lazy per id; added/special tokens map to null). */ declare class TokenByteTable { private readonly tk; private readonly cache; private readonly inv; private readonly added; constructor(tk: TokenBytesSource); bytes(id: number): Uint8Array | null; } //#endregion //#region src/chat/tools.d.ts /** A tool declaration, in the shape Qwen-family models were trained on (and the shape the * OpenAI/HF ecosystems use); the template serializes it verbatim into the system block. */ interface ChatTool { type: 'function'; function: { name: string; description?: string; /** JSON Schema for the arguments object - the same enforceable SUBSET as * format: { json: { schema } }, and the root must be an object. When omitted, the * arguments are only forced to be a valid JSON object. */ parameters?: JsonSchema; }; } /** One parsed tool call from the reply. With tools enabled the arguments are grammar-enforced, * so `JSON.parse` can never have failed; `raw` keeps the exact block text for forensics (and is * the only place to look if a block was cut short by maxTokens - then `name` is ''). */ interface ToolCall { name: string; arguments: Record; /** The exact text between and . */ raw: string; } /** Which tool the model must (or may) call. 'auto' (the default when tools are present) lets the * model decide; { name } FORCES a call to that tool as the entire reply - the forced path is * fully enforced end to end and is the reliable way to use small models. 'none' ignores the * tools for this turn. */ type ToolChoice = 'auto' | 'none' | { name: string; }; /** Validate a tools list + choice; throws on anything the enforcer cannot guarantee. */ declare function validateTools(tools: readonly ChatTool[], choice: ToolChoice): void; declare class ToolBodyMachine { private readonly cands; private readonly schemas; private phase; private lit; private nameBuf; private args; private wsRun; /** true once the closing '}' has landed (only trailing ws may follow). */ complete: boolean; /** the committed tool name (set when its closing quote lands). */ name: string; /** byte-space tool names, and each name's arguments schema */ constructor(cands: readonly string[], schemas: ReadonlyMap); clone(): ToolBodyMachine; static bytesOf(s: string): string; feed(bytes: Uint8Array): boolean; private byte; } /** The subset of ToolBodyMachine the candidate filter relies on (both format machines implement it). */ interface ToolBody { readonly complete: boolean; readonly name: string; feed(bytes: Uint8Array): boolean; clone(): ToolBody; /** When the machine sits at a DETERMINISTIC single-byte scaffold position (the '>' that commits a * name/key, the canonical scaffold '\n'), the byte that must come next - the filter then permits * ONLY the exact single-byte token, pinning the token boundaries to the model's canonical * tokenization (merged tokens like '>\n' produce identical text but off-distribution token ids, * which a 1-bit model cannot recover from). -1 = free position. */ forcedNext?(): number; } /** Per-tool spec the XML machine constrains against (all string keys/literals in BYTE space). */ interface XmlToolProps { keys: readonly string[]; required: readonly string[]; /** byte-space property key -> that parameter's schema (used to pick the value grammar). */ schemas?: ReadonlyMap; } declare class ToolBodyMachineXml implements ToolBody { private readonly cands; private readonly props; private phase; private lit; private nameBuf; private wsRun; private elem; private keyBuf; private keyCands; private declared; private valWs; private reqLeft; private valTail; private valStarted; private valMode; private valBuf; private valEnum; private valJson; private closeLit; complete: boolean; name: string; /** byte-space tool names, and per name its property keys / required subset / param schemas */ constructor(cands: readonly string[], props: ReadonlyMap); clone(): ToolBodyMachineXml; feed(bytes: Uint8Array): boolean; forcedNext(): number; private byte; } interface ToolMarkerIds { open: number; close: number; eos: number; thinkOpen?: number; thinkClose?: number; } interface PreparedTools { tools: readonly ChatTool[]; ids: ToolMarkerIds; /** null = 'auto'; a name = forced single call */ forced: string | null; /** the tool-call wire format the model's template uses: 'json' (Qwen3) or 'xml' (Qwen3.5) */ format: 'json' | 'xml'; } /** Per-step candidate filter for tool turns. Auto mode: free text (everything permitted) until * the model opens , then the body grammar takes over until , then free * text again (another call, prose, or eos). Forced mode: the FIRST token must be , * the body is constrained to the named tool, and after only eos is permitted. * Call advance() with each emitted token to move the real machine. */ declare function makeToolFilter(table: TokenByteTable, prep: PreparedTools, startInThink?: boolean): { filter: (ids: Uint32Array | number[]) => number[]; advance: (id: number) => void; }; /** Stream-safe block extraction (the tool sibling of ThinkSplitter): visible text on * one channel, each COMPLETED block's content as its own string, tags never surfacing anywhere. * Tags can straddle token boundaries, so chunk edges hold back possible partial tags. */ declare class ToolCallSplitter { private readonly open; private readonly close; private inside; private hold; private buf; constructor(open?: string, close?: string); push(chunk: string): { text: string; blocks: string[]; }; /** Emit whatever is held back. A block cut short by maxTokens surfaces as `partial` (its * content never reaches the visible text). */ flush(): { text: string; blocks: string[]; partial: string | null; }; } /** Parse one block's content into a ToolCall. With enforcement on this cannot fail for a * completed block; a failure (unenforced or truncated content) yields name '' and the raw text. */ declare function parseToolCall(raw: string): ToolCall; /** Parse one XML block's content into a ToolCall (the Qwen3.5 `` protocol). * Values are coerced by the tool's schema - string params keep their raw text, everything else is * JSON.parse'd. Returns name '' if the block names an unknown tool/property, a required property is * missing, or a non-string value is not valid JSON (so a surfaced call always conforms). */ declare function parseToolCallXml(raw: string, tools: readonly ChatTool[]): ToolCall; //#endregion //#region src/chat/think.d.ts interface SplitChunk { /** Visible reply text (outside any tag pair). */ text: string; /** Content inside the tag pair (the model's reasoning), without the tags themselves. */ think: string; } declare class ThinkSplitter { private readonly open; private readonly close; private inside; private hold; constructor(open?: string, close?: string, /** Start already inside a think block - for templates whose generation prompt PRE-OPENS `` * (e.g. Qwen3.5 thinking mode), so the opening tag is in the prompt, not the generated stream. */ startInside?: boolean); push(chunk: string): SplitChunk; /** Emit whatever is held back. An unterminated think block (generation hit maxTokens inside it) * flushes to the think channel, never to the visible reply. */ flush(): SplitChunk; } /** Stream-safe stop-sequence scanner: emits visible text up to (excluding) the earliest match of * any stop string, holding back chunk-edge suffixes that could begin one (stops can straddle * token boundaries). Once matched, everything further is swallowed. */ declare class StopScanner { private readonly stops; matched: boolean; private hold; constructor(stops: readonly string[]); push(text: string): string; flush(): string; } /** Confidence-based early stop for the think channel (training-free, DART-lineage heuristic). */ interface ThinkEarlyStop { /** Logit gap (top1 - top2) that counts as a "confident" step. */ gap: number; /** Consecutive confident steps required before firing. */ window: number; /** Reasoning tokens that must be spent before early stop may fire (don't cut the model off * before it has actually reasoned). */ minTokens: number; } /** Budget-forcing for the think channel (s1-style "budget forcing", training-free): counts the * tokens generated inside a block; once `budget` is spent - or the EARLY-STOP heuristic * fires (the model has been decisively confident for `window` consecutive steps after * `minTokens`, a signature of rote continuation rather than active reasoning) - `force()` names * `` as the only permitted candidate (the engine's constrained pick guarantees it is * reachable even when outside the top-K), so the model closes its reasoning and continues * straight into the visible answer. `budget: 0` suppresses reasoning entirely while keeping the * thinking-mode template. advance() must see every emitted token; observe() should see each * step's candidate logits (descending) BEFORE the pick - the filter callback receives exactly * that. */ declare class ThinkBudget { private readonly openId; private readonly closeId; private readonly budget; private readonly early; private inThink; private spent; private closed; private run; private earlyFired; private seen; constructor(openId: number | undefined, closeId: number | undefined, budget: number, startInside: boolean, early?: ThinkEarlyStop | null); advance(id: number): void; /** Feed one step's candidate logits (descending). Only meaningful inside think. Counted at most * once per emitted step: the engine re-invokes the candidate filter (and thus observe) once per * 512-token batch when it has to walk the full vocabulary for a forced token, and those * batch-local gaps must not eat the early-stop window. */ observe(vals: ArrayLike): void; /** The forced token id once the budget is exhausted or early stop fired, else null. */ force(): number | null; } //#endregion //#region src/chat/index.d.ts /** Options for {@link createChat}. Point it at the model directory (which already hosts * tokenizer.json + tokenizer_config.json next to the manifest), at explicit URLs, or at * preloaded JSON (bring your own caching, e.g. OPFS). */ interface ChatOptions { /** Directory holding tokenizer.json + tokenizer_config.json (usually the same modelUrl passed * to createEngine). */ modelUrl?: string; /** Explicit URLs (when the tokenizer files live elsewhere than the weights). */ tokenizerJsonUrl?: string; tokenizerConfigUrl?: string; /** Preloaded tokenizer files (skips fetching entirely). */ tokenizer?: { json: unknown; config: Record; }; /** Override fetching (custom caching / retries). Defaults to fetch + res.json(). */ fetchJson?: (url: string) => Promise; } /** Per-turn options. Sampling fields pass through to the engine (same semantics as * {@link GenerateOptions}); the rest control the chat layer. */ interface ChatSendOptions { maxTokens?: number; temperature?: number; topK?: number; topP?: number; minP?: number; repetitionPenalty?: number; presencePenalty?: number; /** DRY anti-loop penalty strength (see GenerateOptions.dryMultiplier). When set, the chat layer * supplies sequence-breaker token ids from the tokenizer (newline/punctuation/list markers) so * structural repetition is never penalized; pass `dryBreakers` to override. */ dryMultiplier?: number; dryBase?: number; dryAllowedLength?: number; dryRange?: number; dryBreakers?: number[]; topNSigma?: number; noRepeatNgramSize?: number; seed?: number; promptLookup?: GenerateOptions['promptLookup']; /** Per-token TRUE logprobs, N top alternatives per step (see GenerateOptions.logprobs) - * surface model confidence: a low top-1 logprob or a flat top-N is the model guessing. * Disables promptLookup for the turn. */ logprobs?: number; /** Extra stop token ids, in addition to the model's eos. */ stopTokens?: number[]; /** Stop STRINGS: generation ends when the visible reply contains one (matched across token * boundaries); the stop text and anything after it is never emitted, and `finishReason` is * 'stop'. A stop-sequence turn drops the KV cache afterwards (the cache holds a short token * overrun past the cut). */ stopSequences?: string[]; /** Called when the prompt alone exceeds the engine's KV window (maxSeqLen). Return a trimmed * message list to retry ONCE with (a clean full prefill), or null to rethrow the error. Pair * with {@link Chat.countTokens} to implement the trim policy. */ onOverflow?: (info: { promptTokenCount: number; maxSeqLen: number; }) => ChatMessage[] | null; signal?: AbortSignal; /** Render the template with enable_thinking and let the model reason. Think content streams to * `onThink` and lands in `result.thinkText`; it never appears in the visible reply. A think * turn drops the KV cache afterwards (the stripped reply cannot reproduce the cached tokens). * Default false. */ think?: boolean; /** Cap on reasoning length (thinking mode only): after this many generated think tokens the * engine may only emit ``, so the model wraps up and answers - "budget forcing" for * slow on-device decode. `0` suppresses reasoning entirely (thinking template, no think * tokens). Unset = unlimited. Ignored when `think` is off. */ thinkBudget?: number; /** ADAPTIVE early stop for the reasoning phase (thinking mode only; composes with * `thinkBudget`, which stays the hard cap): when the model has been decisively confident - * top-1 vs top-2 logit gap >= `gap` - for `window` consecutive think tokens after at least * `minTokens` of reasoning, `` is forced and the answer begins. Sustained certainty * inside a think block is the signature of rote continuation, not active reasoning; cutting * there buys latency at little answer-quality cost. Pass `true` for the calibrated defaults. */ thinkEarlyStop?: boolean | { gap?: number; window?: number; minTokens?: number; }; /** Streamed visible reply text (clean deltas: UTF-8-safe, think blocks removed). */ onText?: (delta: string) => void; /** Streamed think content (only meaningful with `think: true`). */ onThink?: (delta: string) => void; /** Reuse the KV cache when this turn is a clean append to the previous one (the committed * conversation plus one new user turn). Default true; set false to force a full prefill. */ reuseCache?: boolean; /** Tools the model may call this turn, in the trained (OpenAI-shaped) declaration format. The * model's own chat template renders them into the system block; any blocks in the * reply are extracted (never shown as text), grammar-ENFORCED against the declared names and * each tool's `parameters` schema, and returned parsed in {@link ChatResult.toolCalls}. The * app executes a call and feeds the result back as a `tool` role message (plus the assistant * turn with its `tool_calls`); the engine never executes anything. Enforcement guarantees the * call's SHAPE, not its judgment - whether and what to call is model quality. Cannot combine * with `format`; disables `promptLookup` for the turn. */ tools?: ChatTool[]; /** 'auto' (default): the model decides. { name }: FORCE a call to that tool as the whole reply * (fully enforced end to end - the reliable mode for small models; implies think: false). * 'none': ignore `tools` this turn. */ toolChoice?: ToolChoice; /** Fired as each completed tool call is parsed during streaming. */ onToolCall?: (call: ToolCall) => void; /** Constrained decoding. `'json'` guarantees the reply is one complete, valid JSON value with * an object or array root: every generated token is validated against an incremental JSON * machine (invalid candidates are never sampled), and generation ends when the root value * closes. `{ json: { schema } }` additionally enforces a JSON Schema SUBSET token-by-token - * value types, `properties`/`required`/`additionalProperties: false`, `items`, * `minItems`/`maxItems`, string `enum`, `integer` - so the reply cannot even be shaped wrong * (an array that must hold 5 items cannot close at 1). Unsupported schema keywords throw * loudly up front. Check `finishReason === 'stop'` - `'length'` means maxTokens cut the value * short. Forces `think: false` and disables `promptLookup`. The guarantee is structural, not * semantic: a schema makes the output parse into the right shape, not be true. */ format?: 'json' | { json: { schema?: JsonSchema; }; }; } interface ChatResult { /** The visible reply (think blocks and tool_call blocks removed). */ text: string; /** Content of blocks, when the model emitted any. */ thinkText: string; /** Parsed tool calls, in emission order (empty when the model answered in prose or no tools * were given). Grammar enforcement makes every COMPLETED call well-formed; a call cut short * by maxTokens has name '' and its partial text in `raw` (finishReason is then 'length'). */ toolCalls: ToolCall[]; /** Generated token ids (as returned by the engine; excludes the prompt). */ tokens: number[]; /** The exact token ids fed to the engine this turn (the full prompt, or the reuse delta). */ inputTokenIds: number[]; /** Why generation ended ('tool_calls' = ended at eos after making tool calls). */ finishReason: 'stop' | 'length' | 'abort' | 'tool_calls'; /** True when this turn extended the KV cache instead of a full prefill. */ reusedCache: boolean; /** Per-token logprob records aligned with `tokens` (present when options.logprobs was set). */ logprobs?: TokenLogprobs[]; prefillMs: number; decodeMs: number; tokensPerSecond: number; } /** A saved conversation from {@link Chat.save}: the engine's {@link KvSnapshot} plus the * chat-layer bookkeeping that makes cache reuse safe. Structured-cloneable (store in * IndexedDB / OPFS or postMessage as-is; NOT `JSON.stringify`-able - the KV buffer would be * lost). Treat the fields as opaque. */ interface ChatSnapshot { /** Snapshot format version (currently `1`). */ version: 1; /** The engine-level KV cache + token history snapshot. */ engine: KvSnapshot; /** The committed transcript the cache holds, as messages. */ committed: ChatMessage[]; /** Whether the cached token sequence already ends with the eos token. */ cacheEndsAtEos: boolean; /** Canonical JSON of the tools list the conversation was rendered with (null = no tools). */ toolsKey: string | null; } interface Chat { /** Generate a reply for the message list. Resolves with the full result; stream text via * `onText`. Turns are serialized: overlapping calls queue instead of interleaving. */ send(messages: ChatMessage[], options?: ChatSendOptions): Promise; /** Generate a reply as an async generator of visible-text deltas; the final {@link ChatResult} * is the generator's return value: `const it = chat.stream(msgs); for await (const d of it) ...` */ stream(messages: ChatMessage[], options?: ChatSendOptions): AsyncGenerator; /** Prefill a message prefix (e.g. the static system prompt) into the KV cache without decoding, * so the first real turn is a cheap cache-append instead of a cold full prefill. Pass the same * `tools` the turns will use - the template renders them into the system block, so a prewarm * without them warms a different prompt. */ prewarm(messages: ChatMessage[], opts?: { tools?: ChatTool[]; }): Promise; /** Token count of the rendered prompt for a message list (chat template applied) - use for * window budgeting against `engine.capabilities.maxSeqLen`, e.g. in an onOverflow policy. */ countTokens(messages: ChatMessage[], opts?: { addGenerationPrompt?: boolean; think?: boolean; tools?: ChatTool[]; }): number; /** Forget the conversation: clears the engine's KV cache and the chat's committed transcript. * Use this (not engine.resetCache()) so the two stay in sync. */ reset(): void; /** Snapshot the conversation - the engine's KV cache plus the chat's committed-transcript * bookkeeping - as one structured-cloneable object. Persist it (IndexedDB / OPFS) or ship it * to another worker; restoring it into a chat on the same model and `kvCache` mode makes the * next clean-append turn extend the cache exactly as if the conversation never stopped (no * re-prefill). Returns null when no conversation is committed. Queues behind in-flight turns * like send/stream. * * `{ delta: true }` makes a DELTA snapshot that excludes the shared prewarmed prefix (the system * messages + tools warmed with {@link Chat.prewarm}), so a per-conversation snapshot drops the * redundant system-prompt KV - tens of MB at chat scale, and a smaller structured-clone. Restore * it into a chat freshly `prewarm()`ed with the SAME system + tools (restore validates and throws * on a mismatch). Requires a prior prewarm(); throws otherwise. */ save(opts?: { delta?: boolean; }): Promise; /** Replace the current conversation with a saved snapshot (see {@link Chat.save}). Throws when * the snapshot does not match this engine's model or `kvCache` mode. */ restore(snapshot: ChatSnapshot): Promise; /** The model's end-of-sequence token id. */ readonly eosTokenId: number; /** Escape hatch: encode/decode/applyChatTemplate for callers that need the text boundary. */ readonly tokenizer: ChatTokenizer; } /** Load the tokenizer files and return a {@link Chat} bound to the engine. */ declare function createChat(engine: Engine, options: ChatOptions): Promise; //#endregion export { Chat, type ChatMessage, ChatOptions, ChatResult, ChatSendOptions, ChatSnapshot, ChatTokenizer, type ChatTool, type DecoderStream, JsonMachine, type JsonSchema, StopScanner, ThinkBudget, ThinkSplitter, ToolBodyMachine, ToolBodyMachineXml, type ToolCall, ToolCallSplitter, type ToolChoice, createChat, makeToolFilter, parseToolCall, parseToolCallXml, validateJsonSchema, validateTools }; //# sourceMappingURL=chat.d.ts.map