/** * Translation helpers for the transformers.js LLM adapter. * * @module @nhtio/adk/batteries/llm/transformers_js/helpers * * @remarks * Two layers, like the other LLM batteries: * 1. **Re-exported format-agnostic helpers** from `chat_common` (string/trust-envelope renderers, * the joi→JSON-Schema converter, thought rendering/filtering) — reused verbatim. * 2. **transformers.js-native mappers** defined here — building the `{role,content}[]` message array * + the `tools` definitions, and a stream accumulator that collects decoded text (parsing of tool * calls / reasoning happens once after the stream drains, via the shared parser layer). */ import { Media } from "../../../index"; import { SpooledArtifact } from "../../../index"; import { defaultRenderArtifactHandleBody } from "../chat_common/helpers"; import { renderUntrustedContent as commonRenderUntrustedContent, renderTrustedContent as commonRenderTrustedContent, renderChatCompletionsSystemPrompt, renderStandingInstructions, renderMemories, renderRetrievables, renderRetrievableSafetyDirective, renderFirstPartyRetrievables, renderThirdPartyPublicRetrievables, renderThirdPartyPrivateRetrievables, renderRetrievableHandleBody, renderThought, filterThoughts } from "../openai_chat_completions/helpers"; import type { Tokenizable } from "../../../index"; import type { ArtifactTool, Tool } from "../../../index"; import type { ChatCompletionsTool } from "../openai_chat_completions/types"; import type { Message, Memory, Retrievable, Thought, ToolCall, ToolRegistry } from "../../../index"; import type { TransformersJsMessage, TransformersJsBucketOrder, UnsupportedMediaPolicy, DescriptionLike, JsonSchema } from "./types"; export { descriptionToChatCompletionsJsonSchema, defaultDescriptionToChatCompletionsJsonSchema, renderUntrustedContent, defaultRenderUntrustedContent, renderTrustedContent, defaultRenderTrustedContent, renderStandingInstructions, defaultRenderStandingInstructions, renderMemories, defaultRenderMemories, renderRetrievables, defaultRenderRetrievables, renderRetrievableHandleBody, defaultRenderRetrievableHandleBody, renderRetrievableSafetyDirective, defaultRenderRetrievableSafetyDirective, renderFirstPartyRetrievables, defaultRenderFirstPartyRetrievables, renderThirdPartyPublicRetrievables, defaultRenderThirdPartyPublicRetrievables, renderThirdPartyPrivateRetrievables, defaultRenderThirdPartyPrivateRetrievables, renderThought, defaultRenderThought, filterThoughts, defaultFilterThoughts, renderChatCompletionsSystemPrompt, defaultRenderChatCompletionsSystemPrompt, extractReasoningFields, } from "../openai_chat_completions/helpers"; export { renderArtifactHandleBody, defaultRenderArtifactHandleBody, looksLikeSpooledArtifact, } from "../chat_common/helpers"; export * from "../chat_common/tool_parsers"; export * from "../chat_common/reasoning_parsers"; export * from "../chat_common/lifecycle"; export * from "../chat_common/generation"; export * from "../chat_common/gpu_budget"; /** A tool definition in the transformers.js `tools` array (OpenAI-function-shaped). */ export interface TransformersJsTool { /** Always `'function'` — the only tool type transformers.js chat templates understand. */ type: 'function'; /** The function descriptor: name, optional description, and JSON-Schema parameters. */ function: { name: string; description?: string; parameters?: JsonSchema; }; } /** * Convert ADK {@link @nhtio/adk!Tool} / {@link @nhtio/adk!ArtifactTool} instances into the * transformers.js `tools` array shape (OpenAI-function-shaped — what `apply_chat_template` expects). */ export declare const toolsToTransformersJsTools: (tools: ReadonlyArray, deps?: { descriptionToChatCompletionsJsonSchema: (d: DescriptionLike) => JsonSchema; }) => TransformersJsTool[]; /** Default {@link toolsToTransformersJsTools}. */ export declare const defaultToolsToTransformersJsTools: (tools: ReadonlyArray, deps?: { descriptionToChatCompletionsJsonSchema: (d: DescriptionLike) => JsonSchema; }) => TransformersJsTool[]; /** * Render a {@link @nhtio/adk!ToolCall}'s `results` into a plain-text tool message body. * * @remarks * transformers.js chat templates take a `tool`-role message whose `content` is a string. A * `SpooledArtifact` result renders as a HANDLE (metadata + the forged `artifact_*` tools to read it) * when its `ToolCall.inline === false` — the secure default — and inline via `asString()` only when a * producer opted into `inline: true`. Applies the trust envelope and degrades Media to text. */ export declare const renderTransformersJsToolResult: (input: { toolCall: ToolCall; results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]; tool: Tool | ArtifactTool | undefined; unsupportedMediaPolicy: UnsupportedMediaPolicy; renderUntrustedContent: typeof commonRenderUntrustedContent; renderTrustedContent: typeof commonRenderTrustedContent; /** * Override for the artifact-handle body renderer (see {@link renderArtifactHandleBody}). Defaults to * the shared {@link defaultRenderArtifactHandleBody}. The adapter threads the consumer's * `helpers.renderArtifactHandleBody` here so an app can change which forged `artifact_*` reader the * model is steered toward first. */ renderArtifactHandleBody?: typeof defaultRenderArtifactHandleBody; warn?: (msg: string) => void; }) => Promise; /** Default {@link renderTransformersJsToolResult}. */ export declare const defaultRenderTransformersJsToolResult: (input: { toolCall: ToolCall; results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]; tool: Tool | ArtifactTool | undefined; unsupportedMediaPolicy: UnsupportedMediaPolicy; renderUntrustedContent: typeof commonRenderUntrustedContent; renderTrustedContent: typeof commonRenderTrustedContent; /** * Override for the artifact-handle body renderer (see {@link renderArtifactHandleBody}). Defaults to * the shared {@link defaultRenderArtifactHandleBody}. The adapter threads the consumer's * `helpers.renderArtifactHandleBody` here so an app can change which forged `artifact_*` reader the * model is steered toward first. */ renderArtifactHandleBody?: typeof defaultRenderArtifactHandleBody; warn?: (msg: string) => void; }) => Promise; /** * Build the transformers.js `messages` array + `tools` from the ADK dispatch context buckets. * * @remarks * Leading buckets (system prompt + standing instructions / memories / retrievables) render into a * single `system` message; the timeline (messages, surviving thoughts, tool calls — chronological) * renders into `user`/`assistant`/`tool` messages. Tools are returned separately for the `tools` * generate-kwarg. Mirrors `buildLiteRtConversationInput`. */ export declare const buildTransformersJsMessages: (input: { systemPrompt: Tokenizable; standingInstructions: Iterable; memories: Iterable; retrievables: Iterable; messages: Iterable; thoughts: Iterable; toolCalls: Iterable; tools: ToolRegistry; renderedToolCallResults: Map; bucketOrder: TransformersJsBucketOrder; selfIdentity: string; thoughtSurfacing: "all-self" | "latest-self" | "all"; replayCompatibility: ReadonlyArray; toolsToTransformersJsTools: typeof toolsToTransformersJsTools; renderThought: typeof renderThought; filterThoughts: typeof filterThoughts; renderUntrustedContent: typeof commonRenderUntrustedContent; renderTrustedContent: typeof commonRenderTrustedContent; renderChatCompletionsSystemPrompt: typeof renderChatCompletionsSystemPrompt; renderStandingInstructions: typeof renderStandingInstructions; renderMemories: typeof renderMemories; renderRetrievables: typeof renderRetrievables; renderRetrievableSafetyDirective: typeof renderRetrievableSafetyDirective; renderFirstPartyRetrievables: typeof renderFirstPartyRetrievables; renderThirdPartyPublicRetrievables: typeof renderThirdPartyPublicRetrievables; renderThirdPartyPrivateRetrievables: typeof renderThirdPartyPrivateRetrievables; renderRetrievableHandleBody?: typeof renderRetrievableHandleBody; /** * Multimodal config. Absent/false → text-only (every message renders a plain string `content`, the * byte-for-byte original behavior). When set, a message carrying `attachments` of an enabled kind * renders a content-array (text + `{type:'image'|'audio'}` placeholders) and the decoded media is * collected into `images`/`audio` (consumed positionally by `processor(prompt, images, audio)`). */ multimodal?: { image: boolean; audio: boolean; }; /** Decodes a Media instance to a transformers.js input (RawImage / audio samples). Adapter-injected. */ decodeMedia?: (media: Media) => Promise<{ kind: "image" | "audio"; data: unknown; }>; unsupportedMediaPolicy?: UnsupportedMediaPolicy; warn?: (msg: string) => void; }) => Promise<{ messages: TransformersJsMessage[]; tools: TransformersJsTool[]; images: unknown[]; audio: unknown[]; }>; /** Default {@link buildTransformersJsMessages}. */ export declare const defaultBuildTransformersJsMessages: (input: { systemPrompt: Tokenizable; standingInstructions: Iterable; memories: Iterable; retrievables: Iterable; messages: Iterable; thoughts: Iterable; toolCalls: Iterable; tools: ToolRegistry; renderedToolCallResults: Map; bucketOrder: TransformersJsBucketOrder; selfIdentity: string; thoughtSurfacing: "all-self" | "latest-self" | "all"; replayCompatibility: ReadonlyArray; toolsToTransformersJsTools: typeof toolsToTransformersJsTools; renderThought: typeof renderThought; filterThoughts: typeof filterThoughts; renderUntrustedContent: typeof commonRenderUntrustedContent; renderTrustedContent: typeof commonRenderTrustedContent; renderChatCompletionsSystemPrompt: typeof renderChatCompletionsSystemPrompt; renderStandingInstructions: typeof renderStandingInstructions; renderMemories: typeof renderMemories; renderRetrievables: typeof renderRetrievables; renderRetrievableSafetyDirective: typeof renderRetrievableSafetyDirective; renderFirstPartyRetrievables: typeof renderFirstPartyRetrievables; renderThirdPartyPublicRetrievables: typeof renderThirdPartyPublicRetrievables; renderThirdPartyPrivateRetrievables: typeof renderThirdPartyPrivateRetrievables; renderRetrievableHandleBody?: typeof renderRetrievableHandleBody; /** * Multimodal config. Absent/false → text-only (every message renders a plain string `content`, the * byte-for-byte original behavior). When set, a message carrying `attachments` of an enabled kind * renders a content-array (text + `{type:'image'|'audio'}` placeholders) and the decoded media is * collected into `images`/`audio` (consumed positionally by `processor(prompt, images, audio)`). */ multimodal?: { image: boolean; audio: boolean; }; /** Decodes a Media instance to a transformers.js input (RawImage / audio samples). Adapter-injected. */ decodeMedia?: (media: Media) => Promise<{ kind: "image" | "audio"; data: unknown; }>; unsupportedMediaPolicy?: UnsupportedMediaPolicy; warn?: (msg: string) => void; }) => Promise<{ messages: TransformersJsMessage[]; tools: TransformersJsTool[]; images: unknown[]; audio: unknown[]; }>; /** * Decode an ADK {@link @nhtio/adk!Media} into a transformers.js multimodal input. * * @remarks * Image → `RawImage.fromBlob(...)`; audio → `Float32Array` PCM at the model's sample rate (16 kHz * default) via `read_audio` over a `data:` URL. Imports `@huggingface/transformers` lazily, so it's * only loaded on the multimodal path. (Verified against a real Gemma-4 run — see plan 0a.) */ export declare const mediaToTransformersInput: (media: Media, opts?: { audioSampleRate?: number; }) => Promise<{ kind: "image" | "audio"; data: unknown; }>; /** Default {@link mediaToTransformersInput}. */ export declare const defaultMediaToTransformersInput: (media: Media, opts?: { audioSampleRate?: number; }) => Promise<{ kind: "image" | "audio"; data: unknown; }>; /** * A streaming accumulator over transformers.js `TextStreamer` decoded-text deltas. * * @remarks * transformers.js streams **decoded text** (via the `TextStreamer` callback), not structured events. * This accumulator just concatenates the deltas; tool-call and reasoning extraction run **once after * the stream drains**, over `content()`, via the shared parser layer. */ export interface TransformersJsStreamAccumulator { /** Feed one decoded-text delta; returns it (for live prose reporting). */ feed(delta: string): string; /** The full accumulated text. */ content(): string; } /** Create a {@link TransformersJsStreamAccumulator}. */ export declare const createTransformersJsStreamAccumulator: () => TransformersJsStreamAccumulator; /** Default {@link createTransformersJsStreamAccumulator}. */ export declare const defaultCreateTransformersJsStreamAccumulator: () => TransformersJsStreamAccumulator; export type { ChatCompletionsTool };