/** * Streaming-safe filters for leaked chat-template tool-call and thinking markup. * * Hosted models sometimes leak raw template markup into visible `content` instead * of returning structured events. Tool-call healing delegates to the same * dialect scanners used by owned in-band tool calling; this file keeps the * provider-facing compatibility wrapper and model/provider gating. */ export interface HealedToolCall { readonly id: string; readonly name: string; readonly arguments: string; } export type StreamMarkupHealingPattern = "kimi" | "dsml" | "thinking"; export interface StreamMarkupHealingOptions { readonly pattern: StreamMarkupHealingPattern; } export type StreamMarkupHealingEvent = { readonly type: "text"; readonly text: string; } | { readonly type: "thinking"; readonly thinking: string; } | { readonly type: "toolCall"; readonly call: HealedToolCall; }; /** * State machine that consumes streamed visible text and emits cleaned text, * thinking deltas, and reconstructed tool calls. * * A {@link ThinkingInbandScanner} always heals leaked reasoning idioms * (``, ``, ` ```thinking `, Gemma/Harmony channels, …) out of * the visible channel. For Kimi / DeepSeek-DSML the provider tool-call grammar * runs first and its cleaned text is piped through that thinking healer, so a * model can leak tool-call markup and reasoning in the same stream. * * Feed only one stream channel (usually `delta.content` / `message.content`). * Mixing reasoning and visible text into the same instance can corrupt held-back * partial tag buffers. */ export declare class StreamMarkupHealing { #private; constructor(options: StreamMarkupHealingOptions); get pattern(): StreamMarkupHealingPattern; /** * Feed a chunk and return visible text only. Reconstructed tool calls are * stored for {@link drainCompleted}; thinking blocks are intentionally not * returned by this compatibility helper. Use {@link feedEvents} when the caller * needs ordered text/thinking/tool-call events. */ feed(text: string): string; /** Feed a chunk and return cleaned text/thinking/tool-call events in stream order. */ feedEvents(text: string): StreamMarkupHealingEvent[]; /** * Feed a chunk and return cleaned events, excluding synthesized tool calls. * Used when the upstream chunk also carries structured `tool_calls`, keeping * that structured payload as the single source of truth while preserving * adjacent text and thinking events. */ feedEventsWithoutCalls(text: string): StreamMarkupHealingEvent[]; /** Drain accumulated tool calls from calls to {@link feed}. */ drainCompleted(): HealedToolCall[]; /** * Flush held-back stream-end fragments as ordered events. Partial tool-call * sections/envelopes are dropped by the delegated scanners; unterminated * thinking blocks are emitted as thinking, matching the previous MiniMax parser * behavior. */ flushEvents(): StreamMarkupHealingEvent[]; /** Flush held-back text only. Reconstructed calls are retained for {@link drainCompleted}. */ flushPending(): string; /** True once any configured tool-call section/envelope has fully closed. */ get sectionClosed(): boolean; } /** Cheap model/provider gate for Kimi-K2 chat-template token leaks. */ export declare function modelMayLeakKimiToolCalls(provider: string, modelId: string): boolean; /** Cheap model/provider gate for DeepSeek DSML envelope leaks. */ export declare function modelMayLeakDsmlToolCalls(provider: string, modelId: string): boolean; /** * Pick the leaked-markup healer for an OpenAI-compatible / Ollama visible-text * stream. Kimi chat-template tokens and DeepSeek DSML envelopes need their * dedicated tool-call grammars; every other model uses `"thinking"`. All three * patterns run the generic {@link ThinkingInbandScanner}, so leaked reasoning * idioms (e.g. a Gemini ` ```thinking ` fence on OpenRouter) are always healed. */ export declare function getStreamMarkupHealingPattern(provider: string, modelId: string): StreamMarkupHealingPattern;