{"version":3,"file":"adapter.cjs","names":["#baseline","#pipeline","#resolvePipeline","#pipelinePromise","#mmEngine","#mmEnginePromise","#gen","#resolveMultimodalEngine","#multimodalFlags","#generateKwargs"],"sources":["../../../../src/batteries/llm/transformers_js/adapter.ts"],"sourcesContent":["/**\n * Dual-environment (Node + browser) executor adapter for transformers.js (`@huggingface/transformers`).\n *\n * @module @nhtio/adk/batteries/llm/transformers_js/adapter\n *\n * @remarks\n * On-device text generation via ONNX Runtime — `onnxruntime-node` (native) in Node, `onnxruntime-web`\n * (WASM + WebGPU) in the browser, auto-selected by the package. So this battery is\n * **environment-neutral**: it does NOT gate on WebGPU.\n *\n * **transformers.js is text-in / text-out.** It injects tool definitions into the chat template but\n * does NOT return structured tool calls or reasoning — the model emits both as **family-specific raw\n * text**. This adapter parses them out via the shared, configurable parser layer (`toolCallParser` /\n * `reasoningParser`, both defaulting to `'auto'`): after generation, the reasoning parser pulls\n * thinking into ADK Thoughts and the tool-call parser pulls calls into ADK ToolCalls, leaving clean\n * prose as the assistant Message.\n *\n * Three pluggable layers mirror the other LLM batteries: swappable translation helpers, three-layer\n * options merging (constructor → `executor()` overrides → `ctx.stash.transformersJs`), and an\n * injectable/lazy pipeline (`pipeline` or `createPipeline`, defaulting to a dynamic import).\n */\n\nimport { DateTime } from 'luxon'\nimport { sha256 } from 'js-sha256'\nimport { v6 as uuidv6 } from 'uuid'\nimport { validateOptions } from './validation'\nimport { withModelSource } from './model_source'\nimport { emitLifecycle } from '../chat_common/lifecycle'\nimport { E_LLM_GPU_OUT_OF_MEMORY } from '../chat_common/exceptions'\nimport { isError, isInstanceOf, isObject } from '@nhtio/adk/guards'\nimport { resolveToolCallParser } from '../chat_common/tool_parsers'\nimport { resolveGenerationOptions } from '../chat_common/generation'\nimport { canonicalStringify } from '../../../lib/utils/canonical_json'\nimport { resolveReasoningParser } from '../chat_common/reasoning_parsers'\nimport { InMemorySpoolStore } from '@nhtio/adk/batteries/storage/in_memory'\nimport { isGpuOutOfMemoryError, probeGpuBudget } from '../chat_common/gpu_budget'\nimport {\n  looksLikeSpooledArtifact,\n  stripEnvelopeSpecialTokens,\n  normalizeToolName,\n} from '../chat_common/helpers'\nimport {\n  Tokenizable,\n  ToolCall,\n  Message,\n  Thought,\n  SpooledArtifact,\n  Media,\n  ArtifactTool,\n} from '@nhtio/adk/common'\nimport {\n  E_TRANSFORMERS_JS_CONTEXT_OVERFLOW,\n  E_TRANSFORMERS_JS_STREAM_ERROR,\n  E_TRANSFORMERS_JS_INVALID_TOOL_CALL_ARGS,\n} from './exceptions'\nimport {\n  defaultDescriptionToChatCompletionsJsonSchema,\n  defaultRenderUntrustedContent,\n  defaultRenderTrustedContent,\n  defaultRenderStandingInstructions,\n  defaultRenderMemories,\n  defaultRenderRetrievables,\n  defaultRenderRetrievableHandleBody,\n  defaultRenderRetrievableSafetyDirective,\n  defaultRenderFirstPartyRetrievables,\n  defaultRenderThirdPartyPublicRetrievables,\n  defaultRenderThirdPartyPrivateRetrievables,\n  defaultRenderThought,\n  defaultFilterThoughts,\n  defaultRenderChatCompletionsSystemPrompt,\n  defaultToolsToTransformersJsTools,\n  defaultRenderTransformersJsToolResult,\n  defaultRenderArtifactHandleBody,\n  defaultBuildTransformersJsMessages,\n  defaultMediaToTransformersInput,\n  defaultCreateTransformersJsStreamAccumulator,\n} from './helpers'\nimport type { Tool } from '@nhtio/adk/common'\nimport type { DispatchContext } from '@nhtio/adk/types'\nimport type { ParsedToolCall } from '../chat_common/tool_parsers'\nimport type { TokenEncoding, TokenEncodingId } from '@nhtio/adk/types'\nimport type { ChatSampler, ResolvedGenerationOptions } from '../chat_common/generation'\nimport type { DispatchExecutorFn, DispatchExecutorHelpers } from '@nhtio/adk/dispatch_runner'\nimport type {\n  TransformersJsAdapterOptions,\n  TransformersJsPipeline,\n  TransformersJsModel,\n  TransformersJsProcessor,\n} from './types'\n\n// ─── Option merging (constructor → executor overrides → stash) ────────────────────────────────────\n\nconst mergeHelpers = (\n  layers: ReadonlyArray<Partial<NonNullable<TransformersJsAdapterOptions['helpers']>> | undefined>\n): Partial<NonNullable<TransformersJsAdapterOptions['helpers']>> | undefined => {\n  let merged: Partial<NonNullable<TransformersJsAdapterOptions['helpers']>> | undefined\n  for (const layer of layers) {\n    if (!layer) continue\n    merged = { ...(merged ?? {}), ...layer }\n  }\n  return merged\n}\n\nconst mergeOptions = (\n  baseline: TransformersJsAdapterOptions,\n  exec: Partial<TransformersJsAdapterOptions> | undefined,\n  stash: Partial<TransformersJsAdapterOptions> | undefined\n): Partial<TransformersJsAdapterOptions> => {\n  const layers = [baseline as Partial<TransformersJsAdapterOptions>, exec ?? {}, stash ?? {}]\n  const out: Record<string, unknown> = {}\n  for (const layer of layers) {\n    for (const [k, v] of Object.entries(layer)) {\n      if (v === undefined) continue\n      if (k === 'helpers') continue\n      out[k] = v\n    }\n  }\n  const helpers = mergeHelpers(layers.map((l) => l.helpers))\n  if (helpers !== undefined) out.helpers = helpers\n  return out as Partial<TransformersJsAdapterOptions>\n}\n\n// ─── Helper resolution (fall back to bundled defaults per field) ──────────────────────────────────\n\ninterface ResolvedHelpers {\n  descriptionToChatCompletionsJsonSchema: typeof defaultDescriptionToChatCompletionsJsonSchema\n  renderUntrustedContent: typeof defaultRenderUntrustedContent\n  renderTrustedContent: typeof defaultRenderTrustedContent\n  renderStandingInstructions: typeof defaultRenderStandingInstructions\n  renderMemories: typeof defaultRenderMemories\n  renderRetrievables: typeof defaultRenderRetrievables\n  renderRetrievableSafetyDirective: typeof defaultRenderRetrievableSafetyDirective\n  renderFirstPartyRetrievables: typeof defaultRenderFirstPartyRetrievables\n  renderThirdPartyPublicRetrievables: typeof defaultRenderThirdPartyPublicRetrievables\n  renderThirdPartyPrivateRetrievables: typeof defaultRenderThirdPartyPrivateRetrievables\n  renderThought: typeof defaultRenderThought\n  filterThoughts: typeof defaultFilterThoughts\n  renderChatCompletionsSystemPrompt: typeof defaultRenderChatCompletionsSystemPrompt\n  toolsToTransformersJsTools: typeof defaultToolsToTransformersJsTools\n  renderTransformersJsToolResult: typeof defaultRenderTransformersJsToolResult\n  renderArtifactHandleBody: typeof defaultRenderArtifactHandleBody\n  renderRetrievableHandleBody: typeof defaultRenderRetrievableHandleBody\n  buildTransformersJsMessages: typeof defaultBuildTransformersJsMessages\n  createTransformersJsStreamAccumulator: typeof defaultCreateTransformersJsStreamAccumulator\n}\n\nconst resolveHelpers = (\n  overrides: Partial<TransformersJsAdapterOptions['helpers']> | undefined\n): ResolvedHelpers => {\n  const src = (overrides ?? {}) as Record<string, unknown>\n  const pick = <K extends keyof ResolvedHelpers>(\n    key: K,\n    dflt: ResolvedHelpers[K]\n  ): ResolvedHelpers[K] => (src[key as string] as ResolvedHelpers[K]) ?? dflt\n  return {\n    descriptionToChatCompletionsJsonSchema: pick(\n      'descriptionToChatCompletionsJsonSchema',\n      defaultDescriptionToChatCompletionsJsonSchema\n    ),\n    renderUntrustedContent: pick('renderUntrustedContent', defaultRenderUntrustedContent),\n    renderTrustedContent: pick('renderTrustedContent', defaultRenderTrustedContent),\n    renderStandingInstructions: pick(\n      'renderStandingInstructions',\n      defaultRenderStandingInstructions\n    ),\n    renderMemories: pick('renderMemories', defaultRenderMemories),\n    renderRetrievables: pick('renderRetrievables', defaultRenderRetrievables),\n    renderRetrievableSafetyDirective: pick(\n      'renderRetrievableSafetyDirective',\n      defaultRenderRetrievableSafetyDirective\n    ),\n    renderFirstPartyRetrievables: pick(\n      'renderFirstPartyRetrievables',\n      defaultRenderFirstPartyRetrievables\n    ),\n    renderThirdPartyPublicRetrievables: pick(\n      'renderThirdPartyPublicRetrievables',\n      defaultRenderThirdPartyPublicRetrievables\n    ),\n    renderThirdPartyPrivateRetrievables: pick(\n      'renderThirdPartyPrivateRetrievables',\n      defaultRenderThirdPartyPrivateRetrievables\n    ),\n    renderThought: pick('renderThought', defaultRenderThought),\n    filterThoughts: pick('filterThoughts', defaultFilterThoughts),\n    renderChatCompletionsSystemPrompt: pick(\n      'renderChatCompletionsSystemPrompt',\n      defaultRenderChatCompletionsSystemPrompt\n    ),\n    toolsToTransformersJsTools: pick(\n      'toolsToTransformersJsTools',\n      defaultToolsToTransformersJsTools\n    ),\n    renderTransformersJsToolResult: pick(\n      'renderTransformersJsToolResult',\n      defaultRenderTransformersJsToolResult\n    ),\n    renderArtifactHandleBody: pick('renderArtifactHandleBody', defaultRenderArtifactHandleBody),\n    renderRetrievableHandleBody: pick(\n      'renderRetrievableHandleBody',\n      defaultRenderRetrievableHandleBody\n    ),\n    buildTransformersJsMessages: pick(\n      'buildTransformersJsMessages',\n      defaultBuildTransformersJsMessages\n    ),\n    createTransformersJsStreamAccumulator: pick(\n      'createTransformersJsStreamAccumulator',\n      defaultCreateTransformersJsStreamAccumulator\n    ),\n  }\n}\n\nconst nowIso = (): string => DateTime.now().toISO() as string\n\nconst computeChecksum = (tool: string, args: Record<string, unknown>): string =>\n  sha256(canonicalStringify({ tool, args }))\n\n/**\n * Wrap the consumer's `onInitProgress` so each transformers.js download event ALSO emits a normalized\n * `loading` lifecycle report. The HF `progress` field is 0..100 → forwarded as `progress` 0..1, with the\n * raw payload on `raw`. The original `onInitProgress` is still called verbatim (additive). Returns the\n * original callback unchanged when no lifecycle hooks are configured (zero overhead on the text path).\n */\nconst wrapTransformersInitProgress = (\n  merged: TransformersJsAdapterOptions\n): TransformersJsAdapterOptions['onInitProgress'] => {\n  const hasLifecycle =\n    merged.onLifecycle ??\n    merged.onLoading ??\n    merged.onReady ??\n    merged.onGenerating ??\n    merged.onError\n  if (!hasLifecycle) return merged.onInitProgress\n  return (info: unknown) => {\n    const p = (info as { progress?: number } | undefined)?.progress\n    emitLifecycle(merged, 'transformers_js', merged.model, 'loading', {\n      ...(typeof p === 'number' ? { progress: p / 100 } : {}),\n      raw: info,\n    })\n    merged.onInitProgress?.(info as never)\n  }\n}\n\n/** Markers that signal the start of tool-call / reasoning markup — used to stop streaming prose. */\nconst TEXT_MARKUP_MARKERS = [\n  '<tool_call>',\n  '<|tool_call>',\n  '<|channel',\n  '<think',\n  '[TOOL_CALLS]',\n  '<function=',\n]\n\n/** An assembled tool call ready for execution (args already a parsed object). */\ninterface AssembledToolCall {\n  id: string\n  name: string\n  args: Record<string, unknown>\n  argsWellFormed: boolean\n}\n\n/**\n * Translate a generation-time throw into the right battery exception: a typed, catchable\n * {@link @nhtio/adk/batteries!E_LLM_GPU_OUT_OF_MEMORY} when the message matches a known WebGPU\n * exhaustion signature (so an application can `catch` it structurally instead of string-matching ORT\n * internals — surface, don't impose), else the generic {@link E_TRANSFORMERS_JS_STREAM_ERROR}.\n *\n * @param err - The raw thrown value from `generate()` / streamer / pipeline.\n * @param contextNote - A short human-readable budget/window note carried on the OOM error's message,\n *   shown to the user verbatim by the application layer.\n */\nconst toGenerationError = (\n  err: unknown,\n  contextNote: string\n):\n  | InstanceType<typeof E_LLM_GPU_OUT_OF_MEMORY>\n  | InstanceType<typeof E_TRANSFORMERS_JS_STREAM_ERROR> => {\n  const message = isError(err) ? err.message : String(err)\n  if (isGpuOutOfMemoryError(message)) {\n    return new E_LLM_GPU_OUT_OF_MEMORY([message, contextNote], {\n      cause: isError(err) ? err : undefined,\n    })\n  }\n  return new E_TRANSFORMERS_JS_STREAM_ERROR([message])\n}\n\n/**\n * Whether the resolved device targets the WebGPU execution provider (a scalar `'webgpu'` or a\n * per-submodule record that puts the decoder on webgpu). KV-cache GPU-pinning only applies there —\n * on the wasm/cpu EP there is no `'gpu-buffer'` location and the pin would be meaningless.\n */\nconst isWebGpuDevice = (device: TransformersJsAdapterOptions['device']): boolean => {\n  if (device === undefined) return false\n  if (typeof device === 'string') return device === 'webgpu' || device === 'gpu'\n  // Per-submodule record: pin if the decoder (or any submodule) runs on webgpu.\n  return Object.values(device).some((d) => d === 'webgpu' || d === 'gpu')\n}\n\n/**\n * Build a `preferredOutputLocation` map pinning every KV-cache output (`present.N.key` /\n * `present.N.value`) to `'gpu-buffer'`, so the autoregressive KV cache lives in GPU memory instead of\n * the ONNX-Runtime-Web **wasm32 linear-memory heap** (hard-capped at 4 GiB by the 32-bit address space).\n *\n * @remarks\n * This is the battery's headline in-browser memory fix. transformers.js HAS auto-pinning for this\n * (session.js builds the same map for `cache_sessions` on webgpu), but it silently no-ops on models\n * whose config nests the head/layer counts (e.g. Gemma-4's `text_config`): `getCacheNames` returns\n * empty, so the decoder loads with `preferredOutputLocation: null` and the KV cache stays on the wasm\n * heap (measured: the live `present.*` tensors report `location: \"cpu\"`). Passing the map EXPLICITLY\n * moves them to `location: \"gpu-buffer\"` (measured). We over-specify the layer count — extra\n * `present.*` names that the model doesn't emit are simply ignored by the runtime — so we don't have to\n * read the architecture's layer count first. 96 covers every open-weight decoder we target.\n */\nconst buildKvCacheGpuPinMap = (layers = 96): Record<string, 'gpu-buffer'> => {\n  const map: Record<string, 'gpu-buffer'> = {}\n  for (let i = 0; i < layers; i++) {\n    map[`present.${i}.key`] = 'gpu-buffer'\n    map[`present.${i}.value`] = 'gpu-buffer'\n  }\n  return map\n}\n\n/**\n * Resolve the effective ONNX `session_options` for a load, applying the KV-cache GPU-pin DEFAULT.\n *\n * @remarks\n * Policy (surface-a-safe-default, keep the escape hatch): on the WebGPU EP, pin the KV cache to\n * `'gpu-buffer'` BY DEFAULT (keeps it off the 4 GiB wasm32 heap — the wall hit first in-browser). The\n * consumer can opt out wholesale (`pinKvCacheToGpu: false`) or override precisely (set their own\n * `sessionOptions.preferredOutputLocation`, which always wins — we never clobber an explicit one). On a\n * non-WebGPU device the pin is skipped (no `'gpu-buffer'` location exists there). Returns `undefined`\n * when there is nothing to pass (so the loader's `...(sessionOptions ? … : {})` spread stays a no-op).\n */\nconst resolveSessionOptions = (\n  merged: TransformersJsAdapterOptions\n): TransformersJsAdapterOptions['sessionOptions'] | undefined => {\n  const explicit = merged.sessionOptions\n  const wantPin = (merged.pinKvCacheToGpu ?? true) && isWebGpuDevice(merged.device)\n  // Don't pin if disabled, off-WebGPU, or the consumer already chose an output location (their call).\n  if (!wantPin || explicit?.preferredOutputLocation !== undefined) return explicit\n  return { ...(explicit ?? {}), preferredOutputLocation: buildKvCacheGpuPinMap() }\n}\n\n/**\n * Dual-environment executor adapter for transformers.js text generation.\n *\n * @remarks\n * Construct with at least `{ model }`; wire `new TransformersJsAdapter(opts).executor()` into a\n * `DispatchRunner` as the `executorCallback`. The pipeline is resolved lazily on first dispatch (or\n * eagerly via {@link TransformersJsAdapter.preload}); pass `pipeline` to inject a pre-built one.\n */\nexport class TransformersJsAdapter {\n  /** The `ctx.stash` key under which per-dispatch option overrides are read. */\n  public static readonly STASH_KEY = 'transformersJs' as const\n\n  readonly #baseline: TransformersJsAdapterOptions\n  #pipeline: TransformersJsPipeline | undefined\n  #pipelinePromise: Promise<TransformersJsPipeline> | undefined\n  #mmEngine: { model: TransformersJsModel; processor: TransformersJsProcessor } | undefined\n  #mmEnginePromise:\n    | Promise<{\n        model: TransformersJsModel\n        processor: TransformersJsProcessor\n      }>\n    | undefined\n\n  /**\n   * Whether this battery is available. transformers.js is environment-neutral (Node + browser), so this\n   * is `true` whenever the runtime can import the peer — there is no WebGPU requirement. Static form\n   * returns `true`; the instance form honours an injected `isAvailable` override.\n   */\n  public static isAvailable(): boolean {\n    return true\n  }\n\n  /**\n   * @param options - Raw adapter options, validated against `transformersJsOptionsSchema`.\n   * @throws {@link @nhtio/adk/batteries!E_INVALID_TRANSFORMERS_JS_OPTIONS} when `options` are invalid.\n   */\n  constructor(options: unknown) {\n    this.#baseline = validateOptions(options)\n    this.#pipeline = this.#baseline.pipeline\n  }\n\n  /** Instance availability probe (honours the `isAvailable` option override). */\n  isAvailable(): boolean {\n    return (this.#baseline.isAvailable ?? TransformersJsAdapter.isAvailable)()\n  }\n\n  /**\n   * Eagerly resolve (load) the pipeline before the first dispatch.\n   *\n   * @param overrides - Optional option overrides applied for this load.\n   */\n  async preload(\n    overrides?: Partial<TransformersJsAdapterOptions>\n  ): Promise<TransformersJsPipeline> {\n    const merged = validateOptions(mergeOptions(this.#baseline, overrides, undefined))\n    return this.#resolvePipeline(merged)\n  }\n\n  /** Drop the cached pipeline/engine and any in-flight load so the next dispatch re-resolves it. */\n  reset(): void {\n    this.#pipeline = undefined\n    this.#pipelinePromise = undefined\n    this.#mmEngine = undefined\n    this.#mmEnginePromise = undefined\n  }\n\n  /**\n   * Release the loaded model's underlying ONNX sessions + GPU/wasm buffers, then drop all cached\n   * references (so the next dispatch re-resolves a fresh pipeline).\n   *\n   * @remarks\n   * `reset()` only nulls the JS references — it does NOT free the native ONNX Runtime sessions or the\n   * WebGPU/wasm device memory they hold. Those leak until GC, and in a browser session that loads many\n   * models back-to-back (e.g. a full matrix run) the accumulated sessions exhaust the heap, surfacing as\n   * `Can't create a session … Failed to load external data file … memory copy`. transformers.js exposes\n   * `PreTrainedModel.dispose()` (\"disposes of all the ONNX sessions created during inference\") and\n   * `Pipeline.dispose()` — this awaits them so the memory is actually reclaimed between loads. Settles any\n   * in-flight load first, swallows per-handle disposal errors (a half-loaded model must not throw out of\n   * teardown), and finishes with `reset()`. Idempotent and safe to call when nothing is loaded.\n   */\n  async dispose(): Promise<void> {\n    // Settle any in-flight load so we dispose the resolved handle rather than orphaning it.\n    const pipeline = this.#pipeline ?? (await this.#pipelinePromise?.catch(() => undefined))\n    const mmEngine = this.#mmEngine ?? (await this.#mmEnginePromise?.catch(() => undefined))\n    const disposables: Array<Promise<unknown>> = []\n    const pipeWithDispose = pipeline as { dispose?: () => Promise<unknown> } | undefined\n    if (typeof pipeWithDispose?.dispose === 'function') {\n      disposables.push(Promise.resolve(pipeWithDispose.dispose()).catch(() => undefined))\n    }\n    const mmModel = mmEngine?.model as { dispose?: () => Promise<unknown> } | undefined\n    if (typeof mmModel?.dispose === 'function') {\n      disposables.push(Promise.resolve(mmModel.dispose()).catch(() => undefined))\n    }\n    await Promise.all(disposables)\n    this.reset()\n  }\n\n  /**\n   * Free the WebGPU buffer cache by releasing the model's ONNX sessions, then reload the same model.\n   *\n   * @remarks\n   * The consumer-facing lever for the ONNX Runtime Web WebGPU **buffer-freelist high-water-mark** (see\n   * {@link @nhtio/adk/batteries!probeGpuBudget} and the battery's GPU-budget notes). ORT-web parks freed\n   * activation buffers in per-size buckets sized to the largest tensor shape the model has run; the pool\n   * is flushed ONLY when every session of the model is released (ORT clears the cache at\n   * `sessionCount === 0`; microsoft/onnxruntime#22490). There is no public flag to flush it mid-life, so\n   * the supported way to reclaim that retained working-set without permanently unloading the model is to\n   * dispose the sessions and load again.\n   *\n   * This is exactly `dispose()` followed by `preload()` — surfaced as a named method because \"recycle to\n   * free the GPU buffer cache\" is a distinct, intentional operation (e.g. an application offering a\n   * \"free GPU memory\" action after a {@link @nhtio/adk/batteries!E_LLM_GPU_OUT_OF_MEMORY}), not a\n   * teardown. It is NOT invoked automatically by the battery — the ADK surfaces the lever and leaves the\n   * decision to the consumer. Re-incurs the cold-load cost (download is cached; the WebGPU graph/shader\n   * compile is not). Idempotent.\n   *\n   * @param overrides - Optional option overrides applied to the reload (same as {@link preload}).\n   */\n  async recycle(overrides?: Partial<TransformersJsAdapterOptions>): Promise<void> {\n    await this.dispose()\n    await this.preload(overrides)\n  }\n\n  /**\n   * Resolve the PORTABLE generation contract (shared with LiteRT-LM) from the merged options. Canonical\n   * fields win; the transformers.js-native fields ({@link TransformersJsAdapterOptions.maxNewTokens},\n   * `doSample`, `multimodal`, …) are the fallback layer consulted only when the canonical one is unset.\n   */\n  #gen(merged: TransformersJsAdapterOptions): ResolvedGenerationOptions {\n    // Native `multimodal` is `boolean | {image,audio}` → normalise to the canonical `{image,audio}` shape.\n    const mm = merged.multimodal\n    const normalizedMultimodal: { image?: boolean; audio?: boolean } | undefined =\n      mm === undefined || mm === false\n        ? mm === false\n          ? { image: false, audio: false }\n          : undefined\n        : mm === true\n          ? { image: true, audio: true }\n          : mm\n    // Native `doSample` boolean → canonical sampler strategy. `true` becomes `'top-p'` (the common\n    // nucleus default); an explicit `sampler` canonical field overrides this entirely.\n    const nativeSampler: ChatSampler | undefined =\n      merged.doSample === undefined ? undefined : merged.doSample ? 'top-p' : 'greedy'\n    return resolveGenerationOptions(\n      {\n        maxTokens: merged.maxTokens,\n        sampler: merged.sampler,\n        temperature: merged.temperature,\n        topK: merged.topK,\n        topP: merged.topP,\n        seed: merged.seed,\n        enableThinking: merged.enableThinking,\n        // The canonical `multimodal` IS the native field here (transformers.js already used `{image,audio}`);\n        // pass it as both so canonical-wins is a no-op and the normalized shape flows through.\n        multimodal: normalizedMultimodal,\n      },\n      {\n        maxTokens: merged.maxNewTokens,\n        sampler: nativeSampler,\n        multimodal: normalizedMultimodal,\n      }\n    )\n  }\n\n  /** Normalise multimodal config to `{image,audio}` flags, or undefined when fully off. */\n  #multimodalFlags(\n    merged: TransformersJsAdapterOptions\n  ): { image: boolean; audio: boolean } | undefined {\n    const { multimodal } = this.#gen(merged)\n    return multimodal.image || multimodal.audio ? multimodal : undefined\n  }\n\n  /** Resolve (and cache, single-flight) the multimodal model+processor pair. */\n  async #resolveMultimodalEngine(merged: TransformersJsAdapterOptions): Promise<{\n    model: TransformersJsModel\n    processor: TransformersJsProcessor\n  }> {\n    if (merged.multimodalEngine) {\n      this.#mmEngine = merged.multimodalEngine\n      return merged.multimodalEngine\n    }\n    if (this.#mmEngine) return this.#mmEngine\n    this.#mmEnginePromise ??= (async () => {\n      emitLifecycle(merged, 'transformers_js', merged.model, 'loading', {\n        detail: 'loading multimodal model + processor',\n      })\n      // Forward each provider download event into a `loading` lifecycle report (normalized 0..1).\n      const forwardedInitProgress = wrapTransformersInitProgress(merged)\n      try {\n        const createMultimodal =\n          merged.createMultimodal ??\n          (async ({ model, device, dtype, onInitProgress, sessionOptions }) => {\n            const transformers = await import('@huggingface/transformers')\n            const { AutoModelForImageTextToText, AutoProcessor, env } = transformers\n            const load = async () => {\n              const [m, processor] = await Promise.all([\n                AutoModelForImageTextToText.from_pretrained(model, {\n                  ...(device ? { device } : {}),\n                  ...(dtype ? { dtype } : {}),\n                  ...(onInitProgress ? { progress_callback: onInitProgress } : {}),\n                  // Forward ONNX Runtime session options verbatim (e.g. preferredOutputLocation,\n                  // graphOptimizationLevel). A reachable lever, not auto-applied — see options doc.\n                  ...(sessionOptions ? { session_options: sessionOptions } : {}),\n                } as never) as unknown as Promise<TransformersJsModel>,\n                AutoProcessor.from_pretrained(model) as unknown as Promise<TransformersJsProcessor>,\n              ])\n              return { model: m, processor }\n            }\n            // When a custom model source is configured, serve files through it (OPFS / bundled / etc.)\n            // behind the global-`env` mutex; otherwise load straight from HF (unchanged path).\n            return merged.modelSource\n              ? withModelSource(env as never, merged.modelSource, load)\n              : load()\n          })\n        // `from_pretrained` covers both fetch (reported via progress_callback → `loading`) and the\n        // ONNX-graph / WebGPU-WASM warmup. Mark the latter as `compiling` — a COARSE upper-bound marker\n        // (fetch + compile overlap inside the call, so this is \"now preparing the graph\", not a strict\n        // post-download boundary).\n        emitLifecycle(merged, 'transformers_js', merged.model, 'compiling', {\n          detail: 'compiling multimodal model graph',\n        })\n        const mmSessionOptions = resolveSessionOptions(merged)\n        const engine = await createMultimodal({\n          model: merged.model,\n          device: merged.device,\n          dtype: merged.dtype,\n          onInitProgress: forwardedInitProgress,\n          ...(mmSessionOptions ? { sessionOptions: mmSessionOptions } : {}),\n        })\n        this.#mmEngine = engine\n        emitLifecycle(merged, 'transformers_js', merged.model, 'ready', {\n          detail: 'multimodal model + processor ready',\n          // Surface the WebGPU budget so the consumer can relate its context window to the device's\n          // per-allocation ceiling — observability, never an imposed cap. Absent on non-WebGPU runtimes.\n          gpuBudget: await probeGpuBudget(),\n        })\n        return engine\n      } catch (err) {\n        this.#mmEnginePromise = undefined\n        emitLifecycle(merged, 'transformers_js', merged.model, 'error', {\n          error: err,\n        })\n        throw new E_TRANSFORMERS_JS_STREAM_ERROR([\n          `could not load the transformers.js multimodal model: ${isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`,\n        ])\n      }\n    })()\n    return this.#mmEnginePromise\n  }\n\n  async #resolvePipeline(merged: TransformersJsAdapterOptions): Promise<TransformersJsPipeline> {\n    if (merged.pipeline) {\n      this.#pipeline = merged.pipeline\n      return merged.pipeline\n    }\n    if (this.#pipeline) return this.#pipeline\n    this.#pipelinePromise ??= (async () => {\n      emitLifecycle(merged, 'transformers_js', merged.model, 'loading', {\n        detail: 'loading text-generation pipeline',\n      })\n      const forwardedInitProgress = wrapTransformersInitProgress(merged)\n      try {\n        const createPipeline =\n          merged.createPipeline ??\n          (async ({ model, device, dtype, onInitProgress, sessionOptions }) => {\n            const transformers = await import('@huggingface/transformers')\n            const { pipeline, env } = transformers\n            const load = async () =>\n              (await pipeline('text-generation', model, {\n                ...(device ? { device } : {}),\n                ...(dtype ? { dtype } : {}),\n                ...(onInitProgress ? { progress_callback: onInitProgress } : {}),\n                // Forward ONNX Runtime session options verbatim (e.g. preferredOutputLocation,\n                // graphOptimizationLevel). A reachable lever, not auto-applied — see options doc.\n                ...(sessionOptions ? { session_options: sessionOptions } : {}),\n              } as never)) as unknown as TransformersJsPipeline\n            return merged.modelSource\n              ? withModelSource(env as never, merged.modelSource, load)\n              : load()\n          })\n        // `from_pretrained` covers both fetch (reported via progress_callback → `loading`) and the\n        // ONNX-graph / WebGPU-WASM warmup. Mark the latter as `compiling` — a COARSE upper-bound marker\n        // (fetch + compile overlap inside the call, so this is \"now preparing the graph\", not a strict\n        // post-download boundary).\n        emitLifecycle(merged, 'transformers_js', merged.model, 'compiling', {\n          detail: 'compiling text-generation graph',\n        })\n        const pipelineSessionOptions = resolveSessionOptions(merged)\n        const pipe = await createPipeline({\n          model: merged.model,\n          device: merged.device,\n          dtype: merged.dtype,\n          onInitProgress: forwardedInitProgress,\n          ...(pipelineSessionOptions ? { sessionOptions: pipelineSessionOptions } : {}),\n        })\n        this.#pipeline = pipe\n        emitLifecycle(merged, 'transformers_js', merged.model, 'ready', {\n          detail: 'text-generation pipeline ready',\n          // Surface the WebGPU budget so the consumer can relate its context window to the device's\n          // per-allocation ceiling — observability, never an imposed cap. Absent on non-WebGPU runtimes.\n          gpuBudget: await probeGpuBudget(),\n        })\n        return pipe\n      } catch (err) {\n        this.#pipelinePromise = undefined\n        emitLifecycle(merged, 'transformers_js', merged.model, 'error', {\n          error: err,\n        })\n        throw new E_TRANSFORMERS_JS_STREAM_ERROR([\n          `could not load the transformers.js pipeline: ${isError(err) ? err.message : String(err)} — install the peer dependency (pnpm add @huggingface/transformers)`,\n        ])\n      }\n    })()\n    return this.#pipelinePromise\n  }\n\n  /**\n   * Build the transformers.js `generate` kwargs from the merged options (excluding tools/streamer).\n   *\n   * @remarks\n   * Every sampling/length knob is passed EXPLICITLY with a deterministic-friendly default (resolved via\n   * the shared {@link resolveGenerationOptions} from the portable contract) so the downstream `generate`\n   * never falls back to the model config's own guess — the source of per-model surprises. Greedy maps to\n   * `do_sample:false`; `'top-k'`/`'top-p'` map to `do_sample:true` + the matching cutoff.\n   */\n  #generateKwargs(merged: TransformersJsAdapterOptions): Record<string, unknown> {\n    const gen = this.#gen(merged)\n    const doSample = gen.sampler !== 'greedy'\n    const kw: Record<string, unknown> = {\n      max_new_tokens: gen.maxTokens,\n      do_sample: doSample,\n      repetition_penalty: merged.repetitionPenalty ?? 1.1,\n    }\n    // Sampler knobs are meaningful ONLY when sampling. Greedy ignores them and transformers.js logs a\n    // warning if they're set — so send them only when sampling. We always send BOTH top_k and top_p (the\n    // generate() call accepts both regardless of strategy; the strategy just determines which dominates),\n    // keeping the sampler fully specified. seed is forwarded when provided.\n    if (doSample) {\n      kw.temperature = gen.temperature\n      kw.top_k = gen.topK\n      kw.top_p = gen.topP\n      if (gen.seed !== undefined) kw.seed = gen.seed\n    }\n    if (merged.stopStrings !== undefined) kw.stop_strings = [...merged.stopStrings]\n    return kw\n  }\n\n  /**\n   * Produce the bound {@link DispatchExecutorFn} the `DispatchRunner` invokes.\n   *\n   * @param overrides - Option overrides layered above the constructor baseline (below `ctx.stash`).\n   */\n  executor(overrides?: Partial<TransformersJsAdapterOptions>): DispatchExecutorFn {\n    const baseline = this.#baseline\n    const adapterClass = TransformersJsAdapter\n    const self = this\n    return async (ctx: DispatchContext, helpers: DispatchExecutorHelpers): Promise<void> => {\n      // 1. Three-layer merge + re-validate.\n      const stashRaw = ctx.stash.get(adapterClass.STASH_KEY, {}) as unknown\n      const stashOverrides =\n        stashRaw && typeof stashRaw === 'object'\n          ? (stashRaw as Partial<TransformersJsAdapterOptions>)\n          : {}\n      const merged = validateOptions(mergeOptions(baseline, overrides, stashOverrides))\n      const h = resolveHelpers(merged.helpers)\n      const selfIdentity = merged.selfIdentity ?? 'assistant'\n      const unsupportedMediaPolicy = merged.unsupportedMediaPolicy ?? 'throw'\n      const toolCallParser = resolveToolCallParser(merged.toolCallParser)\n      const reasoningParser = resolveReasoningParser(merged.reasoningParser, undefined, {\n        orphanRecovery: merged.reasoningOrphanRecovery,\n      })\n\n      // 2. Artifact-reader tools are forged by the DispatchRunner CORE into `ctx.tools` before the input\n      //    pipeline runs (generation is a generic core concern; this battery owns only representation).\n      //    Read the pre-forged `ctx.tools` directly — no local merge, no bindContext here.\n\n      // 3. Pre-render persisted tool-call results into plain-text tool message bodies.\n      const renderedToolCallResults = new Map<ToolCall, string>()\n      for (const tc of ctx.turnToolCalls) {\n        const tool = ctx.tools.get(tc.tool)\n        const body = await h.renderTransformersJsToolResult({\n          toolCall: tc,\n          results: tc.results,\n          tool: tool as Tool | ArtifactTool | undefined,\n          unsupportedMediaPolicy,\n          renderUntrustedContent: h.renderUntrustedContent,\n          renderTrustedContent: h.renderTrustedContent,\n          renderArtifactHandleBody: h.renderArtifactHandleBody,\n          warn: (m) =>\n            helpers.log.warn({\n              kind: 'transformers-render-warning',\n              message: m,\n            }),\n        })\n        renderedToolCallResults.set(tc, body)\n      }\n\n      // 4. Optional context-window enforcement.\n      if (merged.tokenEncoding && merged.contextWindow !== undefined) {\n        const enc = merged.tokenEncoding\n        const tally = (s: string): number =>\n          new Tokenizable(s).estimateTokens(enc as TokenEncodingId)\n        let total = tally(ctx.systemPrompt.toString())\n        for (const si of ctx.standingInstructions) total += tally(si.toString())\n        for (const m of ctx.turnMemories) total += tally(m.content.toString())\n        for (const r of ctx.turnRetrievables) {\n          total +=\n            !r.inline && SpooledArtifact.isSpooledArtifact(r.content) && r.content.hasSizeHints()\n              ? r.content.estimateHandleTokens(\n                  r.id,\n                  enc as TokenEncoding,\n                  h.renderRetrievableHandleBody\n                )\n              : tally((await r.contentString?.()) ?? '')\n        }\n        for (const m of ctx.turnMessages) total += tally(m.content?.toString() ?? '')\n        for (const t of ctx.turnThoughts) total += tally(t.content.toString())\n        for (const body of renderedToolCallResults.values()) total += tally(body)\n        // Tool DECLARATIONS: transformers.js feeds the visible tools to `apply_chat_template({tools})`,\n        // where the MODEL'S OWN Jinja template wraps them (per-model, in-process) — so the exact rendered\n        // string isn't reproducible here without running the processor. Tally the serialized tool JSON\n        // (the reproducible, dominant component the adapter actually passes) as an honest FLOOR. Without\n        // this the guard undercounts a tool-heavy prompt by the entire declaration block.\n        const visibleTools = ctx.tools.visible()\n        if (visibleTools.length > 0) {\n          total += tally(JSON.stringify(h.toolsToTransformersJsTools(visibleTools)))\n        }\n        if (total > merged.contextWindow) {\n          throw new E_TRANSFORMERS_JS_CONTEXT_OVERFLOW([\n            total,\n            merged.contextWindow,\n            String(enc),\n            `system+buckets+timeline+tools=${total}`,\n          ])\n        }\n      }\n\n      // 5. Build the transformers.js message array + tools (+ decoded media when multimodal).\n      const mmFlags = self.#multimodalFlags(merged)\n      const {\n        messages: turnMessages,\n        tools: toolDefs,\n        images: mmImages,\n        audio: mmAudio,\n      } = await h.buildTransformersJsMessages({\n        systemPrompt: ctx.systemPrompt,\n        standingInstructions: ctx.standingInstructions,\n        memories: ctx.turnMemories,\n        retrievables: ctx.turnRetrievables,\n        messages: ctx.turnMessages,\n        thoughts: ctx.turnThoughts,\n        toolCalls: ctx.turnToolCalls,\n        tools: ctx.tools,\n        renderedToolCallResults,\n        bucketOrder: merged.bucketOrder ?? [\n          'standingInstructions',\n          'memories',\n          'retrievables',\n          'timeline',\n        ],\n        selfIdentity,\n        thoughtSurfacing: merged.thoughtSurfacing ?? 'all-self',\n        replayCompatibility: merged.replayCompatibility ?? [],\n        toolsToTransformersJsTools: h.toolsToTransformersJsTools,\n        renderThought: h.renderThought,\n        filterThoughts: h.filterThoughts,\n        renderUntrustedContent: h.renderUntrustedContent,\n        renderTrustedContent: h.renderTrustedContent,\n        renderChatCompletionsSystemPrompt: h.renderChatCompletionsSystemPrompt,\n        renderStandingInstructions: h.renderStandingInstructions,\n        renderMemories: h.renderMemories,\n        renderRetrievables: h.renderRetrievables,\n        renderRetrievableSafetyDirective: h.renderRetrievableSafetyDirective,\n        renderFirstPartyRetrievables: h.renderFirstPartyRetrievables,\n        renderThirdPartyPublicRetrievables: h.renderThirdPartyPublicRetrievables,\n        renderThirdPartyPrivateRetrievables: h.renderThirdPartyPrivateRetrievables,\n        renderRetrievableHandleBody: h.renderRetrievableHandleBody,\n        multimodal: mmFlags,\n        decodeMedia: mmFlags ? (media) => defaultMediaToTransformersInput(media) : undefined,\n        unsupportedMediaPolicy,\n        warn: (m) =>\n          helpers.log.warn({\n            kind: 'transformers-history-warning',\n            message: m,\n          }),\n      })\n\n      const spoolStore = merged.spoolStore ?? new InMemorySpoolStore()\n      const stream = merged.stream ?? true\n\n      // One id for this whole generation — correlates the TO tap (onPromptAssembled) with the FROM tap\n      // (onRawGeneration) and the reported message; both dispatch paths below reuse it.\n      const dispatchStreamId = uuidv6()\n\n      // Prompt-assembled observability tap: the EXACT messages + tools going TO the model, the instant\n      // assembly finished (above) and before the pipeline/generate dispatch (below). Mirror of\n      // onRawGeneration. Handed back AS-IS — no redaction — and swallow observer errors so it can never\n      // corrupt the generation path.\n      if (merged.onPromptAssembled) {\n        try {\n          merged.onPromptAssembled({\n            battery: 'transformers_js',\n            kind: 'rendered-prompt',\n            messages: turnMessages,\n            tools: toolDefs,\n            streamed: stream,\n            streamId: dispatchStreamId,\n          })\n        } catch {\n          /* observer errors are non-fatal */\n        }\n      }\n      const gen = self.#gen(merged)\n      const generateKwargs = self.#generateKwargs(merged)\n      const toolNames = ctx.tools.visible().map((t) => t.name)\n      // A short, user-facing note carried on a GPU-OOM error so the application can show WHY it failed\n      // and what to change. We surface the budget/window relationship, never silently cap it.\n      const oomNote =\n        merged.contextWindow !== undefined\n          ? `The configured context window (${merged.contextWindow} tokens, max ${gen.maxTokens} output) exceeded the available GPU memory. Reduce the context window or max output tokens and retry, recycle the adapter to free the WebGPU buffer cache, or switch to a smaller model.`\n          : `The request exceeded the available GPU memory. Reduce the context window or max output tokens and retry, recycle the adapter to free the WebGPU buffer cache, or switch to a smaller model.`\n\n      // 6. Resolve the engine: multimodal model+processor, or the text-generation pipeline.\n      let pipe: TransformersJsPipeline | undefined\n      let mmEngine: { model: TransformersJsModel; processor: TransformersJsProcessor } | undefined\n      try {\n        if (mmFlags) mmEngine = await self.#resolveMultimodalEngine(merged)\n        else pipe = await self.#resolvePipeline(merged)\n      } catch (err) {\n        // A cold WebGPU load can itself exhaust the device (\"Failed to create session\"). Surface that as\n        // the typed GPU-OOM so the consumer gets one consistent, catchable signal for load- and\n        // generation-time exhaustion alike; otherwise pass through the (already-typed) stream error.\n        const loadMsg = isError(err) ? err.message : String(err)\n        ctx.nack(\n          isGpuOutOfMemoryError(loadMsg)\n            ? toGenerationError(err, oomNote)\n            : isInstanceOf(err, 'E_TRANSFORMERS_JS_STREAM_ERROR', E_TRANSFORMERS_JS_STREAM_ERROR)\n              ? err\n              : new E_TRANSFORMERS_JS_STREAM_ERROR([loadMsg])\n        )\n        return\n      }\n\n      if (ctx.abortSignal.aborted) return\n\n      // ── Tool execution + persistence (args already an object — no JSON.parse) ──\n      const executeAndPersistToolCall = async (call: AssembledToolCall): Promise<void> => {\n        const tool = ctx.tools.get(call.name)\n        const completedAt = nowIso()\n        if (!call.argsWellFormed) {\n          const toolName = normalizeToolName(call.name)\n          const err = new E_TRANSFORMERS_JS_INVALID_TOOL_CALL_ARGS([\n            'must be a JSON object',\n            JSON.stringify(call.args),\n          ])\n          const results = new Tokenizable(err.message)\n          helpers.reportToolCall(call.id, { tool: toolName, args: {} })\n          helpers.reportToolCall(call.id, {\n            results,\n            isError: true,\n            isComplete: true,\n          })\n          await ctx.storeToolCall(\n            new ToolCall({\n              id: call.id,\n              tool: toolName,\n              args: {},\n              checksum: computeChecksum(toolName, {}),\n              isComplete: true,\n              isError: true,\n              results,\n              createdAt: completedAt,\n              updatedAt: completedAt,\n              completedAt,\n            })\n          )\n          return\n        }\n        if (!tool) {\n          const toolName = normalizeToolName(call.name)\n          const available = ctx.tools\n            .all()\n            .map((t) => t.name)\n            .sort()\n          const errText =\n            available.length > 0\n              ? `Tool not found: ${toolName}. Available tools: ${available.join(', ')}.`\n              : `Tool not found: ${toolName}. No tools are available this turn.`\n          const results = new Tokenizable(errText)\n          helpers.reportToolCall(call.id, { tool: toolName, args: call.args })\n          helpers.reportToolCall(call.id, {\n            results,\n            isError: true,\n            isComplete: true,\n          })\n          await ctx.storeToolCall(\n            new ToolCall({\n              id: call.id,\n              tool: toolName,\n              args: call.args,\n              checksum: computeChecksum(toolName, call.args),\n              isComplete: true,\n              isError: true,\n              results,\n              createdAt: completedAt,\n              updatedAt: completedAt,\n              completedAt,\n            })\n          )\n          return\n        }\n        helpers.reportToolCall(call.id, { tool: tool.name, args: call.args })\n        const isArtifactTool = ArtifactTool.isArtifactTool(tool)\n        let results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[] =\n          new Tokenizable('')\n        let toolHadError = false\n        try {\n          const raw = await tool.executor(ctx)(call.args)\n          if (isArtifactTool) {\n            results = Tokenizable.isTokenizable(raw)\n              ? raw\n              : typeof raw === 'string'\n                ? new Tokenizable(raw)\n                : (() => {\n                    throw new Error(\n                      `ArtifactTool \"${tool.name}\" returned a non-string/non-Tokenizable value`\n                    )\n                  })()\n          } else if (Media.isMedia(raw)) {\n            results = raw\n          } else if (Array.isArray(raw) && raw.length > 0 && raw.every((m) => Media.isMedia(m))) {\n            results = raw as Media[]\n          } else if (looksLikeSpooledArtifact(raw)) {\n            results = raw as SpooledArtifact\n          } else if (typeof raw === 'string' || isInstanceOf(raw, 'Uint8Array', Uint8Array)) {\n            const reader = await spoolStore.write(call.id, raw as string | Uint8Array)\n            const ArtifactCtor = (tool as Tool).artifactConstructor?.() ?? SpooledArtifact\n            results = new ArtifactCtor(reader)\n          } else {\n            const reader = await spoolStore.write(call.id, String(raw))\n            const ArtifactCtor = (tool as Tool).artifactConstructor?.() ?? SpooledArtifact\n            results = new ArtifactCtor(reader)\n          }\n        } catch (err) {\n          toolHadError = true\n          let detailMsg = isError(err) ? err.message : String(err)\n          if (isError(err) && isError(err.cause) && err.cause.message !== err.message) {\n            detailMsg = `${detailMsg} ${err.cause.message}`\n          }\n          results = new Tokenizable(detailMsg)\n        }\n        helpers.reportToolCall(call.id, {\n          results,\n          isError: toolHadError,\n          isComplete: true,\n        })\n        const completedAt2 = nowIso()\n        await ctx.storeToolCall(\n          new ToolCall({\n            id: call.id,\n            tool: tool.name,\n            args: call.args,\n            checksum: computeChecksum(tool.name, call.args),\n            isComplete: true,\n            isError: toolHadError,\n            results,\n            fromArtifactTool: isArtifactTool,\n            // ArtifactTool results are the documented exception: they inline the slice the model queried\n            // from a prior artifact (handing back a handle to a query result would be recursion). Every\n            // other result keeps the secure default (inline:false → handle).\n            inline: isArtifactTool,\n            createdAt: completedAt2,\n            updatedAt: completedAt2,\n            completedAt: completedAt2,\n          })\n        )\n      }\n\n      const assembleCalls = (raw: ReadonlyArray<ParsedToolCall>): AssembledToolCall[] =>\n        raw.map((c) => ({\n          id: uuidv6(),\n          name: c.name,\n          args: isObject(c.arguments) ? (c.arguments as Record<string, unknown>) : {},\n          argsWellFormed: isObject(c.arguments),\n        }))\n\n      // Parse the full generated text → reasoning + clean prose + tool calls, then persist.\n      const finishFromText = async (\n        rawText: string,\n        streamId: string,\n        streamedProse: boolean,\n        generatedMedia: Media[] = []\n      ): Promise<void> => {\n        // Normalise away non-semantic envelope/turn-boundary special tokens (Llama `<|python_tag|>`/\n        // `<|eom_id|>`, ChatML `<|im_end|>`, …) before parsing. The streaming path decodes with\n        // skip_special_tokens:false (its live prose-stop gate needs the markers), so without this the\n        // parsers would see `<|python_tag|>{json}<|eom_id|>` on stream and decline — even though the\n        // batch path (skip_special_tokens:true) parses the identical call. Idempotent on batch text.\n        const fullText = stripEnvelopeSpecialTokens(rawText)\n        const reasoned = reasoningParser(fullText)\n        const afterReasoning = reasoned.cleanedText\n        const parsed = toolCallParser(afterReasoning, { toolNames })\n        const cleanText = parsed.cleanedText\n\n        // Raw-generation observability tap: surface what the model emitted vs. what parsed, before any\n        // persistence. Purely observational — swallow callback errors so a misbehaving observer can\n        // never corrupt the generation path.\n        if (merged.onRawGeneration) {\n          try {\n            merged.onRawGeneration({\n              rawText: fullText,\n              cleanedText: cleanText,\n              reasoning: reasoned.reasoning,\n              toolCalls: parsed.calls,\n              streamed: streamedProse,\n              streamId,\n            })\n          } catch {\n            /* observer errors are non-fatal */\n          }\n        }\n\n        // Persist reasoning as Thoughts. Drop any trace whose trimmed content is empty — an\n        // empty/whitespace thought (e.g. a model's `<think>\\n\\n</think>` no-think artifact) carries no\n        // information and is just a model quirk; there is no point surfacing it to the consumer.\n        for (const trace of reasoned.reasoning) {\n          if (trace.trim().length === 0) continue\n          const id = uuidv6()\n          helpers.reportThought(id, trace, { isComplete: true })\n          await ctx.storeThought(\n            new Thought({\n              id,\n              content: trace,\n              identity: selfIdentity,\n              createdAt: nowIso(),\n              updatedAt: nowIso(),\n            })\n          )\n        }\n\n        // Persist the assistant message when there is clean prose OR generated media to carry. Media-only\n        // turns (empty text + an audio/image attachment) are legitimate; the contract requires at least one\n        // of `content`/`attachments`, so a turn with neither stores nothing (unchanged from before).\n        if (cleanText.length > 0 || generatedMedia.length > 0) {\n          if (streamedProse) {\n            helpers.reportMessage(streamId, '', { isComplete: true })\n          } else if (cleanText.length > 0) {\n            helpers.reportMessage(streamId, cleanText, { isComplete: true })\n          }\n          await ctx.storeMessage(\n            new Message({\n              id: streamId,\n              role: 'assistant',\n              ...(cleanText.length > 0 ? { content: cleanText } : {}),\n              ...(generatedMedia.length > 0 ? { attachments: generatedMedia } : {}),\n              identity: selfIdentity,\n              createdAt: nowIso(),\n              updatedAt: nowIso(),\n            })\n          )\n        }\n\n        // Execute tool calls.\n        const calls = assembleCalls(parsed.calls)\n        if (calls.length === 0) {\n          if (merged.autoAck) ctx.ack()\n          return\n        }\n        for (const call of calls) {\n          if (ctx.abortSignal.aborted) return\n          await executeAndPersistToolCall(call)\n        }\n      }\n\n      // ── Streaming path ──\n      // Unified generate: drives either the text-generation pipeline OR the multimodal model+processor.\n      // Returns the final decoded text for the non-streaming path; streaming text arrives via `streamer`.\n      // The raw generation object (model.generate / pipeline output) is captured here so the optional\n      // `extractMediaOutputs` hook can surface GENERATED media (audio/image) as assistant attachments.\n      let rawGenerationResult: unknown\n      const runGenerate = async (streamer: unknown): Promise<string> => {\n        if (mmEngine) {\n          const { model, processor } = mmEngine\n          const proc = processor as unknown as {\n            apply_chat_template: (m: unknown, o: unknown) => unknown\n            batch_decode: (t: unknown, o: unknown) => string[]\n          }\n          const callProc = processor as unknown as (\n            ...args: unknown[]\n          ) => Promise<Record<string, unknown>>\n          const prompt = proc.apply_chat_template(turnMessages, {\n            add_generation_prompt: true,\n            tokenize: false,\n            // Explicit thinking flag — never let the template default decide (Qwen3/DeepSeek default ON).\n            enable_thinking: gen.enableThinking,\n            // Pass tool DEFINITIONS through the native template mechanism, exactly as the pipeline path\n            // does. Gemma 4's chat_template renders these as `<|tool>…<tool|>` blocks, which is what\n            // cues the model to emit its TRAINED `call:NAME{…}` tool-call format. Omitting them (the\n            // prior bug) left the model with no native cue, so it improvised raw JSON args that no\n            // parser recognises. This is the multimodal-path equivalent of the pipeline's `tools` arg.\n            ...(toolDefs.length > 0 ? { tools: toolDefs } : {}),\n          })\n          // processor(text, images, audio, options) — positional (verified against the real Gemma-4\n          // `Gemma4Processor._call(text, images = null, audio = null, options)`). The audio slot is THIRD,\n          // so when audio is present the images slot MUST be filled positionally (with `null` when there\n          // is no image) — otherwise audio collapses into the images slot and the image processor throws\n          // `image.rgb is not a function`. `if (images)`/`if (audio)` in the processor treat `null` as absent.\n          const imageArg =\n            mmImages.length === 0 ? null : mmImages.length === 1 ? mmImages[0] : mmImages\n          const audioArg = mmAudio.length === 0 ? null : mmAudio.length === 1 ? mmAudio[0] : mmAudio\n          const procArgs: unknown[] =\n            mmAudio.length > 0\n              ? [prompt, imageArg, audioArg] // audio needs the 3rd slot → fill images (null if none)\n              : mmImages.length > 0\n                ? [prompt, imageArg]\n                : [prompt]\n          const inputs = await callProc(...procArgs)\n          // The processor INPUT tensors are GPU buffers we own. Free them no matter what — including\n          // when generate() itself OOMs — so a failed generate doesn't leak its inputs and starve the\n          // retry. (generate() is INSIDE this try precisely so the finally also covers its throw.)\n          try {\n            const out = await (\n              model as unknown as { generate: (o: unknown) => Promise<unknown> }\n            ).generate({\n              ...inputs,\n              ...generateKwargs,\n              ...(streamer ? { streamer } : {}),\n            })\n            rawGenerationResult = out\n            // Non-stream decode: slice the prompt tokens off, decode the new tail.\n            try {\n              const inputLen = (inputs.input_ids as { dims?: number[] } | undefined)?.dims?.[1] ?? 0\n              const seq = out as { slice?: (...a: unknown[]) => unknown }\n              const newTokens =\n                typeof seq.slice === 'function' ? seq.slice(null, [inputLen, null]) : out\n              const decoded = proc.batch_decode(newTokens, {\n                skip_special_tokens: true,\n              })\n              // Free the slice tensor (a fresh GPU buffer) once decoded — but only when it's distinct\n              // from `out`, which we still need for the media extractor (disposed after this returns).\n              if (newTokens !== out) disposeTensors(newTokens)\n              return (decoded?.[0] ?? '').toString()\n            } catch {\n              return ''\n            }\n          } finally {\n            disposeTensors(inputs)\n          }\n        }\n        const p = pipe as unknown as (m: unknown, k: unknown) => Promise<unknown>\n        const output = await p(turnMessages, {\n          ...generateKwargs,\n          // Explicit thinking flag forwarded to the pipeline's internal apply_chat_template — never let\n          // the template default decide (Qwen3/DeepSeek default thinking ON).\n          enable_thinking: gen.enableThinking,\n          ...(toolDefs.length > 0 ? { tools: toolDefs } : {}),\n          ...(streamer ? { streamer } : {}),\n        })\n        rawGenerationResult = output\n        return extractGeneratedText(output)\n      }\n\n      // Run the optional media-output extractor over the raw generation result, persisting each generated\n      // media via `ctx.storeMediaBytes` and building first-party `Media` attachments. Returns [] when no\n      // hook is configured or it yields nothing — the text-only path then attaches nothing (unchanged).\n      const collectGeneratedMedia = async (): Promise<Media[]> => {\n        if (!merged.extractMediaOutputs || rawGenerationResult === undefined) return []\n        const outputs = await merged.extractMediaOutputs(rawGenerationResult)\n        const media: Media[] = []\n        for (const o of outputs) {\n          const id = uuidv6()\n          const reader = await ctx.storeMediaBytes(id, o.bytes)\n          media.push(\n            Media.toolGenerated({\n              id,\n              kind: o.kind,\n              mimeType: o.mimeType,\n              filename: o.filename ?? `${id}.${o.kind}`,\n              reader,\n            })\n          )\n        }\n        return media\n      }\n      // Free the captured generate OUTPUT tensor after the media extractor (the only consumer of\n      // rawGenerationResult) has run. Together with disposing the processor inputs in runGenerate,\n      // this releases the caller-owned tensors per generate() — hygiene for the manual multimodal\n      // path, which (unlike the pipeline path) hands back tensors we own. Only the multimodal path\n      // captures a tensor here; the pipeline path returns plain objects, for which this is a no-op.\n      const disposeGenerationOutput = (): void => {\n        if (mmEngine && rawGenerationResult !== undefined) disposeTensors(rawGenerationResult)\n        rawGenerationResult = undefined\n      }\n\n      if (stream) {\n        const accumulator = h.createTransformersJsStreamAccumulator()\n        const streamId = dispatchStreamId\n        let proseStopped = false\n        let streamedProse = false\n\n        // The decoded-text sink: feed the accumulator + stream safe prose deltas (stopping prose once\n        // tool-call/think markup appears; the clean message is persisted after generation completes).\n        const onText = (text: string): void => {\n          accumulator.feed(text)\n          if (proseStopped) return\n          if (TEXT_MARKUP_MARKERS.some((m) => accumulator.content().includes(m))) {\n            proseStopped = true\n            return\n          }\n          if (text.length > 0) {\n            streamedProse = true\n            helpers.reportMessage(streamId, text)\n          }\n        }\n\n        // Default streamer factory imports the peer's TextStreamer; `createStreamer` overrides it\n        // (e.g. tests inject a lightweight sink to avoid importing the heavy peer in the browser env).\n        // The tokenizer comes from the multimodal processor when present, else the pipeline.\n        const tokenizerHost = (mmEngine?.processor ?? pipe) as unknown as {\n          tokenizer: unknown\n        }\n        const createStreamer =\n          merged.createStreamer ??\n          (async ({ onText: cb }) => {\n            const { TextStreamer } = await import('@huggingface/transformers')\n            return new TextStreamer(\n              tokenizerHost.tokenizer as never,\n              {\n                skip_prompt: true,\n                skip_special_tokens: false,\n                callback_function: cb,\n              } as never\n            )\n          })\n\n        let streamer: unknown\n        try {\n          streamer = await createStreamer({\n            pipeline: pipe as TransformersJsPipeline,\n            onText,\n          })\n        } catch (err) {\n          emitLifecycle(merged, 'transformers_js', merged.model, 'error', {\n            error: err,\n          })\n          ctx.nack(new E_TRANSFORMERS_JS_STREAM_ERROR([isError(err) ? err.message : String(err)]))\n          return\n        }\n\n        emitLifecycle(merged, 'transformers_js', merged.model, 'generating')\n        try {\n          await runGenerate(streamer)\n        } catch (err) {\n          if (ctx.abortSignal.aborted) return\n          emitLifecycle(merged, 'transformers_js', merged.model, 'error', {\n            error: err,\n          })\n          ctx.nack(toGenerationError(err, oomNote))\n          return\n        }\n        if (ctx.abortSignal.aborted) return\n        const streamMedia = await collectGeneratedMedia()\n        disposeGenerationOutput()\n        await finishFromText(accumulator.content(), streamId, streamedProse, streamMedia)\n        emitLifecycle(merged, 'transformers_js', merged.model, 'complete')\n        return\n      }\n\n      // ── Non-streaming path ──\n      let finalText: string\n      emitLifecycle(merged, 'transformers_js', merged.model, 'generating')\n      try {\n        finalText = await runGenerate(undefined)\n      } catch (err) {\n        emitLifecycle(merged, 'transformers_js', merged.model, 'error', {\n          error: err,\n        })\n        ctx.nack(toGenerationError(err, oomNote))\n        return\n      }\n      if (ctx.abortSignal.aborted) return\n      const nonStreamMedia = await collectGeneratedMedia()\n      disposeGenerationOutput()\n      await finishFromText(finalText, dispatchStreamId, false, nonStreamMedia)\n      emitLifecycle(merged, 'transformers_js', merged.model, 'complete')\n    }\n  }\n}\n\n/**\n * Free the GPU buffers backing a transformers.js value when running on the WebGPU EP.\n *\n * @remarks\n * onnxruntime-web does NOT garbage-collect GPU tensors — each `Tensor` whose `location` is\n * `'gpu-buffer'` owns a Dawn buffer that is reclaimed ONLY by an explicit `.dispose()`. In the\n * manual multimodal `model.generate()` path the battery creates the processor INPUT tensors and\n * captures the generate OUTPUT tensor; transformers.js frees its own internal decode-loop tensors\n * and KV cache, but these caller-owned tensors are ours to free. Skipping that leaks ~the full\n * activation set per `generate()`, so the SECOND generate on a loaded model (a tool-loop iteration,\n * the answer classifier, or simply the next turn) fails with \"Failed to allocate memory for buffer\n * mapping\". The matrix tests never caught this — each cell builds a fresh adapter and generates\n * exactly once.\n *\n * Accepts a processor-inputs object (a map of named tensors), a single tensor, or a nested\n * generate output; walks it shallowly and disposes anything tensor-shaped. Best-effort and never\n * throws — a disposal failure must not break generation. No-op for CPU/WASM tensors (which have no\n * `dispose` or aren't GPU-backed), so it's safe across execution providers.\n */\nconst disposeTensors = (value: unknown): void => {\n  const tryDispose = (t: unknown): void => {\n    const d = t as { dispose?: () => void; location?: string } | null | undefined\n    if (d && typeof d.dispose === 'function') {\n      try {\n        d.dispose()\n      } catch {\n        /* best-effort: a failed dispose must never break generation */\n      }\n    }\n  }\n  if (value === null || value === undefined) return\n  // A bare tensor (has its own dispose).\n  if (typeof (value as { dispose?: unknown }).dispose === 'function') {\n    tryDispose(value)\n    return\n  }\n  // A processor-inputs map { input_ids, attention_mask, pixel_values, … } or an array of tensors.\n  if (typeof value === 'object') {\n    for (const v of Object.values(value as Record<string, unknown>)) tryDispose(v)\n  }\n}\n\n/**\n * Pull the newly-generated assistant text out of a transformers.js text-generation result.\n *\n * @remarks\n * Chat input → `[{ generated_text: Message[] }]` (the last message is the new assistant turn);\n * string input → `[{ generated_text: string }]`. We always send chat input, so we take the last\n * message's content, falling back defensively to a string `generated_text`.\n */\nconst extractGeneratedText = (output: unknown): string => {\n  const first = Array.isArray(output) ? output[0] : output\n  const gen = (first as { generated_text?: unknown } | undefined)?.generated_text\n  if (typeof gen === 'string') return gen\n  if (Array.isArray(gen)) {\n    const last = gen[gen.length - 1] as { content?: unknown } | undefined\n    const content = last?.content\n    if (typeof content === 'string') return content\n    if (Array.isArray(content)) {\n      return content\n        .filter(\n          (i): i is { type: string; text: string } =>\n            isObject(i) && (i as { type?: unknown }).type === 'text'\n        )\n        .map((i) => i.text)\n        .join('')\n    }\n  }\n  return ''\n}\n\nexport { extractGeneratedText as __extractGeneratedText }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4FA,IAAM,gBACJ,WAC8E;CAC9E,IAAI;CACJ,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,CAAC,OAAO;EACZ,SAAS;GAAE,GAAI,UAAU,CAAC;GAAI,GAAG;EAAM;CACzC;CACA,OAAO;AACT;AAEA,IAAM,gBACJ,UACA,MACA,UAC0C;CAC1C,MAAM,SAAS;EAAC;EAAmD,QAAQ,CAAC;EAAG,SAAS,CAAC;CAAC;CAC1F,MAAM,MAA+B,CAAC;CACtC,KAAK,MAAM,SAAS,QAClB,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAK,GAAG;EAC1C,IAAI,MAAM,KAAA,GAAW;EACrB,IAAI,MAAM,WAAW;EACrB,IAAI,KAAK;CACX;CAEF,MAAM,UAAU,aAAa,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC;CACzD,IAAI,YAAY,KAAA,GAAW,IAAI,UAAU;CACzC,OAAO;AACT;AA0BA,IAAM,kBACJ,cACoB;CACpB,MAAM,MAAO,aAAa,CAAC;CAC3B,MAAM,QACJ,KACA,SACwB,IAAI,QAAyC;CACvE,OAAO;EACL,wCAAwC,KACtC,0CACA,gBAAA,6CACF;EACA,wBAAwB,KAAK,0BAA0B,gBAAA,6BAA6B;EACpF,sBAAsB,KAAK,wBAAwB,gBAAA,2BAA2B;EAC9E,4BAA4B,KAC1B,8BACA,gBAAA,iCACF;EACA,gBAAgB,KAAK,kBAAkB,gBAAA,qBAAqB;EAC5D,oBAAoB,KAAK,sBAAsB,gBAAA,yBAAyB;EACxE,kCAAkC,KAChC,oCACA,gBAAA,uCACF;EACA,8BAA8B,KAC5B,gCACA,gBAAA,mCACF;EACA,oCAAoC,KAClC,sCACA,gBAAA,yCACF;EACA,qCAAqC,KACnC,uCACA,gBAAA,0CACF;EACA,eAAe,KAAK,iBAAiB,gBAAA,oBAAoB;EACzD,gBAAgB,KAAK,kBAAkB,gBAAA,qBAAqB;EAC5D,mCAAmC,KACjC,qCACA,gBAAA,wCACF;EACA,4BAA4B,KAC1B,8BACA,8CAAA,iCACF;EACA,gCAAgC,KAC9B,kCACA,8CAAA,qCACF;EACA,0BAA0B,KAAK,4BAA4B,gBAAA,+BAA+B;EAC1F,6BAA6B,KAC3B,+BACA,gBAAA,kCACF;EACA,6BAA6B,KAC3B,+BACA,8CAAA,kCACF;EACA,uCAAuC,KACrC,yCACA,8CAAA,4CACF;CACF;AACF;AAEA,IAAM,eAAuB,MAAA,SAAS,IAAI,EAAE,MAAM;AAElD,IAAM,mBAAmB,MAAc,UAAA,GAAA,UAAA,QAC9B,yBAAA,mBAAmB;CAAE;CAAM;AAAK,CAAC,CAAC;;;;;;;AAQ3C,IAAM,gCACJ,WACmD;CAOnD,IAAI,EALF,OAAO,eACP,OAAO,aACP,OAAO,WACP,OAAO,gBACP,OAAO,UACU,OAAO,OAAO;CACjC,QAAQ,SAAkB;EACxB,MAAM,IAAK,MAA4C;EACvD,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,WAAW;GAChE,GAAI,OAAO,MAAM,WAAW,EAAE,UAAU,IAAI,IAAI,IAAI,CAAC;GACrD,KAAK;EACP,CAAC;EACD,OAAO,iBAAiB,IAAa;CACvC;AACF;;AAGA,IAAM,sBAAsB;CAC1B;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;;;;;;AAoBA,IAAM,qBACJ,KACA,gBAGyD;CACzD,MAAM,UAAU,eAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG;CACvD,IAAI,mBAAA,sBAAsB,OAAO,GAC/B,OAAO,IAAI,6CAAA,wBAAwB,CAAC,SAAS,WAAW,GAAG,EACzD,OAAO,eAAA,QAAQ,GAAG,IAAI,MAAM,KAAA,EAC9B,CAAC;CAEH,OAAO,IAAI,iDAAA,+BAA+B,CAAC,OAAO,CAAC;AACrD;;;;;;AAOA,IAAM,kBAAkB,WAA4D;CAClF,IAAI,WAAW,KAAA,GAAW,OAAO;CACjC,IAAI,OAAO,WAAW,UAAU,OAAO,WAAW,YAAY,WAAW;CAEzE,OAAO,OAAO,OAAO,MAAM,EAAE,MAAM,MAAM,MAAM,YAAY,MAAM,KAAK;AACxE;;;;;;;;;;;;;;;;AAiBA,IAAM,yBAAyB,SAAS,OAAqC;CAC3E,MAAM,MAAoC,CAAC;CAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK;EAC/B,IAAI,WAAW,EAAE,SAAS;EAC1B,IAAI,WAAW,EAAE,WAAW;CAC9B;CACA,OAAO;AACT;;;;;;;;;;;;AAaA,IAAM,yBACJ,WAC+D;CAC/D,MAAM,WAAW,OAAO;CAGxB,IAAI,GAFa,OAAO,mBAAmB,SAAS,eAAe,OAAO,MAAM,MAEhE,UAAU,4BAA4B,KAAA,GAAW,OAAO;CACxE,OAAO;EAAE,GAAI,YAAY,CAAC;EAAI,yBAAyB,sBAAsB;CAAE;AACjF;;;;;;;;;AAUA,IAAa,wBAAb,MAAa,sBAAsB;;CAEjC,OAAuB,YAAY;CAEnC;CACA;CACA;CACA;CACA;;;;;;CAYA,OAAc,cAAuB;EACnC,OAAO;CACT;;;;;CAMA,YAAY,SAAkB;EAC5B,KAAKA,YAAY,iDAAA,gBAAgB,OAAO;EACxC,KAAKC,YAAY,KAAKD,UAAU;CAClC;;CAGA,cAAuB;EACrB,QAAQ,KAAKA,UAAU,eAAe,sBAAsB,aAAa;CAC3E;;;;;;CAOA,MAAM,QACJ,WACiC;EACjC,MAAM,SAAS,iDAAA,gBAAgB,aAAa,KAAKA,WAAW,WAAW,KAAA,CAAS,CAAC;EACjF,OAAO,KAAKE,iBAAiB,MAAM;CACrC;;CAGA,QAAc;EACZ,KAAKD,YAAY,KAAA;EACjB,KAAKE,mBAAmB,KAAA;EACxB,KAAKC,YAAY,KAAA;EACjB,KAAKC,mBAAmB,KAAA;CAC1B;;;;;;;;;;;;;;;CAgBA,MAAM,UAAyB;EAE7B,MAAM,WAAW,KAAKJ,aAAc,MAAM,KAAKE,kBAAkB,YAAY,KAAA,CAAS;EACtF,MAAM,WAAW,KAAKC,aAAc,MAAM,KAAKC,kBAAkB,YAAY,KAAA,CAAS;EACtF,MAAM,cAAuC,CAAC;EAC9C,MAAM,kBAAkB;EACxB,IAAI,OAAO,iBAAiB,YAAY,YACtC,YAAY,KAAK,QAAQ,QAAQ,gBAAgB,QAAQ,CAAC,EAAE,YAAY,KAAA,CAAS,CAAC;EAEpF,MAAM,UAAU,UAAU;EAC1B,IAAI,OAAO,SAAS,YAAY,YAC9B,YAAY,KAAK,QAAQ,QAAQ,QAAQ,QAAQ,CAAC,EAAE,YAAY,KAAA,CAAS,CAAC;EAE5E,MAAM,QAAQ,IAAI,WAAW;EAC7B,KAAK,MAAM;CACb;;;;;;;;;;;;;;;;;;;;;;CAuBA,MAAM,QAAQ,WAAkE;EAC9E,MAAM,KAAK,QAAQ;EACnB,MAAM,KAAK,QAAQ,SAAS;CAC9B;;;;;;CAOA,KAAK,QAAiE;EAEpE,MAAM,KAAK,OAAO;EAClB,MAAM,uBACJ,OAAO,KAAA,KAAa,OAAO,QACvB,OAAO,QACL;GAAE,OAAO;GAAO,OAAO;EAAM,IAC7B,KAAA,IACF,OAAO,OACL;GAAE,OAAO;GAAM,OAAO;EAAK,IAC3B;EAGR,MAAM,gBACJ,OAAO,aAAa,KAAA,IAAY,KAAA,IAAY,OAAO,WAAW,UAAU;EAC1E,OAAO,mBAAA,yBACL;GACE,WAAW,OAAO;GAClB,SAAS,OAAO;GAChB,aAAa,OAAO;GACpB,MAAM,OAAO;GACb,MAAM,OAAO;GACb,MAAM,OAAO;GACb,gBAAgB,OAAO;GAGvB,YAAY;EACd,GACA;GACE,WAAW,OAAO;GAClB,SAAS;GACT,YAAY;EACd,CACF;CACF;;CAGA,iBACE,QACgD;EAChD,MAAM,EAAE,eAAe,KAAKC,KAAK,MAAM;EACvC,OAAO,WAAW,SAAS,WAAW,QAAQ,aAAa,KAAA;CAC7D;;CAGA,MAAMC,yBAAyB,QAG5B;EACD,IAAI,OAAO,kBAAkB;GAC3B,KAAKH,YAAY,OAAO;GACxB,OAAO,OAAO;EAChB;EACA,IAAI,KAAKA,WAAW,OAAO,KAAKA;EAChC,KAAKC,sBAAsB,YAAY;GACrC,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,WAAW,EAChE,QAAQ,uCACV,CAAC;GAED,MAAM,wBAAwB,6BAA6B,MAAM;GACjE,IAAI;IACF,MAAM,mBACJ,OAAO,qBACN,OAAO,EAAE,OAAO,QAAQ,OAAO,gBAAgB,qBAAqB;KAEnE,MAAM,EAAE,6BAA6B,eAAe,QAAQ,MADjC,OAAO;KAElC,MAAM,OAAO,YAAY;MACvB,MAAM,CAAC,GAAG,aAAa,MAAM,QAAQ,IAAI,CACvC,4BAA4B,gBAAgB,OAAO;OACjD,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;OAC3B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;OACzB,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,IAAI,CAAC;OAG9D,GAAI,iBAAiB,EAAE,iBAAiB,eAAe,IAAI,CAAC;MAC9D,CAAU,GACV,cAAc,gBAAgB,KAAK,CACrC,CAAC;MACD,OAAO;OAAE,OAAO;OAAG;MAAU;KAC/B;KAGA,OAAO,OAAO,cACV,mDAAA,gBAAgB,KAAc,OAAO,aAAa,IAAI,IACtD,KAAK;IACX;IAKF,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,aAAa,EAClE,QAAQ,mCACV,CAAC;IACD,MAAM,mBAAmB,sBAAsB,MAAM;IACrD,MAAM,SAAS,MAAM,iBAAiB;KACpC,OAAO,OAAO;KACd,QAAQ,OAAO;KACf,OAAO,OAAO;KACd,gBAAgB;KAChB,GAAI,mBAAmB,EAAE,gBAAgB,iBAAiB,IAAI,CAAC;IACjE,CAAC;IACD,KAAKD,YAAY;IACjB,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,SAAS;KAC9D,QAAQ;KAGR,WAAW,MAAM,mBAAA,eAAe;IAClC,CAAC;IACD,OAAO;GACT,SAAS,KAAK;IACZ,KAAKC,mBAAmB,KAAA;IACxB,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,SAAS,EAC9D,OAAO,IACT,CAAC;IACD,MAAM,IAAI,iDAAA,+BAA+B,CACvC,wDAAwD,eAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAAE,oEACnG,CAAC;GACH;EACF,GAAG;EACH,OAAO,KAAKA;CACd;CAEA,MAAMH,iBAAiB,QAAuE;EAC5F,IAAI,OAAO,UAAU;GACnB,KAAKD,YAAY,OAAO;GACxB,OAAO,OAAO;EAChB;EACA,IAAI,KAAKA,WAAW,OAAO,KAAKA;EAChC,KAAKE,sBAAsB,YAAY;GACrC,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,WAAW,EAChE,QAAQ,mCACV,CAAC;GACD,MAAM,wBAAwB,6BAA6B,MAAM;GACjE,IAAI;IACF,MAAM,iBACJ,OAAO,mBACN,OAAO,EAAE,OAAO,QAAQ,OAAO,gBAAgB,qBAAqB;KAEnE,MAAM,EAAE,UAAU,QAAQ,MADC,OAAO;KAElC,MAAM,OAAO,YACV,MAAM,SAAS,mBAAmB,OAAO;MACxC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;MAC3B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;MACzB,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,IAAI,CAAC;MAG9D,GAAI,iBAAiB,EAAE,iBAAiB,eAAe,IAAI,CAAC;KAC9D,CAAU;KACZ,OAAO,OAAO,cACV,mDAAA,gBAAgB,KAAc,OAAO,aAAa,IAAI,IACtD,KAAK;IACX;IAKF,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,aAAa,EAClE,QAAQ,kCACV,CAAC;IACD,MAAM,yBAAyB,sBAAsB,MAAM;IAC3D,MAAM,OAAO,MAAM,eAAe;KAChC,OAAO,OAAO;KACd,QAAQ,OAAO;KACf,OAAO,OAAO;KACd,gBAAgB;KAChB,GAAI,yBAAyB,EAAE,gBAAgB,uBAAuB,IAAI,CAAC;IAC7E,CAAC;IACD,KAAKF,YAAY;IACjB,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,SAAS;KAC9D,QAAQ;KAGR,WAAW,MAAM,mBAAA,eAAe;IAClC,CAAC;IACD,OAAO;GACT,SAAS,KAAK;IACZ,KAAKE,mBAAmB,KAAA;IACxB,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,SAAS,EAC9D,OAAO,IACT,CAAC;IACD,MAAM,IAAI,iDAAA,+BAA+B,CACvC,gDAAgD,eAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAAE,oEAC3F,CAAC;GACH;EACF,GAAG;EACH,OAAO,KAAKA;CACd;;;;;;;;;;CAWA,gBAAgB,QAA+D;EAC7E,MAAM,MAAM,KAAKG,KAAK,MAAM;EAC5B,MAAM,WAAW,IAAI,YAAY;EACjC,MAAM,KAA8B;GAClC,gBAAgB,IAAI;GACpB,WAAW;GACX,oBAAoB,OAAO,qBAAqB;EAClD;EAKA,IAAI,UAAU;GACZ,GAAG,cAAc,IAAI;GACrB,GAAG,QAAQ,IAAI;GACf,GAAG,QAAQ,IAAI;GACf,IAAI,IAAI,SAAS,KAAA,GAAW,GAAG,OAAO,IAAI;EAC5C;EACA,IAAI,OAAO,gBAAgB,KAAA,GAAW,GAAG,eAAe,CAAC,GAAG,OAAO,WAAW;EAC9E,OAAO;CACT;;;;;;CAOA,SAAS,WAAuE;EAC9E,MAAM,WAAW,KAAKN;EACtB,MAAM,eAAe;EACrB,MAAM,OAAO;EACb,OAAO,OAAO,KAAsB,YAAoD;GAEtF,MAAM,WAAW,IAAI,MAAM,IAAI,aAAa,WAAW,CAAC,CAAC;GAKzD,MAAM,SAAS,iDAAA,gBAAgB,aAAa,UAAU,WAHpD,YAAY,OAAO,aAAa,WAC3B,WACD,CAAC,CACwE,CAAC;GAChF,MAAM,IAAI,eAAe,OAAO,OAAO;GACvC,MAAM,eAAe,OAAO,gBAAgB;GAC5C,MAAM,yBAAyB,OAAO,0BAA0B;GAChE,MAAM,iBAAiB,qBAAA,sBAAsB,OAAO,cAAc;GAClE,MAAM,kBAAkB,mBAAA,uBAAuB,OAAO,iBAAiB,KAAA,GAAW,EAChF,gBAAgB,OAAO,wBACzB,CAAC;GAOD,MAAM,0CAA0B,IAAI,IAAsB;GAC1D,KAAK,MAAM,MAAM,IAAI,eAAe;IAClC,MAAM,OAAO,IAAI,MAAM,IAAI,GAAG,IAAI;IAClC,MAAM,OAAO,MAAM,EAAE,+BAA+B;KAClD,UAAU;KACV,SAAS,GAAG;KACN;KACN;KACA,wBAAwB,EAAE;KAC1B,sBAAsB,EAAE;KACxB,0BAA0B,EAAE;KAC5B,OAAO,MACL,QAAQ,IAAI,KAAK;MACf,MAAM;MACN,SAAS;KACX,CAAC;IACL,CAAC;IACD,wBAAwB,IAAI,IAAI,IAAI;GACtC;GAGA,IAAI,OAAO,iBAAiB,OAAO,kBAAkB,KAAA,GAAW;IAC9D,MAAM,MAAM,OAAO;IACnB,MAAM,SAAS,MACb,IAAI,oBAAA,YAAY,CAAC,EAAE,eAAe,GAAsB;IAC1D,IAAI,QAAQ,MAAM,IAAI,aAAa,SAAS,CAAC;IAC7C,KAAK,MAAM,MAAM,IAAI,sBAAsB,SAAS,MAAM,GAAG,SAAS,CAAC;IACvE,KAAK,MAAM,KAAK,IAAI,cAAc,SAAS,MAAM,EAAE,QAAQ,SAAS,CAAC;IACrE,KAAK,MAAM,KAAK,IAAI,kBAClB,SACE,CAAC,EAAE,UAAU,yBAAA,gBAAgB,kBAAkB,EAAE,OAAO,KAAK,EAAE,QAAQ,aAAa,IAChF,EAAE,QAAQ,qBACR,EAAE,IACF,KACA,EAAE,2BACJ,IACA,MAAO,MAAM,EAAE,gBAAgB,KAAM,EAAE;IAE/C,KAAK,MAAM,KAAK,IAAI,cAAc,SAAS,MAAM,EAAE,SAAS,SAAS,KAAK,EAAE;IAC5E,KAAK,MAAM,KAAK,IAAI,cAAc,SAAS,MAAM,EAAE,QAAQ,SAAS,CAAC;IACrE,KAAK,MAAM,QAAQ,wBAAwB,OAAO,GAAG,SAAS,MAAM,IAAI;IAMxE,MAAM,eAAe,IAAI,MAAM,QAAQ;IACvC,IAAI,aAAa,SAAS,GACxB,SAAS,MAAM,KAAK,UAAU,EAAE,2BAA2B,YAAY,CAAC,CAAC;IAE3E,IAAI,QAAQ,OAAO,eACjB,MAAM,IAAI,iDAAA,mCAAmC;KAC3C;KACA,OAAO;KACP,OAAO,GAAG;KACV,iCAAiC;IACnC,CAAC;GAEL;GAGA,MAAM,UAAU,KAAKQ,iBAAiB,MAAM;GAC5C,MAAM,EACJ,UAAU,cACV,OAAO,UACP,QAAQ,UACR,OAAO,YACL,MAAM,EAAE,4BAA4B;IACtC,cAAc,IAAI;IAClB,sBAAsB,IAAI;IAC1B,UAAU,IAAI;IACd,cAAc,IAAI;IAClB,UAAU,IAAI;IACd,UAAU,IAAI;IACd,WAAW,IAAI;IACf,OAAO,IAAI;IACX;IACA,aAAa,OAAO,eAAe;KACjC;KACA;KACA;KACA;IACF;IACA;IACA,kBAAkB,OAAO,oBAAoB;IAC7C,qBAAqB,OAAO,uBAAuB,CAAC;IACpD,4BAA4B,EAAE;IAC9B,eAAe,EAAE;IACjB,gBAAgB,EAAE;IAClB,wBAAwB,EAAE;IAC1B,sBAAsB,EAAE;IACxB,mCAAmC,EAAE;IACrC,4BAA4B,EAAE;IAC9B,gBAAgB,EAAE;IAClB,oBAAoB,EAAE;IACtB,kCAAkC,EAAE;IACpC,8BAA8B,EAAE;IAChC,oCAAoC,EAAE;IACtC,qCAAqC,EAAE;IACvC,6BAA6B,EAAE;IAC/B,YAAY;IACZ,aAAa,WAAW,UAAU,8CAAA,gCAAgC,KAAK,IAAI,KAAA;IAC3E;IACA,OAAO,MACL,QAAQ,IAAI,KAAK;KACf,MAAM;KACN,SAAS;IACX,CAAC;GACL,CAAC;GAED,MAAM,aAAa,OAAO,cAAc,IAAI,oCAAA,mBAAmB;GAC/D,MAAM,SAAS,OAAO,UAAU;GAIhC,MAAM,oBAAA,GAAA,KAAA,IAA0B;GAMhC,IAAI,OAAO,mBACT,IAAI;IACF,OAAO,kBAAkB;KACvB,SAAS;KACT,MAAM;KACN,UAAU;KACV,OAAO;KACP,UAAU;KACV,UAAU;IACZ,CAAC;GACH,QAAQ,CAER;GAEF,MAAM,MAAM,KAAKF,KAAK,MAAM;GAC5B,MAAM,iBAAiB,KAAKG,gBAAgB,MAAM;GAClD,MAAM,YAAY,IAAI,MAAM,QAAQ,EAAE,KAAK,MAAM,EAAE,IAAI;GAGvD,MAAM,UACJ,OAAO,kBAAkB,KAAA,IACrB,kCAAkC,OAAO,cAAc,eAAe,IAAI,UAAU,4LACpF;GAGN,IAAI;GACJ,IAAI;GACJ,IAAI;IACF,IAAI,SAAS,WAAW,MAAM,KAAKF,yBAAyB,MAAM;SAC7D,OAAO,MAAM,KAAKL,iBAAiB,MAAM;GAChD,SAAS,KAAK;IAIZ,MAAM,UAAU,eAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG;IACvD,IAAI,KACF,mBAAA,sBAAsB,OAAO,IACzB,kBAAkB,KAAK,OAAO,IAC9B,eAAA,aAAa,KAAK,kCAAkC,iDAAA,8BAA8B,IAChF,MACA,IAAI,iDAAA,+BAA+B,CAAC,OAAO,CAAC,CACpD;IACA;GACF;GAEA,IAAI,IAAI,YAAY,SAAS;GAG7B,MAAM,4BAA4B,OAAO,SAA2C;IAClF,MAAM,OAAO,IAAI,MAAM,IAAI,KAAK,IAAI;IACpC,MAAM,cAAc,OAAO;IAC3B,IAAI,CAAC,KAAK,gBAAgB;KACxB,MAAM,WAAW,gBAAA,kBAAkB,KAAK,IAAI;KAK5C,MAAM,UAAU,IAAI,oBAAA,YAAY,IAJhB,iDAAA,yCAAyC,CACvD,yBACA,KAAK,UAAU,KAAK,IAAI,CAC1B,CACgC,EAAI,OAAO;KAC3C,QAAQ,eAAe,KAAK,IAAI;MAAE,MAAM;MAAU,MAAM,CAAC;KAAE,CAAC;KAC5D,QAAQ,eAAe,KAAK,IAAI;MAC9B;MACA,SAAS;MACT,YAAY;KACd,CAAC;KACD,MAAM,IAAI,cACR,IAAI,kBAAA,SAAS;MACX,IAAI,KAAK;MACT,MAAM;MACN,MAAM,CAAC;MACP,UAAU,gBAAgB,UAAU,CAAC,CAAC;MACtC,YAAY;MACZ,SAAS;MACT;MACA,WAAW;MACX,WAAW;MACX;KACF,CAAC,CACH;KACA;IACF;IACA,IAAI,CAAC,MAAM;KACT,MAAM,WAAW,gBAAA,kBAAkB,KAAK,IAAI;KAC5C,MAAM,YAAY,IAAI,MACnB,IAAI,EACJ,KAAK,MAAM,EAAE,IAAI,EACjB,KAAK;KAKR,MAAM,UAAU,IAAI,oBAAA,YAHlB,UAAU,SAAS,IACf,mBAAmB,SAAS,qBAAqB,UAAU,KAAK,IAAI,EAAE,KACtE,mBAAmB,SAAS,oCACK;KACvC,QAAQ,eAAe,KAAK,IAAI;MAAE,MAAM;MAAU,MAAM,KAAK;KAAK,CAAC;KACnE,QAAQ,eAAe,KAAK,IAAI;MAC9B;MACA,SAAS;MACT,YAAY;KACd,CAAC;KACD,MAAM,IAAI,cACR,IAAI,kBAAA,SAAS;MACX,IAAI,KAAK;MACT,MAAM;MACN,MAAM,KAAK;MACX,UAAU,gBAAgB,UAAU,KAAK,IAAI;MAC7C,YAAY;MACZ,SAAS;MACT;MACA,WAAW;MACX,WAAW;MACX;KACF,CAAC,CACH;KACA;IACF;IACA,QAAQ,eAAe,KAAK,IAAI;KAAE,MAAM,KAAK;KAAM,MAAM,KAAK;IAAK,CAAC;IACpE,MAAM,iBAAiB,yBAAA,aAAa,eAAe,IAAI;IACvD,IAAI,UACF,IAAI,oBAAA,YAAY,EAAE;IACpB,IAAI,eAAe;IACnB,IAAI;KACF,MAAM,MAAM,MAAM,KAAK,SAAS,GAAG,EAAE,KAAK,IAAI;KAC9C,IAAI,gBACF,UAAU,oBAAA,YAAY,cAAc,GAAG,IACnC,MACA,OAAO,QAAQ,WACb,IAAI,oBAAA,YAAY,GAAG,WACZ;MACL,MAAM,IAAI,MACR,iBAAiB,KAAK,KAAK,8CAC7B;KACF,GAAG;UACJ,IAAI,kBAAA,MAAM,QAAQ,GAAG,GAC1B,UAAU;UACL,IAAI,MAAM,QAAQ,GAAG,KAAK,IAAI,SAAS,KAAK,IAAI,OAAO,MAAM,kBAAA,MAAM,QAAQ,CAAC,CAAC,GAClF,UAAU;UACL,IAAI,gBAAA,yBAAyB,GAAG,GACrC,UAAU;UACL,IAAI,OAAO,QAAQ,YAAY,eAAA,aAAa,KAAK,cAAc,UAAU,GAAG;MACjF,MAAM,SAAS,MAAM,WAAW,MAAM,KAAK,IAAI,GAA0B;MAEzE,UAAU,MADY,KAAc,sBAAsB,MAAK,yBAAA,iBACpC,MAAM;KACnC,OAAO;MACL,MAAM,SAAS,MAAM,WAAW,MAAM,KAAK,IAAI,OAAO,GAAG,CAAC;MAE1D,UAAU,MADY,KAAc,sBAAsB,MAAK,yBAAA,iBACpC,MAAM;KACnC;IACF,SAAS,KAAK;KACZ,eAAe;KACf,IAAI,YAAY,eAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG;KACvD,IAAI,eAAA,QAAQ,GAAG,KAAK,eAAA,QAAQ,IAAI,KAAK,KAAK,IAAI,MAAM,YAAY,IAAI,SAClE,YAAY,GAAG,UAAU,GAAG,IAAI,MAAM;KAExC,UAAU,IAAI,oBAAA,YAAY,SAAS;IACrC;IACA,QAAQ,eAAe,KAAK,IAAI;KAC9B;KACA,SAAS;KACT,YAAY;IACd,CAAC;IACD,MAAM,eAAe,OAAO;IAC5B,MAAM,IAAI,cACR,IAAI,kBAAA,SAAS;KACX,IAAI,KAAK;KACT,MAAM,KAAK;KACX,MAAM,KAAK;KACX,UAAU,gBAAgB,KAAK,MAAM,KAAK,IAAI;KAC9C,YAAY;KACZ,SAAS;KACT;KACA,kBAAkB;KAIlB,QAAQ;KACR,WAAW;KACX,WAAW;KACX,aAAa;IACf,CAAC,CACH;GACF;GAEA,MAAM,iBAAiB,QACrB,IAAI,KAAK,OAAO;IACd,KAAA,GAAA,KAAA,IAAW;IACX,MAAM,EAAE;IACR,MAAM,eAAA,SAAS,EAAE,SAAS,IAAK,EAAE,YAAwC,CAAC;IAC1E,gBAAgB,eAAA,SAAS,EAAE,SAAS;GACtC,EAAE;GAGJ,MAAM,iBAAiB,OACrB,SACA,UACA,eACA,iBAA0B,CAAC,MACT;IAMlB,MAAM,WAAW,gBAAA,2BAA2B,OAAO;IACnD,MAAM,WAAW,gBAAgB,QAAQ;IACzC,MAAM,iBAAiB,SAAS;IAChC,MAAM,SAAS,eAAe,gBAAgB,EAAE,UAAU,CAAC;IAC3D,MAAM,YAAY,OAAO;IAKzB,IAAI,OAAO,iBACT,IAAI;KACF,OAAO,gBAAgB;MACrB,SAAS;MACT,aAAa;MACb,WAAW,SAAS;MACpB,WAAW,OAAO;MAClB,UAAU;MACV;KACF,CAAC;IACH,QAAQ,CAER;IAMF,KAAK,MAAM,SAAS,SAAS,WAAW;KACtC,IAAI,MAAM,KAAK,EAAE,WAAW,GAAG;KAC/B,MAAM,MAAA,GAAA,KAAA,IAAY;KAClB,QAAQ,cAAc,IAAI,OAAO,EAAE,YAAY,KAAK,CAAC;KACrD,MAAM,IAAI,aACR,IAAI,gBAAA,QAAQ;MACV;MACA,SAAS;MACT,UAAU;MACV,WAAW,OAAO;MAClB,WAAW,OAAO;KACpB,CAAC,CACH;IACF;IAKA,IAAI,UAAU,SAAS,KAAK,eAAe,SAAS,GAAG;KACrD,IAAI,eACF,QAAQ,cAAc,UAAU,IAAI,EAAE,YAAY,KAAK,CAAC;UACnD,IAAI,UAAU,SAAS,GAC5B,QAAQ,cAAc,UAAU,WAAW,EAAE,YAAY,KAAK,CAAC;KAEjE,MAAM,IAAI,aACR,IAAI,gBAAA,QAAQ;MACV,IAAI;MACJ,MAAM;MACN,GAAI,UAAU,SAAS,IAAI,EAAE,SAAS,UAAU,IAAI,CAAC;MACrD,GAAI,eAAe,SAAS,IAAI,EAAE,aAAa,eAAe,IAAI,CAAC;MACnE,UAAU;MACV,WAAW,OAAO;MAClB,WAAW,OAAO;KACpB,CAAC,CACH;IACF;IAGA,MAAM,QAAQ,cAAc,OAAO,KAAK;IACxC,IAAI,MAAM,WAAW,GAAG;KACtB,IAAI,OAAO,SAAS,IAAI,IAAI;KAC5B;IACF;IACA,KAAK,MAAM,QAAQ,OAAO;KACxB,IAAI,IAAI,YAAY,SAAS;KAC7B,MAAM,0BAA0B,IAAI;IACtC;GACF;GAOA,IAAI;GACJ,MAAM,cAAc,OAAO,aAAuC;IAChE,IAAI,UAAU;KACZ,MAAM,EAAE,OAAO,cAAc;KAC7B,MAAM,OAAO;KAIb,MAAM,WAAW;KAGjB,MAAM,SAAS,KAAK,oBAAoB,cAAc;MACpD,uBAAuB;MACvB,UAAU;MAEV,iBAAiB,IAAI;MAMrB,GAAI,SAAS,SAAS,IAAI,EAAE,OAAO,SAAS,IAAI,CAAC;KACnD,CAAC;KAMD,MAAM,WACJ,SAAS,WAAW,IAAI,OAAO,SAAS,WAAW,IAAI,SAAS,KAAK;KACvE,MAAM,WAAW,QAAQ,WAAW,IAAI,OAAO,QAAQ,WAAW,IAAI,QAAQ,KAAK;KAOnF,MAAM,SAAS,MAAM,SAAS,GAL5B,QAAQ,SAAS,IACb;MAAC;MAAQ;MAAU;KAAQ,IAC3B,SAAS,SAAS,IAChB,CAAC,QAAQ,QAAQ,IACjB,CAAC,MAAM,CAC0B;KAIzC,IAAI;MACF,MAAM,MAAM,MACV,MACA,SAAS;OACT,GAAG;OACH,GAAG;OACH,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;MACjC,CAAC;MACD,sBAAsB;MAEtB,IAAI;OACF,MAAM,WAAY,OAAO,WAA+C,OAAO,MAAM;OACrF,MAAM,MAAM;OACZ,MAAM,YACJ,OAAO,IAAI,UAAU,aAAa,IAAI,MAAM,MAAM,CAAC,UAAU,IAAI,CAAC,IAAI;OACxE,MAAM,UAAU,KAAK,aAAa,WAAW,EAC3C,qBAAqB,KACvB,CAAC;OAGD,IAAI,cAAc,KAAK,eAAe,SAAS;OAC/C,QAAQ,UAAU,MAAM,IAAI,SAAS;MACvC,QAAQ;OACN,OAAO;MACT;KACF,UAAU;MACR,eAAe,MAAM;KACvB;IACF;IAEA,MAAM,SAAS,MAAM,KAAE,cAAc;KACnC,GAAG;KAGH,iBAAiB,IAAI;KACrB,GAAI,SAAS,SAAS,IAAI,EAAE,OAAO,SAAS,IAAI,CAAC;KACjD,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;IACjC,CAAC;IACD,sBAAsB;IACtB,OAAO,qBAAqB,MAAM;GACpC;GAKA,MAAM,wBAAwB,YAA8B;IAC1D,IAAI,CAAC,OAAO,uBAAuB,wBAAwB,KAAA,GAAW,OAAO,CAAC;IAC9E,MAAM,UAAU,MAAM,OAAO,oBAAoB,mBAAmB;IACpE,MAAM,QAAiB,CAAC;IACxB,KAAK,MAAM,KAAK,SAAS;KACvB,MAAM,MAAA,GAAA,KAAA,IAAY;KAClB,MAAM,SAAS,MAAM,IAAI,gBAAgB,IAAI,EAAE,KAAK;KACpD,MAAM,KACJ,kBAAA,MAAM,cAAc;MAClB;MACA,MAAM,EAAE;MACR,UAAU,EAAE;MACZ,UAAU,EAAE,YAAY,GAAG,GAAG,GAAG,EAAE;MACnC;KACF,CAAC,CACH;IACF;IACA,OAAO;GACT;GAMA,MAAM,gCAAsC;IAC1C,IAAI,YAAY,wBAAwB,KAAA,GAAW,eAAe,mBAAmB;IACrF,sBAAsB,KAAA;GACxB;GAEA,IAAI,QAAQ;IACV,MAAM,cAAc,EAAE,sCAAsC;IAC5D,MAAM,WAAW;IACjB,IAAI,eAAe;IACnB,IAAI,gBAAgB;IAIpB,MAAM,UAAU,SAAuB;KACrC,YAAY,KAAK,IAAI;KACrB,IAAI,cAAc;KAClB,IAAI,oBAAoB,MAAM,MAAM,YAAY,QAAQ,EAAE,SAAS,CAAC,CAAC,GAAG;MACtE,eAAe;MACf;KACF;KACA,IAAI,KAAK,SAAS,GAAG;MACnB,gBAAgB;MAChB,QAAQ,cAAc,UAAU,IAAI;KACtC;IACF;IAKA,MAAM,gBAAiB,UAAU,aAAa;IAG9C,MAAM,iBACJ,OAAO,mBACN,OAAO,EAAE,QAAQ,SAAS;KACzB,MAAM,EAAE,iBAAiB,MAAM,OAAO;KACtC,OAAO,IAAI,aACT,cAAc,WACd;MACE,aAAa;MACb,qBAAqB;MACrB,mBAAmB;KACrB,CACF;IACF;IAEF,IAAI;IACJ,IAAI;KACF,WAAW,MAAM,eAAe;MAC9B,UAAU;MACV;KACF,CAAC;IACH,SAAS,KAAK;KACZ,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,SAAS,EAC9D,OAAO,IACT,CAAC;KACD,IAAI,KAAK,IAAI,iDAAA,+BAA+B,CAAC,eAAA,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,CAAC,CAAC,CAAC;KACvF;IACF;IAEA,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,YAAY;IACnE,IAAI;KACF,MAAM,YAAY,QAAQ;IAC5B,SAAS,KAAK;KACZ,IAAI,IAAI,YAAY,SAAS;KAC7B,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,SAAS,EAC9D,OAAO,IACT,CAAC;KACD,IAAI,KAAK,kBAAkB,KAAK,OAAO,CAAC;KACxC;IACF;IACA,IAAI,IAAI,YAAY,SAAS;IAC7B,MAAM,cAAc,MAAM,sBAAsB;IAChD,wBAAwB;IACxB,MAAM,eAAe,YAAY,QAAQ,GAAG,UAAU,eAAe,WAAW;IAChF,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,UAAU;IACjE;GACF;GAGA,IAAI;GACJ,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,YAAY;GACnE,IAAI;IACF,YAAY,MAAM,YAAY,KAAA,CAAS;GACzC,SAAS,KAAK;IACZ,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,SAAS,EAC9D,OAAO,IACT,CAAC;IACD,IAAI,KAAK,kBAAkB,KAAK,OAAO,CAAC;IACxC;GACF;GACA,IAAI,IAAI,YAAY,SAAS;GAC7B,MAAM,iBAAiB,MAAM,sBAAsB;GACnD,wBAAwB;GACxB,MAAM,eAAe,WAAW,kBAAkB,OAAO,cAAc;GACvE,kBAAA,cAAc,QAAQ,mBAAmB,OAAO,OAAO,UAAU;EACnE;CACF;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,IAAM,kBAAkB,UAAyB;CAC/C,MAAM,cAAc,MAAqB;EACvC,MAAM,IAAI;EACV,IAAI,KAAK,OAAO,EAAE,YAAY,YAC5B,IAAI;GACF,EAAE,QAAQ;EACZ,QAAQ,CAER;CAEJ;CACA,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW;CAE3C,IAAI,OAAQ,MAAgC,YAAY,YAAY;EAClE,WAAW,KAAK;EAChB;CACF;CAEA,IAAI,OAAO,UAAU,UACnB,KAAK,MAAM,KAAK,OAAO,OAAO,KAAgC,GAAG,WAAW,CAAC;AAEjF;;;;;;;;;AAUA,IAAM,wBAAwB,WAA4B;CAExD,MAAM,OADQ,MAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,SACe;CACjE,IAAI,OAAO,QAAQ,UAAU,OAAO;CACpC,IAAI,MAAM,QAAQ,GAAG,GAAG;EAEtB,MAAM,UADO,IAAI,IAAI,SAAS,IACR;EACtB,IAAI,OAAO,YAAY,UAAU,OAAO;EACxC,IAAI,MAAM,QAAQ,OAAO,GACvB,OAAO,QACJ,QACE,MACC,eAAA,SAAS,CAAC,KAAM,EAAyB,SAAS,MACtD,EACC,KAAK,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;CAEd;CACA,OAAO;AACT"}