workers-ai-provider 3.1.13 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +183 -31
- package/dist/anthropic.d.mts +14 -0
- package/dist/anthropic.mjs +21 -0
- package/dist/anthropic.mjs.map +1 -0
- package/dist/gateway-delegate-BfaUTwDZ.d.mts +385 -0
- package/dist/gateway-provider-1USFWm7c.mjs +583 -0
- package/dist/gateway-provider-1USFWm7c.mjs.map +1 -0
- package/dist/gateway-provider.d.mts +80 -0
- package/dist/gateway-provider.mjs +2 -0
- package/dist/google.d.mts +14 -0
- package/dist/google.mjs +21 -0
- package/dist/google.mjs.map +1 -0
- package/dist/index.d.mts +64 -7
- package/dist/index.mjs +967 -327
- package/dist/index.mjs.map +1 -1
- package/dist/openai.d.mts +20 -0
- package/dist/openai.mjs +27 -0
- package/dist/openai.mjs.map +1 -0
- package/package.json +47 -6
- package/src/anthropic.ts +17 -0
- package/src/client-fallback.ts +70 -0
- package/src/convert-to-workersai-chat-messages.ts +33 -7
- package/src/errors.ts +216 -0
- package/src/gateway-delegate.ts +696 -0
- package/src/gateway-provider.ts +167 -0
- package/src/gateway-providers.ts +457 -0
- package/src/google.ts +19 -0
- package/src/index.ts +180 -9
- package/src/openai.ts +25 -0
- package/src/resumable-stream.ts +223 -0
- package/src/streaming.ts +103 -30
- package/src/utils.ts +206 -6
- package/src/workersai-chat-language-model.ts +87 -26
- package/src/workersai-chat-settings.ts +1 -1
- package/src/workersai-models.ts +11 -3
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["toUint8Array","uint8ArrayToBase64","toUint8Array"],"sources":["../src/convert-to-workersai-chat-messages.ts","../src/map-workersai-usage.ts","../src/map-workersai-finish-reason.ts","../src/streaming.ts","../src/utils.ts","../src/aisearch-chat-language-model.ts","../src/workersai-embedding-model.ts","../src/workersai-chat-language-model.ts","../src/workersai-image-model.ts","../src/workersai-transcription-model.ts","../src/workersai-speech-model.ts","../src/workersai-reranking-model.ts","../src/autorag-chat-language-model.ts","../src/index.ts"],"sourcesContent":["import type { LanguageModelV3DataContent, LanguageModelV3Prompt } from \"@ai-sdk/provider\";\nimport type { WorkersAIContentPart, WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n/**\n * Normalise any LanguageModelV3DataContent value to a Uint8Array.\n *\n * Handles:\n * - Uint8Array → returned as-is\n * - string → decoded from base64 (with or without data-URL prefix)\n * - URL → not supported (Workers AI needs raw bytes, not a reference)\n */\nfunction toUint8Array(data: LanguageModelV3DataContent): Uint8Array | null {\n\tif (data instanceof Uint8Array) {\n\t\treturn data;\n\t}\n\n\tif (typeof data === \"string\") {\n\t\tlet base64 = data;\n\t\tif (base64.startsWith(\"data:\")) {\n\t\t\tconst commaIndex = base64.indexOf(\",\");\n\t\t\tif (commaIndex >= 0) {\n\t\t\t\tbase64 = base64.slice(commaIndex + 1);\n\t\t\t}\n\t\t}\n\t\tconst binaryString = atob(base64);\n\t\tconst bytes = new Uint8Array(binaryString.length);\n\t\tfor (let i = 0; i < binaryString.length; i++) {\n\t\t\tbytes[i] = binaryString.charCodeAt(i);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tif (data instanceof URL) {\n\t\tthrow new Error(\n\t\t\t\"URL image sources are not supported by Workers AI. \" +\n\t\t\t\t\"Provide image data as a Uint8Array or base64 string instead.\",\n\t\t);\n\t}\n\n\treturn null;\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tconst chunkSize = 8192;\n\tfor (let i = 0; i < bytes.length; i += chunkSize) {\n\t\tconst chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));\n\t\tbinary += String.fromCharCode(...chunk);\n\t}\n\treturn btoa(binary);\n}\n\nexport function convertToWorkersAIChatMessages(prompt: LanguageModelV3Prompt): {\n\tmessages: WorkersAIChatPrompt;\n} {\n\tconst messages: WorkersAIChatPrompt = [];\n\n\tfor (const { role, content } of prompt) {\n\t\tswitch (role) {\n\t\t\tcase \"system\": {\n\t\t\t\tmessages.push({ content, role: \"system\" });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"user\": {\n\t\t\t\tconst textParts: string[] = [];\n\t\t\t\tconst imageParts: { image: Uint8Array; mediaType: string | undefined }[] = [];\n\n\t\t\t\tfor (const part of content) {\n\t\t\t\t\tswitch (part.type) {\n\t\t\t\t\t\tcase \"text\": {\n\t\t\t\t\t\t\ttextParts.push(part.text);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase \"file\": {\n\t\t\t\t\t\t\tconst imageBytes = toUint8Array(part.data);\n\t\t\t\t\t\t\tif (imageBytes) {\n\t\t\t\t\t\t\t\timageParts.push({\n\t\t\t\t\t\t\t\t\timage: imageBytes,\n\t\t\t\t\t\t\t\t\tmediaType: part.mediaType,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (imageParts.length > 0) {\n\t\t\t\t\tconst contentArray: WorkersAIContentPart[] = [];\n\t\t\t\t\tif (textParts.length > 0) {\n\t\t\t\t\t\tcontentArray.push({ type: \"text\", text: textParts.join(\"\\n\") });\n\t\t\t\t\t}\n\t\t\t\t\tfor (const img of imageParts) {\n\t\t\t\t\t\tconst base64 = uint8ArrayToBase64(img.image);\n\t\t\t\t\t\tconst mediaType = img.mediaType || \"image/png\";\n\t\t\t\t\t\tcontentArray.push({\n\t\t\t\t\t\t\ttype: \"image_url\",\n\t\t\t\t\t\t\timage_url: { url: `data:${mediaType};base64,${base64}` },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tmessages.push({ content: contentArray, role: \"user\" });\n\t\t\t\t} else {\n\t\t\t\t\tmessages.push({ content: textParts.join(\"\\n\"), role: \"user\" });\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"assistant\": {\n\t\t\t\tlet text = \"\";\n\t\t\t\tlet reasoning = \"\";\n\t\t\t\tconst toolCalls: Array<{\n\t\t\t\t\tid: string;\n\t\t\t\t\ttype: \"function\";\n\t\t\t\t\tfunction: { name: string; arguments: string };\n\t\t\t\t}> = [];\n\n\t\t\t\tfor (const part of content) {\n\t\t\t\t\tswitch (part.type) {\n\t\t\t\t\t\tcase \"text\": {\n\t\t\t\t\t\t\ttext += part.text;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"reasoning\": {\n\t\t\t\t\t\t\t// Reasoning is accumulated separately and sent as the `reasoning`\n\t\t\t\t\t\t\t// field on the message object. This is the field name vLLM expects\n\t\t\t\t\t\t\t// on input for reasoning models (kimi-k2.5, glm-4.7-flash).\n\t\t\t\t\t\t\t// Concatenating it into `content` corrupts the conversation history\n\t\t\t\t\t\t\t// and causes models to produce empty or garbled responses on the\n\t\t\t\t\t\t\t// next turn.\n\t\t\t\t\t\t\treasoning += part.text;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"file\": {\n\t\t\t\t\t\t\t// File parts in assistant messages - no action needed\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"tool-call\": {\n\t\t\t\t\t\t\ttoolCalls.push({\n\t\t\t\t\t\t\t\tfunction: {\n\t\t\t\t\t\t\t\t\targuments: JSON.stringify(part.input),\n\t\t\t\t\t\t\t\t\tname: part.toolName,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tid: part.toolCallId,\n\t\t\t\t\t\t\t\ttype: \"function\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"tool-result\": {\n\t\t\t\t\t\t\t// Tool results in assistant messages - no action needed\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\tconst exhaustiveCheck = part satisfies never;\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Unsupported part type: ${(exhaustiveCheck as { type: string }).type}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmessages.push({\n\t\t\t\t\tcontent: text,\n\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t...(reasoning ? { reasoning } : {}),\n\t\t\t\t\ttool_calls:\n\t\t\t\t\t\ttoolCalls.length > 0\n\t\t\t\t\t\t\t? toolCalls.map(({ function: { name, arguments: args }, id }) => ({\n\t\t\t\t\t\t\t\t\tfunction: { arguments: args, name },\n\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\ttype: \"function\" as const,\n\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t});\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"tool\": {\n\t\t\t\tfor (const toolResponse of content) {\n\t\t\t\t\tif (toolResponse.type === \"tool-result\") {\n\t\t\t\t\t\tconst output = toolResponse.output;\n\t\t\t\t\t\tlet content: string;\n\t\t\t\t\t\tswitch (output.type) {\n\t\t\t\t\t\t\tcase \"text\":\n\t\t\t\t\t\t\tcase \"error-text\":\n\t\t\t\t\t\t\t\tcontent = output.value;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"json\":\n\t\t\t\t\t\t\tcase \"error-json\":\n\t\t\t\t\t\t\t\tcontent = JSON.stringify(output.value);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"execution-denied\":\n\t\t\t\t\t\t\t\tcontent = output.reason\n\t\t\t\t\t\t\t\t\t? `Tool execution denied: ${output.reason}`\n\t\t\t\t\t\t\t\t\t: \"Tool execution was denied.\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"content\":\n\t\t\t\t\t\t\t\tcontent = output.value\n\t\t\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t\t\t(p): p is { type: \"text\"; text: string } =>\n\t\t\t\t\t\t\t\t\t\t\tp.type === \"text\",\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.map((p) => p.text)\n\t\t\t\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tcontent = \"\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tname: toolResponse.toolName,\n\t\t\t\t\t\t\ttool_call_id: toolResponse.toolCallId,\n\t\t\t\t\t\t\trole: \"tool\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// Skip tool-approval-response parts as they're not supported by Workers AI\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst exhaustiveCheck = role satisfies never;\n\t\t\t\tthrow new Error(`Unsupported role: ${exhaustiveCheck}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { messages };\n}\n","import type { LanguageModelV3Usage } from \"@ai-sdk/provider\";\n\n/**\n * Map Workers AI usage data to the AI SDK V3 usage format.\n * Accepts any object that may have a `usage` property with token counts.\n *\n * Workers AI mirrors the OpenAI usage shape, including\n * `prompt_tokens_details.cached_tokens` for prompt-cache hits. OpenAI-style\n * responses don't distinguish cache reads from cache writes, so we treat\n * `cached_tokens` as `cacheRead` and leave `cacheWrite` undefined.\n */\nexport function mapWorkersAIUsage(\n\toutput: Record<string, unknown> | AiTextGenerationOutput | AiTextToImageOutput,\n): LanguageModelV3Usage {\n\tconst usage = (\n\t\toutput as {\n\t\t\tusage?: {\n\t\t\t\tprompt_tokens?: number;\n\t\t\t\tcompletion_tokens?: number;\n\t\t\t\tprompt_tokens_details?: { cached_tokens?: number };\n\t\t\t};\n\t\t}\n\t).usage ?? {\n\t\tcompletion_tokens: 0,\n\t\tprompt_tokens: 0,\n\t};\n\n\tconst promptTokens = usage.prompt_tokens ?? 0;\n\tconst completionTokens = usage.completion_tokens ?? 0;\n\tconst cachedTokens = usage.prompt_tokens_details?.cached_tokens;\n\n\t// Clamp at 0 in case the provider ever reports cached_tokens > prompt_tokens;\n\t// the v3 spec expects non-negative counts.\n\tconst noCache =\n\t\tcachedTokens !== undefined ? Math.max(0, promptTokens - cachedTokens) : undefined;\n\n\treturn {\n\t\toutputTokens: {\n\t\t\ttotal: completionTokens,\n\t\t\ttext: undefined,\n\t\t\treasoning: undefined,\n\t\t},\n\t\tinputTokens: {\n\t\t\ttotal: promptTokens,\n\t\t\tnoCache,\n\t\t\tcacheRead: cachedTokens,\n\t\t\tcacheWrite: undefined,\n\t\t},\n\t\traw: { total: promptTokens + completionTokens },\n\t};\n}\n","import type { LanguageModelV3FinishReason } from \"@ai-sdk/provider\";\n\n/**\n * Map a Workers AI finish reason to the AI SDK unified finish reason.\n *\n * Accepts either:\n * - A raw finish reason string (e.g., \"stop\", \"tool_calls\")\n * - A full response object with finish_reason in various locations\n */\nexport function mapWorkersAIFinishReason(\n\tfinishReasonOrResponse: string | null | undefined | Record<string, unknown>,\n): LanguageModelV3FinishReason {\n\tlet finishReason: string | null | undefined;\n\n\tif (\n\t\ttypeof finishReasonOrResponse === \"string\" ||\n\t\tfinishReasonOrResponse === null ||\n\t\tfinishReasonOrResponse === undefined\n\t) {\n\t\tfinishReason = finishReasonOrResponse;\n\t} else if (typeof finishReasonOrResponse === \"object\" && finishReasonOrResponse !== null) {\n\t\tconst response = finishReasonOrResponse;\n\n\t\t// OpenAI format: { choices: [{ finish_reason: \"stop\" }] }\n\t\tconst choices = response.choices as Array<{ finish_reason?: string }> | undefined;\n\t\tif (Array.isArray(choices) && choices.length > 0) {\n\t\t\tfinishReason = choices[0].finish_reason;\n\t\t} else if (\"finish_reason\" in response) {\n\t\t\tfinishReason = response.finish_reason as string;\n\t\t} else {\n\t\t\tfinishReason = undefined;\n\t\t}\n\t} else {\n\t\t// Numbers, booleans, etc. -- default to stop\n\t\tfinishReason = undefined;\n\t}\n\n\tconst raw = finishReason ?? \"stop\";\n\n\tswitch (finishReason) {\n\t\tcase \"stop\":\n\t\t\treturn { unified: \"stop\", raw };\n\t\tcase \"length\":\n\t\tcase \"model_length\":\n\t\t\treturn { unified: \"length\", raw };\n\t\tcase \"tool_calls\":\n\t\t\treturn { unified: \"tool-calls\", raw };\n\t\tcase \"error\":\n\t\t\treturn { unified: \"error\", raw };\n\t\tcase \"other\":\n\t\tcase \"unknown\":\n\t\t\treturn { unified: \"other\", raw };\n\t\tdefault:\n\t\t\treturn { unified: \"stop\", raw };\n\t}\n}\n","import type {\n\tLanguageModelV3FinishReason,\n\tLanguageModelV3StreamPart,\n\tLanguageModelV3Usage,\n} from \"@ai-sdk/provider\";\nimport { generateId } from \"ai\";\nimport { mapWorkersAIFinishReason } from \"./map-workersai-finish-reason\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\n\n/**\n * Prepend a stream-start event to an existing LanguageModelV3 stream.\n * Uses pipeThrough for proper backpressure and error propagation.\n */\nexport function prependStreamStart(\n\tsource: ReadableStream<LanguageModelV3StreamPart>,\n\twarnings: LanguageModelV3StreamPart extends { type: \"stream-start\" } ? never : unknown,\n): ReadableStream<LanguageModelV3StreamPart> {\n\tlet sentStart = false;\n\treturn source.pipeThrough(\n\t\tnew TransformStream<LanguageModelV3StreamPart, LanguageModelV3StreamPart>({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tif (!sentStart) {\n\t\t\t\t\tsentStart = true;\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"stream-start\",\n\t\t\t\t\t\twarnings: warnings as [],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t},\n\t\t\tflush(controller) {\n\t\t\t\tif (!sentStart) {\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"stream-start\",\n\t\t\t\t\t\twarnings: warnings as [],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t);\n}\n\n/**\n * Check if a streaming tool call chunk is a null-finalization sentinel.\n */\nfunction isNullFinalizationChunk(tc: Record<string, unknown>): boolean {\n\tconst fn = tc.function as Record<string, unknown> | undefined;\n\tconst name = fn?.name ?? tc.name ?? null;\n\tconst args = fn?.arguments ?? tc.arguments ?? null;\n\tconst id = tc.id ?? null;\n\treturn !id && !name && (!args || args === \"\");\n}\n\n/**\n * Maps a Workers AI SSE stream into AI SDK V3 LanguageModelV3StreamPart events.\n *\n * Uses a TransformStream pipeline for proper backpressure — chunks are emitted\n * one at a time as the downstream consumer pulls, not buffered eagerly.\n *\n * Handles two distinct formats:\n * 1. Native format: { response: \"chunk\", tool_calls: [...] }\n * 2. OpenAI format: { choices: [{ delta: { content: \"chunk\" } }] }\n */\nexport function getMappedStream(\n\tresponse: Response | ReadableStream<Uint8Array>,\n): ReadableStream<LanguageModelV3StreamPart> {\n\tconst rawStream =\n\t\tresponse instanceof ReadableStream\n\t\t\t? response\n\t\t\t: (response.body as ReadableStream<Uint8Array>);\n\n\tif (!rawStream) {\n\t\tthrow new Error(\"No readable stream available for SSE parsing.\");\n\t}\n\n\t// State shared across the transform\n\tlet usage: LanguageModelV3Usage = {\n\t\toutputTokens: { total: 0, text: undefined, reasoning: undefined },\n\t\tinputTokens: {\n\t\t\ttotal: 0,\n\t\t\tnoCache: undefined,\n\t\t\tcacheRead: undefined,\n\t\t\tcacheWrite: undefined,\n\t\t},\n\t\traw: { totalTokens: 0 },\n\t};\n\tlet textId: string | null = null;\n\tlet reasoningId: string | null = null;\n\tlet finishReason: LanguageModelV3FinishReason | null = null;\n\tlet receivedDone = false;\n\tlet receivedAnyData = false;\n\n\t// Track tool call streaming state per index.\n\t// When we see the first chunk for a tool call index, we emit tool-input-start.\n\t// Subsequent argument deltas emit tool-input-delta.\n\t// tool-input-end is emitted eagerly when a new tool index starts or a null\n\t// finalization chunk arrives; any remaining open calls are closed in flush().\n\tconst activeToolCalls = new Map<number, { id: string; toolName: string; args: string }>();\n\tconst closedToolCalls = new Set<number>();\n\tlet lastActiveToolIndex: number | null = null;\n\n\t// Step 1: Decode bytes into SSE lines\n\tconst sseStream = rawStream.pipeThrough(new SSEDecoder());\n\n\t// Step 2: Transform SSE events into LanguageModelV3StreamPart\n\treturn sseStream.pipeThrough(\n\t\tnew TransformStream<string, LanguageModelV3StreamPart>({\n\t\t\ttransform(data, controller) {\n\t\t\t\tif (!data || data === \"[DONE]\") {\n\t\t\t\t\tif (data === \"[DONE]\") receivedDone = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\treceivedAnyData = true;\n\t\t\t\tlet chunk: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tchunk = JSON.parse(data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.warn(\"[workers-ai-provider] failed to parse SSE event:\", data);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (chunk.usage) {\n\t\t\t\t\tusage = mapWorkersAIUsage(chunk as Parameters<typeof mapWorkersAIUsage>[0]);\n\t\t\t\t}\n\n\t\t\t\t// Extract finish_reason\n\t\t\t\tconst choices = chunk.choices as\n\t\t\t\t\t| Array<{\n\t\t\t\t\t\t\tfinish_reason?: string;\n\t\t\t\t\t\t\tdelta?: Record<string, unknown>;\n\t\t\t\t\t }>\n\t\t\t\t\t| undefined;\n\t\t\t\tconst choiceFinishReason = choices?.[0]?.finish_reason;\n\t\t\t\tconst directFinishReason = chunk.finish_reason as string | undefined;\n\n\t\t\t\tif (choiceFinishReason != null) {\n\t\t\t\t\tfinishReason = mapWorkersAIFinishReason(choiceFinishReason);\n\t\t\t\t} else if (directFinishReason != null) {\n\t\t\t\t\tfinishReason = mapWorkersAIFinishReason(directFinishReason);\n\t\t\t\t}\n\n\t\t\t\t// --- Native format: top-level `response` field ---\n\t\t\t\tconst nativeResponse = chunk.response;\n\t\t\t\tif (nativeResponse != null && nativeResponse !== \"\") {\n\t\t\t\t\tconst responseText = String(nativeResponse);\n\t\t\t\t\tif (responseText.length > 0) {\n\t\t\t\t\t\t// Close active reasoning block before text starts\n\t\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!textId) {\n\t\t\t\t\t\t\ttextId = generateId();\n\t\t\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id: textId });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\ttype: \"text-delta\",\n\t\t\t\t\t\t\tid: textId,\n\t\t\t\t\t\t\tdelta: responseText,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// --- Native format: top-level `tool_calls` ---\n\t\t\t\tif (Array.isArray(chunk.tool_calls)) {\n\t\t\t\t\t// Close active reasoning block before tool calls start\n\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t}\n\t\t\t\t\temitToolCallDeltas(chunk.tool_calls as Record<string, unknown>[], controller);\n\t\t\t\t}\n\n\t\t\t\t// --- OpenAI format: choices[0].delta ---\n\t\t\t\tif (choices?.[0]?.delta) {\n\t\t\t\t\tconst delta = choices[0].delta;\n\n\t\t\t\t\tconst reasoningDelta = (delta.reasoning_content ?? delta.reasoning) as\n\t\t\t\t\t\t| string\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (reasoningDelta && reasoningDelta.length > 0) {\n\t\t\t\t\t\tif (!reasoningId) {\n\t\t\t\t\t\t\treasoningId = generateId();\n\t\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\t\ttype: \"reasoning-start\",\n\t\t\t\t\t\t\t\tid: reasoningId,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\ttype: \"reasoning-delta\",\n\t\t\t\t\t\t\tid: reasoningId,\n\t\t\t\t\t\t\tdelta: reasoningDelta,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst textDelta = delta.content as string | undefined;\n\t\t\t\t\tif (textDelta && textDelta.length > 0) {\n\t\t\t\t\t\t// Close active reasoning block before text starts\n\t\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!textId) {\n\t\t\t\t\t\t\ttextId = generateId();\n\t\t\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id: textId });\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\ttype: \"text-delta\",\n\t\t\t\t\t\t\tid: textId,\n\t\t\t\t\t\t\tdelta: textDelta,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst deltaToolCalls = delta.tool_calls as\n\t\t\t\t\t\t| Record<string, unknown>[]\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (Array.isArray(deltaToolCalls)) {\n\t\t\t\t\t\t// Close active reasoning block before tool calls start\n\t\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\temitToolCallDeltas(deltaToolCalls, controller);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tflush(controller) {\n\t\t\t\t// Close any tool calls that weren't already closed during streaming\n\t\t\t\tfor (const [idx] of activeToolCalls) {\n\t\t\t\t\tif (closedToolCalls.has(idx)) continue;\n\t\t\t\t\tcloseToolCall(idx, controller);\n\t\t\t\t}\n\n\t\t\t\t// Close open text/reasoning blocks\n\t\t\t\tif (reasoningId) {\n\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t}\n\t\t\t\tif (textId) {\n\t\t\t\t\tcontroller.enqueue({ type: \"text-end\", id: textId });\n\t\t\t\t}\n\n\t\t\t\t// Detect premature termination\n\t\t\t\tconst effectiveFinishReason =\n\t\t\t\t\t!receivedDone && receivedAnyData && !finishReason\n\t\t\t\t\t\t? ({\n\t\t\t\t\t\t\t\tunified: \"error\",\n\t\t\t\t\t\t\t\traw: \"stream-truncated\",\n\t\t\t\t\t\t\t} as LanguageModelV3FinishReason)\n\t\t\t\t\t\t: (finishReason ?? { unified: \"stop\", raw: \"stop\" });\n\n\t\t\t\tcontroller.enqueue({\n\t\t\t\t\tfinishReason: effectiveFinishReason,\n\t\t\t\t\ttype: \"finish\",\n\t\t\t\t\tusage,\n\t\t\t\t});\n\t\t\t},\n\t\t}),\n\t);\n\n\t/**\n\t * Emit tool-input-end + tool-call for a tool call that is complete.\n\t */\n\tfunction closeToolCall(\n\t\tindex: number,\n\t\tcontroller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n\t) {\n\t\tconst tc = activeToolCalls.get(index);\n\t\tif (!tc || closedToolCalls.has(index)) return;\n\t\tclosedToolCalls.add(index);\n\t\tcontroller.enqueue({ type: \"tool-input-end\", id: tc.id });\n\t\tcontroller.enqueue({\n\t\t\ttype: \"tool-call\",\n\t\t\ttoolCallId: tc.id,\n\t\t\ttoolName: tc.toolName,\n\t\t\tinput: tc.args,\n\t\t});\n\t}\n\n\t/**\n\t * Emit incremental tool call events from streaming chunks.\n\t *\n\t * Workers AI streams tool calls as:\n\t * Chunk A: { id, type, index, function: { name } } — start\n\t * Chunk B: { index, function: { arguments: \"partial...\" } } — args delta\n\t * Chunk C: { index, function: { arguments: \"rest...\" } } — args delta\n\t * Chunk D: { id: null, type: null, function: { name: null } } — finalize\n\t *\n\t * We emit tool-input-start on first sight, tool-input-delta for each\n\t * argument chunk, and tool-input-end eagerly — either when a new tool\n\t * index starts (closing the previous one) or on a null finalization\n\t * chunk. Any remaining open calls are closed in flush().\n\t */\n\tfunction emitToolCallDeltas(\n\t\ttoolCalls: Record<string, unknown>[],\n\t\tcontroller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n\t) {\n\t\tfor (const tc of toolCalls) {\n\t\t\tif (isNullFinalizationChunk(tc)) {\n\t\t\t\t// Null finalization sentinel — close the last active tool call\n\t\t\t\tif (lastActiveToolIndex != null) {\n\t\t\t\t\tcloseToolCall(lastActiveToolIndex, controller);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst tcIndex = (tc.index as number) ?? 0;\n\t\t\tconst fn = tc.function as Record<string, unknown> | undefined;\n\t\t\tconst tcName = (fn?.name ?? tc.name ?? null) as string | null;\n\t\t\tconst tcArgs = (fn?.arguments ?? tc.arguments ?? null) as string | null;\n\t\t\tconst tcId = tc.id as string | null;\n\n\t\t\tif (!activeToolCalls.has(tcIndex)) {\n\t\t\t\t// A new tool call is starting — close the previous one first\n\t\t\t\tif (lastActiveToolIndex != null && lastActiveToolIndex !== tcIndex) {\n\t\t\t\t\tcloseToolCall(lastActiveToolIndex, controller);\n\t\t\t\t}\n\n\t\t\t\tconst id = tcId || generateId();\n\t\t\t\tconst toolName = tcName || \"\";\n\t\t\t\tactiveToolCalls.set(tcIndex, { id, toolName, args: \"\" });\n\t\t\t\tlastActiveToolIndex = tcIndex;\n\n\t\t\t\tcontroller.enqueue({\n\t\t\t\t\ttype: \"tool-input-start\",\n\t\t\t\t\tid,\n\t\t\t\t\ttoolName,\n\t\t\t\t});\n\n\t\t\t\tif (tcArgs != null && tcArgs !== \"\") {\n\t\t\t\t\tconst delta = typeof tcArgs === \"string\" ? tcArgs : JSON.stringify(tcArgs);\n\t\t\t\t\tactiveToolCalls.get(tcIndex)!.args += delta;\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"tool-input-delta\",\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst active = activeToolCalls.get(tcIndex)!;\n\t\t\t\tlastActiveToolIndex = tcIndex;\n\t\t\t\tif (tcArgs != null && tcArgs !== \"\") {\n\t\t\t\t\tconst delta = typeof tcArgs === \"string\" ? tcArgs : JSON.stringify(tcArgs);\n\t\t\t\t\tactive.args += delta;\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"tool-input-delta\",\n\t\t\t\t\t\tid: active.id,\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * TransformStream that decodes a raw byte stream into SSE `data:` payloads.\n * Each output chunk is the string content after \"data: \" (one per SSE event).\n * Handles line buffering for partial chunks.\n */\nclass SSEDecoder extends TransformStream<Uint8Array, string> {\n\tconstructor() {\n\t\tlet buffer = \"\";\n\t\tconst decoder = new TextDecoder();\n\n\t\tsuper({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tbuffer += decoder.decode(chunk, { stream: true });\n\t\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\t\tbuffer = lines.pop() || \"\";\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tconst trimmed = line.trim();\n\t\t\t\t\tif (!trimmed) continue;\n\t\t\t\t\tif (trimmed.startsWith(\"data: \")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(6));\n\t\t\t\t\t} else if (trimmed.startsWith(\"data:\")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(5));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tflush(controller) {\n\t\t\t\tif (buffer.trim()) {\n\t\t\t\t\tconst trimmed = buffer.trim();\n\t\t\t\t\tif (trimmed.startsWith(\"data: \")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(6));\n\t\t\t\t\t} else if (trimmed.startsWith(\"data:\")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(5));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n}\n","import type { LanguageModelV3, LanguageModelV3ToolCall } from \"@ai-sdk/provider\";\nimport { generateId } from \"ai\";\nimport type { WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n// ---------------------------------------------------------------------------\n// Workers AI quirk workarounds\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize messages before passing to the Workers AI binding.\n *\n * The binding has strict schema validation that differs from the OpenAI API:\n * - `content` must not be null\n */\nexport function normalizeMessagesForBinding(messages: WorkersAIChatPrompt): WorkersAIChatPrompt {\n\treturn messages.map((msg) => {\n\t\tconst normalized = { ...msg };\n\n\t\t// content: null → content: \"\"\n\t\tif (normalized.content === null || normalized.content === undefined) {\n\t\t\t(normalized as { content: string }).content = \"\";\n\t\t}\n\n\t\treturn normalized;\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// REST API client\n// ---------------------------------------------------------------------------\n\n/**\n * General AI run interface with overloads to handle distinct return types.\n */\nexport interface AiRun {\n\t<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"],\n\t\toptions: AiOptions & { returnRawResponse: true },\n\t): Promise<Response>;\n\n\t<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"] & { stream: true },\n\t\toptions?: AiOptions,\n\t): Promise<ReadableStream<Uint8Array>>;\n\n\t<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"],\n\t\toptions?: AiOptions,\n\t): Promise<AiModels[Name][\"postProcessedOutputs\"]>;\n}\n\n/**\n * Parameters for configuring the Cloudflare-based AI runner.\n */\nexport interface CreateRunConfig {\n\t/** Your Cloudflare account identifier. */\n\taccountId: string;\n\t/** Cloudflare API token/key with appropriate permissions. */\n\tapiKey: string;\n\t/** Custom fetch implementation for intercepting requests. */\n\tfetch?: typeof globalThis.fetch;\n}\n\n/**\n * Creates a run method that emulates the Cloudflare Workers AI binding,\n * but uses the Cloudflare REST API under the hood.\n */\nexport function createRun(config: CreateRunConfig): AiRun {\n\tconst { accountId, apiKey } = config;\n\tconst fetchFn = config.fetch ?? globalThis.fetch;\n\n\treturn async function run<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"],\n\t\toptions?: AiOptions & Record<string, unknown>,\n\t): Promise<Response | ReadableStream<Uint8Array> | AiModels[Name][\"postProcessedOutputs\"]> {\n\t\tconst {\n\t\t\tgateway,\n\t\t\tprefix: _prefix,\n\t\t\textraHeaders,\n\t\t\treturnRawResponse,\n\t\t\tsignal, // AbortSignal — not serializable as a query parameter\n\t\t\t...passthroughOptions\n\t\t} = options || {};\n\n\t\tconst urlParams = new URLSearchParams();\n\t\tfor (const [key, value] of Object.entries(passthroughOptions)) {\n\t\t\tif (value === undefined || value === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Value for option '${key}' is not able to be coerced into a string.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst valueStr = String(value);\n\t\t\t\tif (!valueStr) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\turlParams.append(key, valueStr);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Value for option '${key}' is not able to be coerced into a string.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst queryString = urlParams.toString();\n\n\t\tconst modelPath = String(model).startsWith(\"run/\") ? model : `run/${model}`;\n\n\t\t// Build URL: use AI Gateway if gateway option is provided, otherwise direct API\n\t\tconst url = gateway?.id\n\t\t\t? `https://gateway.ai.cloudflare.com/v1/${accountId}/${gateway.id}/workers-ai/${modelPath}${\n\t\t\t\t\tqueryString ? `?${queryString}` : \"\"\n\t\t\t\t}`\n\t\t\t: `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/${modelPath}${\n\t\t\t\t\tqueryString ? `?${queryString}` : \"\"\n\t\t\t\t}`;\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...(extraHeaders && typeof extraHeaders === \"object\"\n\t\t\t\t? (extraHeaders as Record<string, string>)\n\t\t\t\t: {}),\n\t\t};\n\n\t\tif (gateway) {\n\t\t\tif (gateway.skipCache) {\n\t\t\t\theaders[\"cf-aig-skip-cache\"] = \"true\";\n\t\t\t}\n\t\t\tif (typeof gateway.cacheTtl === \"number\") {\n\t\t\t\theaders[\"cf-aig-cache-ttl\"] = String(gateway.cacheTtl);\n\t\t\t}\n\t\t\tif (gateway.cacheKey) {\n\t\t\t\theaders[\"cf-aig-cache-key\"] = gateway.cacheKey;\n\t\t\t}\n\t\t\tif (gateway.metadata) {\n\t\t\t\theaders[\"cf-aig-metadata\"] = JSON.stringify(gateway.metadata);\n\t\t\t}\n\t\t}\n\n\t\tconst body = JSON.stringify(inputs);\n\n\t\tconst response = await fetchFn(url, {\n\t\t\tbody,\n\t\t\theaders,\n\t\t\tmethod: \"POST\",\n\t\t\tsignal: signal as AbortSignal | undefined,\n\t\t});\n\n\t\t// Check for HTTP errors before processing\n\t\tif (!response.ok && !returnRawResponse) {\n\t\t\tlet errorBody: string;\n\t\t\ttry {\n\t\t\t\terrorBody = await response.text();\n\t\t\t} catch {\n\t\t\t\terrorBody = \"<unable to read response body>\";\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`Workers AI API error (${response.status} ${response.statusText}): ${errorBody}`,\n\t\t\t);\n\t\t}\n\n\t\tif (returnRawResponse) {\n\t\t\treturn response;\n\t\t}\n\n\t\tif ((inputs as AiTextGenerationInput).stream === true) {\n\t\t\tconst contentType = response.headers.get(\"content-type\") || \"\";\n\t\t\tif (contentType.includes(\"event-stream\") && response.body) {\n\t\t\t\treturn response.body;\n\t\t\t}\n\t\t\tif (response.body && !contentType.includes(\"json\")) {\n\t\t\t\t// Unknown content type — assume it's a stream\n\t\t\t\treturn response.body;\n\t\t\t}\n\n\t\t\t// Some models (e.g. GPT-OSS) don't support streaming via the /ai/run/\n\t\t\t// endpoint and return a JSON response with empty result instead of SSE.\n\t\t\t// Retry without streaming so doStream's graceful degradation path can\n\t\t\t// wrap the complete response as a synthetic stream.\n\t\t\t// Use the same URL (gateway or direct) as the original request.\n\t\t\tconst retryResponse = await fetchFn(url, {\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t...(inputs as Record<string, unknown>),\n\t\t\t\t\tstream: false,\n\t\t\t\t}),\n\t\t\t\theaders,\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tsignal: signal as AbortSignal | undefined,\n\t\t\t});\n\n\t\t\tif (!retryResponse.ok) {\n\t\t\t\tlet errorBody: string;\n\t\t\t\ttry {\n\t\t\t\t\terrorBody = await retryResponse.text();\n\t\t\t\t} catch {\n\t\t\t\t\terrorBody = \"<unable to read response body>\";\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Workers AI API error (${retryResponse.status} ${retryResponse.statusText}): ${errorBody}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst retryData = await retryResponse.json<{\n\t\t\t\tresult: AiModels[Name][\"postProcessedOutputs\"];\n\t\t\t}>();\n\t\t\treturn retryData.result;\n\t\t}\n\n\t\tconst data = await response.json<{\n\t\t\tresult: AiModels[Name][\"postProcessedOutputs\"];\n\t\t}>();\n\t\treturn data.result;\n\t};\n}\n\n/**\n * Make a binary REST API call to Workers AI.\n *\n * Some models (e.g. `@cf/deepgram/nova-3`) require raw audio bytes\n * with an appropriate `Content-Type` header instead of JSON.\n *\n * @param config Credentials config\n * @param model Workers AI model name\n * @param audioBytes Raw audio bytes\n * @param contentType MIME type (e.g. \"audio/wav\")\n * @param signal Optional AbortSignal\n * @returns The parsed JSON response body\n */\nexport async function createRunBinary(\n\tconfig: CreateRunConfig,\n\tmodel: string,\n\taudioBytes: Uint8Array,\n\tcontentType: string,\n\tsignal?: AbortSignal,\n): Promise<Record<string, unknown>> {\n\tconst url = `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/ai/run/${model}`;\n\n\tconst response = await fetch(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${config.apiKey}`,\n\t\t\t\"Content-Type\": contentType,\n\t\t},\n\t\tbody: audioBytes,\n\t\tsignal,\n\t});\n\n\tif (!response.ok) {\n\t\tlet errorBody: string;\n\t\ttry {\n\t\t\terrorBody = await response.text();\n\t\t} catch {\n\t\t\terrorBody = \"<unable to read response body>\";\n\t\t}\n\t\tthrow new Error(\n\t\t\t`Workers AI API error (${response.status} ${response.statusText}): ${errorBody}`,\n\t\t);\n\t}\n\n\tconst data = await response.json<{ result?: Record<string, unknown> }>();\n\treturn (data.result ?? data) as Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Tool preparation\n// ---------------------------------------------------------------------------\n\nexport function prepareToolsAndToolChoice(\n\ttools: Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"tools\"],\n\ttoolChoice: Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"toolChoice\"],\n) {\n\tif (tools == null) {\n\t\treturn { tool_choice: undefined, tools: undefined };\n\t}\n\n\tconst mappedTools = tools.map((tool) => ({\n\t\tfunction: {\n\t\t\tdescription: tool.type === \"function\" ? tool.description : undefined,\n\t\t\tname: tool.name,\n\t\t\tparameters: tool.type === \"function\" ? tool.inputSchema : undefined,\n\t\t},\n\t\ttype: \"function\",\n\t}));\n\n\tif (toolChoice == null) {\n\t\treturn { tool_choice: undefined, tools: mappedTools };\n\t}\n\n\tconst type = toolChoice.type;\n\n\tswitch (type) {\n\t\tcase \"auto\":\n\t\t\treturn { tool_choice: type, tools: mappedTools };\n\t\tcase \"none\":\n\t\t\treturn { tool_choice: type, tools: mappedTools };\n\t\tcase \"required\":\n\t\t\treturn { tool_choice: \"required\", tools: mappedTools };\n\n\t\t// Workers AI does not support tool mode directly,\n\t\t// so we filter the tools and force the tool choice through 'required'\n\t\tcase \"tool\":\n\t\t\treturn {\n\t\t\t\ttool_choice: \"required\",\n\t\t\t\ttools: mappedTools.filter((tool) => tool.function.name === toolChoice.toolName),\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst exhaustiveCheck = type satisfies never;\n\t\t\tthrow new Error(`Unsupported tool choice type: ${exhaustiveCheck}`);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Message helpers\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Tool call processing\n// ---------------------------------------------------------------------------\n\n/** Workers AI flat tool call format (non-streaming, native) */\ninterface FlatToolCall {\n\tname: string;\n\targuments: unknown;\n\tid?: string;\n}\n\n/** Workers AI OpenAI-compatible tool call format */\ninterface OpenAIToolCall {\n\tid: string;\n\ttype: \"function\";\n\tfunction: {\n\t\tname: string;\n\t\targuments: unknown;\n\t};\n}\n\n/** Partial tool call from streaming (has index for merging) */\ninterface PartialToolCall {\n\tindex?: number;\n\tid?: string;\n\ttype?: string;\n\tfunction?: {\n\t\tname?: string;\n\t\targuments?: string;\n\t};\n\t// Flat format fields\n\tname?: string;\n\targuments?: string;\n}\n\nfunction mergePartialToolCalls(partialCalls: PartialToolCall[]) {\n\tconst mergedCallsByIndex: Record<\n\t\tnumber,\n\t\t{ function: { arguments: string; name: string }; id: string; type: string }\n\t> = {};\n\n\tfor (const partialCall of partialCalls) {\n\t\tconst index = partialCall.index ?? 0;\n\n\t\tif (!mergedCallsByIndex[index]) {\n\t\t\tmergedCallsByIndex[index] = {\n\t\t\t\tfunction: {\n\t\t\t\t\targuments: \"\",\n\t\t\t\t\tname: partialCall.function?.name || \"\",\n\t\t\t\t},\n\t\t\t\tid: partialCall.id || \"\",\n\t\t\t\ttype: partialCall.type || \"\",\n\t\t\t};\n\t\t} else {\n\t\t\tif (partialCall.id) {\n\t\t\t\tmergedCallsByIndex[index].id = partialCall.id;\n\t\t\t}\n\t\t\tif (partialCall.type) {\n\t\t\t\tmergedCallsByIndex[index].type = partialCall.type;\n\t\t\t}\n\t\t\tif (partialCall.function?.name) {\n\t\t\t\tmergedCallsByIndex[index].function.name = partialCall.function.name;\n\t\t\t}\n\t\t}\n\n\t\t// Append arguments if available (they arrive in order during streaming)\n\t\tif (partialCall.function?.arguments) {\n\t\t\tmergedCallsByIndex[index].function.arguments += partialCall.function.arguments;\n\t\t}\n\t}\n\n\treturn Object.values(mergedCallsByIndex);\n}\n\nfunction processToolCall(toolCall: FlatToolCall | OpenAIToolCall): LanguageModelV3ToolCall {\n\t// OpenAI format: has function.name (the key discriminator)\n\tconst fn =\n\t\t\"function\" in toolCall && typeof toolCall.function === \"object\" && toolCall.function\n\t\t\t? (toolCall.function as { name?: string; arguments?: unknown })\n\t\t\t: null;\n\n\tif (fn?.name) {\n\t\treturn {\n\t\t\tinput:\n\t\t\t\ttypeof fn.arguments === \"string\"\n\t\t\t\t\t? fn.arguments\n\t\t\t\t\t: JSON.stringify(fn.arguments || {}),\n\t\t\ttoolCallId: toolCall.id || generateId(),\n\t\t\ttype: \"tool-call\",\n\t\t\ttoolName: fn.name,\n\t\t};\n\t}\n\n\t// Flat format (native Workers AI non-streaming): has top-level name\n\tconst flat = toolCall as FlatToolCall;\n\treturn {\n\t\tinput:\n\t\t\ttypeof flat.arguments === \"string\"\n\t\t\t\t? flat.arguments\n\t\t\t\t: JSON.stringify(flat.arguments || {}),\n\t\ttoolCallId: flat.id || generateId(),\n\t\ttype: \"tool-call\",\n\t\ttoolName: flat.name,\n\t};\n}\n\nexport function processToolCalls(output: Record<string, unknown>): LanguageModelV3ToolCall[] {\n\tif (output.tool_calls && Array.isArray(output.tool_calls)) {\n\t\treturn output.tool_calls.map((toolCall: FlatToolCall | OpenAIToolCall) =>\n\t\t\tprocessToolCall(toolCall),\n\t\t);\n\t}\n\n\tconst choices = output.choices as\n\t\t| Array<{ message?: { tool_calls?: Array<FlatToolCall | OpenAIToolCall> } }>\n\t\t| undefined;\n\tif (choices?.[0]?.message?.tool_calls && Array.isArray(choices[0].message.tool_calls)) {\n\t\treturn choices[0].message.tool_calls.map((toolCall) => processToolCall(toolCall));\n\t}\n\n\treturn [];\n}\n\nexport function processPartialToolCalls(partialToolCalls: PartialToolCall[]) {\n\tconst mergedToolCalls = mergePartialToolCalls(partialToolCalls);\n\treturn processToolCalls({ tool_calls: mergedToolCalls });\n}\n\n// ---------------------------------------------------------------------------\n// Text extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract text from a Workers AI response, handling multiple response formats:\n * - OpenAI format: { choices: [{ message: { content: \"...\" } }] }\n * - Native format: { response: \"...\" }\n * - Structured output quirk: { response: { ... } } (object instead of string)\n * - Structured output quirk: { response: \"{ ... }\" } (JSON string)\n */\nexport function processText(output: Record<string, unknown>): string | undefined {\n\t// OpenAI format\n\tconst choices = output.choices as Array<{ message?: { content?: string | null } }> | undefined;\n\tconst choiceContent = choices?.[0]?.message?.content;\n\tif (choiceContent != null && String(choiceContent).length > 0) {\n\t\treturn String(choiceContent);\n\t}\n\n\tif (\"response\" in output) {\n\t\tconst response = output.response;\n\t\t// Object response (structured output quirk #2)\n\t\tif (typeof response === \"object\" && response !== null) {\n\t\t\treturn JSON.stringify(response);\n\t\t}\n\t\t// Numeric response (quirk #9)\n\t\tif (typeof response === \"number\") {\n\t\t\treturn String(response);\n\t\t}\n\t\t// Null response (e.g., tool-call-only responses)\n\t\tif (response === null || response === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn String(response);\n\t}\n\treturn undefined;\n}\n","import type { LanguageModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\n\nimport type { AISearchChatSettings } from \"./aisearch-chat-settings\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\nimport { getMappedStream, prependStreamStart } from \"./streaming\";\nimport { processToolCalls } from \"./utils\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\ntype AISearchChatConfig = {\n\tprovider: string;\n\tbinding: AutoRAG;\n\tgateway?: GatewayOptions;\n};\n\nexport class AISearchChatLanguageModel implements LanguageModelV3 {\n\treadonly specificationVersion = \"v3\";\n\treadonly defaultObjectGenerationMode = \"json\";\n\n\treadonly supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>> = {};\n\n\treadonly modelId: TextGenerationModels;\n\treadonly settings: AISearchChatSettings;\n\n\tprivate readonly config: AISearchChatConfig;\n\n\tconstructor(\n\t\tmodelId: TextGenerationModels,\n\t\tsettings: AISearchChatSettings,\n\t\tconfig: AISearchChatConfig,\n\t) {\n\t\tthis.modelId = modelId;\n\t\tthis.settings = settings;\n\t\tthis.config = config;\n\t}\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tprivate getWarnings({\n\t\ttools,\n\t\tfrequencyPenalty,\n\t\tpresencePenalty,\n\t\tresponseFormat,\n\t}: Parameters<LanguageModelV3[\"doGenerate\"]>[0]): SharedV3Warning[] {\n\t\tconst warnings: SharedV3Warning[] = [];\n\n\t\tif (tools != null && tools.length > 0) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[workers-ai-provider] Tools are not supported by AI Search. They will be ignored.\",\n\t\t\t);\n\t\t\twarnings.push({ feature: \"tools\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (frequencyPenalty != null) {\n\t\t\twarnings.push({ feature: \"frequencyPenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (presencePenalty != null) {\n\t\t\twarnings.push({ feature: \"presencePenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (responseFormat?.type === \"json\") {\n\t\t\twarnings.push({ feature: \"responseFormat\", type: \"unsupported\" });\n\t\t}\n\n\t\treturn warnings;\n\t}\n\n\t/**\n\t * Build the search query from messages.\n\t * Flattens the conversation into a single string for aiSearch.\n\t */\n\tprivate buildQuery(prompt: Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"prompt\"]): string {\n\t\tconst { messages } = convertToWorkersAIChatMessages(prompt);\n\t\treturn messages.map(({ content, role }) => `${role}: ${content}`).join(\"\\n\\n\");\n\t}\n\n\tasync doGenerate(\n\t\toptions: Parameters<LanguageModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n\t\tconst warnings = this.getWarnings(options);\n\t\tconst query = this.buildQuery(options.prompt);\n\n\t\tconst output = await this.config.binding.aiSearch({ query });\n\n\t\treturn {\n\t\t\tfinishReason: { unified: \"stop\", raw: \"stop\" },\n\t\t\tcontent: [\n\t\t\t\t...output.data.map(({ file_id, filename, score }) => ({\n\t\t\t\t\ttype: \"source\" as const,\n\t\t\t\t\tsourceType: \"url\" as const,\n\t\t\t\t\tid: file_id,\n\t\t\t\t\turl: filename,\n\t\t\t\t\tproviderMetadata: {\n\t\t\t\t\t\tattributes: { score },\n\t\t\t\t\t},\n\t\t\t\t})),\n\t\t\t\t{\n\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\ttext: output.response,\n\t\t\t\t},\n\t\t\t\t...processToolCalls(output as unknown as Record<string, unknown>),\n\t\t\t],\n\t\t\tusage: mapWorkersAIUsage(output as unknown as Record<string, unknown>),\n\t\t\twarnings,\n\t\t};\n\t}\n\n\tasync doStream(\n\t\toptions: Parameters<LanguageModelV3[\"doStream\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doStream\"]>>> {\n\t\tconst warnings = this.getWarnings(options);\n\t\tconst query = this.buildQuery(options.prompt);\n\n\t\tconst response = await this.config.binding.aiSearch({\n\t\t\tquery,\n\t\t\tstream: true,\n\t\t});\n\n\t\treturn {\n\t\t\tstream: prependStreamStart(\n\t\t\t\tgetMappedStream(response as unknown as Response | ReadableStream<Uint8Array>),\n\t\t\t\twarnings,\n\t\t\t),\n\t\t};\n\t}\n}\n","import type {\n\tEmbeddingModelV3,\n\tEmbeddingModelV3CallOptions,\n\tEmbeddingModelV3Result,\n} from \"@ai-sdk/provider\";\nimport { TooManyEmbeddingValuesForCallError } from \"@ai-sdk/provider\";\nimport type { EmbeddingModels } from \"./workersai-models\";\n\nexport type WorkersAIEmbeddingConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\nexport type WorkersAIEmbeddingSettings = {\n\tgateway?: GatewayOptions;\n\tmaxEmbeddingsPerCall?: number;\n\tsupportsParallelCalls?: boolean;\n\n\t/**\n\t * Passthrough settings that are provided directly to the run function.\n\t */\n\t[key: string]: unknown;\n};\n\nexport class WorkersAIEmbeddingModel implements EmbeddingModelV3 {\n\treadonly specificationVersion = \"v3\";\n\treadonly modelId: EmbeddingModels;\n\tprivate readonly config: WorkersAIEmbeddingConfig;\n\tprivate readonly settings: WorkersAIEmbeddingSettings;\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tget maxEmbeddingsPerCall(): number {\n\t\t// https://developers.cloudflare.com/workers-ai/platform/limits/#text-embeddings\n\t\treturn this.settings.maxEmbeddingsPerCall ?? 3000;\n\t}\n\n\tget supportsParallelCalls(): boolean {\n\t\treturn this.settings.supportsParallelCalls ?? true;\n\t}\n\n\tconstructor(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings: WorkersAIEmbeddingSettings,\n\t\tconfig: WorkersAIEmbeddingConfig,\n\t) {\n\t\tthis.modelId = modelId;\n\t\tthis.settings = settings;\n\t\tthis.config = config;\n\t}\n\n\tasync doEmbed({\n\t\tvalues,\n\t\tabortSignal,\n\t}: EmbeddingModelV3CallOptions): Promise<EmbeddingModelV3Result> {\n\t\tif (values.length > this.maxEmbeddingsPerCall) {\n\t\t\tthrow new TooManyEmbeddingValuesForCallError({\n\t\t\t\tmaxEmbeddingsPerCall: this.maxEmbeddingsPerCall,\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\tprovider: this.provider,\n\t\t\t\tvalues,\n\t\t\t});\n\t\t}\n\n\t\tconst {\n\t\t\tgateway,\n\t\t\tmaxEmbeddingsPerCall: _maxEmbeddingsPerCall,\n\t\t\tsupportsParallelCalls: _supportsParallelCalls,\n\t\t\t...passthroughOptions\n\t\t} = this.settings;\n\n\t\tconst response = await this.config.binding.run(\n\t\t\tthis.modelId as keyof AiModels,\n\t\t\t{\n\t\t\t\ttext: values,\n\t\t\t},\n\t\t\t{\n\t\t\t\tgateway: this.config.gateway ?? gateway,\n\t\t\t\tsignal: abortSignal,\n\t\t\t\t...passthroughOptions,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\treturn {\n\t\t\tembeddings: (response as { data: number[][] }).data,\n\t\t\twarnings: [],\n\t\t};\n\t}\n}\n","import type { LanguageModelV3, SharedV3Warning, LanguageModelV3StreamPart } from \"@ai-sdk/provider\";\nimport { generateId } from \"ai\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport { mapWorkersAIFinishReason } from \"./map-workersai-finish-reason\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\nimport { getMappedStream, prependStreamStart } from \"./streaming\";\nimport {\n\tnormalizeMessagesForBinding,\n\tprepareToolsAndToolChoice,\n\tprocessText,\n\tprocessToolCalls,\n} from \"./utils\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\ntype WorkersAIChatConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n\t/** True when using a real Workers AI binding (not the REST shim). */\n\tisBinding: boolean;\n};\n\nexport class WorkersAIChatLanguageModel implements LanguageModelV3 {\n\treadonly specificationVersion = \"v3\";\n\treadonly defaultObjectGenerationMode = \"json\";\n\n\treadonly supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>> = {};\n\n\treadonly modelId: TextGenerationModels;\n\treadonly settings: WorkersAIChatSettings;\n\n\tprivate readonly config: WorkersAIChatConfig;\n\n\tconstructor(\n\t\tmodelId: TextGenerationModels,\n\t\tsettings: WorkersAIChatSettings,\n\t\tconfig: WorkersAIChatConfig,\n\t) {\n\t\tthis.modelId = modelId;\n\t\tthis.settings = settings;\n\t\tthis.config = config;\n\t}\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tprivate getArgs({\n\t\tresponseFormat,\n\t\ttools,\n\t\ttoolChoice,\n\t\tmaxOutputTokens,\n\t\ttemperature,\n\t\ttopP,\n\t\tfrequencyPenalty,\n\t\tpresencePenalty,\n\t\tseed,\n\t}: Parameters<LanguageModelV3[\"doGenerate\"]>[0]) {\n\t\tconst type = responseFormat?.type ?? \"text\";\n\n\t\tconst warnings: SharedV3Warning[] = [];\n\n\t\tif (frequencyPenalty != null) {\n\t\t\twarnings.push({ feature: \"frequencyPenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (presencePenalty != null) {\n\t\t\twarnings.push({ feature: \"presencePenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tconst baseArgs = {\n\t\t\tmax_tokens: maxOutputTokens,\n\t\t\tmodel: this.modelId,\n\t\t\trandom_seed: seed,\n\t\t\tsafe_prompt: this.settings.safePrompt,\n\t\t\ttemperature,\n\t\t\ttop_p: topP,\n\t\t};\n\n\t\tswitch (type) {\n\t\t\tcase \"text\": {\n\t\t\t\treturn {\n\t\t\t\t\targs: {\n\t\t\t\t\t\t...baseArgs,\n\t\t\t\t\t\tresponse_format: undefined as\n\t\t\t\t\t\t\t| { type: string; json_schema?: unknown }\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t...prepareToolsAndToolChoice(tools, toolChoice),\n\t\t\t\t\t},\n\t\t\t\t\twarnings,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tcase \"json\": {\n\t\t\t\treturn {\n\t\t\t\t\targs: {\n\t\t\t\t\t\t...baseArgs,\n\t\t\t\t\t\tresponse_format: {\n\t\t\t\t\t\t\ttype: \"json_schema\",\n\t\t\t\t\t\t\tjson_schema:\n\t\t\t\t\t\t\t\tresponseFormat?.type === \"json\" ? responseFormat.schema : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttools: undefined,\n\t\t\t\t\t\ttool_choice: undefined,\n\t\t\t\t\t},\n\t\t\t\t\twarnings,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst exhaustiveCheck = type satisfies never;\n\t\t\t\tthrow new Error(`Unsupported type: ${exhaustiveCheck}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build the inputs object for `binding.run()`, shared by doGenerate and doStream.\n\t *\n\t * Images are embedded inline in messages as OpenAI-compatible content\n\t * arrays with `image_url` parts. Both the REST API and the binding\n\t * accept this format at runtime.\n\t *\n\t * The binding path additionally normalises null content to empty strings.\n\t *\n\t * Reasoning controls (`reasoning_effort`, `chat_template_kwargs`) are\n\t * forwarded here from settings. These belong on the INPUTS object, not on\n\t * the 3rd-arg options / REST query string — see\n\t * https://github.com/cloudflare/ai/issues/501. Per-call values from\n\t * `providerOptions[\"workers-ai\"]` override settings.\n\t *\n\t * `reasoning_effort: null` is a valid value (\"disable reasoning\"), so we\n\t * check `!== undefined` rather than truthiness.\n\t */\n\tprivate buildRunInputs(\n\t\targs: ReturnType<typeof this.getArgs>[\"args\"],\n\t\tmessages: ReturnType<typeof convertToWorkersAIChatMessages>[\"messages\"],\n\t\toptions?: { stream?: boolean; providerOptions?: Record<string, unknown> },\n\t) {\n\t\t// The AI SDK types this as `Record<string, JSONObject>` but we defensively\n\t\t// accept anything and only treat it as a lookup if it's a plain object.\n\t\t// `\"key\" in x` throws for primitives, so we can't skip the typeof guard.\n\t\tconst rawPerCall = options?.providerOptions?.[\"workers-ai\"];\n\t\tconst perCall: Record<string, unknown> =\n\t\t\trawPerCall !== null && typeof rawPerCall === \"object\" && !Array.isArray(rawPerCall)\n\t\t\t\t? (rawPerCall as Record<string, unknown>)\n\t\t\t\t: {};\n\t\tconst reasoningEffort =\n\t\t\t\"reasoning_effort\" in perCall\n\t\t\t\t? perCall.reasoning_effort\n\t\t\t\t: this.settings.reasoning_effort;\n\t\tconst chatTemplateKwargs =\n\t\t\t\"chat_template_kwargs\" in perCall\n\t\t\t\t? perCall.chat_template_kwargs\n\t\t\t\t: this.settings.chat_template_kwargs;\n\n\t\treturn {\n\t\t\tmax_tokens: args.max_tokens,\n\t\t\tmessages: this.config.isBinding ? normalizeMessagesForBinding(messages) : messages,\n\t\t\ttemperature: args.temperature,\n\t\t\ttools: args.tools,\n\t\t\t...(args.tool_choice ? { tool_choice: args.tool_choice } : {}),\n\t\t\ttop_p: args.top_p,\n\t\t\t...(args.response_format ? { response_format: args.response_format } : {}),\n\t\t\t...(options?.stream ? { stream: true } : {}),\n\t\t\t...(reasoningEffort !== undefined ? { reasoning_effort: reasoningEffort } : {}),\n\t\t\t...(chatTemplateKwargs !== undefined\n\t\t\t\t? { chat_template_kwargs: chatTemplateKwargs }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\n\t/**\n\t * Get passthrough options for binding.run() from settings.\n\t *\n\t * `reasoning_effort` and `chat_template_kwargs` are explicitly excluded\n\t * here — they belong on the `inputs` object (see `buildRunInputs`), not on\n\t * the `options` (3rd) arg of binding.run() or the REST query string.\n\t */\n\tprivate getRunOptions() {\n\t\tconst {\n\t\t\tgateway,\n\t\t\tsafePrompt: _safePrompt,\n\t\t\tsessionAffinity,\n\t\t\textraHeaders,\n\t\t\treasoning_effort: _reasoningEffort,\n\t\t\tchat_template_kwargs: _chatTemplateKwargs,\n\t\t\t...passthroughOptions\n\t\t} = this.settings;\n\n\t\tconst mergedHeaders = {\n\t\t\t...(extraHeaders && typeof extraHeaders === \"object\"\n\t\t\t\t? (extraHeaders as Record<string, string>)\n\t\t\t\t: {}),\n\t\t\t...(sessionAffinity ? { \"x-session-affinity\": sessionAffinity } : {}),\n\t\t};\n\n\t\treturn {\n\t\t\tgateway: this.config.gateway ?? gateway,\n\t\t\t...(Object.keys(mergedHeaders).length > 0 ? { extraHeaders: mergedHeaders } : {}),\n\t\t\t...passthroughOptions,\n\t\t};\n\t}\n\n\tasync doGenerate(\n\t\toptions: Parameters<LanguageModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n\t\tconst { args, warnings } = this.getArgs(options);\n\t\tconst { messages } = convertToWorkersAIChatMessages(options.prompt);\n\n\t\tconst inputs = this.buildRunInputs(args, messages, {\n\t\t\tproviderOptions: options.providerOptions,\n\t\t});\n\t\tconst runOptions = this.getRunOptions();\n\n\t\tconst output = await this.config.binding.run(\n\t\t\targs.model as keyof AiModels,\n\t\t\tinputs as AiModels[keyof AiModels][\"inputs\"],\n\t\t\t{\n\t\t\t\t...runOptions,\n\t\t\t\tsignal: options.abortSignal,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\tif (output instanceof ReadableStream) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Unexpected streaming response from non-streaming request. Check that `stream: true` was not passed.\",\n\t\t\t);\n\t\t}\n\n\t\tconst outputRecord = output as Record<string, unknown>;\n\t\tconst choices = outputRecord.choices as\n\t\t\t| Array<{\n\t\t\t\t\tmessage?: { reasoning_content?: string; reasoning?: string };\n\t\t\t }>\n\t\t\t| undefined;\n\t\tconst reasoningContent =\n\t\t\tchoices?.[0]?.message?.reasoning_content ?? choices?.[0]?.message?.reasoning;\n\n\t\treturn {\n\t\t\tfinishReason: mapWorkersAIFinishReason(outputRecord),\n\t\t\tcontent: [\n\t\t\t\t...(reasoningContent\n\t\t\t\t\t? [{ type: \"reasoning\" as const, text: reasoningContent }]\n\t\t\t\t\t: []),\n\t\t\t\t{\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: processText(outputRecord) ?? \"\",\n\t\t\t\t},\n\t\t\t\t...processToolCalls(outputRecord),\n\t\t\t],\n\t\t\tusage: mapWorkersAIUsage(output as Record<string, unknown>),\n\t\t\twarnings,\n\t\t};\n\t}\n\n\tasync doStream(\n\t\toptions: Parameters<LanguageModelV3[\"doStream\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doStream\"]>>> {\n\t\tconst { args, warnings } = this.getArgs(options);\n\t\tconst { messages } = convertToWorkersAIChatMessages(options.prompt);\n\n\t\tconst inputs = this.buildRunInputs(args, messages, {\n\t\t\tstream: true,\n\t\t\tproviderOptions: options.providerOptions,\n\t\t});\n\t\tconst runOptions = this.getRunOptions();\n\n\t\tconst response = await this.config.binding.run(\n\t\t\targs.model as keyof AiModels,\n\t\t\tinputs as AiModels[keyof AiModels][\"inputs\"],\n\t\t\t{\n\t\t\t\t...runOptions,\n\t\t\t\tsignal: options.abortSignal,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\t// If the binding returned a stream, pipe it through the SSE mapper\n\t\tif (response instanceof ReadableStream) {\n\t\t\treturn {\n\t\t\t\tstream: prependStreamStart(getMappedStream(response), warnings),\n\t\t\t};\n\t\t}\n\n\t\t// Graceful degradation: some models return a non-streaming response even\n\t\t// when stream:true is requested. Wrap the complete response as a stream.\n\t\tconst outputRecord = response as Record<string, unknown>;\n\t\tconst choices = outputRecord.choices as\n\t\t\t| Array<{\n\t\t\t\t\tmessage?: { reasoning_content?: string; reasoning?: string };\n\t\t\t }>\n\t\t\t| undefined;\n\t\tconst reasoningContent =\n\t\t\tchoices?.[0]?.message?.reasoning_content ?? choices?.[0]?.message?.reasoning;\n\n\t\tlet textId: string | null = null;\n\t\tlet reasoningId: string | null = null;\n\n\t\treturn {\n\t\t\tstream: new ReadableStream<LanguageModelV3StreamPart>({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"stream-start\",\n\t\t\t\t\t\twarnings: warnings as SharedV3Warning[],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (reasoningContent) {\n\t\t\t\t\t\treasoningId = generateId();\n\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-start\", id: reasoningId });\n\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\ttype: \"reasoning-delta\",\n\t\t\t\t\t\t\tid: reasoningId,\n\t\t\t\t\t\t\tdelta: reasoningContent,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t}\n\n\t\t\t\t\tconst text = processText(outputRecord);\n\t\t\t\t\tif (text) {\n\t\t\t\t\t\ttextId = generateId();\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id: textId });\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-delta\", id: textId, delta: text });\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-end\", id: textId });\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const toolCall of processToolCalls(outputRecord)) {\n\t\t\t\t\t\tcontroller.enqueue(toolCall);\n\t\t\t\t\t}\n\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"finish\",\n\t\t\t\t\t\tfinishReason: mapWorkersAIFinishReason(outputRecord),\n\t\t\t\t\t\tusage: mapWorkersAIUsage(response as Record<string, unknown>),\n\t\t\t\t\t});\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t}),\n\t\t};\n\t}\n}\n","import type { ImageModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAIImageSettings } from \"./workersai-image-settings\";\nimport type { ImageGenerationModels } from \"./workersai-models\";\n\nexport type WorkersAIImageConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\nexport class WorkersAIImageModel implements ImageModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget maxImagesPerCall(): number {\n\t\treturn this.settings.maxImagesPerCall ?? 1;\n\t}\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: ImageGenerationModels,\n\t\treadonly settings: WorkersAIImageSettings,\n\t\treadonly config: WorkersAIImageConfig,\n\t) {}\n\n\tasync doGenerate({\n\t\tprompt,\n\t\tn,\n\t\tsize,\n\t\taspectRatio,\n\t\tseed,\n\t\tabortSignal,\n\t}: Parameters<ImageModelV3[\"doGenerate\"]>[0]): Promise<\n\t\tAwaited<ReturnType<ImageModelV3[\"doGenerate\"]>>\n\t> {\n\t\tconst { width, height } = getDimensionsFromSizeString(size);\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\tif (aspectRatio != null) {\n\t\t\twarnings.push({\n\t\t\t\tdetails: \"This model does not support aspect ratio. Use `size` instead.\",\n\t\t\t\tfeature: \"aspectRatio\",\n\t\t\t\ttype: \"unsupported\",\n\t\t\t});\n\t\t}\n\n\t\tconst generateImage = async () => {\n\t\t\tconst output = (await this.config.binding.run(\n\t\t\t\tthis.modelId as keyof AiModels,\n\t\t\t\t{\n\t\t\t\t\theight,\n\t\t\t\t\tprompt: prompt ?? \"\",\n\t\t\t\t\tseed,\n\t\t\t\t\twidth,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tgateway: this.config.gateway,\n\t\t\t\t\tsignal: abortSignal,\n\t\t\t\t} as AiOptions,\n\t\t\t)) as unknown;\n\n\t\t\treturn toUint8Array(output);\n\t\t};\n\n\t\tconst images: Uint8Array[] = await Promise.all(\n\t\t\tArray.from({ length: n }, () => generateImage()),\n\t\t);\n\n\t\treturn {\n\t\t\timages,\n\t\t\tresponse: {\n\t\t\t\theaders: {},\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\ttimestamp: new Date(),\n\t\t\t},\n\t\t\twarnings,\n\t\t};\n\t}\n}\n\nfunction getDimensionsFromSizeString(size: string | undefined) {\n\tconst [width, height] = size?.split(\"x\") ?? [undefined, undefined];\n\n\treturn {\n\t\theight: parseInteger(height),\n\t\twidth: parseInteger(width),\n\t};\n}\n\nfunction parseInteger(value?: string) {\n\tif (value === \"\" || !value) return undefined;\n\tconst number = Number(value);\n\treturn Number.isInteger(number) ? number : undefined;\n}\n\n/**\n * Convert various output types from binding.run() to Uint8Array.\n * Workers AI image models return different types depending on the runtime:\n * - ReadableStream<Uint8Array> (most common in workerd)\n * - Uint8Array / ArrayBuffer (direct binary)\n * - Response (needs .arrayBuffer())\n * - { image: string } with base64 data\n */\nasync function toUint8Array(output: unknown): Promise<Uint8Array> {\n\tif (output instanceof Uint8Array) {\n\t\treturn output;\n\t}\n\tif (output instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(output);\n\t}\n\tif (output instanceof ReadableStream) {\n\t\tconst reader = (output as ReadableStream<Uint8Array>).getReader();\n\t\tconst chunks: Uint8Array[] = [];\n\t\tlet totalLength = 0;\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tchunks.push(value);\n\t\t\ttotalLength += value.length;\n\t\t}\n\t\tconst result = new Uint8Array(totalLength);\n\t\tlet offset = 0;\n\t\tfor (const chunk of chunks) {\n\t\t\tresult.set(chunk, offset);\n\t\t\toffset += chunk.length;\n\t\t}\n\t\treturn result;\n\t}\n\t// Response object (e.g., from REST shim)\n\tif (output instanceof Response) {\n\t\treturn new Uint8Array(await output.arrayBuffer());\n\t}\n\t// Object with binary-like properties\n\tif (typeof output === \"object\" && output !== null) {\n\t\tconst obj = output as Record<string, unknown>;\n\t\t// { image: base64string }\n\t\tif (typeof obj.image === \"string\") {\n\t\t\treturn Uint8Array.from(atob(obj.image), (c) => c.charCodeAt(0));\n\t\t}\n\t\t// { data: Uint8Array }\n\t\tif (obj.data instanceof Uint8Array) {\n\t\t\treturn obj.data;\n\t\t}\n\t\t// { data: ArrayBuffer }\n\t\tif (obj.data instanceof ArrayBuffer) {\n\t\t\treturn new Uint8Array(obj.data);\n\t\t}\n\t\t// Try to get a body if it looks response-like\n\t\tif (typeof obj.arrayBuffer === \"function\") {\n\t\t\treturn new Uint8Array(await (obj as unknown as Response).arrayBuffer());\n\t\t}\n\t}\n\tthrow new Error(\n\t\t`Unexpected output type from image model. Got ${Object.prototype.toString.call(output)} with keys: ${\n\t\t\ttypeof output === \"object\" && output !== null\n\t\t\t\t? JSON.stringify(Object.keys(output))\n\t\t\t\t: \"N/A\"\n\t\t}`,\n\t);\n}\n","import type { TranscriptionModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAITranscriptionSettings } from \"./workersai-transcription-settings\";\nimport type { TranscriptionModels } from \"./workersai-models\";\nimport { createRunBinary, type CreateRunConfig } from \"./utils\";\n\nexport type WorkersAITranscriptionConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n\t/**\n\t * Whether the binding is a real `env.AI` binding (true) or a REST shim (false).\n\t * Nova-3 uses different upload paths depending on this.\n\t */\n\tisBinding: boolean;\n\t/**\n\t * REST credentials, only set when `isBinding` is false.\n\t * Needed for Nova-3 which requires binary upload, bypassing the JSON-based REST shim.\n\t */\n\tcredentials?: CreateRunConfig;\n};\n\n/**\n * Workers AI transcription model implementing the AI SDK's `TranscriptionModelV3` interface.\n *\n * Supports:\n * - Whisper models (`@cf/openai/whisper`, `whisper-tiny-en`, `whisper-large-v3-turbo`)\n * - Deepgram Nova-3 (`@cf/deepgram/nova-3`) — uses a different input/output format\n */\nexport class WorkersAITranscriptionModel implements TranscriptionModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: TranscriptionModels,\n\t\treadonly settings: WorkersAITranscriptionSettings,\n\t\treadonly config: WorkersAITranscriptionConfig,\n\t) {}\n\n\tasync doGenerate(\n\t\toptions: Parameters<TranscriptionModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<TranscriptionModelV3[\"doGenerate\"]>>> {\n\t\tconst { audio, mediaType, abortSignal } = options;\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\t// The AI SDK always converts audio to Uint8Array via\n\t\t// convertDataContentToUint8Array before calling doGenerate.\n\t\tconst audioBytes =\n\t\t\ttypeof audio === \"string\"\n\t\t\t\t? Uint8Array.from(atob(audio), (c) => c.charCodeAt(0))\n\t\t\t\t: audio;\n\n\t\tconst isNova3 = this.modelId === \"@cf/deepgram/nova-3\";\n\n\t\tlet rawResult: unknown;\n\n\t\tif (isNova3) {\n\t\t\trawResult = await this.runNova3(audioBytes, mediaType, abortSignal);\n\t\t} else {\n\t\t\trawResult = await this.runWhisper(audioBytes, abortSignal);\n\t\t}\n\n\t\tconst result = rawResult as Record<string, unknown>;\n\n\t\t// Normalize response into AI SDK format\n\t\tif (isNova3) {\n\t\t\treturn this.normalizeNova3Response(result, warnings);\n\t\t}\n\t\treturn this.normalizeWhisperResponse(result, warnings);\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Whisper models\n\t// ---------------------------------------------------------------------------\n\n\tprivate async runWhisper(audioBytes: Uint8Array, abortSignal?: AbortSignal): Promise<unknown> {\n\t\t// whisper-large-v3-turbo requires base64 audio (both binding and REST).\n\t\t// Other Whisper models accept number[].\n\t\tconst modelStr = this.modelId as string;\n\t\tconst audio =\n\t\t\tmodelStr === \"@cf/openai/whisper-large-v3-turbo\"\n\t\t\t\t? uint8ArrayToBase64(audioBytes)\n\t\t\t\t: Array.from(audioBytes);\n\n\t\tconst inputs: Record<string, unknown> = { audio };\n\n\t\tif (this.settings.language) {\n\t\t\tinputs.language = this.settings.language;\n\t\t}\n\t\tif (this.settings.prompt) {\n\t\t\tinputs.initial_prompt = this.settings.prompt;\n\t\t}\n\n\t\treturn this.config.binding.run(\n\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\tinputs as Parameters<Ai[\"run\"]>[1],\n\t\t\t{ gateway: this.config.gateway, signal: abortSignal } as AiOptions,\n\t\t);\n\t}\n\n\tprivate normalizeWhisperResponse(\n\t\traw: Record<string, unknown>,\n\t\twarnings: Array<SharedV3Warning>,\n\t): Awaited<ReturnType<TranscriptionModelV3[\"doGenerate\"]>> {\n\t\tconst text = (raw.text as string) ?? \"\";\n\n\t\t// Build segments from Whisper's various formats\n\t\tconst segments: Array<{ text: string; startSecond: number; endSecond: number }> = [];\n\n\t\t// whisper-large-v3-turbo returns segments[]\n\t\tif (raw.segments && Array.isArray(raw.segments)) {\n\t\t\tfor (const seg of raw.segments) {\n\t\t\t\tsegments.push({\n\t\t\t\t\ttext: ((seg as Record<string, unknown>).text as string) ?? \"\",\n\t\t\t\t\tstartSecond: ((seg as Record<string, unknown>).start as number) ?? 0,\n\t\t\t\t\tendSecond: ((seg as Record<string, unknown>).end as number) ?? 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// basic whisper returns words[]\n\t\telse if (raw.words && Array.isArray(raw.words)) {\n\t\t\tfor (const w of raw.words) {\n\t\t\t\tsegments.push({\n\t\t\t\t\ttext: ((w as Record<string, unknown>).word as string) ?? \"\",\n\t\t\t\t\tstartSecond: ((w as Record<string, unknown>).start as number) ?? 0,\n\t\t\t\t\tendSecond: ((w as Record<string, unknown>).end as number) ?? 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Language and duration from transcription_info (v3-turbo)\n\t\tconst info = raw.transcription_info as Record<string, unknown> | undefined;\n\n\t\treturn {\n\t\t\ttext,\n\t\t\tsegments,\n\t\t\tlanguage: (info?.language as string) ?? undefined,\n\t\t\tdurationInSeconds: (info?.duration as number) ?? undefined,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Deepgram Nova-3\n\t// ---------------------------------------------------------------------------\n\n\tprivate async runNova3(\n\t\taudioBytes: Uint8Array,\n\t\tmediaType: string,\n\t\tabortSignal?: AbortSignal,\n\t): Promise<unknown> {\n\t\tif (this.config.isBinding) {\n\t\t\t// Binding path: Nova-3 accepts { audio: { body: base64, contentType } }\n\t\t\treturn this.config.binding.run(\n\t\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\t\t{\n\t\t\t\t\taudio: { body: uint8ArrayToBase64(audioBytes), contentType: mediaType },\n\t\t\t\t} as Parameters<Ai[\"run\"]>[1],\n\t\t\t\t{ gateway: this.config.gateway, signal: abortSignal } as AiOptions,\n\t\t\t);\n\t\t}\n\n\t\t// REST path: Nova-3 requires raw binary with a Content-Type header,\n\t\t// not JSON. The createRun shim always sends JSON, so we bypass it\n\t\t// and use createRunBinary which sends the audio bytes directly.\n\t\tif (!this.config.credentials) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Nova-3 transcription via REST requires credentials in the config. \" +\n\t\t\t\t\t\"This is a bug — credentials should have been set by createWorkersAI.\",\n\t\t\t);\n\t\t}\n\t\treturn createRunBinary(\n\t\t\tthis.config.credentials,\n\t\t\tthis.modelId,\n\t\t\taudioBytes,\n\t\t\tmediaType,\n\t\t\tabortSignal,\n\t\t);\n\t}\n\n\tprivate normalizeNova3Response(\n\t\traw: Record<string, unknown>,\n\t\twarnings: Array<SharedV3Warning>,\n\t): Awaited<ReturnType<TranscriptionModelV3[\"doGenerate\"]>> {\n\t\t// Nova-3 format: { results: { channels: [{ alternatives: [{ transcript, words }] }] } }\n\t\tconst results = raw.results as Record<string, unknown> | undefined;\n\t\tconst channels = results?.channels as\n\t\t\t| Array<{\n\t\t\t\t\talternatives?: Array<{\n\t\t\t\t\t\ttranscript?: string;\n\t\t\t\t\t\tconfidence?: number;\n\t\t\t\t\t\twords?: Array<{ word: string; start: number; end: number }>;\n\t\t\t\t\t}>;\n\t\t\t }>\n\t\t\t| undefined;\n\t\tconst alt = channels?.[0]?.alternatives?.[0];\n\n\t\tconst text = alt?.transcript ?? \"\";\n\t\tconst segments: Array<{ text: string; startSecond: number; endSecond: number }> = [];\n\n\t\tif (alt?.words && Array.isArray(alt.words)) {\n\t\t\tfor (const w of alt.words) {\n\t\t\t\tsegments.push({\n\t\t\t\t\ttext: w.word ?? \"\",\n\t\t\t\t\tstartSecond: w.start ?? 0,\n\t\t\t\t\tendSecond: w.end ?? 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttext,\n\t\t\tsegments,\n\t\t\tlanguage: undefined,\n\t\t\tdurationInSeconds: undefined,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbinary += String.fromCharCode(bytes[i]!);\n\t}\n\treturn btoa(binary);\n}\n","import type { SpeechModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAISpeechSettings } from \"./workersai-speech-settings\";\nimport type { SpeechModels } from \"./workersai-models\";\n\nexport type WorkersAISpeechConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\n/**\n * Workers AI speech (text-to-speech) model implementing the AI SDK's `SpeechModelV3` interface.\n *\n * Currently supports Deepgram Aura-1 (`@cf/deepgram/aura-1`).\n * The model accepts `{ text, voice?, speed? }` and returns raw audio bytes.\n */\nexport class WorkersAISpeechModel implements SpeechModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: SpeechModels,\n\t\treadonly settings: WorkersAISpeechSettings,\n\t\treadonly config: WorkersAISpeechConfig,\n\t) {}\n\n\tasync doGenerate(\n\t\toptions: Parameters<SpeechModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<SpeechModelV3[\"doGenerate\"]>>> {\n\t\tconst { text, voice, speed, abortSignal } = options;\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\tif (options.instructions) {\n\t\t\twarnings.push({\n\t\t\t\tdetails: \"Workers AI TTS models do not support instructions.\",\n\t\t\t\tfeature: \"instructions\",\n\t\t\t\ttype: \"unsupported\",\n\t\t\t});\n\t\t}\n\n\t\tif (options.outputFormat) {\n\t\t\twarnings.push({\n\t\t\t\tdetails:\n\t\t\t\t\t\"Workers AI TTS models do not support output format selection. Audio is returned as MP3.\",\n\t\t\t\tfeature: \"outputFormat\",\n\t\t\t\ttype: \"unsupported\",\n\t\t\t});\n\t\t}\n\n\t\t// Build inputs for Workers AI TTS\n\t\tconst inputs: Record<string, unknown> = { text };\n\t\tif (voice) inputs.voice = voice;\n\t\tif (speed != null) inputs.speed = speed;\n\n\t\tconst result = await this.config.binding.run(\n\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\tinputs as Parameters<Ai[\"run\"]>[1],\n\t\t\t{\n\t\t\t\tgateway: this.config.gateway,\n\t\t\t\tsignal: abortSignal,\n\t\t\t\t// returnRawResponse prevents the createRun REST shim from trying\n\t\t\t\t// to JSON.parse binary audio. Real env.AI bindings don't recognize\n\t\t\t\t// this option — it has no effect, and the binding returns the normal\n\t\t\t\t// binary result (Uint8Array/ReadableStream) which toUint8Array handles.\n\t\t\t\treturnRawResponse: true,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\t// Workers AI TTS returns binary audio in various formats:\n\t\t// - Binding: Uint8Array, ArrayBuffer, ReadableStream, or { audio: base64 }\n\t\t// - REST (returnRawResponse): Response object\n\t\tconst audio = await toUint8Array(result);\n\n\t\treturn {\n\t\t\taudio,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert various output types from binding.run() to Uint8Array.\n * Workers AI TTS models return different types depending on the runtime:\n * - Response (from REST shim with returnRawResponse)\n * - ReadableStream<Uint8Array> (most common in workerd)\n * - Uint8Array / ArrayBuffer (direct binary)\n * - { audio: string } with base64 data\n */\nasync function toUint8Array(output: unknown): Promise<Uint8Array> {\n\t// Response object (from REST shim with returnRawResponse: true)\n\tif (output instanceof Response) {\n\t\treturn new Uint8Array(await output.arrayBuffer());\n\t}\n\tif (output instanceof Uint8Array) {\n\t\treturn output;\n\t}\n\tif (output instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(output);\n\t}\n\tif (output instanceof ReadableStream) {\n\t\tconst reader = (output as ReadableStream<Uint8Array>).getReader();\n\t\tconst chunks: Uint8Array[] = [];\n\t\tlet totalLength = 0;\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tchunks.push(value);\n\t\t\ttotalLength += value.length;\n\t\t}\n\t\tconst result = new Uint8Array(totalLength);\n\t\tlet offset = 0;\n\t\tfor (const chunk of chunks) {\n\t\t\tresult.set(chunk, offset);\n\t\t\toffset += chunk.length;\n\t\t}\n\t\treturn result;\n\t}\n\t// Object with audio property (e.g. { audio: base64string })\n\tif (typeof output === \"object\" && output !== null) {\n\t\tconst obj = output as Record<string, unknown>;\n\t\tif (typeof obj.audio === \"string\") {\n\t\t\treturn Uint8Array.from(atob(obj.audio), (c) => c.charCodeAt(0));\n\t\t}\n\t}\n\tthrow new Error(\n\t\t`Unexpected output type from TTS model. Got ${Object.prototype.toString.call(output)}`,\n\t);\n}\n","import type { RerankingModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAIRerankingSettings } from \"./workersai-reranking-settings\";\nimport type { RerankingModels } from \"./workersai-models\";\n\nexport type WorkersAIRerankingConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\n/**\n * Workers AI reranking model implementing the AI SDK's `RerankingModelV3` interface.\n *\n * Supports BGE reranker models (`@cf/baai/bge-reranker-base`, `bge-reranker-v2-m3`).\n *\n * Workers AI reranking API:\n * - Input: `{ query, contexts: [{ text }], top_k? }`\n * - Output: `{ response: [{ id, score }] }`\n */\nexport class WorkersAIRerankingModel implements RerankingModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: RerankingModels,\n\t\treadonly settings: WorkersAIRerankingSettings,\n\t\treadonly config: WorkersAIRerankingConfig,\n\t) {}\n\n\tasync doRerank(\n\t\toptions: Parameters<RerankingModelV3[\"doRerank\"]>[0],\n\t): Promise<Awaited<ReturnType<RerankingModelV3[\"doRerank\"]>>> {\n\t\tconst { documents, query, topN, abortSignal } = options;\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\t// Convert AI SDK documents to Workers AI contexts format\n\t\tconst contexts = documentsToContexts(documents, warnings);\n\n\t\t// Build Workers AI inputs\n\t\tconst inputs: Record<string, unknown> = {\n\t\t\tquery,\n\t\t\tcontexts,\n\t\t};\n\t\tif (topN != null) {\n\t\t\tinputs.top_k = topN;\n\t\t}\n\n\t\tconst result = (await this.config.binding.run(\n\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\tinputs as Parameters<Ai[\"run\"]>[1],\n\t\t\t{ gateway: this.config.gateway, signal: abortSignal } as AiOptions,\n\t\t)) as Record<string, unknown>;\n\n\t\t// Workers AI returns { response: [{ id, score }] }\n\t\tconst response = result.response as Array<{ id?: number; score?: number }> | undefined;\n\n\t\tconst ranking = (response ?? [])\n\t\t\t.map((item) => ({\n\t\t\t\tindex: item.id ?? 0,\n\t\t\t\trelevanceScore: item.score ?? 0,\n\t\t\t}))\n\t\t\t.sort((a, b) => b.relevanceScore - a.relevanceScore);\n\n\t\treturn {\n\t\t\tranking,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert AI SDK document format to Workers AI contexts format.\n *\n * AI SDK supports two document types:\n * - `{ type: 'text', values: string[] }` — direct text strings\n * - `{ type: 'object', values: JSONObject[] }` — JSON objects (stringified for Workers AI)\n */\nfunction documentsToContexts(\n\tdocuments: Parameters<RerankingModelV3[\"doRerank\"]>[0][\"documents\"],\n\twarnings: Array<SharedV3Warning>,\n): Array<{ text: string }> {\n\tif (documents.type === \"text\") {\n\t\treturn documents.values.map((text) => ({ text }));\n\t}\n\n\t// Object documents: stringify each object for the reranker\n\twarnings.push({\n\t\tmessage: \"Workers AI reranker expects text contexts. JSON objects have been stringified.\",\n\t\ttype: \"other\",\n\t});\n\n\treturn documents.values.map((obj) => ({ text: JSON.stringify(obj) }));\n}\n","import { AISearchChatLanguageModel } from \"./aisearch-chat-language-model\";\n\n/**\n * @deprecated Use `AISearchChatLanguageModel` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport class AutoRAGChatLanguageModel extends AISearchChatLanguageModel {}\n","import { AISearchChatLanguageModel } from \"./aisearch-chat-language-model\";\nimport type { AISearchChatSettings } from \"./aisearch-chat-settings\";\nimport { createRun } from \"./utils\";\nimport {\n\tWorkersAIEmbeddingModel,\n\ttype WorkersAIEmbeddingSettings,\n} from \"./workersai-embedding-model\";\nimport { WorkersAIChatLanguageModel } from \"./workersai-chat-language-model\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport { WorkersAIImageModel } from \"./workersai-image-model\";\nimport type { WorkersAIImageSettings } from \"./workersai-image-settings\";\nimport { WorkersAITranscriptionModel } from \"./workersai-transcription-model\";\nimport type { WorkersAITranscriptionSettings } from \"./workersai-transcription-settings\";\nimport { WorkersAISpeechModel } from \"./workersai-speech-model\";\nimport type { WorkersAISpeechSettings } from \"./workersai-speech-settings\";\nimport { WorkersAIRerankingModel } from \"./workersai-reranking-model\";\nimport type { WorkersAIRerankingSettings } from \"./workersai-reranking-settings\";\nimport type {\n\tEmbeddingModels,\n\tImageGenerationModels,\n\tTextGenerationModels,\n\tTranscriptionModels,\n\tSpeechModels,\n\tRerankingModels,\n} from \"./workersai-models\";\n\n// Re-export deprecated AutoRAG aliases\nexport { AutoRAGChatLanguageModel } from \"./autorag-chat-language-model\";\nexport type { AutoRAGChatSettings } from \"./autorag-chat-settings\";\n\n// Export new AI Search types\nexport { AISearchChatLanguageModel } from \"./aisearch-chat-language-model\";\nexport type { AISearchChatSettings } from \"./aisearch-chat-settings\";\n\n// Export transcription and speech types\nexport { WorkersAITranscriptionModel } from \"./workersai-transcription-model\";\nexport type { WorkersAITranscriptionSettings } from \"./workersai-transcription-settings\";\nexport { WorkersAISpeechModel } from \"./workersai-speech-model\";\nexport type { WorkersAISpeechSettings } from \"./workersai-speech-settings\";\nexport { WorkersAIRerankingModel } from \"./workersai-reranking-model\";\nexport type { WorkersAIRerankingSettings } from \"./workersai-reranking-settings\";\n\n// ---------------------------------------------------------------------------\n// Workers AI\n// ---------------------------------------------------------------------------\n\nexport type WorkersAISettings = (\n\t| {\n\t\t\t/**\n\t\t\t * Provide a Cloudflare AI binding.\n\t\t\t */\n\t\t\tbinding: Ai;\n\n\t\t\t/**\n\t\t\t * Credentials must be absent when a binding is given.\n\t\t\t */\n\t\t\taccountId?: never;\n\t\t\tapiKey?: never;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * Provide Cloudflare API credentials directly. Must be used if a binding is not specified.\n\t\t\t */\n\t\t\taccountId: string;\n\t\t\tapiKey: string;\n\t\t\t/**\n\t\t\t * Both binding must be absent if credentials are used directly.\n\t\t\t */\n\t\t\tbinding?: never;\n\n\t\t\t/**\n\t\t\t * Custom fetch implementation. You can use it as a middleware to\n\t\t\t * intercept requests, or to provide a custom fetch implementation\n\t\t\t * for e.g. testing. Only available in credentials mode.\n\t\t\t */\n\t\t\tfetch?: typeof globalThis.fetch;\n\t }\n) & {\n\t/**\n\t * Optionally specify a gateway.\n\t */\n\tgateway?: GatewayOptions;\n};\n\nexport interface WorkersAI {\n\t(modelId: TextGenerationModels, settings?: WorkersAIChatSettings): WorkersAIChatLanguageModel;\n\t/**\n\t * Creates a model for text generation.\n\t **/\n\tchat(\n\t\tmodelId: TextGenerationModels,\n\t\tsettings?: WorkersAIChatSettings,\n\t): WorkersAIChatLanguageModel;\n\n\tembedding(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings?: WorkersAIEmbeddingSettings,\n\t): WorkersAIEmbeddingModel;\n\n\ttextEmbedding(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings?: WorkersAIEmbeddingSettings,\n\t): WorkersAIEmbeddingModel;\n\n\ttextEmbeddingModel(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings?: WorkersAIEmbeddingSettings,\n\t): WorkersAIEmbeddingModel;\n\n\t/**\n\t * Creates a model for image generation.\n\t **/\n\timage(modelId: ImageGenerationModels, settings?: WorkersAIImageSettings): WorkersAIImageModel;\n\timageModel(\n\t\tmodelId: ImageGenerationModels,\n\t\tsettings?: WorkersAIImageSettings,\n\t): WorkersAIImageModel;\n\n\t/**\n\t * Creates a model for speech-to-text transcription.\n\t **/\n\ttranscription(\n\t\tmodelId: TranscriptionModels,\n\t\tsettings?: WorkersAITranscriptionSettings,\n\t): WorkersAITranscriptionModel;\n\ttranscriptionModel(\n\t\tmodelId: TranscriptionModels,\n\t\tsettings?: WorkersAITranscriptionSettings,\n\t): WorkersAITranscriptionModel;\n\n\t/**\n\t * Creates a model for text-to-speech synthesis.\n\t **/\n\tspeech(modelId: SpeechModels, settings?: WorkersAISpeechSettings): WorkersAISpeechModel;\n\tspeechModel(modelId: SpeechModels, settings?: WorkersAISpeechSettings): WorkersAISpeechModel;\n\n\t/**\n\t * Creates a model for document reranking.\n\t **/\n\treranking(\n\t\tmodelId: RerankingModels,\n\t\tsettings?: WorkersAIRerankingSettings,\n\t): WorkersAIRerankingModel;\n\trerankingModel(\n\t\tmodelId: RerankingModels,\n\t\tsettings?: WorkersAIRerankingSettings,\n\t): WorkersAIRerankingModel;\n}\n\n/**\n * Create a Workers AI provider instance.\n */\nexport function createWorkersAI(options: WorkersAISettings): WorkersAI {\n\tif (!options.binding && !(\"accountId\" in options && \"apiKey\" in options)) {\n\t\tthrow new Error(\n\t\t\t\"Invalid Workers AI configuration: you must provide either a binding (e.g. { binding: env.AI }) \" +\n\t\t\t\t\"or credentials ({ accountId, apiKey }).\",\n\t\t);\n\t}\n\n\tlet binding: Ai;\n\tconst isBinding = !!options.binding;\n\n\tif (options.binding) {\n\t\tbinding = options.binding;\n\t} else {\n\t\tconst { accountId, apiKey } = options;\n\t\tbinding = {\n\t\t\trun: createRun({ accountId, apiKey, fetch: options.fetch }),\n\t\t} as Ai;\n\t}\n\n\tconst createChatModel = (modelId: TextGenerationModels, settings: WorkersAIChatSettings = {}) =>\n\t\tnew WorkersAIChatLanguageModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.chat\",\n\t\t\tisBinding,\n\t\t});\n\n\tconst createImageModel = (\n\t\tmodelId: ImageGenerationModels,\n\t\tsettings: WorkersAIImageSettings = {},\n\t) =>\n\t\tnew WorkersAIImageModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.image\",\n\t\t});\n\tconst createEmbeddingModel = (\n\t\tmodelId: EmbeddingModels,\n\t\tsettings: WorkersAIEmbeddingSettings = {},\n\t) =>\n\t\tnew WorkersAIEmbeddingModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.embedding\",\n\t\t});\n\n\tconst createTranscriptionModel = (\n\t\tmodelId: TranscriptionModels,\n\t\tsettings: WorkersAITranscriptionSettings = {},\n\t) =>\n\t\tnew WorkersAITranscriptionModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.transcription\",\n\t\t\tisBinding,\n\t\t\tcredentials:\n\t\t\t\t!isBinding && \"accountId\" in options\n\t\t\t\t\t? { accountId: options.accountId, apiKey: options.apiKey }\n\t\t\t\t\t: undefined,\n\t\t});\n\n\tconst createSpeechModel = (modelId: SpeechModels, settings: WorkersAISpeechSettings = {}) =>\n\t\tnew WorkersAISpeechModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.speech\",\n\t\t});\n\n\tconst createRerankingModel = (\n\t\tmodelId: RerankingModels,\n\t\tsettings: WorkersAIRerankingSettings = {},\n\t) =>\n\t\tnew WorkersAIRerankingModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.reranking\",\n\t\t});\n\n\tconst provider = (modelId: TextGenerationModels, settings?: WorkersAIChatSettings) => {\n\t\tif (new.target) {\n\t\t\tthrow new Error(\"The WorkersAI model function cannot be called with the new keyword.\");\n\t\t}\n\t\treturn createChatModel(modelId, settings);\n\t};\n\n\tprovider.chat = createChatModel;\n\tprovider.embedding = createEmbeddingModel;\n\tprovider.textEmbedding = createEmbeddingModel;\n\tprovider.textEmbeddingModel = createEmbeddingModel;\n\tprovider.image = createImageModel;\n\tprovider.imageModel = createImageModel;\n\tprovider.transcription = createTranscriptionModel;\n\tprovider.transcriptionModel = createTranscriptionModel;\n\tprovider.speech = createSpeechModel;\n\tprovider.speechModel = createSpeechModel;\n\tprovider.reranking = createRerankingModel;\n\tprovider.rerankingModel = createRerankingModel;\n\n\treturn provider;\n}\n\n// ---------------------------------------------------------------------------\n// AI Search (formerly AutoRAG)\n// ---------------------------------------------------------------------------\n\nexport type AISearchSettings = {\n\tbinding: AutoRAG;\n};\n\nexport interface AISearchProvider {\n\t(settings?: AISearchChatSettings): AISearchChatLanguageModel;\n\t/**\n\t * Creates a model for text generation.\n\t **/\n\tchat(settings?: AISearchChatSettings): AISearchChatLanguageModel;\n}\n\n/**\n * Create an AI Search provider instance.\n *\n * AI Search (formerly AutoRAG) is Cloudflare's managed search service.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport function createAISearch(\n\toptions: AISearchSettings,\n\t/** @internal */\n\tproviderName = \"aisearch.chat\",\n): AISearchProvider {\n\tconst binding = options.binding;\n\n\tconst createChatModel = (settings: AISearchChatSettings = {}) =>\n\t\tnew AISearchChatLanguageModel(\"@cf/meta/llama-3.3-70b-instruct-fp8-fast\", settings, {\n\t\t\tbinding,\n\t\t\tprovider: providerName,\n\t\t});\n\n\tconst provider = (settings?: AISearchChatSettings) => {\n\t\tif (new.target) {\n\t\t\tthrow new Error(\"The AISearch model function cannot be called with the new keyword.\");\n\t\t}\n\t\treturn createChatModel(settings);\n\t};\n\n\tprovider.chat = createChatModel;\n\n\treturn provider;\n}\n\n// ---------------------------------------------------------------------------\n// Deprecated AutoRAG aliases\n// ---------------------------------------------------------------------------\n\n/**\n * @deprecated Use `AISearchSettings` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport type AutoRAGSettings = AISearchSettings;\n\n/**\n * @deprecated Use `AISearchProvider` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport type AutoRAGProvider = AISearchProvider;\n\nlet autoRAGWarned = false;\n\n/**\n * @deprecated Use `createAISearch` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport function createAutoRAG(options: AISearchSettings): AISearchProvider {\n\tif (!autoRAGWarned) {\n\t\tautoRAGWarned = true;\n\t\tconsole.warn(\n\t\t\t\"[workers-ai-provider] createAutoRAG is deprecated. Use createAISearch instead. \" +\n\t\t\t\t\"AutoRAG has been renamed to AI Search. \" +\n\t\t\t\t\"See https://developers.cloudflare.com/ai-search/\",\n\t\t);\n\t}\n\treturn createAISearch(options, \"autorag.chat\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["exhaustiveCheck","toUint8Array","uint8ArrayToBase64","exhaustiveCheck","exhaustiveCheck","toUint8Array","ai"],"sources":["../src/utils.ts","../src/convert-to-workersai-chat-messages.ts","../src/map-workersai-usage.ts","../src/map-workersai-finish-reason.ts","../src/streaming.ts","../src/aisearch-chat-language-model.ts","../src/workersai-embedding-model.ts","../src/workersai-chat-language-model.ts","../src/workersai-image-model.ts","../src/workersai-transcription-model.ts","../src/workersai-speech-model.ts","../src/workersai-reranking-model.ts","../src/autorag-chat-language-model.ts","../src/client-fallback.ts","../src/resumable-stream.ts","../src/gateway-delegate.ts","../src/index.ts"],"sourcesContent":["import type { LanguageModelV3, LanguageModelV3ToolCall } from \"@ai-sdk/provider\";\nimport { generateId } from \"ai\";\nimport type { WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n// ---------------------------------------------------------------------------\n// Workers AI quirk workarounds\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize messages before passing to the Workers AI binding.\n *\n * The binding has strict schema validation that differs from the OpenAI API:\n * - `content` must not be null\n */\nexport function normalizeMessagesForBinding(messages: WorkersAIChatPrompt): WorkersAIChatPrompt {\n\treturn messages.map((msg) => {\n\t\tconst normalized = { ...msg };\n\n\t\t// content: null → content: \"\"\n\t\tif (normalized.content === null || normalized.content === undefined) {\n\t\t\t(normalized as { content: string }).content = \"\";\n\t\t}\n\n\t\treturn normalized;\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// REST API client\n// ---------------------------------------------------------------------------\n\n/**\n * General AI run interface with overloads to handle distinct return types.\n */\nexport interface AiRun {\n\t<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"],\n\t\toptions: AiOptions & { returnRawResponse: true },\n\t): Promise<Response>;\n\n\t<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"] & { stream: true },\n\t\toptions?: AiOptions,\n\t): Promise<ReadableStream<Uint8Array>>;\n\n\t<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"],\n\t\toptions?: AiOptions,\n\t): Promise<AiModels[Name][\"postProcessedOutputs\"]>;\n}\n\n/**\n * Parameters for configuring the Cloudflare-based AI runner.\n */\nexport interface CreateRunConfig {\n\t/** Your Cloudflare account identifier. */\n\taccountId: string;\n\t/** Cloudflare API token/key with appropriate permissions. */\n\tapiKey: string;\n\t/** Custom fetch implementation for intercepting requests. */\n\tfetch?: typeof globalThis.fetch;\n}\n\n/**\n * Creates a run method that emulates the Cloudflare Workers AI binding,\n * but uses the Cloudflare REST API under the hood.\n */\nexport function createRun(config: CreateRunConfig): AiRun {\n\tconst { accountId, apiKey } = config;\n\tconst fetchFn = config.fetch ?? globalThis.fetch;\n\n\treturn async function run<Name extends keyof AiModels>(\n\t\tmodel: Name,\n\t\tinputs: AiModels[Name][\"inputs\"],\n\t\toptions?: AiOptions & Record<string, unknown>,\n\t): Promise<Response | ReadableStream<Uint8Array> | AiModels[Name][\"postProcessedOutputs\"]> {\n\t\tconst {\n\t\t\tgateway,\n\t\t\tprefix: _prefix,\n\t\t\textraHeaders,\n\t\t\treturnRawResponse,\n\t\t\tsignal, // AbortSignal — not serializable as a query parameter\n\t\t\t...passthroughOptions\n\t\t} = options || {};\n\n\t\tconst urlParams = new URLSearchParams();\n\t\tfor (const [key, value] of Object.entries(passthroughOptions)) {\n\t\t\tif (value === undefined || value === null) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Value for option '${key}' is not able to be coerced into a string.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst valueStr = String(value);\n\t\t\t\tif (!valueStr) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\turlParams.append(key, valueStr);\n\t\t\t} catch {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Value for option '${key}' is not able to be coerced into a string.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst queryString = urlParams.toString();\n\n\t\tconst modelPath = String(model).startsWith(\"run/\") ? model : `run/${model}`;\n\n\t\t// Build URL: use AI Gateway if gateway option is provided, otherwise direct API\n\t\tconst url = gateway?.id\n\t\t\t? `https://gateway.ai.cloudflare.com/v1/${accountId}/${gateway.id}/workers-ai/${modelPath}${\n\t\t\t\t\tqueryString ? `?${queryString}` : \"\"\n\t\t\t\t}`\n\t\t\t: `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/${modelPath}${\n\t\t\t\t\tqueryString ? `?${queryString}` : \"\"\n\t\t\t\t}`;\n\n\t\tconst headers: Record<string, string> = {\n\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...(extraHeaders && typeof extraHeaders === \"object\"\n\t\t\t\t? (extraHeaders as Record<string, string>)\n\t\t\t\t: {}),\n\t\t};\n\n\t\tif (gateway) {\n\t\t\tif (gateway.skipCache) {\n\t\t\t\theaders[\"cf-aig-skip-cache\"] = \"true\";\n\t\t\t}\n\t\t\tif (typeof gateway.cacheTtl === \"number\") {\n\t\t\t\theaders[\"cf-aig-cache-ttl\"] = String(gateway.cacheTtl);\n\t\t\t}\n\t\t\tif (gateway.cacheKey) {\n\t\t\t\theaders[\"cf-aig-cache-key\"] = gateway.cacheKey;\n\t\t\t}\n\t\t\tif (gateway.metadata) {\n\t\t\t\theaders[\"cf-aig-metadata\"] = JSON.stringify(gateway.metadata);\n\t\t\t}\n\t\t}\n\n\t\tconst body = JSON.stringify(inputs);\n\n\t\tconst response = await fetchFn(url, {\n\t\t\tbody,\n\t\t\theaders,\n\t\t\tmethod: \"POST\",\n\t\t\tsignal: signal as AbortSignal | undefined,\n\t\t});\n\n\t\t// Check for HTTP errors before processing\n\t\tif (!response.ok && !returnRawResponse) {\n\t\t\tlet errorBody: string;\n\t\t\ttry {\n\t\t\t\terrorBody = await response.text();\n\t\t\t} catch {\n\t\t\t\terrorBody = \"<unable to read response body>\";\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`Workers AI API error (${response.status} ${response.statusText}): ${errorBody}`,\n\t\t\t);\n\t\t}\n\n\t\tif (returnRawResponse) {\n\t\t\treturn response;\n\t\t}\n\n\t\tif ((inputs as AiTextGenerationInput).stream === true) {\n\t\t\tconst contentType = response.headers.get(\"content-type\") || \"\";\n\t\t\tif (contentType.includes(\"event-stream\") && response.body) {\n\t\t\t\treturn response.body;\n\t\t\t}\n\t\t\tif (response.body && !contentType.includes(\"json\")) {\n\t\t\t\t// Unknown content type — assume it's a stream\n\t\t\t\treturn response.body;\n\t\t\t}\n\n\t\t\t// Some models (e.g. GPT-OSS) don't support streaming via the /ai/run/\n\t\t\t// endpoint and return a JSON response with empty result instead of SSE.\n\t\t\t// Retry without streaming so doStream's graceful degradation path can\n\t\t\t// wrap the complete response as a synthetic stream.\n\t\t\t// Use the same URL (gateway or direct) as the original request.\n\t\t\tconst retryResponse = await fetchFn(url, {\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\t...(inputs as Record<string, unknown>),\n\t\t\t\t\tstream: false,\n\t\t\t\t}),\n\t\t\t\theaders,\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tsignal: signal as AbortSignal | undefined,\n\t\t\t});\n\n\t\t\tif (!retryResponse.ok) {\n\t\t\t\tlet errorBody: string;\n\t\t\t\ttry {\n\t\t\t\t\terrorBody = await retryResponse.text();\n\t\t\t\t} catch {\n\t\t\t\t\terrorBody = \"<unable to read response body>\";\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Workers AI API error (${retryResponse.status} ${retryResponse.statusText}): ${errorBody}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst retryData = await retryResponse.json<{\n\t\t\t\tresult: AiModels[Name][\"postProcessedOutputs\"];\n\t\t\t}>();\n\t\t\treturn retryData.result;\n\t\t}\n\n\t\tconst data = await response.json<{\n\t\t\tresult: AiModels[Name][\"postProcessedOutputs\"];\n\t\t}>();\n\t\treturn data.result;\n\t};\n}\n\n/**\n * Make a binary REST API call to Workers AI.\n *\n * Some models (e.g. `@cf/deepgram/nova-3`) require raw audio bytes\n * with an appropriate `Content-Type` header instead of JSON.\n *\n * @param config Credentials config\n * @param model Workers AI model name\n * @param audioBytes Raw audio bytes\n * @param contentType MIME type (e.g. \"audio/wav\")\n * @param signal Optional AbortSignal\n * @returns The parsed JSON response body\n */\nexport async function createRunBinary(\n\tconfig: CreateRunConfig,\n\tmodel: string,\n\taudioBytes: Uint8Array,\n\tcontentType: string,\n\tsignal?: AbortSignal,\n): Promise<Record<string, unknown>> {\n\tconst url = `https://api.cloudflare.com/client/v4/accounts/${config.accountId}/ai/run/${model}`;\n\n\tconst response = await fetch(url, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${config.apiKey}`,\n\t\t\t\"Content-Type\": contentType,\n\t\t},\n\t\tbody: audioBytes,\n\t\tsignal,\n\t});\n\n\tif (!response.ok) {\n\t\tlet errorBody: string;\n\t\ttry {\n\t\t\terrorBody = await response.text();\n\t\t} catch {\n\t\t\terrorBody = \"<unable to read response body>\";\n\t\t}\n\t\tthrow new Error(\n\t\t\t`Workers AI API error (${response.status} ${response.statusText}): ${errorBody}`,\n\t\t);\n\t}\n\n\tconst data = await response.json<{ result?: Record<string, unknown> }>();\n\treturn (data.result ?? data) as Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Structured output (JSON mode)\n// ---------------------------------------------------------------------------\n\n/**\n * Build the `response_format.json_schema` payload for native Workers AI models.\n *\n * Native Workers AI (`@cf/...`) expects `json_schema` to be a **bare** JSON\n * Schema, NOT OpenAI's `{ name, schema, strict }` envelope. That envelope is\n * only required by partner-model routes (e.g. `openai/...`), which never reach\n * this code — they go through the gateway delegate and the real `@ai-sdk/*`\n * providers, which build the envelope themselves. Wrapping the schema here would\n * break native models, so we must keep the bare shape.\n *\n * The AI SDK's structured-output `name` / `description` (from\n * `Output.object({ schema, name, description })` / `generateObject`) would\n * otherwise be silently dropped on this path. We preserve them as the standard\n * JSON Schema `title` (from `name`) and `description` keywords, which keeps the\n * payload a valid bare schema while still passing the LLM guidance through.\n *\n * Existing schema-level `title` / `description` are never overwritten, empty\n * strings are ignored, and the input schema object is never mutated.\n *\n * See https://github.com/cloudflare/ai/issues/559.\n */\nexport function buildJsonSchemaPayload(\n\tschema: unknown,\n\tname?: string,\n\tdescription?: string,\n): unknown {\n\t// Only objects can carry JSON Schema keywords. Anything else (incl.\n\t// `undefined` when no schema was supplied) passes through untouched.\n\tif (typeof schema !== \"object\" || schema === null || Array.isArray(schema)) {\n\t\treturn schema;\n\t}\n\n\tconst record = schema as Record<string, unknown>;\n\tconst addTitle = !!name && record.title === undefined;\n\tconst addDescription = !!description && record.description === undefined;\n\n\tif (!addTitle && !addDescription) {\n\t\treturn schema;\n\t}\n\n\treturn {\n\t\t...record,\n\t\t...(addTitle ? { title: name } : {}),\n\t\t...(addDescription ? { description } : {}),\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Tool preparation\n// ---------------------------------------------------------------------------\n\nexport function prepareToolsAndToolChoice(\n\ttools: Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"tools\"],\n\ttoolChoice: Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"toolChoice\"],\n) {\n\tif (tools == null) {\n\t\treturn { tool_choice: undefined, tools: undefined };\n\t}\n\n\tconst mappedTools = tools.map((tool) => ({\n\t\tfunction: {\n\t\t\tdescription: tool.type === \"function\" ? tool.description : undefined,\n\t\t\tname: tool.name,\n\t\t\tparameters: tool.type === \"function\" ? tool.inputSchema : undefined,\n\t\t},\n\t\ttype: \"function\",\n\t}));\n\n\tif (toolChoice == null) {\n\t\treturn { tool_choice: undefined, tools: mappedTools };\n\t}\n\n\tconst type = toolChoice.type;\n\n\tswitch (type) {\n\t\tcase \"auto\":\n\t\t\treturn { tool_choice: type, tools: mappedTools };\n\t\tcase \"none\":\n\t\t\treturn { tool_choice: type, tools: mappedTools };\n\t\tcase \"required\":\n\t\t\treturn { tool_choice: \"required\", tools: mappedTools };\n\n\t\t// Force a specific tool via the OpenAI-style named-function form.\n\t\t// Workers AI enforces this server-side, unlike \"required\" which is\n\t\t// advisory and \"fails open\" on long contexts / reasoning models (the\n\t\t// model can answer in prose instead of calling the tool). The full tool\n\t\t// list is kept (not filtered to the single function) to match OpenAI\n\t\t// semantics and preserve tool-result context fidelity.\n\t\t// See https://github.com/cloudflare/ai/issues/560.\n\t\tcase \"tool\":\n\t\t\treturn {\n\t\t\t\ttool_choice: { type: \"function\", function: { name: toolChoice.toolName } },\n\t\t\t\ttools: mappedTools,\n\t\t\t};\n\t\tdefault: {\n\t\t\tconst exhaustiveCheck = type satisfies never;\n\t\t\tthrow new Error(`Unsupported tool choice type: ${exhaustiveCheck}`);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Message helpers\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Tool call processing\n// ---------------------------------------------------------------------------\n\nconst TOOL_CALL_ID_MARKER = \"::cf-wai-tool-call::\";\n\nexport function createAISDKToolCallId(toolCallId: string | null | undefined): string {\n\tconst originalId = toolCallId || generateId();\n\treturn `${originalId}${TOOL_CALL_ID_MARKER}${generateId()}`;\n}\n\nexport function toWorkersAIToolCallId(toolCallId: string): string {\n\tconst markerIndex = toolCallId.lastIndexOf(TOOL_CALL_ID_MARKER);\n\tif (markerIndex === -1) return toolCallId;\n\n\tconst suffixIndex = markerIndex + TOOL_CALL_ID_MARKER.length;\n\tif (suffixIndex >= toolCallId.length) return toolCallId;\n\n\treturn toolCallId.slice(0, markerIndex);\n}\n\n/** Workers AI flat tool call format (non-streaming, native) */\ninterface FlatToolCall {\n\tname: string;\n\targuments: unknown;\n\tid?: string;\n}\n\n/** Workers AI OpenAI-compatible tool call format */\ninterface OpenAIToolCall {\n\tid: string;\n\ttype: \"function\";\n\tfunction: {\n\t\tname: string;\n\t\targuments: unknown;\n\t};\n}\n\n/** Partial tool call from streaming (has index for merging) */\ninterface PartialToolCall {\n\tindex?: number;\n\tid?: string;\n\ttype?: string;\n\tfunction?: {\n\t\tname?: string;\n\t\targuments?: string;\n\t};\n\t// Flat format fields\n\tname?: string;\n\targuments?: string;\n}\n\nfunction mergePartialToolCalls(partialCalls: PartialToolCall[]) {\n\tconst mergedCallsByIndex: Record<\n\t\tnumber,\n\t\t{ function: { arguments: string; name: string }; id: string; type: string }\n\t> = {};\n\n\tfor (const partialCall of partialCalls) {\n\t\tconst index = partialCall.index ?? 0;\n\n\t\tif (!mergedCallsByIndex[index]) {\n\t\t\tmergedCallsByIndex[index] = {\n\t\t\t\tfunction: {\n\t\t\t\t\targuments: \"\",\n\t\t\t\t\tname: partialCall.function?.name || \"\",\n\t\t\t\t},\n\t\t\t\tid: partialCall.id || \"\",\n\t\t\t\ttype: partialCall.type || \"\",\n\t\t\t};\n\t\t} else {\n\t\t\tif (partialCall.id) {\n\t\t\t\tmergedCallsByIndex[index].id = partialCall.id;\n\t\t\t}\n\t\t\tif (partialCall.type) {\n\t\t\t\tmergedCallsByIndex[index].type = partialCall.type;\n\t\t\t}\n\t\t\tif (partialCall.function?.name) {\n\t\t\t\tmergedCallsByIndex[index].function.name = partialCall.function.name;\n\t\t\t}\n\t\t}\n\n\t\t// Append arguments if available (they arrive in order during streaming)\n\t\tif (partialCall.function?.arguments) {\n\t\t\tmergedCallsByIndex[index].function.arguments += partialCall.function.arguments;\n\t\t}\n\t}\n\n\treturn Object.values(mergedCallsByIndex);\n}\n\nfunction processToolCall(toolCall: FlatToolCall | OpenAIToolCall): LanguageModelV3ToolCall {\n\t// OpenAI format: has function.name (the key discriminator)\n\tconst fn =\n\t\t\"function\" in toolCall && typeof toolCall.function === \"object\" && toolCall.function\n\t\t\t? (toolCall.function as { name?: string; arguments?: unknown })\n\t\t\t: null;\n\n\tif (fn?.name) {\n\t\treturn {\n\t\t\tinput:\n\t\t\t\ttypeof fn.arguments === \"string\"\n\t\t\t\t\t? fn.arguments\n\t\t\t\t\t: JSON.stringify(fn.arguments || {}),\n\t\t\ttoolCallId: createAISDKToolCallId(toolCall.id),\n\t\t\ttype: \"tool-call\",\n\t\t\ttoolName: fn.name,\n\t\t};\n\t}\n\n\t// Flat format (native Workers AI non-streaming): has top-level name\n\tconst flat = toolCall as FlatToolCall;\n\treturn {\n\t\tinput:\n\t\t\ttypeof flat.arguments === \"string\"\n\t\t\t\t? flat.arguments\n\t\t\t\t: JSON.stringify(flat.arguments || {}),\n\t\ttoolCallId: createAISDKToolCallId(flat.id),\n\t\ttype: \"tool-call\",\n\t\ttoolName: flat.name,\n\t};\n}\n\nexport function processToolCalls(output: Record<string, unknown>): LanguageModelV3ToolCall[] {\n\tif (output.tool_calls && Array.isArray(output.tool_calls)) {\n\t\treturn output.tool_calls.map((toolCall: FlatToolCall | OpenAIToolCall) =>\n\t\t\tprocessToolCall(toolCall),\n\t\t);\n\t}\n\n\tconst choices = output.choices as\n\t\t| Array<{ message?: { tool_calls?: Array<FlatToolCall | OpenAIToolCall> } }>\n\t\t| undefined;\n\tif (choices?.[0]?.message?.tool_calls && Array.isArray(choices[0].message.tool_calls)) {\n\t\treturn choices[0].message.tool_calls.map((toolCall) => processToolCall(toolCall));\n\t}\n\n\treturn [];\n}\n\nexport function processPartialToolCalls(partialToolCalls: PartialToolCall[]) {\n\tconst mergedToolCalls = mergePartialToolCalls(partialToolCalls);\n\treturn processToolCalls({ tool_calls: mergedToolCalls });\n}\n\n// ---------------------------------------------------------------------------\n// Forced tool-call salvage (gpt-oss harmony quirk)\n// ---------------------------------------------------------------------------\n\n/**\n * Was a specific tool forced for this request?\n *\n * True for both `tool_choice: \"required\"` and the named-function form\n * `{ type: \"function\", function: { name } }`.\n */\nexport function isForcedToolChoice(toolChoice: unknown): boolean {\n\tif (toolChoice === \"required\") return true;\n\treturn (\n\t\ttypeof toolChoice === \"object\" &&\n\t\ttoolChoice !== null &&\n\t\t(toolChoice as { type?: unknown }).type === \"function\"\n\t);\n}\n\n/**\n * Parse tool calls that a model leaked as JSON text instead of structured\n * `tool_calls`. Shared by the non-streaming salvage and the streaming buffer.\n *\n * Only JSON objects whose `name` is one of `knownToolNames` are recovered;\n * everything else (prose, harmony channel/role leaks like `{\"name\":\"analysis\"}`,\n * hallucinated names) is ignored to avoid fabricating bogus calls.\n */\nexport function parseLeakedToolCalls(\n\ttext: string,\n\tknownToolNames: Set<string>,\n): LanguageModelV3ToolCall[] {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(text.trim());\n\t} catch {\n\t\treturn [];\n\t}\n\n\tconst candidates = Array.isArray(parsed) ? parsed : [parsed];\n\tconst salvaged: LanguageModelV3ToolCall[] = [];\n\n\tfor (const candidate of candidates) {\n\t\tif (typeof candidate !== \"object\" || candidate === null) continue;\n\t\tconst obj = candidate as Record<string, unknown>;\n\t\tconst name = obj.name;\n\t\tif (typeof name !== \"string\" || !knownToolNames.has(name)) continue;\n\n\t\t// Arguments may be wrapped (`arguments`/`parameters`) or flattened as\n\t\t// siblings of `name`.\n\t\tlet args: unknown;\n\t\tif (\"arguments\" in obj) {\n\t\t\targs = obj.arguments;\n\t\t} else if (\"parameters\" in obj) {\n\t\t\targs = obj.parameters;\n\t\t} else {\n\t\t\tconst { name: _name, ...rest } = obj;\n\t\t\targs = rest;\n\t\t}\n\n\t\tsalvaged.push({\n\t\t\tinput: typeof args === \"string\" ? args : JSON.stringify(args ?? {}),\n\t\t\ttoolCallId: createAISDKToolCallId(undefined),\n\t\t\ttype: \"tool-call\",\n\t\t\ttoolName: name,\n\t\t});\n\t}\n\n\treturn salvaged;\n}\n\n/** Collect the requested tool names from mapped tools. */\nexport function getToolNames(\n\ttools: Array<{ function: { name?: string } }> | undefined,\n): Set<string> {\n\treturn new Set(\n\t\t(tools ?? [])\n\t\t\t.map((tool) => tool.function?.name)\n\t\t\t.filter((name): name is string => typeof name === \"string\"),\n\t);\n}\n\n/**\n * Salvage a tool call that a model leaked into text content instead of the\n * structured `tool_calls` field.\n *\n * Workers AI's gpt-oss models (harmony format) sometimes emit a forced tool\n * call as raw JSON in `message.content` with an empty `tool_calls` array and\n * `finish_reason: \"stop\"` — typically when the forced tool is a poor fit for\n * the conversation. The content looks like one of:\n *\n * {\"name\":\"read_skill_resource\",\"path\":\"feedback.txt\"} (flat args)\n * {\"name\":\"calc\",\"arguments\":{\"a\":1}} (wrapped args)\n * [{\"name\":\"calc\",\"parameters\":{\"a\":1}}] (array form)\n *\n * This reinterprets that text as a structured tool call. It is intentionally\n * narrow to avoid false positives:\n * - only runs when a tool was *forced* (required / named-function), so a\n * tool call was explicitly demanded by the caller;\n * - only runs when there are no real structured tool calls to override;\n * - only matches JSON objects whose `name` is one of the requested tools.\n *\n * Returns the salvaged tool calls, or `null` when nothing was salvaged.\n *\n * See https://github.com/cloudflare/ai/issues/560.\n */\nexport function salvageToolCallsFromText(\n\toutput: Record<string, unknown>,\n\tcontext: {\n\t\ttools: Array<{ function: { name?: string } }> | undefined;\n\t\ttoolChoice: unknown;\n\t},\n): LanguageModelV3ToolCall[] | null {\n\tif (!isForcedToolChoice(context.toolChoice)) return null;\n\n\t// Never override real tool calls.\n\tif (processToolCalls(output).length > 0) return null;\n\n\tconst knownToolNames = getToolNames(context.tools);\n\tif (knownToolNames.size === 0) return null;\n\n\tconst text = processText(output);\n\tif (!text) return null;\n\n\tconst salvaged = parseLeakedToolCalls(text, knownToolNames);\n\treturn salvaged.length > 0 ? salvaged : null;\n}\n\n// ---------------------------------------------------------------------------\n// Text extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Extract text from a Workers AI response, handling multiple response formats:\n * - OpenAI format: { choices: [{ message: { content: \"...\" } }] }\n * - Native format: { response: \"...\" }\n * - Structured output quirk: { response: { ... } } (object instead of string)\n * - Structured output quirk: { response: \"{ ... }\" } (JSON string)\n */\nexport function processText(output: Record<string, unknown>): string | undefined {\n\t// OpenAI format\n\tconst choices = output.choices as Array<{ message?: { content?: string | null } }> | undefined;\n\tconst choiceContent = choices?.[0]?.message?.content;\n\tif (choiceContent != null && String(choiceContent).length > 0) {\n\t\treturn String(choiceContent);\n\t}\n\n\tif (\"response\" in output) {\n\t\tconst response = output.response;\n\t\t// Object response (structured output quirk #2)\n\t\tif (typeof response === \"object\" && response !== null) {\n\t\t\treturn JSON.stringify(response);\n\t\t}\n\t\t// Numeric response (quirk #9)\n\t\tif (typeof response === \"number\") {\n\t\t\treturn String(response);\n\t\t}\n\t\t// Null response (e.g., tool-call-only responses)\n\t\tif (response === null || response === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn String(response);\n\t}\n\treturn undefined;\n}\n","import type { LanguageModelV3DataContent, LanguageModelV3Prompt } from \"@ai-sdk/provider\";\nimport { UnsupportedFunctionalityError } from \"@ai-sdk/provider\";\nimport { toWorkersAIToolCallId } from \"./utils\";\nimport type { WorkersAIContentPart, WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n/**\n * Normalise any LanguageModelV3DataContent value to a Uint8Array.\n *\n * Handles:\n * - Uint8Array → returned as-is\n * - string → decoded from base64 (with or without data-URL prefix)\n * - URL → not supported (Workers AI needs raw bytes, not a reference)\n */\nfunction toUint8Array(data: LanguageModelV3DataContent): Uint8Array | null {\n\tif (data instanceof Uint8Array) {\n\t\treturn data;\n\t}\n\n\tif (typeof data === \"string\") {\n\t\tlet base64 = data;\n\t\tif (base64.startsWith(\"data:\")) {\n\t\t\tconst commaIndex = base64.indexOf(\",\");\n\t\t\tif (commaIndex >= 0) {\n\t\t\t\tbase64 = base64.slice(commaIndex + 1);\n\t\t\t}\n\t\t}\n\t\tconst binaryString = atob(base64);\n\t\tconst bytes = new Uint8Array(binaryString.length);\n\t\tfor (let i = 0; i < binaryString.length; i++) {\n\t\t\tbytes[i] = binaryString.charCodeAt(i);\n\t\t}\n\t\treturn bytes;\n\t}\n\n\tif (data instanceof URL) {\n\t\tthrow new Error(\n\t\t\t\"URL image sources are not supported by Workers AI. \" +\n\t\t\t\t\"Provide image data as a Uint8Array or base64 string instead.\",\n\t\t);\n\t}\n\n\treturn null;\n}\n\nfunction assertImageMediaType(mediaType: string | undefined): string {\n\tif (!mediaType) {\n\t\tthrow new UnsupportedFunctionalityError({\n\t\t\tfunctionality: \"file-part-without-media-type\",\n\t\t\tmessage:\n\t\t\t\t\"Workers AI chat only supports image file parts with an image/* mediaType. \" +\n\t\t\t\t\"Received a file part without a mediaType.\",\n\t\t});\n\t}\n\n\t// Media types are case-insensitive (RFC 2045), so compare against a\n\t// lower-cased copy while preserving the caller's original casing on output.\n\tif (!mediaType.toLowerCase().startsWith(\"image/\")) {\n\t\tthrow new UnsupportedFunctionalityError({\n\t\t\tfunctionality: \"non-image-file-part\",\n\t\t\tmessage:\n\t\t\t\t\"Workers AI chat only supports image file parts with an image/* mediaType. \" +\n\t\t\t\t`Received mediaType \"${mediaType}\".`,\n\t\t});\n\t}\n\n\treturn mediaType;\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tconst chunkSize = 8192;\n\tfor (let i = 0; i < bytes.length; i += chunkSize) {\n\t\tconst chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));\n\t\tbinary += String.fromCharCode(...chunk);\n\t}\n\treturn btoa(binary);\n}\n\nexport function convertToWorkersAIChatMessages(prompt: LanguageModelV3Prompt): {\n\tmessages: WorkersAIChatPrompt;\n} {\n\tconst messages: WorkersAIChatPrompt = [];\n\n\tfor (const { role, content } of prompt) {\n\t\tswitch (role) {\n\t\t\tcase \"system\": {\n\t\t\t\tmessages.push({ content, role: \"system\" });\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"user\": {\n\t\t\t\tconst textParts: string[] = [];\n\t\t\t\tconst imageParts: { image: Uint8Array; mediaType: string }[] = [];\n\n\t\t\t\tfor (const part of content) {\n\t\t\t\t\tswitch (part.type) {\n\t\t\t\t\t\tcase \"text\": {\n\t\t\t\t\t\t\ttextParts.push(part.text);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase \"file\": {\n\t\t\t\t\t\t\tconst mediaType = assertImageMediaType(part.mediaType);\n\t\t\t\t\t\t\tconst imageBytes = toUint8Array(part.data);\n\t\t\t\t\t\t\tif (imageBytes) {\n\t\t\t\t\t\t\t\timageParts.push({\n\t\t\t\t\t\t\t\t\timage: imageBytes,\n\t\t\t\t\t\t\t\t\tmediaType,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (imageParts.length > 0) {\n\t\t\t\t\tconst contentArray: WorkersAIContentPart[] = [];\n\t\t\t\t\tif (textParts.length > 0) {\n\t\t\t\t\t\tcontentArray.push({ type: \"text\", text: textParts.join(\"\\n\") });\n\t\t\t\t\t}\n\t\t\t\t\tfor (const img of imageParts) {\n\t\t\t\t\t\tconst base64 = uint8ArrayToBase64(img.image);\n\t\t\t\t\t\tcontentArray.push({\n\t\t\t\t\t\t\ttype: \"image_url\",\n\t\t\t\t\t\t\timage_url: { url: `data:${img.mediaType};base64,${base64}` },\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tmessages.push({ content: contentArray, role: \"user\" });\n\t\t\t\t} else {\n\t\t\t\t\tmessages.push({ content: textParts.join(\"\\n\"), role: \"user\" });\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"assistant\": {\n\t\t\t\tlet text = \"\";\n\t\t\t\tlet reasoning = \"\";\n\t\t\t\tconst toolCalls: Array<{\n\t\t\t\t\tid: string;\n\t\t\t\t\ttype: \"function\";\n\t\t\t\t\tfunction: { name: string; arguments: string };\n\t\t\t\t}> = [];\n\n\t\t\t\tfor (const part of content) {\n\t\t\t\t\tswitch (part.type) {\n\t\t\t\t\t\tcase \"text\": {\n\t\t\t\t\t\t\ttext += part.text;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"reasoning\": {\n\t\t\t\t\t\t\t// Reasoning is accumulated separately and sent as the `reasoning`\n\t\t\t\t\t\t\t// field on the message object. This is the field name vLLM expects\n\t\t\t\t\t\t\t// on input for reasoning models (kimi-k2.7-code, glm-4.7-flash).\n\t\t\t\t\t\t\t// Concatenating it into `content` corrupts the conversation history\n\t\t\t\t\t\t\t// and causes models to produce empty or garbled responses on the\n\t\t\t\t\t\t\t// next turn.\n\t\t\t\t\t\t\treasoning += part.text;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"file\": {\n\t\t\t\t\t\t\t// File parts in assistant messages - no action needed\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"tool-call\": {\n\t\t\t\t\t\t\ttoolCalls.push({\n\t\t\t\t\t\t\t\tfunction: {\n\t\t\t\t\t\t\t\t\targuments: JSON.stringify(part.input),\n\t\t\t\t\t\t\t\t\tname: part.toolName,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tid: toWorkersAIToolCallId(part.toolCallId),\n\t\t\t\t\t\t\t\ttype: \"function\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcase \"tool-result\": {\n\t\t\t\t\t\t\t// Tool results in assistant messages - no action needed\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\tconst exhaustiveCheck = part satisfies never;\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Unsupported part type: ${(exhaustiveCheck as { type: string }).type}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tmessages.push({\n\t\t\t\t\tcontent: text,\n\t\t\t\t\trole: \"assistant\",\n\t\t\t\t\t...(reasoning ? { reasoning } : {}),\n\t\t\t\t\ttool_calls:\n\t\t\t\t\t\ttoolCalls.length > 0\n\t\t\t\t\t\t\t? toolCalls.map(({ function: { name, arguments: args }, id }) => ({\n\t\t\t\t\t\t\t\t\tfunction: { arguments: args, name },\n\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\ttype: \"function\" as const,\n\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t});\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"tool\": {\n\t\t\t\tfor (const toolResponse of content) {\n\t\t\t\t\tif (toolResponse.type === \"tool-result\") {\n\t\t\t\t\t\tconst output = toolResponse.output;\n\t\t\t\t\t\tlet content: string;\n\t\t\t\t\t\tswitch (output.type) {\n\t\t\t\t\t\t\tcase \"text\":\n\t\t\t\t\t\t\tcase \"error-text\":\n\t\t\t\t\t\t\t\tcontent = output.value;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"json\":\n\t\t\t\t\t\t\tcase \"error-json\":\n\t\t\t\t\t\t\t\tcontent = JSON.stringify(output.value);\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"execution-denied\":\n\t\t\t\t\t\t\t\tcontent = output.reason\n\t\t\t\t\t\t\t\t\t? `Tool execution denied: ${output.reason}`\n\t\t\t\t\t\t\t\t\t: \"Tool execution was denied.\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"content\":\n\t\t\t\t\t\t\t\tcontent = output.value\n\t\t\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t\t\t(p): p is { type: \"text\"; text: string } =>\n\t\t\t\t\t\t\t\t\t\t\tp.type === \"text\",\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.map((p) => p.text)\n\t\t\t\t\t\t\t\t\t.join(\"\\n\");\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tcontent = \"\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmessages.push({\n\t\t\t\t\t\t\tcontent,\n\t\t\t\t\t\t\tname: toolResponse.toolName,\n\t\t\t\t\t\t\ttool_call_id: toWorkersAIToolCallId(toolResponse.toolCallId),\n\t\t\t\t\t\t\trole: \"tool\",\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// Skip tool-approval-response parts as they're not supported by Workers AI\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst exhaustiveCheck = role satisfies never;\n\t\t\t\tthrow new Error(`Unsupported role: ${exhaustiveCheck}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { messages };\n}\n","import type { LanguageModelV3Usage } from \"@ai-sdk/provider\";\n\n/**\n * Map Workers AI usage data to the AI SDK V3 usage format.\n * Accepts any object that may have a `usage` property with token counts.\n *\n * Workers AI mirrors the OpenAI usage shape, including\n * `prompt_tokens_details.cached_tokens` for prompt-cache hits. OpenAI-style\n * responses don't distinguish cache reads from cache writes, so we treat\n * `cached_tokens` as `cacheRead` and leave `cacheWrite` undefined.\n */\nexport function mapWorkersAIUsage(\n\toutput: Record<string, unknown> | AiTextGenerationOutput | AiTextToImageOutput,\n): LanguageModelV3Usage {\n\tconst usage = (\n\t\toutput as {\n\t\t\tusage?: {\n\t\t\t\tprompt_tokens?: number;\n\t\t\t\tcompletion_tokens?: number;\n\t\t\t\tprompt_tokens_details?: { cached_tokens?: number };\n\t\t\t};\n\t\t}\n\t).usage ?? {\n\t\tcompletion_tokens: 0,\n\t\tprompt_tokens: 0,\n\t};\n\n\tconst promptTokens = usage.prompt_tokens ?? 0;\n\tconst completionTokens = usage.completion_tokens ?? 0;\n\tconst cachedTokens = usage.prompt_tokens_details?.cached_tokens;\n\n\t// Clamp at 0 in case the provider ever reports cached_tokens > prompt_tokens;\n\t// the v3 spec expects non-negative counts.\n\tconst noCache =\n\t\tcachedTokens !== undefined ? Math.max(0, promptTokens - cachedTokens) : undefined;\n\n\treturn {\n\t\toutputTokens: {\n\t\t\ttotal: completionTokens,\n\t\t\ttext: undefined,\n\t\t\treasoning: undefined,\n\t\t},\n\t\tinputTokens: {\n\t\t\ttotal: promptTokens,\n\t\t\tnoCache,\n\t\t\tcacheRead: cachedTokens,\n\t\t\tcacheWrite: undefined,\n\t\t},\n\t\traw: { total: promptTokens + completionTokens },\n\t};\n}\n","import type { LanguageModelV3FinishReason } from \"@ai-sdk/provider\";\n\n/**\n * Map a Workers AI finish reason to the AI SDK unified finish reason.\n *\n * Accepts either:\n * - A raw finish reason string (e.g., \"stop\", \"tool_calls\")\n * - A full response object with finish_reason in various locations\n */\nexport function mapWorkersAIFinishReason(\n\tfinishReasonOrResponse: string | null | undefined | Record<string, unknown>,\n): LanguageModelV3FinishReason {\n\tlet finishReason: string | null | undefined;\n\n\tif (\n\t\ttypeof finishReasonOrResponse === \"string\" ||\n\t\tfinishReasonOrResponse === null ||\n\t\tfinishReasonOrResponse === undefined\n\t) {\n\t\tfinishReason = finishReasonOrResponse;\n\t} else if (typeof finishReasonOrResponse === \"object\" && finishReasonOrResponse !== null) {\n\t\tconst response = finishReasonOrResponse;\n\n\t\t// OpenAI format: { choices: [{ finish_reason: \"stop\" }] }\n\t\tconst choices = response.choices as Array<{ finish_reason?: string }> | undefined;\n\t\tif (Array.isArray(choices) && choices.length > 0) {\n\t\t\tfinishReason = choices[0].finish_reason;\n\t\t} else if (\"finish_reason\" in response) {\n\t\t\tfinishReason = response.finish_reason as string;\n\t\t} else {\n\t\t\tfinishReason = undefined;\n\t\t}\n\t} else {\n\t\t// Numbers, booleans, etc. -- default to stop\n\t\tfinishReason = undefined;\n\t}\n\n\tconst raw = finishReason ?? \"stop\";\n\n\tswitch (finishReason) {\n\t\tcase \"stop\":\n\t\t\treturn { unified: \"stop\", raw };\n\t\tcase \"length\":\n\t\tcase \"model_length\":\n\t\t\treturn { unified: \"length\", raw };\n\t\tcase \"tool_calls\":\n\t\t\treturn { unified: \"tool-calls\", raw };\n\t\tcase \"error\":\n\t\t\treturn { unified: \"error\", raw };\n\t\tcase \"other\":\n\t\tcase \"unknown\":\n\t\t\treturn { unified: \"other\", raw };\n\t\tdefault:\n\t\t\treturn { unified: \"stop\", raw };\n\t}\n}\n","import type {\n\tLanguageModelV3FinishReason,\n\tLanguageModelV3StreamPart,\n\tLanguageModelV3Usage,\n} from \"@ai-sdk/provider\";\nimport { generateId } from \"ai\";\nimport { mapWorkersAIFinishReason } from \"./map-workersai-finish-reason\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\nimport {\n\tcreateAISDKToolCallId,\n\tgetToolNames,\n\tisForcedToolChoice,\n\tparseLeakedToolCalls,\n} from \"./utils\";\n\n/**\n * Prepend a stream-start event to an existing LanguageModelV3 stream.\n * Uses pipeThrough for proper backpressure and error propagation.\n */\nexport function prependStreamStart(\n\tsource: ReadableStream<LanguageModelV3StreamPart>,\n\twarnings: LanguageModelV3StreamPart extends { type: \"stream-start\" } ? never : unknown,\n): ReadableStream<LanguageModelV3StreamPart> {\n\tlet sentStart = false;\n\treturn source.pipeThrough(\n\t\tnew TransformStream<LanguageModelV3StreamPart, LanguageModelV3StreamPart>({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tif (!sentStart) {\n\t\t\t\t\tsentStart = true;\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"stream-start\",\n\t\t\t\t\t\twarnings: warnings as [],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontroller.enqueue(chunk);\n\t\t\t},\n\t\t\tflush(controller) {\n\t\t\t\tif (!sentStart) {\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"stream-start\",\n\t\t\t\t\t\twarnings: warnings as [],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t);\n}\n\n/**\n * Check if a streaming tool call chunk is a null-finalization sentinel.\n */\nfunction isNullFinalizationChunk(tc: Record<string, unknown>): boolean {\n\tconst fn = tc.function as Record<string, unknown> | undefined;\n\tconst name = fn?.name ?? tc.name ?? null;\n\tconst args = fn?.arguments ?? tc.arguments ?? null;\n\tconst id = tc.id ?? null;\n\treturn !id && !name && (!args || args === \"\");\n}\n\n/**\n * Maps a Workers AI SSE stream into AI SDK V3 LanguageModelV3StreamPart events.\n *\n * Uses a TransformStream pipeline for proper backpressure — chunks are emitted\n * one at a time as the downstream consumer pulls, not buffered eagerly.\n *\n * Handles two distinct formats:\n * 1. Native format: { response: \"chunk\", tool_calls: [...] }\n * 2. OpenAI format: { choices: [{ delta: { content: \"chunk\" } }] }\n */\nexport function getMappedStream(\n\tresponse: Response | ReadableStream<Uint8Array>,\n\tsalvageContext?: {\n\t\ttools: Array<{ function: { name?: string } }> | undefined;\n\t\ttoolChoice: unknown;\n\t},\n): ReadableStream<LanguageModelV3StreamPart> {\n\tconst rawStream =\n\t\tresponse instanceof ReadableStream\n\t\t\t? response\n\t\t\t: (response.body as ReadableStream<Uint8Array>);\n\n\tif (!rawStream) {\n\t\tthrow new Error(\"No readable stream available for SSE parsing.\");\n\t}\n\n\t// gpt-oss harmony quirk: a forced tool call can be streamed as `content`\n\t// text deltas instead of structured tool calls. When a tool was forced,\n\t// buffer the text content (rather than emitting it incrementally) so we can\n\t// reinterpret it as a tool call at flush time. Text is unexpected in forced\n\t// mode anyway, so buffering it does not regress a useful stream.\n\t// See https://github.com/cloudflare/ai/issues/560.\n\tconst knownToolNames = getToolNames(salvageContext?.tools);\n\tconst bufferContentForSalvage =\n\t\tisForcedToolChoice(salvageContext?.toolChoice) && knownToolNames.size > 0;\n\tlet contentBuffer = \"\";\n\tlet anyToolCallStarted = false;\n\n\t// State shared across the transform\n\tlet usage: LanguageModelV3Usage = {\n\t\toutputTokens: { total: 0, text: undefined, reasoning: undefined },\n\t\tinputTokens: {\n\t\t\ttotal: 0,\n\t\t\tnoCache: undefined,\n\t\t\tcacheRead: undefined,\n\t\t\tcacheWrite: undefined,\n\t\t},\n\t\traw: { totalTokens: 0 },\n\t};\n\tlet textId: string | null = null;\n\tlet reasoningId: string | null = null;\n\tlet finishReason: LanguageModelV3FinishReason | null = null;\n\tlet receivedDone = false;\n\tlet receivedAnyData = false;\n\n\t// Track tool call streaming state per index.\n\t// When we see the first chunk for a tool call index, we emit tool-input-start.\n\t// Subsequent argument deltas emit tool-input-delta.\n\t// tool-input-end is emitted eagerly when a new tool index starts or a null\n\t// finalization chunk arrives; any remaining open calls are closed in flush().\n\tconst activeToolCalls = new Map<number, { id: string; toolName: string; args: string }>();\n\tconst closedToolCalls = new Set<number>();\n\tlet lastActiveToolIndex: number | null = null;\n\n\t// Step 1: Decode bytes into SSE lines\n\tconst sseStream = rawStream.pipeThrough(new SSEDecoder());\n\n\t// Step 2: Transform SSE events into LanguageModelV3StreamPart\n\treturn sseStream.pipeThrough(\n\t\tnew TransformStream<string, LanguageModelV3StreamPart>({\n\t\t\ttransform(data, controller) {\n\t\t\t\tif (!data || data === \"[DONE]\") {\n\t\t\t\t\tif (data === \"[DONE]\") receivedDone = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\treceivedAnyData = true;\n\t\t\t\tlet chunk: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tchunk = JSON.parse(data);\n\t\t\t\t} catch {\n\t\t\t\t\tconsole.warn(\"[workers-ai-provider] failed to parse SSE event:\", data);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (chunk.usage) {\n\t\t\t\t\tusage = mapWorkersAIUsage(chunk as Parameters<typeof mapWorkersAIUsage>[0]);\n\t\t\t\t}\n\n\t\t\t\t// Extract finish_reason\n\t\t\t\tconst choices = chunk.choices as\n\t\t\t\t\t| Array<{\n\t\t\t\t\t\t\tfinish_reason?: string;\n\t\t\t\t\t\t\tdelta?: Record<string, unknown>;\n\t\t\t\t\t }>\n\t\t\t\t\t| undefined;\n\t\t\t\tconst choiceFinishReason = choices?.[0]?.finish_reason;\n\t\t\t\tconst directFinishReason = chunk.finish_reason as string | undefined;\n\n\t\t\t\tif (choiceFinishReason != null) {\n\t\t\t\t\tfinishReason = mapWorkersAIFinishReason(choiceFinishReason);\n\t\t\t\t} else if (directFinishReason != null) {\n\t\t\t\t\tfinishReason = mapWorkersAIFinishReason(directFinishReason);\n\t\t\t\t}\n\n\t\t\t\t// --- Native format: top-level `response` field ---\n\t\t\t\tconst nativeResponse = chunk.response;\n\t\t\t\tif (nativeResponse != null && nativeResponse !== \"\") {\n\t\t\t\t\tconst responseText = String(nativeResponse);\n\t\t\t\t\tif (responseText.length > 0) {\n\t\t\t\t\t\tif (bufferContentForSalvage) {\n\t\t\t\t\t\t\tcontentBuffer += responseText;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Close active reasoning block before text starts\n\t\t\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!textId) {\n\t\t\t\t\t\t\t\ttextId = generateId();\n\t\t\t\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id: textId });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\t\ttype: \"text-delta\",\n\t\t\t\t\t\t\t\tid: textId,\n\t\t\t\t\t\t\t\tdelta: responseText,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// --- Native format: top-level `tool_calls` ---\n\t\t\t\tif (Array.isArray(chunk.tool_calls)) {\n\t\t\t\t\t// Close active reasoning block before tool calls start\n\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t}\n\t\t\t\t\temitToolCallDeltas(chunk.tool_calls as Record<string, unknown>[], controller);\n\t\t\t\t}\n\n\t\t\t\t// --- OpenAI format: choices[0].delta ---\n\t\t\t\tif (choices?.[0]?.delta) {\n\t\t\t\t\tconst delta = choices[0].delta;\n\n\t\t\t\t\tconst reasoningDelta = (delta.reasoning_content ?? delta.reasoning) as\n\t\t\t\t\t\t| string\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (reasoningDelta && reasoningDelta.length > 0) {\n\t\t\t\t\t\tif (!reasoningId) {\n\t\t\t\t\t\t\treasoningId = generateId();\n\t\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\t\ttype: \"reasoning-start\",\n\t\t\t\t\t\t\t\tid: reasoningId,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\ttype: \"reasoning-delta\",\n\t\t\t\t\t\t\tid: reasoningId,\n\t\t\t\t\t\t\tdelta: reasoningDelta,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tconst textDelta = delta.content as string | undefined;\n\t\t\t\t\tif (textDelta && textDelta.length > 0) {\n\t\t\t\t\t\tif (bufferContentForSalvage) {\n\t\t\t\t\t\t\tcontentBuffer += textDelta;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Close active reasoning block before text starts\n\t\t\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!textId) {\n\t\t\t\t\t\t\t\ttextId = generateId();\n\t\t\t\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id: textId });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\t\ttype: \"text-delta\",\n\t\t\t\t\t\t\t\tid: textId,\n\t\t\t\t\t\t\t\tdelta: textDelta,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst deltaToolCalls = delta.tool_calls as\n\t\t\t\t\t\t| Record<string, unknown>[]\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tif (Array.isArray(deltaToolCalls)) {\n\t\t\t\t\t\t// Close active reasoning block before tool calls start\n\t\t\t\t\t\tif (reasoningId) {\n\t\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t\t\treasoningId = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\temitToolCallDeltas(deltaToolCalls, controller);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tflush(controller) {\n\t\t\t\t// Close any tool calls that weren't already closed during streaming\n\t\t\t\tfor (const [idx] of activeToolCalls) {\n\t\t\t\t\tif (closedToolCalls.has(idx)) continue;\n\t\t\t\t\tcloseToolCall(idx, controller);\n\t\t\t\t}\n\n\t\t\t\t// Close open reasoning block before any salvaged tool calls.\n\t\t\t\tif (reasoningId) {\n\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t}\n\n\t\t\t\t// Salvage a forced tool call that streamed as buffered text.\n\t\t\t\tlet salvagedToolCalls = false;\n\t\t\t\tif (bufferContentForSalvage && !anyToolCallStarted && contentBuffer.trim()) {\n\t\t\t\t\tconst salvaged = parseLeakedToolCalls(contentBuffer, knownToolNames);\n\t\t\t\t\tif (salvaged.length > 0) {\n\t\t\t\t\t\tfor (const call of salvaged) {\n\t\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\t\ttype: \"tool-input-start\",\n\t\t\t\t\t\t\t\tid: call.toolCallId,\n\t\t\t\t\t\t\t\ttoolName: call.toolName,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\t\ttype: \"tool-input-delta\",\n\t\t\t\t\t\t\t\tid: call.toolCallId,\n\t\t\t\t\t\t\t\tdelta: call.input,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tcontroller.enqueue({ type: \"tool-input-end\", id: call.toolCallId });\n\t\t\t\t\t\t\tcontroller.enqueue(call);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsalvagedToolCalls = true;\n\t\t\t\t\t\t// Stream warnings are fixed at stream-start, so surface the\n\t\t\t\t\t\t// reinterpretation here for observability instead.\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[workers-ai-provider] Recovered ${salvaged.length} forced tool call(s) that the model streamed as text content instead of structured tool calls.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Not a recoverable tool call — emit the buffered text as-is.\n\t\t\t\t\t\tconst id = generateId();\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id });\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-delta\", id, delta: contentBuffer });\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-end\", id });\n\t\t\t\t\t}\n\t\t\t\t} else if (bufferContentForSalvage && contentBuffer.trim()) {\n\t\t\t\t\t// Real tool calls were present alongside buffered text — emit text.\n\t\t\t\t\tconst id = generateId();\n\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id });\n\t\t\t\t\tcontroller.enqueue({ type: \"text-delta\", id, delta: contentBuffer });\n\t\t\t\t\tcontroller.enqueue({ type: \"text-end\", id });\n\t\t\t\t}\n\n\t\t\t\tif (textId) {\n\t\t\t\t\tcontroller.enqueue({ type: \"text-end\", id: textId });\n\t\t\t\t}\n\n\t\t\t\t// Detect premature termination\n\t\t\t\tconst effectiveFinishReason = salvagedToolCalls\n\t\t\t\t\t? ({ unified: \"tool-calls\", raw: \"stop\" } as LanguageModelV3FinishReason)\n\t\t\t\t\t: !receivedDone && receivedAnyData && !finishReason\n\t\t\t\t\t\t? ({\n\t\t\t\t\t\t\t\tunified: \"error\",\n\t\t\t\t\t\t\t\traw: \"stream-truncated\",\n\t\t\t\t\t\t\t} as LanguageModelV3FinishReason)\n\t\t\t\t\t\t: (finishReason ?? { unified: \"stop\", raw: \"stop\" });\n\n\t\t\t\tcontroller.enqueue({\n\t\t\t\t\tfinishReason: effectiveFinishReason,\n\t\t\t\t\ttype: \"finish\",\n\t\t\t\t\tusage,\n\t\t\t\t});\n\t\t\t},\n\t\t}),\n\t);\n\n\t/**\n\t * Emit tool-input-end + tool-call for a tool call that is complete.\n\t */\n\tfunction closeToolCall(\n\t\tindex: number,\n\t\tcontroller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n\t) {\n\t\tconst tc = activeToolCalls.get(index);\n\t\tif (!tc || closedToolCalls.has(index)) return;\n\t\tclosedToolCalls.add(index);\n\t\tcontroller.enqueue({ type: \"tool-input-end\", id: tc.id });\n\t\tcontroller.enqueue({\n\t\t\ttype: \"tool-call\",\n\t\t\ttoolCallId: tc.id,\n\t\t\ttoolName: tc.toolName,\n\t\t\tinput: tc.args,\n\t\t});\n\t}\n\n\t/**\n\t * Emit incremental tool call events from streaming chunks.\n\t *\n\t * Workers AI streams tool calls as:\n\t * Chunk A: { id, type, index, function: { name } } — start\n\t * Chunk B: { index, function: { arguments: \"partial...\" } } — args delta\n\t * Chunk C: { index, function: { arguments: \"rest...\" } } — args delta\n\t * Chunk D: { id: null, type: null, function: { name: null } } — finalize\n\t *\n\t * We emit tool-input-start on first sight, tool-input-delta for each\n\t * argument chunk, and tool-input-end eagerly — either when a new tool\n\t * index starts (closing the previous one) or on a null finalization\n\t * chunk. Any remaining open calls are closed in flush().\n\t */\n\tfunction emitToolCallDeltas(\n\t\ttoolCalls: Record<string, unknown>[],\n\t\tcontroller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n\t) {\n\t\tfor (const tc of toolCalls) {\n\t\t\tif (isNullFinalizationChunk(tc)) {\n\t\t\t\t// Null finalization sentinel — close the last active tool call\n\t\t\t\tif (lastActiveToolIndex != null) {\n\t\t\t\t\tcloseToolCall(lastActiveToolIndex, controller);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst tcIndex = (tc.index as number) ?? 0;\n\t\t\tconst fn = tc.function as Record<string, unknown> | undefined;\n\t\t\tconst tcName = (fn?.name ?? tc.name ?? null) as string | null;\n\t\t\tconst tcArgs = (fn?.arguments ?? tc.arguments ?? null) as string | null;\n\t\t\tconst tcId = tc.id as string | null;\n\n\t\t\tif (!activeToolCalls.has(tcIndex)) {\n\t\t\t\t// A new tool call is starting — close the previous one first\n\t\t\t\tif (lastActiveToolIndex != null && lastActiveToolIndex !== tcIndex) {\n\t\t\t\t\tcloseToolCall(lastActiveToolIndex, controller);\n\t\t\t\t}\n\n\t\t\t\tconst id = createAISDKToolCallId(tcId);\n\t\t\t\tconst toolName = tcName || \"\";\n\t\t\t\tactiveToolCalls.set(tcIndex, { id, toolName, args: \"\" });\n\t\t\t\tlastActiveToolIndex = tcIndex;\n\t\t\t\tanyToolCallStarted = true;\n\n\t\t\t\tcontroller.enqueue({\n\t\t\t\t\ttype: \"tool-input-start\",\n\t\t\t\t\tid,\n\t\t\t\t\ttoolName,\n\t\t\t\t});\n\n\t\t\t\tif (tcArgs != null && tcArgs !== \"\") {\n\t\t\t\t\tconst delta = typeof tcArgs === \"string\" ? tcArgs : JSON.stringify(tcArgs);\n\t\t\t\t\tactiveToolCalls.get(tcIndex)!.args += delta;\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"tool-input-delta\",\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst active = activeToolCalls.get(tcIndex)!;\n\t\t\t\tlastActiveToolIndex = tcIndex;\n\t\t\t\tif (tcArgs != null && tcArgs !== \"\") {\n\t\t\t\t\tconst delta = typeof tcArgs === \"string\" ? tcArgs : JSON.stringify(tcArgs);\n\t\t\t\t\tactive.args += delta;\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"tool-input-delta\",\n\t\t\t\t\t\tid: active.id,\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * TransformStream that decodes a raw byte stream into SSE `data:` payloads.\n * Each output chunk is the string content after \"data: \" (one per SSE event).\n * Handles line buffering for partial chunks.\n */\nclass SSEDecoder extends TransformStream<Uint8Array, string> {\n\tconstructor() {\n\t\tlet buffer = \"\";\n\t\tconst decoder = new TextDecoder();\n\n\t\tsuper({\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tbuffer += decoder.decode(chunk, { stream: true });\n\t\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\t\tbuffer = lines.pop() || \"\";\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tconst trimmed = line.trim();\n\t\t\t\t\tif (!trimmed) continue;\n\t\t\t\t\tif (trimmed.startsWith(\"data: \")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(6));\n\t\t\t\t\t} else if (trimmed.startsWith(\"data:\")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(5));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tflush(controller) {\n\t\t\t\tif (buffer.trim()) {\n\t\t\t\t\tconst trimmed = buffer.trim();\n\t\t\t\t\tif (trimmed.startsWith(\"data: \")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(6));\n\t\t\t\t\t} else if (trimmed.startsWith(\"data:\")) {\n\t\t\t\t\t\tcontroller.enqueue(trimmed.slice(5));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n}\n","import type { LanguageModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\n\nimport type { AISearchChatSettings } from \"./aisearch-chat-settings\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\nimport { getMappedStream, prependStreamStart } from \"./streaming\";\nimport { processToolCalls } from \"./utils\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\ntype AISearchChatConfig = {\n\tprovider: string;\n\tbinding: AutoRAG;\n\tgateway?: GatewayOptions;\n};\n\nexport class AISearchChatLanguageModel implements LanguageModelV3 {\n\treadonly specificationVersion = \"v3\";\n\treadonly defaultObjectGenerationMode = \"json\";\n\n\treadonly supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>> = {};\n\n\treadonly modelId: TextGenerationModels;\n\treadonly settings: AISearchChatSettings;\n\n\tprivate readonly config: AISearchChatConfig;\n\n\tconstructor(\n\t\tmodelId: TextGenerationModels,\n\t\tsettings: AISearchChatSettings,\n\t\tconfig: AISearchChatConfig,\n\t) {\n\t\tthis.modelId = modelId;\n\t\tthis.settings = settings;\n\t\tthis.config = config;\n\t}\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tprivate getWarnings({\n\t\ttools,\n\t\tfrequencyPenalty,\n\t\tpresencePenalty,\n\t\tresponseFormat,\n\t}: Parameters<LanguageModelV3[\"doGenerate\"]>[0]): SharedV3Warning[] {\n\t\tconst warnings: SharedV3Warning[] = [];\n\n\t\tif (tools != null && tools.length > 0) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[workers-ai-provider] Tools are not supported by AI Search. They will be ignored.\",\n\t\t\t);\n\t\t\twarnings.push({ feature: \"tools\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (frequencyPenalty != null) {\n\t\t\twarnings.push({ feature: \"frequencyPenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (presencePenalty != null) {\n\t\t\twarnings.push({ feature: \"presencePenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (responseFormat?.type === \"json\") {\n\t\t\twarnings.push({ feature: \"responseFormat\", type: \"unsupported\" });\n\t\t}\n\n\t\treturn warnings;\n\t}\n\n\t/**\n\t * Build the search query from messages.\n\t * Flattens the conversation into a single string for aiSearch.\n\t */\n\tprivate buildQuery(prompt: Parameters<LanguageModelV3[\"doGenerate\"]>[0][\"prompt\"]): string {\n\t\tconst { messages } = convertToWorkersAIChatMessages(prompt);\n\t\treturn messages.map(({ content, role }) => `${role}: ${content}`).join(\"\\n\\n\");\n\t}\n\n\tasync doGenerate(\n\t\toptions: Parameters<LanguageModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n\t\tconst warnings = this.getWarnings(options);\n\t\tconst query = this.buildQuery(options.prompt);\n\n\t\tconst output = await this.config.binding.aiSearch({ query });\n\n\t\treturn {\n\t\t\tfinishReason: { unified: \"stop\", raw: \"stop\" },\n\t\t\tcontent: [\n\t\t\t\t...output.data.map(({ file_id, filename, score }) => ({\n\t\t\t\t\ttype: \"source\" as const,\n\t\t\t\t\tsourceType: \"url\" as const,\n\t\t\t\t\tid: file_id,\n\t\t\t\t\turl: filename,\n\t\t\t\t\tproviderMetadata: {\n\t\t\t\t\t\tattributes: { score },\n\t\t\t\t\t},\n\t\t\t\t})),\n\t\t\t\t{\n\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\ttext: output.response,\n\t\t\t\t},\n\t\t\t\t...processToolCalls(output as unknown as Record<string, unknown>),\n\t\t\t],\n\t\t\tusage: mapWorkersAIUsage(output as unknown as Record<string, unknown>),\n\t\t\twarnings,\n\t\t};\n\t}\n\n\tasync doStream(\n\t\toptions: Parameters<LanguageModelV3[\"doStream\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doStream\"]>>> {\n\t\tconst warnings = this.getWarnings(options);\n\t\tconst query = this.buildQuery(options.prompt);\n\n\t\tconst response = await this.config.binding.aiSearch({\n\t\t\tquery,\n\t\t\tstream: true,\n\t\t});\n\n\t\treturn {\n\t\t\tstream: prependStreamStart(\n\t\t\t\tgetMappedStream(response as unknown as Response | ReadableStream<Uint8Array>),\n\t\t\t\twarnings,\n\t\t\t),\n\t\t};\n\t}\n}\n","import type {\n\tEmbeddingModelV3,\n\tEmbeddingModelV3CallOptions,\n\tEmbeddingModelV3Result,\n} from \"@ai-sdk/provider\";\nimport { TooManyEmbeddingValuesForCallError } from \"@ai-sdk/provider\";\nimport type { EmbeddingModels } from \"./workersai-models\";\n\nexport type WorkersAIEmbeddingConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\nexport type WorkersAIEmbeddingSettings = {\n\tgateway?: GatewayOptions;\n\tmaxEmbeddingsPerCall?: number;\n\tsupportsParallelCalls?: boolean;\n\n\t/**\n\t * Passthrough settings that are provided directly to the run function.\n\t */\n\t[key: string]: unknown;\n};\n\nexport class WorkersAIEmbeddingModel implements EmbeddingModelV3 {\n\treadonly specificationVersion = \"v3\";\n\treadonly modelId: EmbeddingModels;\n\tprivate readonly config: WorkersAIEmbeddingConfig;\n\tprivate readonly settings: WorkersAIEmbeddingSettings;\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tget maxEmbeddingsPerCall(): number {\n\t\t// https://developers.cloudflare.com/workers-ai/platform/limits/#text-embeddings\n\t\treturn this.settings.maxEmbeddingsPerCall ?? 3000;\n\t}\n\n\tget supportsParallelCalls(): boolean {\n\t\treturn this.settings.supportsParallelCalls ?? true;\n\t}\n\n\tconstructor(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings: WorkersAIEmbeddingSettings,\n\t\tconfig: WorkersAIEmbeddingConfig,\n\t) {\n\t\tthis.modelId = modelId;\n\t\tthis.settings = settings;\n\t\tthis.config = config;\n\t}\n\n\tasync doEmbed({\n\t\tvalues,\n\t\tabortSignal,\n\t}: EmbeddingModelV3CallOptions): Promise<EmbeddingModelV3Result> {\n\t\tif (values.length > this.maxEmbeddingsPerCall) {\n\t\t\tthrow new TooManyEmbeddingValuesForCallError({\n\t\t\t\tmaxEmbeddingsPerCall: this.maxEmbeddingsPerCall,\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\tprovider: this.provider,\n\t\t\t\tvalues,\n\t\t\t});\n\t\t}\n\n\t\tconst {\n\t\t\tgateway,\n\t\t\tmaxEmbeddingsPerCall: _maxEmbeddingsPerCall,\n\t\t\tsupportsParallelCalls: _supportsParallelCalls,\n\t\t\t...passthroughOptions\n\t\t} = this.settings;\n\n\t\tconst response = await this.config.binding.run(\n\t\t\tthis.modelId as keyof AiModels,\n\t\t\t{\n\t\t\t\ttext: values,\n\t\t\t},\n\t\t\t{\n\t\t\t\tgateway: this.config.gateway ?? gateway,\n\t\t\t\tsignal: abortSignal,\n\t\t\t\t...passthroughOptions,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\treturn {\n\t\t\tembeddings: (response as { data: number[][] }).data,\n\t\t\twarnings: [],\n\t\t};\n\t}\n}\n","import type { LanguageModelV3, SharedV3Warning, LanguageModelV3StreamPart } from \"@ai-sdk/provider\";\nimport { generateId } from \"ai\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport { mapWorkersAIFinishReason } from \"./map-workersai-finish-reason\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\nimport { getMappedStream, prependStreamStart } from \"./streaming\";\nimport {\n\tbuildJsonSchemaPayload,\n\tnormalizeMessagesForBinding,\n\tprepareToolsAndToolChoice,\n\tprocessText,\n\tprocessToolCalls,\n\tsalvageToolCallsFromText,\n} from \"./utils\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\ntype WorkersAIChatConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n\t/** True when using a real Workers AI binding (not the REST shim). */\n\tisBinding: boolean;\n};\n\nexport class WorkersAIChatLanguageModel implements LanguageModelV3 {\n\treadonly specificationVersion = \"v3\";\n\treadonly defaultObjectGenerationMode = \"json\";\n\n\treadonly supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>> = {};\n\n\treadonly modelId: TextGenerationModels;\n\treadonly settings: WorkersAIChatSettings;\n\n\tprivate readonly config: WorkersAIChatConfig;\n\n\tconstructor(\n\t\tmodelId: TextGenerationModels,\n\t\tsettings: WorkersAIChatSettings,\n\t\tconfig: WorkersAIChatConfig,\n\t) {\n\t\tthis.modelId = modelId;\n\t\tthis.settings = settings;\n\t\tthis.config = config;\n\t}\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tprivate getArgs({\n\t\tresponseFormat,\n\t\ttools,\n\t\ttoolChoice,\n\t\tmaxOutputTokens,\n\t\ttemperature,\n\t\ttopP,\n\t\tfrequencyPenalty,\n\t\tpresencePenalty,\n\t\tseed,\n\t}: Parameters<LanguageModelV3[\"doGenerate\"]>[0]) {\n\t\tconst type = responseFormat?.type ?? \"text\";\n\n\t\tconst warnings: SharedV3Warning[] = [];\n\n\t\tif (frequencyPenalty != null) {\n\t\t\twarnings.push({ feature: \"frequencyPenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tif (presencePenalty != null) {\n\t\t\twarnings.push({ feature: \"presencePenalty\", type: \"unsupported\" });\n\t\t}\n\n\t\tconst baseArgs = {\n\t\t\tmax_tokens: maxOutputTokens,\n\t\t\tmodel: this.modelId,\n\t\t\trandom_seed: seed,\n\t\t\tsafe_prompt: this.settings.safePrompt,\n\t\t\ttemperature,\n\t\t\ttop_p: topP,\n\t\t};\n\n\t\tswitch (type) {\n\t\t\tcase \"text\": {\n\t\t\t\treturn {\n\t\t\t\t\targs: {\n\t\t\t\t\t\t...baseArgs,\n\t\t\t\t\t\tresponse_format: undefined as\n\t\t\t\t\t\t\t| { type: string; json_schema?: unknown }\n\t\t\t\t\t\t\t| undefined,\n\t\t\t\t\t\t...prepareToolsAndToolChoice(tools, toolChoice),\n\t\t\t\t\t},\n\t\t\t\t\twarnings,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tcase \"json\": {\n\t\t\t\t// Native Workers AI expects a BARE JSON Schema under `json_schema`\n\t\t\t\t// (not OpenAI's `{ name, schema, strict }` envelope — partner models\n\t\t\t\t// that need that go through the gateway delegate, not this path). We\n\t\t\t\t// fold the AI SDK's `name`/`description` into the schema as `title`/\n\t\t\t\t// `description` so they aren't lost. See\n\t\t\t\t// https://github.com/cloudflare/ai/issues/559.\n\t\t\t\tconst json = responseFormat?.type === \"json\" ? responseFormat : undefined;\n\t\t\t\treturn {\n\t\t\t\t\targs: {\n\t\t\t\t\t\t...baseArgs,\n\t\t\t\t\t\tresponse_format: {\n\t\t\t\t\t\t\ttype: \"json_schema\",\n\t\t\t\t\t\t\tjson_schema: buildJsonSchemaPayload(\n\t\t\t\t\t\t\t\tjson?.schema,\n\t\t\t\t\t\t\t\tjson?.name,\n\t\t\t\t\t\t\t\tjson?.description,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttools: undefined,\n\t\t\t\t\t\ttool_choice: undefined,\n\t\t\t\t\t},\n\t\t\t\t\twarnings,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst exhaustiveCheck = type satisfies never;\n\t\t\t\tthrow new Error(`Unsupported type: ${exhaustiveCheck}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build the inputs object for `binding.run()`, shared by doGenerate and doStream.\n\t *\n\t * Images are embedded inline in messages as OpenAI-compatible content\n\t * arrays with `image_url` parts. Both the REST API and the binding\n\t * accept this format at runtime.\n\t *\n\t * The binding path additionally normalises null content to empty strings.\n\t *\n\t * Reasoning controls (`reasoning_effort`, `chat_template_kwargs`) are\n\t * forwarded here from settings. These belong on the INPUTS object, not on\n\t * the 3rd-arg options / REST query string — see\n\t * https://github.com/cloudflare/ai/issues/501. Per-call values from\n\t * `providerOptions[\"workers-ai\"]` override settings.\n\t *\n\t * `reasoning_effort: null` is a valid value (\"disable reasoning\"), so we\n\t * check `!== undefined` rather than truthiness.\n\t */\n\tprivate buildRunInputs(\n\t\targs: ReturnType<typeof this.getArgs>[\"args\"],\n\t\tmessages: ReturnType<typeof convertToWorkersAIChatMessages>[\"messages\"],\n\t\toptions?: { stream?: boolean; providerOptions?: Record<string, unknown> },\n\t) {\n\t\t// The AI SDK types this as `Record<string, JSONObject>` but we defensively\n\t\t// accept anything and only treat it as a lookup if it's a plain object.\n\t\t// `\"key\" in x` throws for primitives, so we can't skip the typeof guard.\n\t\tconst rawPerCall = options?.providerOptions?.[\"workers-ai\"];\n\t\tconst perCall: Record<string, unknown> =\n\t\t\trawPerCall !== null && typeof rawPerCall === \"object\" && !Array.isArray(rawPerCall)\n\t\t\t\t? (rawPerCall as Record<string, unknown>)\n\t\t\t\t: {};\n\t\tconst reasoningEffort =\n\t\t\t\"reasoning_effort\" in perCall\n\t\t\t\t? perCall.reasoning_effort\n\t\t\t\t: this.settings.reasoning_effort;\n\t\tconst chatTemplateKwargs =\n\t\t\t\"chat_template_kwargs\" in perCall\n\t\t\t\t? perCall.chat_template_kwargs\n\t\t\t\t: this.settings.chat_template_kwargs;\n\n\t\treturn {\n\t\t\tmax_tokens: args.max_tokens,\n\t\t\tmessages: this.config.isBinding ? normalizeMessagesForBinding(messages) : messages,\n\t\t\ttemperature: args.temperature,\n\t\t\ttools: args.tools,\n\t\t\t...(args.tool_choice ? { tool_choice: args.tool_choice } : {}),\n\t\t\ttop_p: args.top_p,\n\t\t\t...(args.response_format ? { response_format: args.response_format } : {}),\n\t\t\t...(options?.stream ? { stream: true } : {}),\n\t\t\t...(reasoningEffort !== undefined ? { reasoning_effort: reasoningEffort } : {}),\n\t\t\t...(chatTemplateKwargs !== undefined\n\t\t\t\t? { chat_template_kwargs: chatTemplateKwargs }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\n\t/**\n\t * Get passthrough options for binding.run() from settings.\n\t *\n\t * `reasoning_effort` and `chat_template_kwargs` are explicitly excluded\n\t * here — they belong on the `inputs` object (see `buildRunInputs`), not on\n\t * the `options` (3rd) arg of binding.run() or the REST query string.\n\t */\n\tprivate getRunOptions() {\n\t\tconst {\n\t\t\tgateway,\n\t\t\tsafePrompt: _safePrompt,\n\t\t\tsessionAffinity,\n\t\t\textraHeaders,\n\t\t\treasoning_effort: _reasoningEffort,\n\t\t\tchat_template_kwargs: _chatTemplateKwargs,\n\t\t\t...passthroughOptions\n\t\t} = this.settings;\n\n\t\tconst mergedHeaders = {\n\t\t\t...(extraHeaders && typeof extraHeaders === \"object\"\n\t\t\t\t? (extraHeaders as Record<string, string>)\n\t\t\t\t: {}),\n\t\t\t...(sessionAffinity ? { \"x-session-affinity\": sessionAffinity } : {}),\n\t\t};\n\n\t\treturn {\n\t\t\tgateway: this.config.gateway ?? gateway,\n\t\t\t...(Object.keys(mergedHeaders).length > 0 ? { extraHeaders: mergedHeaders } : {}),\n\t\t\t...passthroughOptions,\n\t\t};\n\t}\n\n\t/**\n\t * Extract reasoning, text, and tool calls from a non-streaming response.\n\t *\n\t * Shared by `doGenerate` and `doStream`'s graceful-degradation branch (the\n\t * path gpt-oss falls through, since it doesn't support `/ai/run/` streaming\n\t * and is retried non-streaming). When a forced tool call was leaked into\n\t * text content (gpt-oss harmony quirk), it is salvaged into a structured\n\t * tool call and the leaked JSON text is suppressed. A warning is appended in\n\t * place so callers can observe the reinterpretation.\n\t */\n\tprivate extractContent(\n\t\toutputRecord: Record<string, unknown>,\n\t\targs: ReturnType<typeof this.getArgs>[\"args\"],\n\t\twarnings: SharedV3Warning[],\n\t) {\n\t\tconst choices = outputRecord.choices as\n\t\t\t| Array<{ message?: { reasoning_content?: string; reasoning?: string } }>\n\t\t\t| undefined;\n\t\tconst reasoningContent =\n\t\t\tchoices?.[0]?.message?.reasoning_content ?? choices?.[0]?.message?.reasoning;\n\n\t\tconst toolCalls = processToolCalls(outputRecord);\n\t\tconst salvaged =\n\t\t\ttoolCalls.length === 0\n\t\t\t\t? salvageToolCallsFromText(outputRecord, {\n\t\t\t\t\t\ttools: args.tools,\n\t\t\t\t\t\ttoolChoice: args.tool_choice,\n\t\t\t\t\t})\n\t\t\t\t: null;\n\n\t\tif (salvaged) {\n\t\t\twarnings.push({\n\t\t\t\ttype: \"other\",\n\t\t\t\tmessage: `Recovered ${salvaged.length} forced tool call(s) that the model emitted as text content instead of structured tool calls (model: ${this.modelId}).`,\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\treasoningContent,\n\t\t\t// Suppress the leaked JSON text when we salvaged a tool call from it.\n\t\t\ttext: salvaged ? \"\" : (processText(outputRecord) ?? \"\"),\n\t\t\ttoolCalls: salvaged ?? toolCalls,\n\t\t\t// When salvaged, the upstream finish_reason is \"stop\"; report\n\t\t\t// \"tool-calls\" so the response is indistinguishable from a native\n\t\t\t// tool call and the agentic loop continues correctly.\n\t\t\tfinishReason: salvaged\n\t\t\t\t? ({ unified: \"tool-calls\", raw: \"stop\" } as const)\n\t\t\t\t: mapWorkersAIFinishReason(outputRecord),\n\t\t};\n\t}\n\n\tasync doGenerate(\n\t\toptions: Parameters<LanguageModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doGenerate\"]>>> {\n\t\tconst { args, warnings } = this.getArgs(options);\n\t\tconst { messages } = convertToWorkersAIChatMessages(options.prompt);\n\n\t\tconst inputs = this.buildRunInputs(args, messages, {\n\t\t\tproviderOptions: options.providerOptions,\n\t\t});\n\t\tconst runOptions = this.getRunOptions();\n\n\t\tconst output = await this.config.binding.run(\n\t\t\targs.model as keyof AiModels,\n\t\t\tinputs as AiModels[keyof AiModels][\"inputs\"],\n\t\t\t{\n\t\t\t\t...runOptions,\n\t\t\t\tsignal: options.abortSignal,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\tif (output instanceof ReadableStream) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Unexpected streaming response from non-streaming request. Check that `stream: true` was not passed.\",\n\t\t\t);\n\t\t}\n\n\t\tconst outputRecord = output as Record<string, unknown>;\n\t\tconst { reasoningContent, text, toolCalls, finishReason } = this.extractContent(\n\t\t\toutputRecord,\n\t\t\targs,\n\t\t\twarnings,\n\t\t);\n\n\t\treturn {\n\t\t\tfinishReason,\n\t\t\tcontent: [\n\t\t\t\t...(reasoningContent\n\t\t\t\t\t? [{ type: \"reasoning\" as const, text: reasoningContent }]\n\t\t\t\t\t: []),\n\t\t\t\t{ type: \"text\" as const, text },\n\t\t\t\t...toolCalls,\n\t\t\t],\n\t\t\tusage: mapWorkersAIUsage(output as Record<string, unknown>),\n\t\t\twarnings,\n\t\t};\n\t}\n\n\tasync doStream(\n\t\toptions: Parameters<LanguageModelV3[\"doStream\"]>[0],\n\t): Promise<Awaited<ReturnType<LanguageModelV3[\"doStream\"]>>> {\n\t\tconst { args, warnings } = this.getArgs(options);\n\t\tconst { messages } = convertToWorkersAIChatMessages(options.prompt);\n\n\t\tconst inputs = this.buildRunInputs(args, messages, {\n\t\t\tstream: true,\n\t\t\tproviderOptions: options.providerOptions,\n\t\t});\n\t\tconst runOptions = this.getRunOptions();\n\n\t\tconst response = await this.config.binding.run(\n\t\t\targs.model as keyof AiModels,\n\t\t\tinputs as AiModels[keyof AiModels][\"inputs\"],\n\t\t\t{\n\t\t\t\t...runOptions,\n\t\t\t\tsignal: options.abortSignal,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\t// If the binding returned a stream, pipe it through the SSE mapper\n\t\tif (response instanceof ReadableStream) {\n\t\t\treturn {\n\t\t\t\tstream: prependStreamStart(\n\t\t\t\t\tgetMappedStream(response, {\n\t\t\t\t\t\ttools: args.tools,\n\t\t\t\t\t\ttoolChoice: args.tool_choice,\n\t\t\t\t\t}),\n\t\t\t\t\twarnings,\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\t// Graceful degradation: some models return a non-streaming response even\n\t\t// when stream:true is requested. Wrap the complete response as a stream.\n\t\tconst outputRecord = response as Record<string, unknown>;\n\t\tconst { reasoningContent, text, toolCalls, finishReason } = this.extractContent(\n\t\t\toutputRecord,\n\t\t\targs,\n\t\t\twarnings,\n\t\t);\n\n\t\tlet textId: string | null = null;\n\t\tlet reasoningId: string | null = null;\n\n\t\treturn {\n\t\t\tstream: new ReadableStream<LanguageModelV3StreamPart>({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"stream-start\",\n\t\t\t\t\t\twarnings: warnings as SharedV3Warning[],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (reasoningContent) {\n\t\t\t\t\t\treasoningId = generateId();\n\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-start\", id: reasoningId });\n\t\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\t\ttype: \"reasoning-delta\",\n\t\t\t\t\t\t\tid: reasoningId,\n\t\t\t\t\t\t\tdelta: reasoningContent,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontroller.enqueue({ type: \"reasoning-end\", id: reasoningId });\n\t\t\t\t\t}\n\n\t\t\t\t\tif (text) {\n\t\t\t\t\t\ttextId = generateId();\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-start\", id: textId });\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-delta\", id: textId, delta: text });\n\t\t\t\t\t\tcontroller.enqueue({ type: \"text-end\", id: textId });\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const toolCall of toolCalls) {\n\t\t\t\t\t\tcontroller.enqueue(toolCall);\n\t\t\t\t\t}\n\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"finish\",\n\t\t\t\t\t\tfinishReason,\n\t\t\t\t\t\tusage: mapWorkersAIUsage(response as Record<string, unknown>),\n\t\t\t\t\t});\n\t\t\t\t\tcontroller.close();\n\t\t\t\t},\n\t\t\t}),\n\t\t};\n\t}\n}\n","import type { ImageModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAIImageSettings } from \"./workersai-image-settings\";\nimport type { ImageGenerationModels } from \"./workersai-models\";\n\nexport type WorkersAIImageConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\nexport class WorkersAIImageModel implements ImageModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget maxImagesPerCall(): number {\n\t\treturn this.settings.maxImagesPerCall ?? 1;\n\t}\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: ImageGenerationModels,\n\t\treadonly settings: WorkersAIImageSettings,\n\t\treadonly config: WorkersAIImageConfig,\n\t) {}\n\n\tasync doGenerate({\n\t\tprompt,\n\t\tn,\n\t\tsize,\n\t\taspectRatio,\n\t\tseed,\n\t\tabortSignal,\n\t}: Parameters<ImageModelV3[\"doGenerate\"]>[0]): Promise<\n\t\tAwaited<ReturnType<ImageModelV3[\"doGenerate\"]>>\n\t> {\n\t\tconst { width, height } = getDimensionsFromSizeString(size);\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\tif (aspectRatio != null) {\n\t\t\twarnings.push({\n\t\t\t\tdetails: \"This model does not support aspect ratio. Use `size` instead.\",\n\t\t\t\tfeature: \"aspectRatio\",\n\t\t\t\ttype: \"unsupported\",\n\t\t\t});\n\t\t}\n\n\t\tconst generateImage = async () => {\n\t\t\tconst output = (await this.config.binding.run(\n\t\t\t\tthis.modelId as keyof AiModels,\n\t\t\t\t{\n\t\t\t\t\theight,\n\t\t\t\t\tprompt: prompt ?? \"\",\n\t\t\t\t\tseed,\n\t\t\t\t\twidth,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tgateway: this.config.gateway,\n\t\t\t\t\tsignal: abortSignal,\n\t\t\t\t} as AiOptions,\n\t\t\t)) as unknown;\n\n\t\t\treturn toUint8Array(output);\n\t\t};\n\n\t\tconst images: Uint8Array[] = await Promise.all(\n\t\t\tArray.from({ length: n }, () => generateImage()),\n\t\t);\n\n\t\treturn {\n\t\t\timages,\n\t\t\tresponse: {\n\t\t\t\theaders: {},\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\ttimestamp: new Date(),\n\t\t\t},\n\t\t\twarnings,\n\t\t};\n\t}\n}\n\nfunction getDimensionsFromSizeString(size: string | undefined) {\n\tconst [width, height] = size?.split(\"x\") ?? [undefined, undefined];\n\n\treturn {\n\t\theight: parseInteger(height),\n\t\twidth: parseInteger(width),\n\t};\n}\n\nfunction parseInteger(value?: string) {\n\tif (value === \"\" || !value) return undefined;\n\tconst number = Number(value);\n\treturn Number.isInteger(number) ? number : undefined;\n}\n\n/**\n * Convert various output types from binding.run() to Uint8Array.\n * Workers AI image models return different types depending on the runtime:\n * - ReadableStream<Uint8Array> (most common in workerd)\n * - Uint8Array / ArrayBuffer (direct binary)\n * - Response (needs .arrayBuffer())\n * - { image: string } with base64 data\n */\nasync function toUint8Array(output: unknown): Promise<Uint8Array> {\n\tif (output instanceof Uint8Array) {\n\t\treturn output;\n\t}\n\tif (output instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(output);\n\t}\n\tif (output instanceof ReadableStream) {\n\t\tconst reader = (output as ReadableStream<Uint8Array>).getReader();\n\t\tconst chunks: Uint8Array[] = [];\n\t\tlet totalLength = 0;\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tchunks.push(value);\n\t\t\ttotalLength += value.length;\n\t\t}\n\t\tconst result = new Uint8Array(totalLength);\n\t\tlet offset = 0;\n\t\tfor (const chunk of chunks) {\n\t\t\tresult.set(chunk, offset);\n\t\t\toffset += chunk.length;\n\t\t}\n\t\treturn result;\n\t}\n\t// Response object (e.g., from REST shim)\n\tif (output instanceof Response) {\n\t\treturn new Uint8Array(await output.arrayBuffer());\n\t}\n\t// Object with binary-like properties\n\tif (typeof output === \"object\" && output !== null) {\n\t\tconst obj = output as Record<string, unknown>;\n\t\t// { image: base64string }\n\t\tif (typeof obj.image === \"string\") {\n\t\t\treturn Uint8Array.from(atob(obj.image), (c) => c.charCodeAt(0));\n\t\t}\n\t\t// { data: Uint8Array }\n\t\tif (obj.data instanceof Uint8Array) {\n\t\t\treturn obj.data;\n\t\t}\n\t\t// { data: ArrayBuffer }\n\t\tif (obj.data instanceof ArrayBuffer) {\n\t\t\treturn new Uint8Array(obj.data);\n\t\t}\n\t\t// Try to get a body if it looks response-like\n\t\tif (typeof obj.arrayBuffer === \"function\") {\n\t\t\treturn new Uint8Array(await (obj as unknown as Response).arrayBuffer());\n\t\t}\n\t}\n\tthrow new Error(\n\t\t`Unexpected output type from image model. Got ${Object.prototype.toString.call(output)} with keys: ${\n\t\t\ttypeof output === \"object\" && output !== null\n\t\t\t\t? JSON.stringify(Object.keys(output))\n\t\t\t\t: \"N/A\"\n\t\t}`,\n\t);\n}\n","import type { TranscriptionModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAITranscriptionSettings } from \"./workersai-transcription-settings\";\nimport type { TranscriptionModels } from \"./workersai-models\";\nimport { createRunBinary, type CreateRunConfig } from \"./utils\";\n\nexport type WorkersAITranscriptionConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n\t/**\n\t * Whether the binding is a real `env.AI` binding (true) or a REST shim (false).\n\t * Nova-3 uses different upload paths depending on this.\n\t */\n\tisBinding: boolean;\n\t/**\n\t * REST credentials, only set when `isBinding` is false.\n\t * Needed for Nova-3 which requires binary upload, bypassing the JSON-based REST shim.\n\t */\n\tcredentials?: CreateRunConfig;\n};\n\n/**\n * Workers AI transcription model implementing the AI SDK's `TranscriptionModelV3` interface.\n *\n * Supports:\n * - Whisper models (`@cf/openai/whisper`, `whisper-tiny-en`, `whisper-large-v3-turbo`)\n * - Deepgram Nova-3 (`@cf/deepgram/nova-3`) — uses a different input/output format\n */\nexport class WorkersAITranscriptionModel implements TranscriptionModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: TranscriptionModels,\n\t\treadonly settings: WorkersAITranscriptionSettings,\n\t\treadonly config: WorkersAITranscriptionConfig,\n\t) {}\n\n\tasync doGenerate(\n\t\toptions: Parameters<TranscriptionModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<TranscriptionModelV3[\"doGenerate\"]>>> {\n\t\tconst { audio, mediaType, abortSignal } = options;\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\t// The AI SDK always converts audio to Uint8Array via\n\t\t// convertDataContentToUint8Array before calling doGenerate.\n\t\tconst audioBytes =\n\t\t\ttypeof audio === \"string\"\n\t\t\t\t? Uint8Array.from(atob(audio), (c) => c.charCodeAt(0))\n\t\t\t\t: audio;\n\n\t\tconst isNova3 = this.modelId === \"@cf/deepgram/nova-3\";\n\n\t\tlet rawResult: unknown;\n\n\t\tif (isNova3) {\n\t\t\trawResult = await this.runNova3(audioBytes, mediaType, abortSignal);\n\t\t} else {\n\t\t\trawResult = await this.runWhisper(audioBytes, abortSignal);\n\t\t}\n\n\t\tconst result = rawResult as Record<string, unknown>;\n\n\t\t// Normalize response into AI SDK format\n\t\tif (isNova3) {\n\t\t\treturn this.normalizeNova3Response(result, warnings);\n\t\t}\n\t\treturn this.normalizeWhisperResponse(result, warnings);\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Whisper models\n\t// ---------------------------------------------------------------------------\n\n\tprivate async runWhisper(audioBytes: Uint8Array, abortSignal?: AbortSignal): Promise<unknown> {\n\t\t// whisper-large-v3-turbo requires base64 audio (both binding and REST).\n\t\t// Other Whisper models accept number[].\n\t\tconst modelStr = this.modelId as string;\n\t\tconst audio =\n\t\t\tmodelStr === \"@cf/openai/whisper-large-v3-turbo\"\n\t\t\t\t? uint8ArrayToBase64(audioBytes)\n\t\t\t\t: Array.from(audioBytes);\n\n\t\tconst inputs: Record<string, unknown> = { audio };\n\n\t\tif (this.settings.language) {\n\t\t\tinputs.language = this.settings.language;\n\t\t}\n\t\tif (this.settings.prompt) {\n\t\t\tinputs.initial_prompt = this.settings.prompt;\n\t\t}\n\n\t\treturn this.config.binding.run(\n\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\tinputs as Parameters<Ai[\"run\"]>[1],\n\t\t\t{ gateway: this.config.gateway, signal: abortSignal } as AiOptions,\n\t\t);\n\t}\n\n\tprivate normalizeWhisperResponse(\n\t\traw: Record<string, unknown>,\n\t\twarnings: Array<SharedV3Warning>,\n\t): Awaited<ReturnType<TranscriptionModelV3[\"doGenerate\"]>> {\n\t\tconst text = (raw.text as string) ?? \"\";\n\n\t\t// Build segments from Whisper's various formats\n\t\tconst segments: Array<{ text: string; startSecond: number; endSecond: number }> = [];\n\n\t\t// whisper-large-v3-turbo returns segments[]\n\t\tif (raw.segments && Array.isArray(raw.segments)) {\n\t\t\tfor (const seg of raw.segments) {\n\t\t\t\tsegments.push({\n\t\t\t\t\ttext: ((seg as Record<string, unknown>).text as string) ?? \"\",\n\t\t\t\t\tstartSecond: ((seg as Record<string, unknown>).start as number) ?? 0,\n\t\t\t\t\tendSecond: ((seg as Record<string, unknown>).end as number) ?? 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t// basic whisper returns words[]\n\t\telse if (raw.words && Array.isArray(raw.words)) {\n\t\t\tfor (const w of raw.words) {\n\t\t\t\tsegments.push({\n\t\t\t\t\ttext: ((w as Record<string, unknown>).word as string) ?? \"\",\n\t\t\t\t\tstartSecond: ((w as Record<string, unknown>).start as number) ?? 0,\n\t\t\t\t\tendSecond: ((w as Record<string, unknown>).end as number) ?? 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Language and duration from transcription_info (v3-turbo)\n\t\tconst info = raw.transcription_info as Record<string, unknown> | undefined;\n\n\t\treturn {\n\t\t\ttext,\n\t\t\tsegments,\n\t\t\tlanguage: (info?.language as string) ?? undefined,\n\t\t\tdurationInSeconds: (info?.duration as number) ?? undefined,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n\n\t// ---------------------------------------------------------------------------\n\t// Deepgram Nova-3\n\t// ---------------------------------------------------------------------------\n\n\tprivate async runNova3(\n\t\taudioBytes: Uint8Array,\n\t\tmediaType: string,\n\t\tabortSignal?: AbortSignal,\n\t): Promise<unknown> {\n\t\tif (this.config.isBinding) {\n\t\t\t// Binding path: Nova-3 accepts { audio: { body: base64, contentType } }\n\t\t\treturn this.config.binding.run(\n\t\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\t\t{\n\t\t\t\t\taudio: { body: uint8ArrayToBase64(audioBytes), contentType: mediaType },\n\t\t\t\t} as Parameters<Ai[\"run\"]>[1],\n\t\t\t\t{ gateway: this.config.gateway, signal: abortSignal } as AiOptions,\n\t\t\t);\n\t\t}\n\n\t\t// REST path: Nova-3 requires raw binary with a Content-Type header,\n\t\t// not JSON. The createRun shim always sends JSON, so we bypass it\n\t\t// and use createRunBinary which sends the audio bytes directly.\n\t\tif (!this.config.credentials) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Nova-3 transcription via REST requires credentials in the config. \" +\n\t\t\t\t\t\"This is a bug — credentials should have been set by createWorkersAI.\",\n\t\t\t);\n\t\t}\n\t\treturn createRunBinary(\n\t\t\tthis.config.credentials,\n\t\t\tthis.modelId,\n\t\t\taudioBytes,\n\t\t\tmediaType,\n\t\t\tabortSignal,\n\t\t);\n\t}\n\n\tprivate normalizeNova3Response(\n\t\traw: Record<string, unknown>,\n\t\twarnings: Array<SharedV3Warning>,\n\t): Awaited<ReturnType<TranscriptionModelV3[\"doGenerate\"]>> {\n\t\t// Nova-3 format: { results: { channels: [{ alternatives: [{ transcript, words }] }] } }\n\t\tconst results = raw.results as Record<string, unknown> | undefined;\n\t\tconst channels = results?.channels as\n\t\t\t| Array<{\n\t\t\t\t\talternatives?: Array<{\n\t\t\t\t\t\ttranscript?: string;\n\t\t\t\t\t\tconfidence?: number;\n\t\t\t\t\t\twords?: Array<{ word: string; start: number; end: number }>;\n\t\t\t\t\t}>;\n\t\t\t }>\n\t\t\t| undefined;\n\t\tconst alt = channels?.[0]?.alternatives?.[0];\n\n\t\tconst text = alt?.transcript ?? \"\";\n\t\tconst segments: Array<{ text: string; startSecond: number; endSecond: number }> = [];\n\n\t\tif (alt?.words && Array.isArray(alt.words)) {\n\t\t\tfor (const w of alt.words) {\n\t\t\t\tsegments.push({\n\t\t\t\t\ttext: w.word ?? \"\",\n\t\t\t\t\tstartSecond: w.start ?? 0,\n\t\t\t\t\tendSecond: w.end ?? 0,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttext,\n\t\t\tsegments,\n\t\t\tlanguage: undefined,\n\t\t\tdurationInSeconds: undefined,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n\tlet binary = \"\";\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbinary += String.fromCharCode(bytes[i]!);\n\t}\n\treturn btoa(binary);\n}\n","import type { SpeechModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAISpeechSettings } from \"./workersai-speech-settings\";\nimport type { SpeechModels } from \"./workersai-models\";\n\nexport type WorkersAISpeechConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\n/**\n * Workers AI speech (text-to-speech) model implementing the AI SDK's `SpeechModelV3` interface.\n *\n * Currently supports Deepgram Aura-1 (`@cf/deepgram/aura-1`).\n * The model accepts `{ text, voice?, speed? }` and returns raw audio bytes.\n */\nexport class WorkersAISpeechModel implements SpeechModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: SpeechModels,\n\t\treadonly settings: WorkersAISpeechSettings,\n\t\treadonly config: WorkersAISpeechConfig,\n\t) {}\n\n\tasync doGenerate(\n\t\toptions: Parameters<SpeechModelV3[\"doGenerate\"]>[0],\n\t): Promise<Awaited<ReturnType<SpeechModelV3[\"doGenerate\"]>>> {\n\t\tconst { text, voice, speed, abortSignal } = options;\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\tif (options.instructions) {\n\t\t\twarnings.push({\n\t\t\t\tdetails: \"Workers AI TTS models do not support instructions.\",\n\t\t\t\tfeature: \"instructions\",\n\t\t\t\ttype: \"unsupported\",\n\t\t\t});\n\t\t}\n\n\t\tif (options.outputFormat) {\n\t\t\twarnings.push({\n\t\t\t\tdetails:\n\t\t\t\t\t\"Workers AI TTS models do not support output format selection. Audio is returned as MP3.\",\n\t\t\t\tfeature: \"outputFormat\",\n\t\t\t\ttype: \"unsupported\",\n\t\t\t});\n\t\t}\n\n\t\t// Build inputs for Workers AI TTS\n\t\tconst inputs: Record<string, unknown> = { text };\n\t\tif (voice) inputs.voice = voice;\n\t\tif (speed != null) inputs.speed = speed;\n\n\t\tconst result = await this.config.binding.run(\n\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\tinputs as Parameters<Ai[\"run\"]>[1],\n\t\t\t{\n\t\t\t\tgateway: this.config.gateway,\n\t\t\t\tsignal: abortSignal,\n\t\t\t\t// returnRawResponse prevents the createRun REST shim from trying\n\t\t\t\t// to JSON.parse binary audio. Real env.AI bindings don't recognize\n\t\t\t\t// this option — it has no effect, and the binding returns the normal\n\t\t\t\t// binary result (Uint8Array/ReadableStream) which toUint8Array handles.\n\t\t\t\treturnRawResponse: true,\n\t\t\t} as AiOptions,\n\t\t);\n\n\t\t// Workers AI TTS returns binary audio in various formats:\n\t\t// - Binding: Uint8Array, ArrayBuffer, ReadableStream, or { audio: base64 }\n\t\t// - REST (returnRawResponse): Response object\n\t\tconst audio = await toUint8Array(result);\n\n\t\treturn {\n\t\t\taudio,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert various output types from binding.run() to Uint8Array.\n * Workers AI TTS models return different types depending on the runtime:\n * - Response (from REST shim with returnRawResponse)\n * - ReadableStream<Uint8Array> (most common in workerd)\n * - Uint8Array / ArrayBuffer (direct binary)\n * - { audio: string } with base64 data\n */\nasync function toUint8Array(output: unknown): Promise<Uint8Array> {\n\t// Response object (from REST shim with returnRawResponse: true)\n\tif (output instanceof Response) {\n\t\treturn new Uint8Array(await output.arrayBuffer());\n\t}\n\tif (output instanceof Uint8Array) {\n\t\treturn output;\n\t}\n\tif (output instanceof ArrayBuffer) {\n\t\treturn new Uint8Array(output);\n\t}\n\tif (output instanceof ReadableStream) {\n\t\tconst reader = (output as ReadableStream<Uint8Array>).getReader();\n\t\tconst chunks: Uint8Array[] = [];\n\t\tlet totalLength = 0;\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tchunks.push(value);\n\t\t\ttotalLength += value.length;\n\t\t}\n\t\tconst result = new Uint8Array(totalLength);\n\t\tlet offset = 0;\n\t\tfor (const chunk of chunks) {\n\t\t\tresult.set(chunk, offset);\n\t\t\toffset += chunk.length;\n\t\t}\n\t\treturn result;\n\t}\n\t// Object with audio property (e.g. { audio: base64string })\n\tif (typeof output === \"object\" && output !== null) {\n\t\tconst obj = output as Record<string, unknown>;\n\t\tif (typeof obj.audio === \"string\") {\n\t\t\treturn Uint8Array.from(atob(obj.audio), (c) => c.charCodeAt(0));\n\t\t}\n\t}\n\tthrow new Error(\n\t\t`Unexpected output type from TTS model. Got ${Object.prototype.toString.call(output)}`,\n\t);\n}\n","import type { RerankingModelV3, SharedV3Warning } from \"@ai-sdk/provider\";\nimport type { WorkersAIRerankingSettings } from \"./workersai-reranking-settings\";\nimport type { RerankingModels } from \"./workersai-models\";\n\nexport type WorkersAIRerankingConfig = {\n\tprovider: string;\n\tbinding: Ai;\n\tgateway?: GatewayOptions;\n};\n\n/**\n * Workers AI reranking model implementing the AI SDK's `RerankingModelV3` interface.\n *\n * Supports BGE reranker models (`@cf/baai/bge-reranker-base`, `bge-reranker-v2-m3`).\n *\n * Workers AI reranking API:\n * - Input: `{ query, contexts: [{ text }], top_k? }`\n * - Output: `{ response: [{ id, score }] }`\n */\nexport class WorkersAIRerankingModel implements RerankingModelV3 {\n\treadonly specificationVersion = \"v3\";\n\n\tget provider(): string {\n\t\treturn this.config.provider;\n\t}\n\n\tconstructor(\n\t\treadonly modelId: RerankingModels,\n\t\treadonly settings: WorkersAIRerankingSettings,\n\t\treadonly config: WorkersAIRerankingConfig,\n\t) {}\n\n\tasync doRerank(\n\t\toptions: Parameters<RerankingModelV3[\"doRerank\"]>[0],\n\t): Promise<Awaited<ReturnType<RerankingModelV3[\"doRerank\"]>>> {\n\t\tconst { documents, query, topN, abortSignal } = options;\n\n\t\tconst warnings: Array<SharedV3Warning> = [];\n\n\t\t// Convert AI SDK documents to Workers AI contexts format\n\t\tconst contexts = documentsToContexts(documents, warnings);\n\n\t\t// Build Workers AI inputs\n\t\tconst inputs: Record<string, unknown> = {\n\t\t\tquery,\n\t\t\tcontexts,\n\t\t};\n\t\tif (topN != null) {\n\t\t\tinputs.top_k = topN;\n\t\t}\n\n\t\tconst result = (await this.config.binding.run(\n\t\t\tthis.modelId as Parameters<Ai[\"run\"]>[0],\n\t\t\tinputs as Parameters<Ai[\"run\"]>[1],\n\t\t\t{ gateway: this.config.gateway, signal: abortSignal } as AiOptions,\n\t\t)) as Record<string, unknown>;\n\n\t\t// Workers AI returns { response: [{ id, score }] }\n\t\tconst response = result.response as Array<{ id?: number; score?: number }> | undefined;\n\n\t\tconst ranking = (response ?? [])\n\t\t\t.map((item) => ({\n\t\t\t\tindex: item.id ?? 0,\n\t\t\t\trelevanceScore: item.score ?? 0,\n\t\t\t}))\n\t\t\t.sort((a, b) => b.relevanceScore - a.relevanceScore);\n\n\t\treturn {\n\t\t\tranking,\n\t\t\twarnings,\n\t\t\tresponse: {\n\t\t\t\ttimestamp: new Date(),\n\t\t\t\tmodelId: this.modelId,\n\t\t\t\theaders: {},\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert AI SDK document format to Workers AI contexts format.\n *\n * AI SDK supports two document types:\n * - `{ type: 'text', values: string[] }` — direct text strings\n * - `{ type: 'object', values: JSONObject[] }` — JSON objects (stringified for Workers AI)\n */\nfunction documentsToContexts(\n\tdocuments: Parameters<RerankingModelV3[\"doRerank\"]>[0][\"documents\"],\n\twarnings: Array<SharedV3Warning>,\n): Array<{ text: string }> {\n\tif (documents.type === \"text\") {\n\t\treturn documents.values.map((text) => ({ text }));\n\t}\n\n\t// Object documents: stringify each object for the reranker\n\twarnings.push({\n\t\tmessage: \"Workers AI reranker expects text contexts. JSON objects have been stringified.\",\n\t\ttype: \"other\",\n\t});\n\n\treturn documents.values.map((obj) => ({ text: JSON.stringify(obj) }));\n}\n","import { AISearchChatLanguageModel } from \"./aisearch-chat-language-model\";\n\n/**\n * @deprecated Use `AISearchChatLanguageModel` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport class AutoRAGChatLanguageModel extends AISearchChatLanguageModel {}\n","import type {\n\tLanguageModelV3,\n\tLanguageModelV3CallOptions,\n\tLanguageModelV3GenerateResult,\n\tLanguageModelV3StreamResult,\n} from \"@ai-sdk/provider\";\nimport { type FallbackAttempt, WorkersAIFallbackError, WorkersAIGatewayError } from \"./errors\";\nimport type { Transport } from \"./gateway-delegate\";\n\n/** One model in a client-side fallback chain. */\nexport interface FallbackLeg {\n\t/** The model slug this leg dispatches. */\n\tslug: string;\n\t/** The built AI SDK model. */\n\tmodel: LanguageModelV3;\n\t/** Transport the leg uses. */\n\ttransport: Transport;\n}\n\n/**\n * Wrap a chain of models so a failed *pre-stream* dispatch falls through to the\n * next model, preserving resume on each leg's own transport. If every leg fails,\n * throws a {@link WorkersAIFallbackError} carrying the full attempt tree.\n *\n * Fallback triggers on `doGenerate`/`doStream` rejection (the dispatch never\n * produced a stream). Errors that surface *mid-stream* — after content has\n * already been emitted — are not recoverable here and propagate as-is.\n */\nexport function createClientFallbackModel(legs: FallbackLeg[]): LanguageModelV3 {\n\tif (legs.length === 0) {\n\t\tthrow new Error(\"createClientFallbackModel requires at least one model leg.\");\n\t}\n\tconst primary = legs[0].model;\n\n\tasync function attempt<T>(run: (model: LanguageModelV3) => PromiseLike<T>): Promise<T> {\n\t\tconst attempts: FallbackAttempt[] = [];\n\t\tfor (const leg of legs) {\n\t\t\ttry {\n\t\t\t\tconst result = await run(leg.model);\n\t\t\t\tattempts.push({ model: leg.slug, transport: leg.transport, ok: true });\n\t\t\t\treturn result;\n\t\t\t} catch (e) {\n\t\t\t\tconst err = WorkersAIGatewayError.fromUnknown(e);\n\t\t\t\tattempts.push({\n\t\t\t\t\tmodel: leg.slug,\n\t\t\t\t\ttransport: leg.transport,\n\t\t\t\t\tok: false,\n\t\t\t\t\tstatus: err.status,\n\t\t\t\t\terror: err,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthrow new WorkersAIFallbackError(attempts);\n\t}\n\n\treturn {\n\t\tspecificationVersion: \"v3\",\n\t\tprovider: primary.provider,\n\t\tmodelId: primary.modelId,\n\t\tsupportedUrls: primary.supportedUrls,\n\t\tdoGenerate(\n\t\t\toptions: LanguageModelV3CallOptions,\n\t\t): PromiseLike<LanguageModelV3GenerateResult> {\n\t\t\treturn attempt((m) => m.doGenerate(options));\n\t\t},\n\t\tdoStream(options: LanguageModelV3CallOptions): PromiseLike<LanguageModelV3StreamResult> {\n\t\t\treturn attempt((m) => m.doStream(options));\n\t\t},\n\t};\n}\n","import { GatewayDelegateError } from \"./gateway-delegate\";\n\n/**\n * Resumable run-path stream (RFC §7.1).\n *\n * Wraps the byte stream from a run-path response (`env.AI.run(..., {\n * returnRawResponse })`) so a transient mid-stream drop is recovered\n * transparently: the wrapper reconnects to the gateway resume endpoint and keeps\n * feeding bytes to the same consumer, so the downstream `@ai-sdk/*` parser never\n * sees the break.\n *\n * Byte alignment is the one correctness subtlety. The gateway `resume?from=N`\n * endpoint takes an SSE *event index* (count of `\\n\\n` terminators) and replays\n * whole events from that index. So the wrapper only ever emits *complete* events\n * downstream and buffers any trailing partial event. On a drop the buffered\n * partial is discarded and resume starts from the count of complete events\n * already emitted — landing exactly on the next event boundary, with no\n * duplicated or truncated bytes.\n *\n * Expiry: once the gateway buffer TTL (~5.5 min) elapses, resume returns 404\n * `{\"error\":\"Request not found\"}`. Behavior is governed by `onResumeExpired`:\n * `\"error\"` (default) surfaces a `GatewayDelegateError(\"resume-expired\")` into\n * the stream; `\"accept-partial\"` ends the stream cleanly with whatever was\n * already delivered (the caller's higher layer — e.g. Think — can then continue\n * or regenerate).\n */\n\ntype AiWithFetch = Ai & {\n\tfetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;\n};\n\nexport type ResumeExpiredPolicy = \"error\" | \"accept-partial\";\n\nexport interface ResumableStreamOptions {\n\t/** Cloudflare AI binding (e.g. `env.AI`) — used for the resume fetch. */\n\tbinding: Ai;\n\t/** Gateway id the run was issued under. */\n\tgateway: string;\n\t/** The `cf-aig-run-id` of the run to resume. */\n\trunId: string;\n\t/**\n\t * Initial run-path response body. Omit for **cross-invocation re-attach**: the\n\t * stream then starts by fetching `resume?from={fromEvent}` directly (e.g. a new\n\t * Durable Object invocation re-attaching to a run after eviction).\n\t */\n\tinitial?: ReadableStream<Uint8Array>;\n\t/**\n\t * SSE event index to (re-)attach from. Defaults to `0`. Used as the starting\n\t * `from` when `initial` is omitted, and as the base offset for the event\n\t * counter (so a later reconnect resumes from the correct absolute index).\n\t */\n\tfromEvent?: number;\n\t/** What to do when the resume buffer has expired (404). Defaults to `\"error\"`. */\n\tonResumeExpired?: ResumeExpiredPolicy;\n\t/** Max reconnect attempts before giving up. Defaults to 5. */\n\tmaxReconnects?: number;\n\t/** Fired before each reconnect with the resume `from` index and attempt number. */\n\tonReconnect?: (fromEvent: number, attempt: number) => void;\n\t/**\n\t * Fired with the cumulative SSE event offset whenever complete events are\n\t * emitted. Use it to persist `{ runId, eventOffset }` for cross-invocation\n\t * re-attach (throttle your own writes — this can fire per chunk).\n\t */\n\tonProgress?: (eventOffset: number) => void;\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array): Uint8Array<ArrayBuffer> {\n\tconst out = new Uint8Array(new ArrayBuffer(a.length + b.length));\n\tout.set(a, 0);\n\tout.set(b, a.length);\n\treturn out;\n}\n\n/** Index just past the last `\\n\\n` in `buf`, or -1 if there is no complete event. */\nfunction lastEventBoundary(buf: Uint8Array): number {\n\tfor (let i = buf.length - 2; i >= 0; i--) {\n\t\tif (buf[i] === 0x0a && buf[i + 1] === 0x0a) return i + 2;\n\t}\n\treturn -1;\n}\n\n/** Count of `\\n\\n` terminators (= complete SSE events) in `buf`. */\nfunction countEvents(buf: Uint8Array): number {\n\tlet n = 0;\n\tfor (let i = 0; i + 1 < buf.length; i++) {\n\t\tif (buf[i] === 0x0a && buf[i + 1] === 0x0a) {\n\t\t\tn++;\n\t\t\ti++; // don't double-count \"\\n\\n\\n\"\n\t\t}\n\t}\n\treturn n;\n}\n\nfunction resumeUrl(gateway: string, runId: string, from: number): string {\n\treturn `https://workers-binding.ai/ai-gateway/gateways/${gateway}/run/${runId}/resume?from=${from}`;\n}\n\nexport function createResumableStream(options: ResumableStreamOptions): ReadableStream<Uint8Array> {\n\tconst { binding, gateway, runId } = options;\n\tconst maxReconnects = options.maxReconnects ?? 5;\n\tconst onExpired = options.onResumeExpired ?? \"error\";\n\n\tlet emittedEvents = options.fromEvent ?? 0; // absolute SSE event index reached\n\tlet pending: Uint8Array<ArrayBuffer> = new Uint8Array(new ArrayBuffer(0));\n\tlet reconnects = 0;\n\n\t// Fetch `resume?from={emittedEvents}`; on a terminal outcome (expiry / error /\n\t// network throw) it settles the controller and returns null.\n\tasync function fetchResume(\n\t\tcontroller: ReadableStreamDefaultController<Uint8Array>,\n\t): Promise<ReadableStream<Uint8Array> | null> {\n\t\tlet res: Response;\n\t\ttry {\n\t\t\tres = await (binding as AiWithFetch).fetch(resumeUrl(gateway, runId, emittedEvents), {\n\t\t\t\tmethod: \"GET\",\n\t\t\t});\n\t\t} catch (fetchErr) {\n\t\t\tcontroller.error(\n\t\t\t\tnew GatewayDelegateError(\n\t\t\t\t\t\"dispatch\",\n\t\t\t\t\t`Resume request threw at event ${emittedEvents}.`,\n\t\t\t\t\tfetchErr,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\n\t\tif (res.status === 404) {\n\t\t\tif (onExpired === \"accept-partial\") {\n\t\t\t\tcontroller.close();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tcontroller.error(\n\t\t\t\tnew GatewayDelegateError(\n\t\t\t\t\t\"resume-expired\",\n\t\t\t\t\t`Resume buffer expired (404) at event ${emittedEvents}. The gateway buffer ` +\n\t\t\t\t\t\t\"TTL (~5.5 min) elapsed; fall back to continuation or regeneration.\",\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t\tif (!res.ok || !res.body) {\n\t\t\tcontroller.error(\n\t\t\t\tnew GatewayDelegateError(\n\t\t\t\t\t\"dispatch\",\n\t\t\t\t\t`Resume failed (${res.status}) at event ${emittedEvents}.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn null;\n\t\t}\n\t\treturn res.body;\n\t}\n\n\treturn new ReadableStream<Uint8Array>({\n\t\tasync start(controller) {\n\t\t\t// In-stream wrap starts from the live body; cross-invocation re-attach\n\t\t\t// (no `initial`) starts by resuming from `fromEvent`. An initial-attach\n\t\t\t// failure is terminal — it is not charged against the reconnect budget.\n\t\t\tlet current: ReadableStream<Uint8Array>;\n\t\t\tif (options.initial) {\n\t\t\t\tcurrent = options.initial;\n\t\t\t} else {\n\t\t\t\tconst body = await fetchResume(controller);\n\t\t\t\tif (!body) return;\n\t\t\t\tcurrent = body;\n\t\t\t}\n\n\t\t\tfor (;;) {\n\t\t\t\tconst reader = current.getReader();\n\t\t\t\ttry {\n\t\t\t\t\tfor (;;) {\n\t\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\t\tif (done) {\n\t\t\t\t\t\t\tif (pending.length > 0) {\n\t\t\t\t\t\t\t\tcontroller.enqueue(pending);\n\t\t\t\t\t\t\t\tpending = new Uint8Array(new ArrayBuffer(0));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!value || value.length === 0) continue;\n\n\t\t\t\t\t\tpending = concat(pending, value);\n\t\t\t\t\t\tconst boundary = lastEventBoundary(pending);\n\t\t\t\t\t\tif (boundary > 0) {\n\t\t\t\t\t\t\tconst complete = pending.slice(0, boundary);\n\t\t\t\t\t\t\tcontroller.enqueue(complete);\n\t\t\t\t\t\t\temittedEvents += countEvents(complete);\n\t\t\t\t\t\t\toptions.onProgress?.(emittedEvents);\n\t\t\t\t\t\t\tpending = pending.slice(boundary);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treader.releaseLock();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// reader may already be released\n\t\t\t\t\t}\n\n\t\t\t\t\tif (reconnects >= maxReconnects) {\n\t\t\t\t\t\tcontroller.error(\n\t\t\t\t\t\t\tnew GatewayDelegateError(\n\t\t\t\t\t\t\t\t\"resume-expired\",\n\t\t\t\t\t\t\t\t`Exceeded ${maxReconnects} reconnect attempts at event ${emittedEvents}.`,\n\t\t\t\t\t\t\t\terr,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard the unfinished partial — resume realigns on the boundary.\n\t\t\t\t\tpending = new Uint8Array(new ArrayBuffer(0));\n\t\t\t\t\treconnects++;\n\t\t\t\t\toptions.onReconnect?.(emittedEvents, reconnects);\n\n\t\t\t\t\tconst body = await fetchResume(controller);\n\t\t\t\t\tif (!body) return;\n\t\t\t\t\tcurrent = body;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t});\n}\n","import type { LanguageModelV3 } from \"@ai-sdk/provider\";\nimport { createClientFallbackModel } from \"./client-fallback\";\nimport { findProviderBySlug, type GatewayProviderInfo, type WireFormat } from \"./gateway-providers\";\nimport { createResumableStream, type ResumeExpiredPolicy } from \"./resumable-stream\";\n\nexport {\n\tcreateResumableStream,\n\ttype ResumableStreamOptions,\n\ttype ResumeExpiredPolicy,\n} from \"./resumable-stream\";\nexport {\n\ttype FallbackAttempt,\n\ttype GatewayErrorCode,\n\ttype GatewayErrorContext,\n\tWorkersAIFallbackError,\n\tWorkersAIGatewayError,\n} from \"./errors\";\nexport { type FallbackLeg, createClientFallbackModel } from \"./client-fallback\";\nexport {\n\ttype Billing,\n\tGATEWAY_PROVIDERS,\n\ttype GatewayProviderInfo,\n\ttype WireFormat,\n\tdetectProviderByUrl,\n\tfindProviderBySlug,\n\twireableProviders,\n} from \"./gateway-providers\";\n\n/**\n * Gateway delegate — route AI SDK catalog models through Cloudflare AI Gateway,\n * with capability-driven transport selection.\n *\n * Two transports back the same model, chosen from the requested options:\n *\n * - **Run path** `env.AI.run(slug, body, { returnRawResponse })` — resumable\n * streaming (`cf-aig-run-id`). The default.\n * - **Gateway path** `env.AI.gateway(id).run([entry, …fallback])` — server-side\n * fallback and caching. Does not surface `cf-aig-run-id`, so resume is off.\n *\n * The SAME `@ai-sdk/*` provider parses the response on either path, so there is no\n * per-provider or per-path response parsing here. Provider plugins (which import\n * `@ai-sdk/openai`, `@ai-sdk/anthropic`, …) are injected from sub-path modules\n * (`workers-ai-provider/openai`, …) so those AI SDK packages stay OPTIONAL peer\n * dependencies — you only install the ones you use.\n *\n * @example\n * ```ts\n * import { createGatewayDelegate } from \"workers-ai-provider/gateway-delegate\";\n * import { openai } from \"workers-ai-provider/openai\";\n * import { streamText } from \"ai\";\n *\n * const wai = createGatewayDelegate({\n * binding: env.AI,\n * gateway: \"my-gateway\",\n * providers: [openai],\n * });\n *\n * const result = streamText({ model: wai(\"openai/gpt-5\"), prompt: \"Hello\" });\n * // result.response.headers[\"cf-aig-run-id\"] is set — resume from there.\n * ```\n */\n\n// ---------------------------------------------------------------------------\n// Slug parsing\n// ---------------------------------------------------------------------------\n\nexport interface ParsedSlug {\n\t/** First path segment — the registry resolver key (selects provider + wire format). */\n\tresolverKey: string;\n\t/** Remaining segments — the provider-native model id. */\n\tmodelId: string;\n}\n\n/**\n * Parse a `vendor/model` slug. The first segment is the resolver key (which\n * registry entry handles it); the rest is the provider-native model id. Routing\n * providers keep multi-segment model ids, e.g. `openrouter/anthropic/claude`.\n */\nexport function parseSlug(slug: string): ParsedSlug {\n\tconst slash = slug.indexOf(\"/\");\n\tif (slash === -1) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t`Model slug \"${slug}\" has no resolver key. Use \"<provider>/<model>\" (e.g. \"openai/gpt-5\").`,\n\t\t);\n\t}\n\tconst resolverKey = slug.slice(0, slash);\n\tconst modelId = slug.slice(slash + 1);\n\tif (!resolverKey || !modelId) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t`Model slug \"${slug}\" is malformed. Use \"<provider>/<model>\" (e.g. \"openai/gpt-5\").`,\n\t\t);\n\t}\n\treturn { resolverKey, modelId };\n}\n\n/**\n * Resolve a slug to its registry entry, raising a helpful error for unknown or\n * bring-your-own-provider-only providers.\n */\nexport function resolveProvider(slug: string, parsed: ParsedSlug): GatewayProviderInfo {\n\tconst info = findProviderBySlug(parsed.resolverKey);\n\tif (!info) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t`Unknown gateway provider \"${parsed.resolverKey}\" (from slug \"${slug}\"). ` +\n\t\t\t\t\"See the AI Gateway provider directory for valid slugs, or use \" +\n\t\t\t\t\"createGatewayProvider to bring your own @ai-sdk provider.\",\n\t\t);\n\t}\n\tif (!info.wireFormat) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t`Provider \"${parsed.resolverKey}\" is not chat/completions-shaped and has no built-in ` +\n\t\t\t\t\"parser. Reach it with createGatewayProvider (bring your own @ai-sdk provider).\",\n\t\t);\n\t}\n\treturn info;\n}\n\n// ---------------------------------------------------------------------------\n// Provider plugins (injected from sub-path modules)\n// ---------------------------------------------------------------------------\n\n/**\n * Adapts a `@ai-sdk/*` provider to the delegate, keyed by the response wire\n * format it parses. Imported from a sub-path module (e.g.\n * `workers-ai-provider/openai`) so the AI SDK package stays an optional peer\n * dependency. One plugin serves every registry provider of that wire format —\n * the `openai` plugin covers the whole OpenAI-compatible long tail (deepseek,\n * grok, groq, mistral, perplexity, openrouter, …).\n */\nexport interface ProviderPlugin {\n\t/** The response wire format this builder parses. */\n\treadonly wireFormat: WireFormat;\n\t/**\n\t * Build the AI SDK model, wiring the gateway-dispatching `fetch`. `baseURL`\n\t * (when provided by the registry) targets the provider's host so the request\n\t * URL host-strips to its gateway-native endpoint — pass it to the underlying\n\t * `@ai-sdk` provider.\n\t */\n\tcreate(args: {\n\t\tmodelId: string;\n\t\tfetch: typeof globalThis.fetch;\n\t\tbaseURL?: string;\n\t}): LanguageModelV3;\n}\n\n// ---------------------------------------------------------------------------\n// Options + transport selection\n// ---------------------------------------------------------------------------\n\nexport type Transport = \"run\" | \"gateway\";\n\nexport interface FallbackOptions {\n\t/** `\"client\"` keeps resume (sequential run-path attempts); `\"server\"` uses the gateway path. */\n\tmode: \"client\" | \"server\";\n\t/** Ordered model slugs to try after the primary. */\n\tmodels: string[];\n}\n\nexport interface DispatchInfo {\n\ttransport: Transport;\n\tresumeEnabled: boolean;\n\twarnings: string[];\n\trunId: string | null;\n\tstatus: number | null;\n\tcfStep: string | null;\n\tcacheStatus: string | null;\n\tlogId: string | null;\n}\n\nexport interface DelegateCallOptions {\n\t/** Resumable streaming (run path). Defaults to the delegate's `resume` (true). */\n\tresume?: boolean;\n\t/** Cross-model fallback. `\"server\"` mode uses the gateway path (disables resume). */\n\tfallback?: FallbackOptions;\n\t/** Gateway-path response caching (seconds). Forces the gateway path. */\n\tcacheTtl?: number;\n\t/** Bypass gateway cache. Forces the gateway path. */\n\tskipCache?: boolean;\n\t/** Escape hatch: force a transport. */\n\ttransport?: Transport;\n\t/**\n\t * Run path only: behavior when the resume buffer has expired (404) after a\n\t * mid-stream drop. `\"error\"` (default) surfaces a `GatewayDelegateError`;\n\t * `\"accept-partial\"` ends the stream cleanly with whatever was delivered.\n\t */\n\tonResumeExpired?: ResumeExpiredPolicy;\n\t/** Extra request headers (run path: `extraHeaders`; gateway path: entry headers). */\n\textraHeaders?: Record<string, string>;\n\t/**\n\t * Gateway path only: forward the upstream provider key instead of stripping it.\n\t * Required for BYOK providers (not on unified billing). Supply the key via\n\t * `extraHeaders` (e.g. `{ authorization: \"Bearer …\" }`); without `byok` the\n\t * delegate strips provider auth headers so unified billing applies.\n\t */\n\tbyok?: boolean;\n\t/** Override the delegate's gateway for this model. */\n\tgateway?: GatewayOptions | string;\n\t/**\n\t * Custom metadata attached to the gateway log for this request (spend\n\t * attribution, tenant ids, etc.). Merges over any `metadata` already set via\n\t * `gateway: { metadata }`. Applied on both transports (run path: gateway\n\t * options; gateway path: `cf-aig-metadata` header). `bigint` values are\n\t * coerced to strings for the header form.\n\t */\n\tmetadata?: Record<string, number | string | boolean | null | bigint>;\n\t/** Force gateway log collection on/off for this request (both transports). */\n\tcollectLog?: boolean;\n\t/** Called once per dispatch with the resolved transport + gateway headers. */\n\tonDispatch?: (info: DispatchInfo) => void;\n\t/**\n\t * Run path only: fired with the cumulative SSE event offset as the resumable\n\t * stream advances. Pair with `onDispatch` (for `runId`) to persist\n\t * `{ runId, eventOffset }` for cross-invocation re-attach after eviction.\n\t * Throttle your own writes — this can fire per chunk.\n\t */\n\tonProgress?: (eventOffset: number) => void;\n}\n\ninterface Selection {\n\ttransport: Transport;\n\tresumeEnabled: boolean;\n\twarnings: string[];\n}\n\n/**\n * Resolve the transport from the requested options. Gateway-only features (server\n * fallback, caching) force the gateway path and disable resume — with a loud\n * warning if resume was merely defaulted, or a thrown error if it was explicitly\n * requested.\n */\nexport function selectTransport(\n\topts: DelegateCallOptions,\n\tresumeExplicitlyTrue: boolean,\n\trunCatalog = true,\n\tgatewayAvailable = true,\n): Selection {\n\tconst warnings: string[] = [];\n\tconst wantsServerFallback = opts.fallback?.mode === \"server\";\n\tconst wantsCaching = opts.cacheTtl !== undefined || opts.skipCache === true;\n\tconst gatewayOnly = wantsServerFallback || wantsCaching;\n\tconst feature = wantsServerFallback ? 'fallback.mode:\"server\"' : \"caching (cacheTtl/skipCache)\";\n\n\t// Run-path-only providers (on the run catalog, but not native gateway\n\t// providers) have no gateway path at all — reject anything that would need it\n\t// here, with a clear message, rather than letting it fail upstream.\n\tif (runCatalog && !gatewayAvailable && (opts.transport === \"gateway\" || gatewayOnly)) {\n\t\tconst what = opts.transport === \"gateway\" ? 'transport:\"gateway\"' : feature;\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t`${what} is unavailable: this provider is on the unified run catalog but is not a ` +\n\t\t\t\t\"native gateway provider, so it has no gateway path (no caching, server-side \" +\n\t\t\t\t'fallback, or transport:\"gateway\"). Use the default run path, or fallback.mode:\"client\".',\n\t\t);\n\t}\n\n\t// BYOK providers are not on the resumable run catalog — they can only be\n\t// reached through the gateway path.\n\tif (!runCatalog) {\n\t\tif (opts.transport === \"run\") {\n\t\t\tthrow new GatewayDelegateError(\n\t\t\t\t\"config\",\n\t\t\t\t'transport:\"run\" is unavailable: this provider is not on the unified-billing run ' +\n\t\t\t\t\t\"catalog, so it can only be reached through the gateway path (BYOK).\",\n\t\t\t);\n\t\t}\n\t\tif (resumeExplicitlyTrue) {\n\t\t\tthrow new GatewayDelegateError(\n\t\t\t\t\"config\",\n\t\t\t\t\"resume:true is unavailable: this provider is not on the resumable run catalog \" +\n\t\t\t\t\t\"(cf-aig-run-id requires the unified-billing run path).\",\n\t\t\t);\n\t\t}\n\t\treturn { transport: \"gateway\", resumeEnabled: false, warnings };\n\t}\n\n\tif (opts.transport === \"run\" && gatewayOnly) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t`transport:\"run\" cannot satisfy ${feature}: those features are only available on the ` +\n\t\t\t\t'gateway path. Use the gateway transport, or fallback.mode:\"client\".',\n\t\t);\n\t}\n\tif (opts.transport === \"gateway\" && resumeExplicitlyTrue) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t'transport:\"gateway\" cannot provide resume — cf-aig-run-id is only on the run path.',\n\t\t);\n\t}\n\n\tif (gatewayOnly) {\n\t\tif (resumeExplicitlyTrue) {\n\t\t\tthrow new GatewayDelegateError(\n\t\t\t\t\"config\",\n\t\t\t\t`resume:true conflicts with ${feature}: resume (cf-aig-run-id) is only on the run path, ` +\n\t\t\t\t\t`which does not support ${wantsServerFallback ? \"server-side fallback\" : \"caching\"}. ` +\n\t\t\t\t\t'Use fallback.mode:\"client\" to keep resume, or drop resume.',\n\t\t\t);\n\t\t}\n\t\twarnings.push(\n\t\t\t`[workers-ai-provider] resume disabled: ${feature} requires the gateway path, which does ` +\n\t\t\t\t'not surface cf-aig-run-id. Use fallback.mode:\"client\" to keep resumable streaming.',\n\t\t);\n\t\treturn { transport: \"gateway\", resumeEnabled: false, warnings };\n\t}\n\n\tconst transport = opts.transport ?? \"run\";\n\treturn {\n\t\ttransport,\n\t\tresumeEnabled: transport === \"run\" && opts.resume !== false,\n\t\twarnings,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport type GatewayDelegateErrorKind = \"config\" | \"dispatch\" | \"provider\" | \"resume-expired\";\n\nexport class GatewayDelegateError extends Error {\n\treadonly kind: GatewayDelegateErrorKind;\n\toverride readonly cause?: unknown;\n\n\tconstructor(kind: GatewayDelegateErrorKind, message: string, cause?: unknown) {\n\t\tsuper(message);\n\t\tthis.name = \"GatewayDelegateError\";\n\t\tthis.kind = kind;\n\t\tthis.cause = cause;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Dispatch internals\n// ---------------------------------------------------------------------------\n\n// Always stripped on the gateway path (transport-level headers the binding sets).\nconst STRIP_HEADERS_BASE = new Set([\"content-length\", \"host\"]);\n\ninterface GatewayEntry {\n\tprovider: string;\n\tendpoint: string;\n\theaders: Record<string, string>;\n\tquery: Record<string, unknown>;\n}\n\ninterface AiGatewayRunner {\n\trun(body: unknown, options?: Record<string, unknown>): Promise<Response>;\n}\n\nfunction asText(body: BodyInit | null | undefined): string {\n\tif (typeof body === \"string\") return body;\n\tif (body instanceof Uint8Array) return new TextDecoder().decode(body);\n\tif (body instanceof ArrayBuffer) return new TextDecoder().decode(body);\n\treturn \"{}\";\n}\n\nfunction headersToObject(h: HeadersInit | undefined): Record<string, string> {\n\tconst out: Record<string, string> = {};\n\tif (!h) return out;\n\tif (h instanceof Headers) {\n\t\tfor (const [k, v] of h) out[k] = v;\n\t} else if (Array.isArray(h)) {\n\t\tfor (const [k, v] of h) out[k] = v;\n\t} else {\n\t\tObject.assign(out, h);\n\t}\n\treturn out;\n}\n\nfunction normalizeGateway(gateway: GatewayOptions | string | undefined): {\n\tid: string;\n\toptions: GatewayOptions;\n} {\n\tif (!gateway) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t\"A gateway is required for the delegate (resume needs a gateway). \" +\n\t\t\t\t'Pass `gateway: \"<gateway-id>\"` to createGatewayDelegate or per call.',\n\t\t);\n\t}\n\tif (typeof gateway === \"string\") return { id: gateway, options: { id: gateway } };\n\treturn { id: gateway.id, options: gateway };\n}\n\nexport interface GatewayDelegateConfig {\n\t/** A Cloudflare AI binding (e.g. `env.AI`). Required — the gateway path needs `binding.gateway()`. */\n\tbinding: Ai;\n\t/** Default gateway id (or options) for all models. Overridable per call. */\n\tgateway?: GatewayOptions | string;\n\t/** Provider plugins from sub-path modules (e.g. `[openai, anthropic]`). */\n\tproviders: ProviderPlugin[];\n\t/** Default resume behavior when a call does not specify one. Defaults to `true`. */\n\tresume?: boolean;\n\t/** Default resume-expiry policy (run path). Defaults to `\"error\"`. */\n\tonResumeExpired?: ResumeExpiredPolicy;\n}\n\nexport interface GatewayDelegate {\n\t(slug: string, options?: DelegateCallOptions): LanguageModelV3;\n}\n\n/**\n * Create a gateway delegate. Returns a function that builds an AI SDK model for a\n * `\"<provider>/<model>\"` slug, dispatched through AI Gateway on the transport the\n * requested options imply.\n */\nexport function createGatewayDelegate(config: GatewayDelegateConfig): GatewayDelegate {\n\tif (!config?.binding) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t\"createGatewayDelegate requires a `binding` (e.g. { binding: env.AI }).\",\n\t\t);\n\t}\n\tif (!config.providers?.length) {\n\t\tthrow new GatewayDelegateError(\n\t\t\t\"config\",\n\t\t\t\"createGatewayDelegate requires at least one provider plugin, e.g. \" +\n\t\t\t\t'`providers: [openai]` from \"workers-ai-provider/openai\".',\n\t\t);\n\t}\n\n\tconst plugins = new Map<WireFormat, ProviderPlugin>();\n\tfor (const p of config.providers) plugins.set(p.wireFormat, p);\n\tconst defaultResume = config.resume ?? true;\n\n\tconst buildOne = (\n\t\tslug: string,\n\t\toptions: DelegateCallOptions,\n\t): { model: LanguageModelV3; transport: Transport } => {\n\t\tconst parsed = parseSlug(slug);\n\t\tconst info = resolveProvider(slug, parsed);\n\n\t\tconst resumeExplicitlyTrue = options.resume === true;\n\t\tconst effectiveOptions: DelegateCallOptions = {\n\t\t\t...options,\n\t\t\tresume: options.resume ?? defaultResume,\n\t\t\tonResumeExpired: options.onResumeExpired ?? config.onResumeExpired,\n\t\t};\n\t\tconst selection = selectTransport(\n\t\t\teffectiveOptions,\n\t\t\tresumeExplicitlyTrue,\n\t\t\tinfo.runCatalog,\n\t\t\tinfo.gatewayPath !== false,\n\t\t);\n\t\tfor (const w of selection.warnings) console.warn(w);\n\n\t\t// Pick the parser by transport. The unified-billing run path (`env.AI.run`)\n\t\t// does NOT speak a uniform wire format: Cloudflare normalizes most providers\n\t\t// to OpenAI chat-completions (so `google` is parsed with the `openai` plugin\n\t\t// on the run path), but passes Anthropic through natively. So the run path\n\t\t// uses the registry's `runWireFormat` (default \"openai\"), while the gateway\n\t\t// path — which hits provider-native endpoints — uses the native `wireFormat`.\n\t\tconst wire: WireFormat =\n\t\t\tselection.transport === \"run\"\n\t\t\t\t? (info.runWireFormat ?? \"openai\")\n\t\t\t\t: (info.wireFormat as WireFormat);\n\t\tconst plugin = plugins.get(wire);\n\t\tif (!plugin) {\n\t\t\tthrow new GatewayDelegateError(\n\t\t\t\t\"config\",\n\t\t\t\tselection.transport === \"run\"\n\t\t\t\t\t? `The run path for \"${parsed.resolverKey}\" (from slug \"${slug}\") returns ` +\n\t\t\t\t\t\t\t`\"${wire}\"-wire responses, so it needs the \"${wire}\" plugin. ` +\n\t\t\t\t\t\t\t`Install + pass it from \"workers-ai-provider/${wire}\". ` +\n\t\t\t\t\t\t\t`Registered: ${[...plugins.keys()].join(\", \") || \"<none>\"}.`\n\t\t\t\t\t: `No provider plugin for wire format \"${wire}\" (needed by \"${parsed.resolverKey}\" ` +\n\t\t\t\t\t\t\t`on the gateway path from slug \"${slug}\"). ` +\n\t\t\t\t\t\t\t`Registered: ${[...plugins.keys()].join(\", \") || \"<none>\"}. ` +\n\t\t\t\t\t\t\t`Install + pass the matching plugin from \"workers-ai-provider/${wire}\".`,\n\t\t\t);\n\t\t}\n\n\t\tconst { id: gatewayId, options: gatewayOptions } = normalizeGateway(\n\t\t\toptions.gateway ?? config.gateway,\n\t\t);\n\n\t\tconst fetchImpl =\n\t\t\tselection.transport === \"run\"\n\t\t\t\t? makeRunFetch(\n\t\t\t\t\t\tconfig.binding,\n\t\t\t\t\t\t// Use the canonical run-catalog author (e.g. \"grok\" → \"xai\"), not the\n\t\t\t\t\t\t// raw alias the caller typed, so `env.AI.run` resolves the model.\n\t\t\t\t\t\t`${info.resolverKey}/${parsed.modelId}`,\n\t\t\t\t\t\tgatewayOptions,\n\t\t\t\t\t\teffectiveOptions,\n\t\t\t\t\t\tselection,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t)\n\t\t\t\t: makeGatewayFetch(\n\t\t\t\t\t\tconfig.binding,\n\t\t\t\t\t\tinfo,\n\t\t\t\t\t\tgatewayId,\n\t\t\t\t\t\tgatewayOptions,\n\t\t\t\t\t\teffectiveOptions,\n\t\t\t\t\t\tselection,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t);\n\n\t\treturn {\n\t\t\tmodel: plugin.create({\n\t\t\t\tmodelId: parsed.modelId,\n\t\t\t\tfetch: fetchImpl,\n\t\t\t\t// baseURL only matters on the gateway path (host-strip to the native\n\t\t\t\t// endpoint); the run path ignores the request URL entirely.\n\t\t\t\t...(selection.transport === \"gateway\" && info.baseURL\n\t\t\t\t\t? { baseURL: info.baseURL }\n\t\t\t\t\t: {}),\n\t\t\t}),\n\t\t\ttransport: selection.transport,\n\t\t};\n\t};\n\n\treturn (slug, options = {}) => {\n\t\t// Client-side fallback: build a model per slug and wrap them so a failed\n\t\t// pre-stream dispatch falls through to the next, each on its own transport\n\t\t// (so resume is preserved per leg). Server-side fallback stays on the\n\t\t// gateway path inside makeGatewayFetch.\n\t\tif (options.fallback?.mode === \"client\") {\n\t\t\tconst { fallback, ...rest } = options;\n\t\t\tconst slugs = [slug, ...fallback.models];\n\t\t\tconst legs = slugs.map((s) => {\n\t\t\t\tconst { model, transport } = buildOne(s, rest);\n\t\t\t\treturn { slug: s, model, transport };\n\t\t\t});\n\t\t\treturn createClientFallbackModel(legs);\n\t\t}\n\t\treturn buildOne(slug, options).model;\n\t};\n}\n\nfunction fireDispatch(resp: Response, selection: Selection, options: DelegateCallOptions): void {\n\tif (!options.onDispatch) return;\n\toptions.onDispatch({\n\t\ttransport: selection.transport,\n\t\tresumeEnabled: selection.resumeEnabled,\n\t\twarnings: selection.warnings,\n\t\tstatus: resp.status,\n\t\trunId: resp.headers.get(\"cf-aig-run-id\"),\n\t\tcfStep: resp.headers.get(\"cf-aig-step\"),\n\t\tcacheStatus: resp.headers.get(\"cf-aig-cache-status\"),\n\t\tlogId: resp.headers.get(\"cf-aig-log-id\"),\n\t});\n}\n\ntype GatewayMetadata = Record<string, number | string | boolean | null | bigint>;\n\n/** Merge call-level metadata over gateway-option metadata (call wins). */\nfunction mergeMetadata(\n\tbase: GatewayMetadata | undefined,\n\toverride: GatewayMetadata | undefined,\n): GatewayMetadata | undefined {\n\tif (!base && !override) return undefined;\n\treturn { ...base, ...override };\n}\n\n/** JSON-encode metadata for the `cf-aig-metadata` header (bigint → string). */\nfunction serializeMetadata(metadata: GatewayMetadata): string {\n\treturn JSON.stringify(metadata, (_k, v) => (typeof v === \"bigint\" ? v.toString() : v));\n}\n\nfunction makeRunFetch(\n\tbinding: Ai,\n\tslug: string,\n\tgatewayOptions: GatewayOptions,\n\topts: DelegateCallOptions,\n\tselection: Selection,\n\tcallOptions: DelegateCallOptions,\n): typeof globalThis.fetch {\n\treturn (async (_input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n\t\tconst body = JSON.parse(asText(init?.body)) as Record<string, unknown>;\n\t\t// The slug carries the model; drop the redundant body field (both are tolerated).\n\t\tdelete body.model;\n\n\t\t// Fold first-class metadata/collectLog over anything supplied via\n\t\t// `gateway: { ... }`; explicit call options win.\n\t\tconst mergedGateway: GatewayOptions = { ...gatewayOptions };\n\t\tconst mergedMeta = mergeMetadata(gatewayOptions.metadata, opts.metadata);\n\t\tif (mergedMeta) mergedGateway.metadata = mergedMeta;\n\t\tif (opts.collectLog !== undefined) mergedGateway.collectLog = opts.collectLog;\n\n\t\tconst runOptions = {\n\t\t\tgateway: mergedGateway,\n\t\t\treturnRawResponse: true,\n\t\t\t...(opts.extraHeaders ? { extraHeaders: opts.extraHeaders } : {}),\n\t\t\t...(init?.signal ? { signal: init.signal } : {}),\n\t\t};\n\n\t\t// The binding's `run` is heavily overloaded; narrow to the raw-Response\n\t\t// streaming signature. Call as a METHOD on the binding — extracting it\n\t\t// into a bare variable detaches `this` and the binding throws on a private\n\t\t// field access (\"Cannot set properties of undefined (setting '#options')\").\n\t\tconst ai = binding as unknown as {\n\t\t\trun(\n\t\t\t\tmodel: string,\n\t\t\t\tinputs: Record<string, unknown>,\n\t\t\t\toptions: Record<string, unknown>,\n\t\t\t): Promise<Response>;\n\t\t};\n\t\tconst resp = await ai.run(slug, body, runOptions);\n\t\tfireDispatch(resp, selection, callOptions);\n\n\t\t// Wrap the stream so a transient mid-stream drop reconnects via the gateway\n\t\t// resume endpoint transparently — the @ai-sdk parser never sees the break.\n\t\tconst runId = resp.headers.get(\"cf-aig-run-id\");\n\t\tif (selection.resumeEnabled && runId && resp.body) {\n\t\t\tconst resumable = createResumableStream({\n\t\t\t\tbinding,\n\t\t\t\tgateway: gatewayOptions.id,\n\t\t\t\trunId,\n\t\t\t\tinitial: resp.body,\n\t\t\t\tonResumeExpired: opts.onResumeExpired,\n\t\t\t\t...(opts.onProgress ? { onProgress: opts.onProgress } : {}),\n\t\t\t});\n\t\t\treturn new Response(resumable, { status: resp.status, headers: resp.headers });\n\t\t}\n\t\treturn resp;\n\t}) as typeof globalThis.fetch;\n}\n\nfunction makeGatewayFetch(\n\tbinding: Ai,\n\tinfo: GatewayProviderInfo,\n\tgatewayId: string,\n\tgatewayOptions: GatewayOptions,\n\topts: DelegateCallOptions,\n\tselection: Selection,\n\tcallOptions: DelegateCallOptions,\n): typeof globalThis.fetch {\n\t// Strip the AI SDK's placeholder provider key unless BYOK forwards a real one;\n\t// unified billing / the gateway's stored key authenticates upstream otherwise.\n\tconst strip = new Set(STRIP_HEADERS_BASE);\n\tif (!opts.byok) for (const h of info.authHeaders) strip.add(h.toLowerCase());\n\n\treturn (async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n\t\tconst rawUrl = typeof input === \"string\" ? input : input.toString();\n\t\t// Host-strip to the provider's gateway-native endpoint. The registry\n\t\t// transform matches because the builder targeted the provider's baseURL;\n\t\t// fall back to a generic pathname strip if it somehow doesn't.\n\t\tconst endpoint = info.transformEndpoint\n\t\t\t? info.transformEndpoint(rawUrl)\n\t\t\t: new URL(rawUrl).pathname.replace(/^\\//, \"\") + (new URL(rawUrl).search || \"\");\n\t\tconst body = JSON.parse(asText(init?.body)) as Record<string, unknown>;\n\n\t\tconst headers: Record<string, string> = {};\n\t\tfor (const [k, v] of Object.entries(headersToObject(init?.headers))) {\n\t\t\tif (!strip.has(k.toLowerCase())) headers[k] = v;\n\t\t}\n\t\tif (opts.extraHeaders) Object.assign(headers, opts.extraHeaders);\n\t\t// Best-effort gateway cache control (gateway-side config may still override).\n\t\tif (opts.cacheTtl !== undefined) headers[\"cf-aig-cache-ttl\"] = String(opts.cacheTtl);\n\t\tif (opts.skipCache) headers[\"cf-aig-skip-cache\"] = \"true\";\n\t\t// Gateway log controls (mirror the run path's typed gateway options).\n\t\tconst metadata = mergeMetadata(gatewayOptions.metadata, opts.metadata);\n\t\tif (metadata) headers[\"cf-aig-metadata\"] = serializeMetadata(metadata);\n\t\tif (opts.collectLog !== undefined) {\n\t\t\theaders[\"cf-aig-collect-log\"] = String(opts.collectLog);\n\t\t}\n\n\t\tconst primary: GatewayEntry = {\n\t\t\tprovider: info.gatewayProviderId,\n\t\t\tendpoint,\n\t\t\theaders,\n\t\t\tquery: body,\n\t\t};\n\t\tconst entries: GatewayEntry[] = [primary];\n\n\t\tif (opts.fallback?.mode === \"server\") {\n\t\t\tfor (const fb of opts.fallback.models) {\n\t\t\t\tconst fbParsed = parseSlug(fb);\n\t\t\t\tconst fbInfo = resolveProvider(fb, fbParsed);\n\t\t\t\tif (fbInfo.gatewayProviderId !== info.gatewayProviderId) {\n\t\t\t\t\tthrow new GatewayDelegateError(\n\t\t\t\t\t\t\"config\",\n\t\t\t\t\t\t`Cross-vendor server-side fallback (${info.gatewayProviderId} → ` +\n\t\t\t\t\t\t\t`${fbInfo.gatewayProviderId}) is not supported yet. Use fallback.mode:\"client\", ` +\n\t\t\t\t\t\t\t\"or same-vendor fallback models.\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tentries.push({ ...primary, query: { ...body, model: fbParsed.modelId } });\n\t\t\t}\n\t\t}\n\n\t\tconst gw = (binding as unknown as { gateway(id: string): AiGatewayRunner }).gateway(\n\t\t\tgatewayId,\n\t\t);\n\t\tconst runOptions: Record<string, unknown> = {};\n\t\tif (init?.signal) runOptions.signal = init.signal;\n\t\tconst resp = await gw.run(entries, runOptions);\n\t\tfireDispatch(resp, selection, callOptions);\n\t\treturn resp;\n\t}) as typeof globalThis.fetch;\n}\n","import { AISearchChatLanguageModel } from \"./aisearch-chat-language-model\";\nimport type { AISearchChatSettings } from \"./aisearch-chat-settings\";\nimport { createRun } from \"./utils\";\nimport {\n\tWorkersAIEmbeddingModel,\n\ttype WorkersAIEmbeddingSettings,\n} from \"./workersai-embedding-model\";\nimport { WorkersAIChatLanguageModel } from \"./workersai-chat-language-model\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport { WorkersAIImageModel } from \"./workersai-image-model\";\nimport type { WorkersAIImageSettings } from \"./workersai-image-settings\";\nimport { WorkersAITranscriptionModel } from \"./workersai-transcription-model\";\nimport type { WorkersAITranscriptionSettings } from \"./workersai-transcription-settings\";\nimport { WorkersAISpeechModel } from \"./workersai-speech-model\";\nimport type { WorkersAISpeechSettings } from \"./workersai-speech-settings\";\nimport { WorkersAIRerankingModel } from \"./workersai-reranking-model\";\nimport type { WorkersAIRerankingSettings } from \"./workersai-reranking-settings\";\nimport type {\n\tEmbeddingModels,\n\tImageGenerationModels,\n\tKnownTextGenerationModels,\n\tTextGenerationModels,\n\tTranscriptionModels,\n\tSpeechModels,\n\tRerankingModels,\n} from \"./workersai-models\";\n\n// Re-export deprecated AutoRAG aliases\nexport { AutoRAGChatLanguageModel } from \"./autorag-chat-language-model\";\nexport type { AutoRAGChatSettings } from \"./autorag-chat-settings\";\n\n// Export new AI Search types\nexport { AISearchChatLanguageModel } from \"./aisearch-chat-language-model\";\nexport type { AISearchChatSettings } from \"./aisearch-chat-settings\";\n\n// Export transcription and speech types\nexport { WorkersAITranscriptionModel } from \"./workersai-transcription-model\";\nexport type { WorkersAITranscriptionSettings } from \"./workersai-transcription-settings\";\nexport { WorkersAISpeechModel } from \"./workersai-speech-model\";\nexport type { WorkersAISpeechSettings } from \"./workersai-speech-settings\";\nexport { WorkersAIRerankingModel } from \"./workersai-reranking-model\";\nexport type { WorkersAIRerankingSettings } from \"./workersai-reranking-settings\";\n\n// ---------------------------------------------------------------------------\n// AI Gateway delegate (route catalog models through AI Gateway)\n//\n// The delegate factory itself is internal — it's wired through\n// `createWorkersAI({ providers })` (see below), so `createWorkersAI` is the\n// single public entry point. The transport types, error classes, registry, and\n// resume helpers are safe to re-export here (no optional `@ai-sdk/*` peer\n// imports). The provider plugins (`openai`, `anthropic`, `google`) stay\n// sub-path-only so those packages remain optional.\n// ---------------------------------------------------------------------------\n\nexport {\n\ttype Billing,\n\tcreateClientFallbackModel,\n\ttype DelegateCallOptions,\n\ttype DispatchInfo,\n\ttype FallbackAttempt,\n\ttype FallbackLeg,\n\ttype FallbackOptions,\n\tGatewayDelegateError,\n\ttype GatewayErrorCode,\n\ttype GatewayErrorContext,\n\tGATEWAY_PROVIDERS,\n\ttype GatewayProviderInfo,\n\ttype ParsedSlug,\n\ttype ProviderPlugin,\n\ttype ResumableStreamOptions,\n\ttype ResumeExpiredPolicy,\n\ttype Transport,\n\ttype WireFormat,\n\tWorkersAIFallbackError,\n\tWorkersAIGatewayError,\n\tcreateResumableStream,\n\tdetectProviderByUrl,\n\tfindProviderBySlug,\n\tparseSlug,\n\tselectTransport,\n\twireableProviders,\n} from \"./gateway-delegate\";\nexport {\n\tcreateGatewayFetch,\n\tcreateGatewayProvider,\n\ttype GatewayFetchConfig,\n} from \"./gateway-provider\";\n\nimport {\n\tcreateGatewayDelegate,\n\ttype DelegateCallOptions,\n\ttype GatewayDelegate,\n\ttype ProviderPlugin,\n\ttype ResumeExpiredPolicy,\n} from \"./gateway-delegate\";\n\n// ---------------------------------------------------------------------------\n// Workers AI\n// ---------------------------------------------------------------------------\n\n/**\n * The account-wide AI Gateway used for catalog routing when no `gateway` is\n * configured. Every Cloudflare account has a `\"default\"` gateway.\n */\nconst DEFAULT_GATEWAY_ID = \"default\";\n\nexport type WorkersAISettings = (\n\t| {\n\t\t\t/**\n\t\t\t * Provide a Cloudflare AI binding.\n\t\t\t */\n\t\t\tbinding: Ai;\n\n\t\t\t/**\n\t\t\t * Credentials must be absent when a binding is given.\n\t\t\t */\n\t\t\taccountId?: never;\n\t\t\tapiKey?: never;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * Provide Cloudflare API credentials directly. Must be used if a binding is not specified.\n\t\t\t */\n\t\t\taccountId: string;\n\t\t\tapiKey: string;\n\t\t\t/**\n\t\t\t * Both binding must be absent if credentials are used directly.\n\t\t\t */\n\t\t\tbinding?: never;\n\n\t\t\t/**\n\t\t\t * Custom fetch implementation. You can use it as a middleware to\n\t\t\t * intercept requests, or to provide a custom fetch implementation\n\t\t\t * for e.g. testing. Only available in credentials mode.\n\t\t\t */\n\t\t\tfetch?: typeof globalThis.fetch;\n\t }\n) & {\n\t/**\n\t * Optionally specify a gateway. For third-party catalog routing (see\n\t * `providers`) this defaults to the account's `\"default\"` gateway when unset.\n\t */\n\tgateway?: GatewayOptions;\n\n\t/**\n\t * Provider plugins that enable routing third-party catalog models\n\t * (e.g. `\"openai/gpt-5-mini\"`) through AI Gateway. Supply them from the\n\t * sub-path modules, e.g. `import { openai } from \"workers-ai-provider/openai\"`.\n\t *\n\t * When set, calling the provider with a `\"<provider>/<model>\"` slug (anything\n\t * that is not a `@cf/...` Workers AI model id) is automatically dispatched\n\t * through the {@link createGatewayDelegate | gateway delegate}. Leaving this\n\t * unset preserves the exact prior behavior — only Workers AI models are built.\n\t *\n\t * @experimental The gateway delegate is an experimental surface.\n\t */\n\tproviders?: ProviderPlugin[];\n\n\t/**\n\t * Default resume behavior for gateway-routed catalog models. Defaults to\n\t * `true`. Overridable per call. Only relevant when `providers` is set.\n\t */\n\tresume?: boolean;\n\n\t/**\n\t * Default resume-expiry policy for gateway-routed catalog models (run path).\n\t * Defaults to `\"error\"`. Only relevant when `providers` is set.\n\t */\n\tonResumeExpired?: ResumeExpiredPolicy;\n};\n\n/**\n * True when a literal model id is a `\"<provider>/<model>\"` AI Gateway catalog\n * slug rather than a `@cf/...` Workers AI id. Bare `string` (a non-literal,\n * e.g. a variable) resolves to `false` so the common path keeps chat settings.\n */\ntype IsCatalogSlug<M extends string> = string extends M\n\t? false\n\t: M extends `@${string}`\n\t\t? false\n\t\t: M extends `${string}/${string}`\n\t\t\t? true\n\t\t\t: false;\n\n/**\n * Picks the per-model settings type from the (captured) literal model id:\n * `DelegateCallOptions` for catalog slugs, `WorkersAIChatSettings` otherwise.\n * This is what lets `workersai(\"openai/gpt-5\", { … })` autocomplete delegate\n * options while `workersai(\"@cf/…\", { … })` autocompletes chat settings.\n */\ntype ModelSettings<M extends string> =\n\tIsCatalogSlug<M> extends true ? DelegateCallOptions : WorkersAIChatSettings;\n\nexport interface WorkersAI {\n\t<M extends string>(\n\t\tmodelId: M | KnownTextGenerationModels,\n\t\tsettings?: ModelSettings<M>,\n\t): WorkersAIChatLanguageModel;\n\t/**\n\t * Creates a model for text generation. Accepts a `@cf/...` Workers AI id, or\n\t * a `\"<provider>/<model>\"` catalog slug when `providers` is configured.\n\t **/\n\tchat<M extends string>(\n\t\tmodelId: M | KnownTextGenerationModels,\n\t\tsettings?: ModelSettings<M>,\n\t): WorkersAIChatLanguageModel;\n\n\tembedding(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings?: WorkersAIEmbeddingSettings,\n\t): WorkersAIEmbeddingModel;\n\n\ttextEmbedding(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings?: WorkersAIEmbeddingSettings,\n\t): WorkersAIEmbeddingModel;\n\n\ttextEmbeddingModel(\n\t\tmodelId: EmbeddingModels,\n\t\tsettings?: WorkersAIEmbeddingSettings,\n\t): WorkersAIEmbeddingModel;\n\n\t/**\n\t * Creates a model for image generation.\n\t **/\n\timage(modelId: ImageGenerationModels, settings?: WorkersAIImageSettings): WorkersAIImageModel;\n\timageModel(\n\t\tmodelId: ImageGenerationModels,\n\t\tsettings?: WorkersAIImageSettings,\n\t): WorkersAIImageModel;\n\n\t/**\n\t * Creates a model for speech-to-text transcription.\n\t **/\n\ttranscription(\n\t\tmodelId: TranscriptionModels,\n\t\tsettings?: WorkersAITranscriptionSettings,\n\t): WorkersAITranscriptionModel;\n\ttranscriptionModel(\n\t\tmodelId: TranscriptionModels,\n\t\tsettings?: WorkersAITranscriptionSettings,\n\t): WorkersAITranscriptionModel;\n\n\t/**\n\t * Creates a model for text-to-speech synthesis.\n\t **/\n\tspeech(modelId: SpeechModels, settings?: WorkersAISpeechSettings): WorkersAISpeechModel;\n\tspeechModel(modelId: SpeechModels, settings?: WorkersAISpeechSettings): WorkersAISpeechModel;\n\n\t/**\n\t * Creates a model for document reranking.\n\t **/\n\treranking(\n\t\tmodelId: RerankingModels,\n\t\tsettings?: WorkersAIRerankingSettings,\n\t): WorkersAIRerankingModel;\n\trerankingModel(\n\t\tmodelId: RerankingModels,\n\t\tsettings?: WorkersAIRerankingSettings,\n\t): WorkersAIRerankingModel;\n}\n\n/**\n * Create a Workers AI provider instance.\n */\nexport function createWorkersAI(options: WorkersAISettings): WorkersAI {\n\tif (!options.binding && !(\"accountId\" in options && \"apiKey\" in options)) {\n\t\tthrow new Error(\n\t\t\t\"Invalid Workers AI configuration: you must provide either a binding (e.g. { binding: env.AI }) \" +\n\t\t\t\t\"or credentials ({ accountId, apiKey }).\",\n\t\t);\n\t}\n\n\tlet binding: Ai;\n\tconst isBinding = !!options.binding;\n\n\tif (options.binding) {\n\t\tbinding = options.binding;\n\t} else {\n\t\tconst { accountId, apiKey } = options;\n\t\tbinding = {\n\t\t\trun: createRun({ accountId, apiKey, fetch: options.fetch }),\n\t\t} as Ai;\n\t}\n\n\tconst createChatModel = (modelId: TextGenerationModels, settings: WorkersAIChatSettings = {}) =>\n\t\tnew WorkersAIChatLanguageModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.chat\",\n\t\t\tisBinding,\n\t\t});\n\n\t// Third-party catalog routing: when `providers` is configured, a non-`@cf/`\n\t// `\"<provider>/<model>\"` slug is dispatched through the gateway delegate\n\t// instead of being treated as a Workers AI model id. Built lazily so the\n\t// delegate (and its plugin requirements) only materializes on first use.\n\tlet delegate: GatewayDelegate | undefined;\n\tconst getDelegate = (slug: string): GatewayDelegate => {\n\t\tif (!options.providers?.length) {\n\t\t\tthrow new Error(\n\t\t\t\t`\"${slug}\" looks like a third-party AI Gateway catalog model, but this Workers AI ` +\n\t\t\t\t\t\"provider was not configured to route them. Pass provider plugins, e.g.:\\n\" +\n\t\t\t\t\t' import { openai } from \"workers-ai-provider/openai\";\\n' +\n\t\t\t\t\t\" createWorkersAI({ binding: env.AI, providers: [openai] });\\n\" +\n\t\t\t\t\t'A gateway defaults to \"default\" but can be set via `gateway`. ' +\n\t\t\t\t\t'Otherwise use a Workers AI model id (e.g. \"@cf/meta/llama-3.1-8b-instruct\").',\n\t\t\t);\n\t\t}\n\t\tdelegate ??= createGatewayDelegate({\n\t\t\tbinding,\n\t\t\t// Catalog routing needs a gateway (resume runs through it). When one\n\t\t\t// isn't configured, fall back to the account's `\"default\"` gateway so\n\t\t\t// `createWorkersAI({ providers })` works out of the box. An explicit\n\t\t\t// `gateway` (here or per call) always wins.\n\t\t\tgateway: options.gateway ?? { id: DEFAULT_GATEWAY_ID },\n\t\t\tproviders: options.providers,\n\t\t\tresume: options.resume,\n\t\t\tonResumeExpired: options.onResumeExpired,\n\t\t});\n\t\treturn delegate;\n\t};\n\n\t// Workers AI model ids are always `@cf/...`; gateway catalog slugs are\n\t// `\"<provider>/<model>\"`. Anything with a slash that is not `@`-prefixed is\n\t// treated as a catalog slug.\n\tconst isGatewaySlug = (id: unknown): id is string =>\n\t\ttypeof id === \"string\" && !id.startsWith(\"@\") && id.includes(\"/\");\n\n\t// Settings is the union of both shapes here; the public `WorkersAI` interface\n\t// narrows it per call via `ModelSettings<M>`. We branch at runtime and cast to\n\t// the concrete shape each path expects.\n\tconst buildChat = (\n\t\tmodelId: TextGenerationModels,\n\t\tsettings?: WorkersAIChatSettings | DelegateCallOptions,\n\t): WorkersAIChatLanguageModel => {\n\t\tif (isGatewaySlug(modelId)) {\n\t\t\t// The delegate returns a `LanguageModelV3` built by the configured plugin.\n\t\t\t// It's structurally compatible with the AI SDK consumers this provider is\n\t\t\t// used with; the cast keeps the public return type unchanged.\n\t\t\treturn getDelegate(modelId)(\n\t\t\t\tmodelId,\n\t\t\t\tsettings as DelegateCallOptions,\n\t\t\t) as unknown as WorkersAIChatLanguageModel;\n\t\t}\n\t\treturn createChatModel(modelId, settings as WorkersAIChatSettings | undefined);\n\t};\n\n\tconst createImageModel = (\n\t\tmodelId: ImageGenerationModels,\n\t\tsettings: WorkersAIImageSettings = {},\n\t) =>\n\t\tnew WorkersAIImageModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.image\",\n\t\t});\n\tconst createEmbeddingModel = (\n\t\tmodelId: EmbeddingModels,\n\t\tsettings: WorkersAIEmbeddingSettings = {},\n\t) =>\n\t\tnew WorkersAIEmbeddingModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.embedding\",\n\t\t});\n\n\tconst createTranscriptionModel = (\n\t\tmodelId: TranscriptionModels,\n\t\tsettings: WorkersAITranscriptionSettings = {},\n\t) =>\n\t\tnew WorkersAITranscriptionModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.transcription\",\n\t\t\tisBinding,\n\t\t\tcredentials:\n\t\t\t\t!isBinding && \"accountId\" in options\n\t\t\t\t\t? { accountId: options.accountId, apiKey: options.apiKey }\n\t\t\t\t\t: undefined,\n\t\t});\n\n\tconst createSpeechModel = (modelId: SpeechModels, settings: WorkersAISpeechSettings = {}) =>\n\t\tnew WorkersAISpeechModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.speech\",\n\t\t});\n\n\tconst createRerankingModel = (\n\t\tmodelId: RerankingModels,\n\t\tsettings: WorkersAIRerankingSettings = {},\n\t) =>\n\t\tnew WorkersAIRerankingModel(modelId, settings, {\n\t\t\tbinding,\n\t\t\tgateway: options.gateway,\n\t\t\tprovider: \"workersai.reranking\",\n\t\t});\n\n\tconst provider = (\n\t\tmodelId: TextGenerationModels,\n\t\tsettings?: WorkersAIChatSettings | DelegateCallOptions,\n\t) => {\n\t\tif (new.target) {\n\t\t\tthrow new Error(\"The WorkersAI model function cannot be called with the new keyword.\");\n\t\t}\n\t\treturn buildChat(modelId, settings);\n\t};\n\n\tprovider.chat = buildChat;\n\tprovider.embedding = createEmbeddingModel;\n\tprovider.textEmbedding = createEmbeddingModel;\n\tprovider.textEmbeddingModel = createEmbeddingModel;\n\tprovider.image = createImageModel;\n\tprovider.imageModel = createImageModel;\n\tprovider.transcription = createTranscriptionModel;\n\tprovider.transcriptionModel = createTranscriptionModel;\n\tprovider.speech = createSpeechModel;\n\tprovider.speechModel = createSpeechModel;\n\tprovider.reranking = createRerankingModel;\n\tprovider.rerankingModel = createRerankingModel;\n\n\treturn provider;\n}\n\n// ---------------------------------------------------------------------------\n// AI Search (formerly AutoRAG)\n// ---------------------------------------------------------------------------\n\nexport type AISearchSettings = {\n\tbinding: AutoRAG;\n};\n\nexport interface AISearchProvider {\n\t(settings?: AISearchChatSettings): AISearchChatLanguageModel;\n\t/**\n\t * Creates a model for text generation.\n\t **/\n\tchat(settings?: AISearchChatSettings): AISearchChatLanguageModel;\n}\n\n/**\n * Create an AI Search provider instance.\n *\n * AI Search (formerly AutoRAG) is Cloudflare's managed search service.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport function createAISearch(\n\toptions: AISearchSettings,\n\t/** @internal */\n\tproviderName = \"aisearch.chat\",\n): AISearchProvider {\n\tconst binding = options.binding;\n\n\tconst createChatModel = (settings: AISearchChatSettings = {}) =>\n\t\tnew AISearchChatLanguageModel(\"@cf/meta/llama-3.3-70b-instruct-fp8-fast\", settings, {\n\t\t\tbinding,\n\t\t\tprovider: providerName,\n\t\t});\n\n\tconst provider = (settings?: AISearchChatSettings) => {\n\t\tif (new.target) {\n\t\t\tthrow new Error(\"The AISearch model function cannot be called with the new keyword.\");\n\t\t}\n\t\treturn createChatModel(settings);\n\t};\n\n\tprovider.chat = createChatModel;\n\n\treturn provider;\n}\n\n// ---------------------------------------------------------------------------\n// Deprecated AutoRAG aliases\n// ---------------------------------------------------------------------------\n\n/**\n * @deprecated Use `AISearchSettings` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport type AutoRAGSettings = AISearchSettings;\n\n/**\n * @deprecated Use `AISearchProvider` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport type AutoRAGProvider = AISearchProvider;\n\nlet autoRAGWarned = false;\n\n/**\n * @deprecated Use `createAISearch` instead. AutoRAG has been renamed to AI Search.\n * @see https://developers.cloudflare.com/ai-search/\n */\nexport function createAutoRAG(options: AISearchSettings): AISearchProvider {\n\tif (!autoRAGWarned) {\n\t\tautoRAGWarned = true;\n\t\tconsole.warn(\n\t\t\t\"[workers-ai-provider] createAutoRAG is deprecated. Use createAISearch instead. \" +\n\t\t\t\t\"AutoRAG has been renamed to AI Search. \" +\n\t\t\t\t\"See https://developers.cloudflare.com/ai-search/\",\n\t\t);\n\t}\n\treturn createAISearch(options, \"autorag.chat\");\n}\n"],"mappings":";;;;;;;;;;AAcA,SAAgB,4BAA4B,UAAoD;CAC/F,OAAO,SAAS,KAAK,QAAQ;EAC5B,MAAM,aAAa,EAAE,GAAG,IAAI;EAG5B,IAAI,WAAW,YAAY,QAAQ,WAAW,YAAY,KAAA,GACzD,WAAoC,UAAU;EAG/C,OAAO;CACR,CAAC;AACF;;;;;AA6CA,SAAgB,UAAU,QAAgC;CACzD,MAAM,EAAE,WAAW,WAAW;CAC9B,MAAM,UAAU,OAAO,SAAS,WAAW;CAE3C,OAAO,eAAe,IACrB,OACA,QACA,SAC0F;EAC1F,MAAM,EACL,SACA,QAAQ,SACR,cACA,mBACA,QACA,GAAG,uBACA,WAAW,CAAC;EAEhB,MAAM,YAAY,IAAI,gBAAgB;EACtC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,kBAAkB,GAAG;GAC9D,IAAI,UAAU,KAAA,KAAa,UAAU,MACpC,MAAM,IAAI,MACT,qBAAqB,IAAI,2CAC1B;GAED,IAAI;IACH,MAAM,WAAW,OAAO,KAAK;IAC7B,IAAI,CAAC,UACJ;IAED,UAAU,OAAO,KAAK,QAAQ;GAC/B,QAAQ;IACP,MAAM,IAAI,MACT,qBAAqB,IAAI,2CAC1B;GACD;EACD;EAEA,MAAM,cAAc,UAAU,SAAS;EAEvC,MAAM,YAAY,OAAO,KAAK,CAAC,CAAC,WAAW,MAAM,IAAI,QAAQ,OAAO;EAGpE,MAAM,MAAM,SAAS,KAClB,wCAAwC,UAAU,GAAG,QAAQ,GAAG,cAAc,YAC9E,cAAc,IAAI,gBAAgB,OAElC,iDAAiD,UAAU,MAAM,YACjE,cAAc,IAAI,gBAAgB;EAGrC,MAAM,UAAkC;GACvC,eAAe,UAAU;GACzB,gBAAgB;GAChB,GAAI,gBAAgB,OAAO,iBAAiB,WACxC,eACD,CAAC;EACL;EAEA,IAAI,SAAS;GACZ,IAAI,QAAQ,WACX,QAAQ,uBAAuB;GAEhC,IAAI,OAAO,QAAQ,aAAa,UAC/B,QAAQ,sBAAsB,OAAO,QAAQ,QAAQ;GAEtD,IAAI,QAAQ,UACX,QAAQ,sBAAsB,QAAQ;GAEvC,IAAI,QAAQ,UACX,QAAQ,qBAAqB,KAAK,UAAU,QAAQ,QAAQ;EAE9D;EAIA,MAAM,WAAW,MAAM,QAAQ,KAAK;GACnC,MAHY,KAAK,UAAU,MAGxB;GACH;GACA,QAAQ;GACA;EACT,CAAC;EAGD,IAAI,CAAC,SAAS,MAAM,CAAC,mBAAmB;GACvC,IAAI;GACJ,IAAI;IACH,YAAY,MAAM,SAAS,KAAK;GACjC,QAAQ;IACP,YAAY;GACb;GACA,MAAM,IAAI,MACT,yBAAyB,SAAS,OAAO,GAAG,SAAS,WAAW,KAAK,WACtE;EACD;EAEA,IAAI,mBACH,OAAO;EAGR,IAAK,OAAiC,WAAW,MAAM;GACtD,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;GAC5D,IAAI,YAAY,SAAS,cAAc,KAAK,SAAS,MACpD,OAAO,SAAS;GAEjB,IAAI,SAAS,QAAQ,CAAC,YAAY,SAAS,MAAM,GAEhD,OAAO,SAAS;GAQjB,MAAM,gBAAgB,MAAM,QAAQ,KAAK;IACxC,MAAM,KAAK,UAAU;KACpB,GAAI;KACJ,QAAQ;IACT,CAAC;IACD;IACA,QAAQ;IACA;GACT,CAAC;GAED,IAAI,CAAC,cAAc,IAAI;IACtB,IAAI;IACJ,IAAI;KACH,YAAY,MAAM,cAAc,KAAK;IACtC,QAAQ;KACP,YAAY;IACb;IACA,MAAM,IAAI,MACT,yBAAyB,cAAc,OAAO,GAAG,cAAc,WAAW,KAAK,WAChF;GACD;GAKA,QAAO,MAHiB,cAAc,KAEnC,EAAA,CACc;EAClB;EAKA,QAAO,MAHY,SAAS,KAEzB,EAAA,CACS;CACb;AACD;;;;;;;;;;;;;;AAeA,eAAsB,gBACrB,QACA,OACA,YACA,aACA,QACmC;CACnC,MAAM,MAAM,iDAAiD,OAAO,UAAU,UAAU;CAExF,MAAM,WAAW,MAAM,MAAM,KAAK;EACjC,QAAQ;EACR,SAAS;GACR,eAAe,UAAU,OAAO;GAChC,gBAAgB;EACjB;EACA,MAAM;EACN;CACD,CAAC;CAED,IAAI,CAAC,SAAS,IAAI;EACjB,IAAI;EACJ,IAAI;GACH,YAAY,MAAM,SAAS,KAAK;EACjC,QAAQ;GACP,YAAY;EACb;EACA,MAAM,IAAI,MACT,yBAAyB,SAAS,OAAO,GAAG,SAAS,WAAW,KAAK,WACtE;CACD;CAEA,MAAM,OAAO,MAAM,SAAS,KAA2C;CACvE,OAAQ,KAAK,UAAU;AACxB;;;;;;;;;;;;;;;;;;;;;;AA2BA,SAAgB,uBACf,QACA,MACA,aACU;CAGV,IAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GACxE,OAAO;CAGR,MAAM,SAAS;CACf,MAAM,WAAW,CAAC,CAAC,QAAQ,OAAO,UAAU,KAAA;CAC5C,MAAM,iBAAiB,CAAC,CAAC,eAAe,OAAO,gBAAgB,KAAA;CAE/D,IAAI,CAAC,YAAY,CAAC,gBACjB,OAAO;CAGR,OAAO;EACN,GAAG;EACH,GAAI,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;EAClC,GAAI,iBAAiB,EAAE,YAAY,IAAI,CAAC;CACzC;AACD;AAMA,SAAgB,0BACf,OACA,YACC;CACD,IAAI,SAAS,MACZ,OAAO;EAAE,aAAa,KAAA;EAAW,OAAO,KAAA;CAAU;CAGnD,MAAM,cAAc,MAAM,KAAK,UAAU;EACxC,UAAU;GACT,aAAa,KAAK,SAAS,aAAa,KAAK,cAAc,KAAA;GAC3D,MAAM,KAAK;GACX,YAAY,KAAK,SAAS,aAAa,KAAK,cAAc,KAAA;EAC3D;EACA,MAAM;CACP,EAAE;CAEF,IAAI,cAAc,MACjB,OAAO;EAAE,aAAa,KAAA;EAAW,OAAO;CAAY;CAGrD,MAAM,OAAO,WAAW;CAExB,QAAQ,MAAR;EACC,KAAK,QACJ,OAAO;GAAE,aAAa;GAAM,OAAO;EAAY;EAChD,KAAK,QACJ,OAAO;GAAE,aAAa;GAAM,OAAO;EAAY;EAChD,KAAK,YACJ,OAAO;GAAE,aAAa;GAAY,OAAO;EAAY;EAStD,KAAK,QACJ,OAAO;GACN,aAAa;IAAE,MAAM;IAAY,UAAU,EAAE,MAAM,WAAW,SAAS;GAAE;GACzE,OAAO;EACR;EACD,SAEC,MAAM,IAAI,MAAM,iCAAiCA,MAAiB;CAEpE;AACD;AAUA,MAAM,sBAAsB;AAE5B,SAAgB,sBAAsB,YAA+C;CAEpF,OAAO,GADY,cAAc,WAAW,IACrB,sBAAsB,WAAW;AACzD;AAEA,SAAgB,sBAAsB,YAA4B;CACjE,MAAM,cAAc,WAAW,YAAY,mBAAmB;CAC9D,IAAI,gBAAgB,IAAI,OAAO;CAG/B,IADoB,cAAc,MACf,WAAW,QAAQ,OAAO;CAE7C,OAAO,WAAW,MAAM,GAAG,WAAW;AACvC;AAwEA,SAAS,gBAAgB,UAAkE;CAE1F,MAAM,KACL,cAAc,YAAY,OAAO,SAAS,aAAa,YAAY,SAAS,WACxE,SAAS,WACV;CAEJ,IAAI,IAAI,MACP,OAAO;EACN,OACC,OAAO,GAAG,cAAc,WACrB,GAAG,YACH,KAAK,UAAU,GAAG,aAAa,CAAC,CAAC;EACrC,YAAY,sBAAsB,SAAS,EAAE;EAC7C,MAAM;EACN,UAAU,GAAG;CACd;CAID,MAAM,OAAO;CACb,OAAO;EACN,OACC,OAAO,KAAK,cAAc,WACvB,KAAK,YACL,KAAK,UAAU,KAAK,aAAa,CAAC,CAAC;EACvC,YAAY,sBAAsB,KAAK,EAAE;EACzC,MAAM;EACN,UAAU,KAAK;CAChB;AACD;AAEA,SAAgB,iBAAiB,QAA4D;CAC5F,IAAI,OAAO,cAAc,MAAM,QAAQ,OAAO,UAAU,GACvD,OAAO,OAAO,WAAW,KAAK,aAC7B,gBAAgB,QAAQ,CACzB;CAGD,MAAM,UAAU,OAAO;CAGvB,IAAI,UAAU,EAAE,EAAE,SAAS,cAAc,MAAM,QAAQ,QAAQ,EAAE,CAAC,QAAQ,UAAU,GACnF,OAAO,QAAQ,EAAE,CAAC,QAAQ,WAAW,KAAK,aAAa,gBAAgB,QAAQ,CAAC;CAGjF,OAAO,CAAC;AACT;;;;;;;AAiBA,SAAgB,mBAAmB,YAA8B;CAChE,IAAI,eAAe,YAAY,OAAO;CACtC,OACC,OAAO,eAAe,YACtB,eAAe,QACd,WAAkC,SAAS;AAE9C;;;;;;;;;AAUA,SAAgB,qBACf,MACA,gBAC4B;CAC5B,IAAI;CACJ,IAAI;EACH,SAAS,KAAK,MAAM,KAAK,KAAK,CAAC;CAChC,QAAQ;EACP,OAAO,CAAC;CACT;CAEA,MAAM,aAAa,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;CAC3D,MAAM,WAAsC,CAAC;CAE7C,KAAK,MAAM,aAAa,YAAY;EACnC,IAAI,OAAO,cAAc,YAAY,cAAc,MAAM;EACzD,MAAM,MAAM;EACZ,MAAM,OAAO,IAAI;EACjB,IAAI,OAAO,SAAS,YAAY,CAAC,eAAe,IAAI,IAAI,GAAG;EAI3D,IAAI;EACJ,IAAI,eAAe,KAClB,OAAO,IAAI;OACL,IAAI,gBAAgB,KAC1B,OAAO,IAAI;OACL;GACN,MAAM,EAAE,MAAM,OAAO,GAAG,SAAS;GACjC,OAAO;EACR;EAEA,SAAS,KAAK;GACb,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,QAAQ,CAAC,CAAC;GAClE,YAAY,sBAAsB,KAAA,CAAS;GAC3C,MAAM;GACN,UAAU;EACX,CAAC;CACF;CAEA,OAAO;AACR;;AAGA,SAAgB,aACf,OACc;CACd,OAAO,IAAI,KACT,SAAS,CAAC,EAAA,CACT,KAAK,SAAS,KAAK,UAAU,IAAI,CAAC,CAClC,QAAQ,SAAyB,OAAO,SAAS,QAAQ,CAC5D;AACD;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,SAAgB,yBACf,QACA,SAImC;CACnC,IAAI,CAAC,mBAAmB,QAAQ,UAAU,GAAG,OAAO;CAGpD,IAAI,iBAAiB,MAAM,CAAC,CAAC,SAAS,GAAG,OAAO;CAEhD,MAAM,iBAAiB,aAAa,QAAQ,KAAK;CACjD,IAAI,eAAe,SAAS,GAAG,OAAO;CAEtC,MAAM,OAAO,YAAY,MAAM;CAC/B,IAAI,CAAC,MAAM,OAAO;CAElB,MAAM,WAAW,qBAAqB,MAAM,cAAc;CAC1D,OAAO,SAAS,SAAS,IAAI,WAAW;AACzC;;;;;;;;AAaA,SAAgB,YAAY,QAAqD;CAGhF,MAAM,gBADU,OAAO,UACS,EAAE,EAAE,SAAS;CAC7C,IAAI,iBAAiB,QAAQ,OAAO,aAAa,CAAC,CAAC,SAAS,GAC3D,OAAO,OAAO,aAAa;CAG5B,IAAI,cAAc,QAAQ;EACzB,MAAM,WAAW,OAAO;EAExB,IAAI,OAAO,aAAa,YAAY,aAAa,MAChD,OAAO,KAAK,UAAU,QAAQ;EAG/B,IAAI,OAAO,aAAa,UACvB,OAAO,OAAO,QAAQ;EAGvB,IAAI,aAAa,QAAQ,aAAa,KAAA,GACrC;EAED,OAAO,OAAO,QAAQ;CACvB;AAED;;;;;;;;;;;AChqBA,SAASC,eAAa,MAAqD;CAC1E,IAAI,gBAAgB,YACnB,OAAO;CAGR,IAAI,OAAO,SAAS,UAAU;EAC7B,IAAI,SAAS;EACb,IAAI,OAAO,WAAW,OAAO,GAAG;GAC/B,MAAM,aAAa,OAAO,QAAQ,GAAG;GACrC,IAAI,cAAc,GACjB,SAAS,OAAO,MAAM,aAAa,CAAC;EAEtC;EACA,MAAM,eAAe,KAAK,MAAM;EAChC,MAAM,QAAQ,IAAI,WAAW,aAAa,MAAM;EAChD,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACxC,MAAM,KAAK,aAAa,WAAW,CAAC;EAErC,OAAO;CACR;CAEA,IAAI,gBAAgB,KACnB,MAAM,IAAI,MACT,iHAED;CAGD,OAAO;AACR;AAEA,SAAS,qBAAqB,WAAuC;CACpE,IAAI,CAAC,WACJ,MAAM,IAAI,8BAA8B;EACvC,eAAe;EACf,SACC;CAEF,CAAC;CAKF,IAAI,CAAC,UAAU,YAAY,CAAC,CAAC,WAAW,QAAQ,GAC/C,MAAM,IAAI,8BAA8B;EACvC,eAAe;EACf,SACC,iGACuB,UAAU;CACnC,CAAC;CAGF,OAAO;AACR;AAEA,SAASC,qBAAmB,OAA2B;CACtD,IAAI,SAAS;CACb,MAAM,YAAY;CAClB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,WAAW;EACjD,MAAM,QAAQ,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,WAAW,MAAM,MAAM,CAAC;EACrE,UAAU,OAAO,aAAa,GAAG,KAAK;CACvC;CACA,OAAO,KAAK,MAAM;AACnB;AAEA,SAAgB,+BAA+B,QAE7C;CACD,MAAM,WAAgC,CAAC;CAEvC,KAAK,MAAM,EAAE,MAAM,aAAa,QAC/B,QAAQ,MAAR;EACC,KAAK;GACJ,SAAS,KAAK;IAAE;IAAS,MAAM;GAAS,CAAC;GACzC;EAGD,KAAK,QAAQ;GACZ,MAAM,YAAsB,CAAC;GAC7B,MAAM,aAAyD,CAAC;GAEhE,KAAK,MAAM,QAAQ,SAClB,QAAQ,KAAK,MAAb;IACC,KAAK;KACJ,UAAU,KAAK,KAAK,IAAI;KACxB;IAED,KAAK,QAAQ;KACZ,MAAM,YAAY,qBAAqB,KAAK,SAAS;KACrD,MAAM,aAAaD,eAAa,KAAK,IAAI;KACzC,IAAI,YACH,WAAW,KAAK;MACf,OAAO;MACP;KACD,CAAC;KAEF;IACD;GACD;GAGD,IAAI,WAAW,SAAS,GAAG;IAC1B,MAAM,eAAuC,CAAC;IAC9C,IAAI,UAAU,SAAS,GACtB,aAAa,KAAK;KAAE,MAAM;KAAQ,MAAM,UAAU,KAAK,IAAI;IAAE,CAAC;IAE/D,KAAK,MAAM,OAAO,YAAY;KAC7B,MAAM,SAASC,qBAAmB,IAAI,KAAK;KAC3C,aAAa,KAAK;MACjB,MAAM;MACN,WAAW,EAAE,KAAK,QAAQ,IAAI,UAAU,UAAU,SAAS;KAC5D,CAAC;IACF;IACA,SAAS,KAAK;KAAE,SAAS;KAAc,MAAM;IAAO,CAAC;GACtD,OACC,SAAS,KAAK;IAAE,SAAS,UAAU,KAAK,IAAI;IAAG,MAAM;GAAO,CAAC;GAG9D;EACD;EAEA,KAAK,aAAa;GACjB,IAAI,OAAO;GACX,IAAI,YAAY;GAChB,MAAM,YAID,CAAC;GAEN,KAAK,MAAM,QAAQ,SAClB,QAAQ,KAAK,MAAb;IACC,KAAK;KACJ,QAAQ,KAAK;KACb;IAGD,KAAK;KAOJ,aAAa,KAAK;KAClB;IAGD,KAAK,QAEJ;IAGD,KAAK;KACJ,UAAU,KAAK;MACd,UAAU;OACT,WAAW,KAAK,UAAU,KAAK,KAAK;OACpC,MAAM,KAAK;MACZ;MACA,IAAI,sBAAsB,KAAK,UAAU;MACzC,MAAM;KACP,CAAC;KACD;IAGD,KAAK,eAEJ;IAGD,SAEC,MAAM,IAAI,MACT,0BAA2BC,KAAqC,MACjE;GAEF;GAGD,SAAS,KAAK;IACb,SAAS;IACT,MAAM;IACN,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;IACjC,YACC,UAAU,SAAS,IAChB,UAAU,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,QAAQ,UAAU;KAChE,UAAU;MAAE,WAAW;MAAM;KAAK;KAClC;KACA,MAAM;IACP,EAAE,IACD,KAAA;GACL,CAAC;GAED;EACD;EAEA,KAAK;GACJ,KAAK,MAAM,gBAAgB,SAC1B,IAAI,aAAa,SAAS,eAAe;IACxC,MAAM,SAAS,aAAa;IAC5B,IAAI;IACJ,QAAQ,OAAO,MAAf;KACC,KAAK;KACL,KAAK;MACJ,UAAU,OAAO;MACjB;KACD,KAAK;KACL,KAAK;MACJ,UAAU,KAAK,UAAU,OAAO,KAAK;MACrC;KACD,KAAK;MACJ,UAAU,OAAO,SACd,0BAA0B,OAAO,WACjC;MACH;KACD,KAAK;MACJ,UAAU,OAAO,MACf,QACC,MACA,EAAE,SAAS,MACb,CAAC,CACA,KAAK,MAAM,EAAE,IAAI,CAAC,CAClB,KAAK,IAAI;MACX;KACD;MACC,UAAU;MACV;IACF;IACA,SAAS,KAAK;KACb;KACA,MAAM,aAAa;KACnB,cAAc,sBAAsB,aAAa,UAAU;KAC3D,MAAM;IACP,CAAC;GACF;GAGD;EAGD,SAEC,MAAM,IAAI,MAAM,qBAAqBA,MAAiB;CAExD;CAGD,OAAO,EAAE,SAAS;AACnB;;;;;;;;;;;;AC1PA,SAAgB,kBACf,QACuB;CACvB,MAAM,QACL,OAOC,SAAS;EACV,mBAAmB;EACnB,eAAe;CAChB;CAEA,MAAM,eAAe,MAAM,iBAAiB;CAC5C,MAAM,mBAAmB,MAAM,qBAAqB;CACpD,MAAM,eAAe,MAAM,uBAAuB;CAIlD,MAAM,UACL,iBAAiB,KAAA,IAAY,KAAK,IAAI,GAAG,eAAe,YAAY,IAAI,KAAA;CAEzE,OAAO;EACN,cAAc;GACb,OAAO;GACP,MAAM,KAAA;GACN,WAAW,KAAA;EACZ;EACA,aAAa;GACZ,OAAO;GACP;GACA,WAAW;GACX,YAAY,KAAA;EACb;EACA,KAAK,EAAE,OAAO,eAAe,iBAAiB;CAC/C;AACD;;;;;;;;;;ACzCA,SAAgB,yBACf,wBAC8B;CAC9B,IAAI;CAEJ,IACC,OAAO,2BAA2B,YAClC,2BAA2B,QAC3B,2BAA2B,KAAA,GAE3B,eAAe;MACT,IAAI,OAAO,2BAA2B,YAAY,2BAA2B,MAAM;EACzF,MAAM,WAAW;EAGjB,MAAM,UAAU,SAAS;EACzB,IAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,GAC9C,eAAe,QAAQ,EAAE,CAAC;OACpB,IAAI,mBAAmB,UAC7B,eAAe,SAAS;OAExB,eAAe,KAAA;CAEjB,OAEC,eAAe,KAAA;CAGhB,MAAM,MAAM,gBAAgB;CAE5B,QAAQ,cAAR;EACC,KAAK,QACJ,OAAO;GAAE,SAAS;GAAQ;EAAI;EAC/B,KAAK;EACL,KAAK,gBACJ,OAAO;GAAE,SAAS;GAAU;EAAI;EACjC,KAAK,cACJ,OAAO;GAAE,SAAS;GAAc;EAAI;EACrC,KAAK,SACJ,OAAO;GAAE,SAAS;GAAS;EAAI;EAChC,KAAK;EACL,KAAK,WACJ,OAAO;GAAE,SAAS;GAAS;EAAI;EAChC,SACC,OAAO;GAAE,SAAS;GAAQ;EAAI;CAChC;AACD;;;;;;;ACpCA,SAAgB,mBACf,QACA,UAC4C;CAC5C,IAAI,YAAY;CAChB,OAAO,OAAO,YACb,IAAI,gBAAsE;EACzE,UAAU,OAAO,YAAY;GAC5B,IAAI,CAAC,WAAW;IACf,YAAY;IACZ,WAAW,QAAQ;KAClB,MAAM;KACI;IACX,CAAC;GACF;GACA,WAAW,QAAQ,KAAK;EACzB;EACA,MAAM,YAAY;GACjB,IAAI,CAAC,WACJ,WAAW,QAAQ;IAClB,MAAM;IACI;GACX,CAAC;EAEH;CACD,CAAC,CACF;AACD;;;;AAKA,SAAS,wBAAwB,IAAsC;CACtE,MAAM,KAAK,GAAG;CACd,MAAM,OAAO,IAAI,QAAQ,GAAG,QAAQ;CACpC,MAAM,OAAO,IAAI,aAAa,GAAG,aAAa;CAE9C,OAAO,EADI,GAAG,MAAM,SACN,CAAC,SAAS,CAAC,QAAQ,SAAS;AAC3C;;;;;;;;;;;AAYA,SAAgB,gBACf,UACA,gBAI4C;CAC5C,MAAM,YACL,oBAAoB,iBACjB,WACC,SAAS;CAEd,IAAI,CAAC,WACJ,MAAM,IAAI,MAAM,+CAA+C;CAShE,MAAM,iBAAiB,aAAa,gBAAgB,KAAK;CACzD,MAAM,0BACL,mBAAmB,gBAAgB,UAAU,KAAK,eAAe,OAAO;CACzE,IAAI,gBAAgB;CACpB,IAAI,qBAAqB;CAGzB,IAAI,QAA8B;EACjC,cAAc;GAAE,OAAO;GAAG,MAAM,KAAA;GAAW,WAAW,KAAA;EAAU;EAChE,aAAa;GACZ,OAAO;GACP,SAAS,KAAA;GACT,WAAW,KAAA;GACX,YAAY,KAAA;EACb;EACA,KAAK,EAAE,aAAa,EAAE;CACvB;CACA,IAAI,SAAwB;CAC5B,IAAI,cAA6B;CACjC,IAAI,eAAmD;CACvD,IAAI,eAAe;CACnB,IAAI,kBAAkB;CAOtB,MAAM,kCAAkB,IAAI,IAA4D;CACxF,MAAM,kCAAkB,IAAI,IAAY;CACxC,IAAI,sBAAqC;CAMzC,OAHkB,UAAU,YAAY,IAAI,WAAW,CAGxC,CAAC,CAAC,YAChB,IAAI,gBAAmD;EACtD,UAAU,MAAM,YAAY;GAC3B,IAAI,CAAC,QAAQ,SAAS,UAAU;IAC/B,IAAI,SAAS,UAAU,eAAe;IACtC;GACD;GAEA,kBAAkB;GAClB,IAAI;GACJ,IAAI;IACH,QAAQ,KAAK,MAAM,IAAI;GACxB,QAAQ;IACP,QAAQ,KAAK,oDAAoD,IAAI;IACrE;GACD;GAEA,IAAI,MAAM,OACT,QAAQ,kBAAkB,KAAgD;GAI3E,MAAM,UAAU,MAAM;GAMtB,MAAM,qBAAqB,UAAU,EAAE,EAAE;GACzC,MAAM,qBAAqB,MAAM;GAEjC,IAAI,sBAAsB,MACzB,eAAe,yBAAyB,kBAAkB;QACpD,IAAI,sBAAsB,MAChC,eAAe,yBAAyB,kBAAkB;GAI3D,MAAM,iBAAiB,MAAM;GAC7B,IAAI,kBAAkB,QAAQ,mBAAmB,IAAI;IACpD,MAAM,eAAe,OAAO,cAAc;IAC1C,IAAI,aAAa,SAAS,GACzB,IAAI,yBACH,iBAAiB;SACX;KAEN,IAAI,aAAa;MAChB,WAAW,QAAQ;OAAE,MAAM;OAAiB,IAAI;MAAY,CAAC;MAC7D,cAAc;KACf;KACA,IAAI,CAAC,QAAQ;MACZ,SAAS,WAAW;MACpB,WAAW,QAAQ;OAAE,MAAM;OAAc,IAAI;MAAO,CAAC;KACtD;KACA,WAAW,QAAQ;MAClB,MAAM;MACN,IAAI;MACJ,OAAO;KACR,CAAC;IACF;GAEF;GAGA,IAAI,MAAM,QAAQ,MAAM,UAAU,GAAG;IAEpC,IAAI,aAAa;KAChB,WAAW,QAAQ;MAAE,MAAM;MAAiB,IAAI;KAAY,CAAC;KAC7D,cAAc;IACf;IACA,mBAAmB,MAAM,YAAyC,UAAU;GAC7E;GAGA,IAAI,UAAU,EAAE,EAAE,OAAO;IACxB,MAAM,QAAQ,QAAQ,EAAE,CAAC;IAEzB,MAAM,iBAAkB,MAAM,qBAAqB,MAAM;IAGzD,IAAI,kBAAkB,eAAe,SAAS,GAAG;KAChD,IAAI,CAAC,aAAa;MACjB,cAAc,WAAW;MACzB,WAAW,QAAQ;OAClB,MAAM;OACN,IAAI;MACL,CAAC;KACF;KACA,WAAW,QAAQ;MAClB,MAAM;MACN,IAAI;MACJ,OAAO;KACR,CAAC;IACF;IAEA,MAAM,YAAY,MAAM;IACxB,IAAI,aAAa,UAAU,SAAS,GACnC,IAAI,yBACH,iBAAiB;SACX;KAEN,IAAI,aAAa;MAChB,WAAW,QAAQ;OAAE,MAAM;OAAiB,IAAI;MAAY,CAAC;MAC7D,cAAc;KACf;KACA,IAAI,CAAC,QAAQ;MACZ,SAAS,WAAW;MACpB,WAAW,QAAQ;OAAE,MAAM;OAAc,IAAI;MAAO,CAAC;KACtD;KACA,WAAW,QAAQ;MAClB,MAAM;MACN,IAAI;MACJ,OAAO;KACR,CAAC;IACF;IAGD,MAAM,iBAAiB,MAAM;IAG7B,IAAI,MAAM,QAAQ,cAAc,GAAG;KAElC,IAAI,aAAa;MAChB,WAAW,QAAQ;OAAE,MAAM;OAAiB,IAAI;MAAY,CAAC;MAC7D,cAAc;KACf;KACA,mBAAmB,gBAAgB,UAAU;IAC9C;GACD;EACD;EAEA,MAAM,YAAY;GAEjB,KAAK,MAAM,CAAC,QAAQ,iBAAiB;IACpC,IAAI,gBAAgB,IAAI,GAAG,GAAG;IAC9B,cAAc,KAAK,UAAU;GAC9B;GAGA,IAAI,aACH,WAAW,QAAQ;IAAE,MAAM;IAAiB,IAAI;GAAY,CAAC;GAI9D,IAAI,oBAAoB;GACxB,IAAI,2BAA2B,CAAC,sBAAsB,cAAc,KAAK,GAAG;IAC3E,MAAM,WAAW,qBAAqB,eAAe,cAAc;IACnE,IAAI,SAAS,SAAS,GAAG;KACxB,KAAK,MAAM,QAAQ,UAAU;MAC5B,WAAW,QAAQ;OAClB,MAAM;OACN,IAAI,KAAK;OACT,UAAU,KAAK;MAChB,CAAC;MACD,WAAW,QAAQ;OAClB,MAAM;OACN,IAAI,KAAK;OACT,OAAO,KAAK;MACb,CAAC;MACD,WAAW,QAAQ;OAAE,MAAM;OAAkB,IAAI,KAAK;MAAW,CAAC;MAClE,WAAW,QAAQ,IAAI;KACxB;KACA,oBAAoB;KAGpB,QAAQ,KACP,mCAAmC,SAAS,OAAO,+FACpD;IACD,OAAO;KAEN,MAAM,KAAK,WAAW;KACtB,WAAW,QAAQ;MAAE,MAAM;MAAc;KAAG,CAAC;KAC7C,WAAW,QAAQ;MAAE,MAAM;MAAc;MAAI,OAAO;KAAc,CAAC;KACnE,WAAW,QAAQ;MAAE,MAAM;MAAY;KAAG,CAAC;IAC5C;GACD,OAAO,IAAI,2BAA2B,cAAc,KAAK,GAAG;IAE3D,MAAM,KAAK,WAAW;IACtB,WAAW,QAAQ;KAAE,MAAM;KAAc;IAAG,CAAC;IAC7C,WAAW,QAAQ;KAAE,MAAM;KAAc;KAAI,OAAO;IAAc,CAAC;IACnE,WAAW,QAAQ;KAAE,MAAM;KAAY;IAAG,CAAC;GAC5C;GAEA,IAAI,QACH,WAAW,QAAQ;IAAE,MAAM;IAAY,IAAI;GAAO,CAAC;GAIpD,MAAM,wBAAwB,oBAC1B;IAAE,SAAS;IAAc,KAAK;GAAO,IACtC,CAAC,gBAAgB,mBAAmB,CAAC,eACnC;IACD,SAAS;IACT,KAAK;GACN,IACE,gBAAgB;IAAE,SAAS;IAAQ,KAAK;GAAO;GAEpD,WAAW,QAAQ;IAClB,cAAc;IACd,MAAM;IACN;GACD,CAAC;EACF;CACD,CAAC,CACF;;;;CAKA,SAAS,cACR,OACA,YACC;EACD,MAAM,KAAK,gBAAgB,IAAI,KAAK;EACpC,IAAI,CAAC,MAAM,gBAAgB,IAAI,KAAK,GAAG;EACvC,gBAAgB,IAAI,KAAK;EACzB,WAAW,QAAQ;GAAE,MAAM;GAAkB,IAAI,GAAG;EAAG,CAAC;EACxD,WAAW,QAAQ;GAClB,MAAM;GACN,YAAY,GAAG;GACf,UAAU,GAAG;GACb,OAAO,GAAG;EACX,CAAC;CACF;;;;;;;;;;;;;;;CAgBA,SAAS,mBACR,WACA,YACC;EACD,KAAK,MAAM,MAAM,WAAW;GAC3B,IAAI,wBAAwB,EAAE,GAAG;IAEhC,IAAI,uBAAuB,MAC1B,cAAc,qBAAqB,UAAU;IAE9C;GACD;GAEA,MAAM,UAAW,GAAG,SAAoB;GACxC,MAAM,KAAK,GAAG;GACd,MAAM,SAAU,IAAI,QAAQ,GAAG,QAAQ;GACvC,MAAM,SAAU,IAAI,aAAa,GAAG,aAAa;GACjD,MAAM,OAAO,GAAG;GAEhB,IAAI,CAAC,gBAAgB,IAAI,OAAO,GAAG;IAElC,IAAI,uBAAuB,QAAQ,wBAAwB,SAC1D,cAAc,qBAAqB,UAAU;IAG9C,MAAM,KAAK,sBAAsB,IAAI;IACrC,MAAM,WAAW,UAAU;IAC3B,gBAAgB,IAAI,SAAS;KAAE;KAAI;KAAU,MAAM;IAAG,CAAC;IACvD,sBAAsB;IACtB,qBAAqB;IAErB,WAAW,QAAQ;KAClB,MAAM;KACN;KACA;IACD,CAAC;IAED,IAAI,UAAU,QAAQ,WAAW,IAAI;KACpC,MAAM,QAAQ,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,MAAM;KACzE,gBAAgB,IAAI,OAAO,CAAC,CAAE,QAAQ;KACtC,WAAW,QAAQ;MAClB,MAAM;MACN;MACA;KACD,CAAC;IACF;GACD,OAAO;IACN,MAAM,SAAS,gBAAgB,IAAI,OAAO;IAC1C,sBAAsB;IACtB,IAAI,UAAU,QAAQ,WAAW,IAAI;KACpC,MAAM,QAAQ,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,MAAM;KACzE,OAAO,QAAQ;KACf,WAAW,QAAQ;MAClB,MAAM;MACN,IAAI,OAAO;MACX;KACD,CAAC;IACF;GACD;EACD;CACD;AACD;;;;;;AAOA,IAAM,aAAN,cAAyB,gBAAoC;CAC5D,cAAc;EACb,IAAI,SAAS;EACb,MAAM,UAAU,IAAI,YAAY;EAEhC,MAAM;GACL,UAAU,OAAO,YAAY;IAC5B,UAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;IAChD,MAAM,QAAQ,OAAO,MAAM,IAAI;IAC/B,SAAS,MAAM,IAAI,KAAK;IAExB,KAAK,MAAM,QAAQ,OAAO;KACzB,MAAM,UAAU,KAAK,KAAK;KAC1B,IAAI,CAAC,SAAS;KACd,IAAI,QAAQ,WAAW,QAAQ,GAC9B,WAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;UAC7B,IAAI,QAAQ,WAAW,OAAO,GACpC,WAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;IAErC;GACD;GAEA,MAAM,YAAY;IACjB,IAAI,OAAO,KAAK,GAAG;KAClB,MAAM,UAAU,OAAO,KAAK;KAC5B,IAAI,QAAQ,WAAW,QAAQ,GAC9B,WAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;UAC7B,IAAI,QAAQ,WAAW,OAAO,GACpC,WAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;IAErC;GACD;EACD,CAAC;CACF;AACD;;;ACrcA,IAAa,4BAAb,MAAkE;CAWjE,YACC,SACA,UACA,QACC;wBAdO,wBAAuB,IAAA;wBACvB,+BAA8B,MAAA;wBAE9B,iBAAkF,CAAC,CAAA;wBAEnF,WAAA,KAAA,CAAA;wBACA,YAAA,KAAA,CAAA;wBAEQ,UAAA,KAAA,CAAA;EAOhB,KAAK,UAAU;EACf,KAAK,WAAW;EAChB,KAAK,SAAS;CACf;CAEA,IAAI,WAAmB;EACtB,OAAO,KAAK,OAAO;CACpB;CAEA,YAAoB,EACnB,OACA,kBACA,iBACA,kBACmE;EACnE,MAAM,WAA8B,CAAC;EAErC,IAAI,SAAS,QAAQ,MAAM,SAAS,GAAG;GACtC,QAAQ,KACP,mFACD;GACA,SAAS,KAAK;IAAE,SAAS;IAAS,MAAM;GAAc,CAAC;EACxD;EAEA,IAAI,oBAAoB,MACvB,SAAS,KAAK;GAAE,SAAS;GAAoB,MAAM;EAAc,CAAC;EAGnE,IAAI,mBAAmB,MACtB,SAAS,KAAK;GAAE,SAAS;GAAmB,MAAM;EAAc,CAAC;EAGlE,IAAI,gBAAgB,SAAS,QAC5B,SAAS,KAAK;GAAE,SAAS;GAAkB,MAAM;EAAc,CAAC;EAGjE,OAAO;CACR;;;;;CAMA,WAAmB,QAAwE;EAC1F,MAAM,EAAE,aAAa,+BAA+B,MAAM;EAC1D,OAAO,SAAS,KAAK,EAAE,SAAS,WAAW,GAAG,KAAK,IAAI,SAAS,CAAC,CAAC,KAAK,MAAM;CAC9E;CAEA,MAAM,WACL,SAC8D;EAC9D,MAAM,WAAW,KAAK,YAAY,OAAO;EACzC,MAAM,QAAQ,KAAK,WAAW,QAAQ,MAAM;EAE5C,MAAM,SAAS,MAAM,KAAK,OAAO,QAAQ,SAAS,EAAE,MAAM,CAAC;EAE3D,OAAO;GACN,cAAc;IAAE,SAAS;IAAQ,KAAK;GAAO;GAC7C,SAAS;IACR,GAAG,OAAO,KAAK,KAAK,EAAE,SAAS,UAAU,aAAa;KACrD,MAAM;KACN,YAAY;KACZ,IAAI;KACJ,KAAK;KACL,kBAAkB,EACjB,YAAY,EAAE,MAAM,EACrB;IACD,EAAE;IACF;KACC,MAAM;KACN,MAAM,OAAO;IACd;IACA,GAAG,iBAAiB,MAA4C;GACjE;GACA,OAAO,kBAAkB,MAA4C;GACrE;EACD;CACD;CAEA,MAAM,SACL,SAC4D;EAC5D,MAAM,WAAW,KAAK,YAAY,OAAO;EACzC,MAAM,QAAQ,KAAK,WAAW,QAAQ,MAAM;EAO5C,OAAO,EACN,QAAQ,mBACP,gBAAgB,MAPK,KAAK,OAAO,QAAQ,SAAS;GACnD;GACA,QAAQ;EACT,CAAC,CAI6E,GAC5E,QACD,EACD;CACD;AACD;;;ACvGA,IAAa,0BAAb,MAAiE;CAMhE,IAAI,WAAmB;EACtB,OAAO,KAAK,OAAO;CACpB;CAEA,IAAI,uBAA+B;EAElC,OAAO,KAAK,SAAS,wBAAwB;CAC9C;CAEA,IAAI,wBAAiC;EACpC,OAAO,KAAK,SAAS,yBAAyB;CAC/C;CAEA,YACC,SACA,UACA,QACC;wBAtBO,wBAAuB,IAAA;wBACvB,WAAA,KAAA,CAAA;wBACQ,UAAA,KAAA,CAAA;wBACA,YAAA,KAAA,CAAA;EAoBhB,KAAK,UAAU;EACf,KAAK,WAAW;EAChB,KAAK,SAAS;CACf;CAEA,MAAM,QAAQ,EACb,QACA,eACgE;EAChE,IAAI,OAAO,SAAS,KAAK,sBACxB,MAAM,IAAI,mCAAmC;GAC5C,sBAAsB,KAAK;GAC3B,SAAS,KAAK;GACd,UAAU,KAAK;GACf;EACD,CAAC;EAGF,MAAM,EACL,SACA,sBAAsB,uBACtB,uBAAuB,wBACvB,GAAG,uBACA,KAAK;EAcT,OAAO;GACN,aAAa,MAbS,KAAK,OAAO,QAAQ,IAC1C,KAAK,SACL,EACC,MAAM,OACP,GACA;IACC,SAAS,KAAK,OAAO,WAAW;IAChC,QAAQ;IACR,GAAG;GACJ,CACD,EAAA,CAGgD;GAC/C,UAAU,CAAC;EACZ;CACD;AACD;;;AClEA,IAAa,6BAAb,MAAmE;CAWlE,YACC,SACA,UACA,QACC;wBAdO,wBAAuB,IAAA;wBACvB,+BAA8B,MAAA;wBAE9B,iBAAkF,CAAC,CAAA;wBAEnF,WAAA,KAAA,CAAA;wBACA,YAAA,KAAA,CAAA;wBAEQ,UAAA,KAAA,CAAA;EAOhB,KAAK,UAAU;EACf,KAAK,WAAW;EAChB,KAAK,SAAS;CACf;CAEA,IAAI,WAAmB;EACtB,OAAO,KAAK,OAAO;CACpB;CAEA,QAAgB,EACf,gBACA,OACA,YACA,iBACA,aACA,MACA,kBACA,iBACA,QACgD;EAChD,MAAM,OAAO,gBAAgB,QAAQ;EAErC,MAAM,WAA8B,CAAC;EAErC,IAAI,oBAAoB,MACvB,SAAS,KAAK;GAAE,SAAS;GAAoB,MAAM;EAAc,CAAC;EAGnE,IAAI,mBAAmB,MACtB,SAAS,KAAK;GAAE,SAAS;GAAmB,MAAM;EAAc,CAAC;EAGlE,MAAM,WAAW;GAChB,YAAY;GACZ,OAAO,KAAK;GACZ,aAAa;GACb,aAAa,KAAK,SAAS;GAC3B;GACA,OAAO;EACR;EAEA,QAAQ,MAAR;GACC,KAAK,QACJ,OAAO;IACN,MAAM;KACL,GAAG;KACH,iBAAiB,KAAA;KAGjB,GAAG,0BAA0B,OAAO,UAAU;IAC/C;IACA;GACD;GAGD,KAAK,QAAQ;IAOZ,MAAM,OAAO,gBAAgB,SAAS,SAAS,iBAAiB,KAAA;IAChE,OAAO;KACN,MAAM;MACL,GAAG;MACH,iBAAiB;OAChB,MAAM;OACN,aAAa,uBACZ,MAAM,QACN,MAAM,MACN,MAAM,WACP;MACD;MACA,OAAO,KAAA;MACP,aAAa,KAAA;KACd;KACA;IACD;GACD;GAEA,SAEC,MAAM,IAAI,MAAM,qBAAqBC,MAAiB;EAExD;CACD;;;;;;;;;;;;;;;;;;;CAoBA,eACC,MACA,UACA,SACC;EAID,MAAM,aAAa,SAAS,kBAAkB;EAC9C,MAAM,UACL,eAAe,QAAQ,OAAO,eAAe,YAAY,CAAC,MAAM,QAAQ,UAAU,IAC9E,aACD,CAAC;EACL,MAAM,kBACL,sBAAsB,UACnB,QAAQ,mBACR,KAAK,SAAS;EAClB,MAAM,qBACL,0BAA0B,UACvB,QAAQ,uBACR,KAAK,SAAS;EAElB,OAAO;GACN,YAAY,KAAK;GACjB,UAAU,KAAK,OAAO,YAAY,4BAA4B,QAAQ,IAAI;GAC1E,aAAa,KAAK;GAClB,OAAO,KAAK;GACZ,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;GAC5D,OAAO,KAAK;GACZ,GAAI,KAAK,kBAAkB,EAAE,iBAAiB,KAAK,gBAAgB,IAAI,CAAC;GACxE,GAAI,SAAS,SAAS,EAAE,QAAQ,KAAK,IAAI,CAAC;GAC1C,GAAI,oBAAoB,KAAA,IAAY,EAAE,kBAAkB,gBAAgB,IAAI,CAAC;GAC7E,GAAI,uBAAuB,KAAA,IACxB,EAAE,sBAAsB,mBAAmB,IAC3C,CAAC;EACL;CACD;;;;;;;;CASA,gBAAwB;EACvB,MAAM,EACL,SACA,YAAY,aACZ,iBACA,cACA,kBAAkB,kBAClB,sBAAsB,qBACtB,GAAG,uBACA,KAAK;EAET,MAAM,gBAAgB;GACrB,GAAI,gBAAgB,OAAO,iBAAiB,WACxC,eACD,CAAC;GACJ,GAAI,kBAAkB,EAAE,sBAAsB,gBAAgB,IAAI,CAAC;EACpE;EAEA,OAAO;GACN,SAAS,KAAK,OAAO,WAAW;GAChC,GAAI,OAAO,KAAK,aAAa,CAAC,CAAC,SAAS,IAAI,EAAE,cAAc,cAAc,IAAI,CAAC;GAC/E,GAAG;EACJ;CACD;;;;;;;;;;;CAYA,eACC,cACA,MACA,UACC;EACD,MAAM,UAAU,aAAa;EAG7B,MAAM,mBACL,UAAU,EAAE,EAAE,SAAS,qBAAqB,UAAU,EAAE,EAAE,SAAS;EAEpE,MAAM,YAAY,iBAAiB,YAAY;EAC/C,MAAM,WACL,UAAU,WAAW,IAClB,yBAAyB,cAAc;GACvC,OAAO,KAAK;GACZ,YAAY,KAAK;EAClB,CAAC,IACA;EAEJ,IAAI,UACH,SAAS,KAAK;GACb,MAAM;GACN,SAAS,aAAa,SAAS,OAAO,uGAAuG,KAAK,QAAQ;EAC3J,CAAC;EAGF,OAAO;GACN;GAEA,MAAM,WAAW,KAAM,YAAY,YAAY,KAAK;GACpD,WAAW,YAAY;GAIvB,cAAc,WACV;IAAE,SAAS;IAAc,KAAK;GAAO,IACtC,yBAAyB,YAAY;EACzC;CACD;CAEA,MAAM,WACL,SAC8D;EAC9D,MAAM,EAAE,MAAM,aAAa,KAAK,QAAQ,OAAO;EAC/C,MAAM,EAAE,aAAa,+BAA+B,QAAQ,MAAM;EAElE,MAAM,SAAS,KAAK,eAAe,MAAM,UAAU,EAClD,iBAAiB,QAAQ,gBAC1B,CAAC;EACD,MAAM,aAAa,KAAK,cAAc;EAEtC,MAAM,SAAS,MAAM,KAAK,OAAO,QAAQ,IACxC,KAAK,OACL,QACA;GACC,GAAG;GACH,QAAQ,QAAQ;EACjB,CACD;EAEA,IAAI,kBAAkB,gBACrB,MAAM,IAAI,MACT,qGACD;EAGD,MAAM,eAAe;EACrB,MAAM,EAAE,kBAAkB,MAAM,WAAW,iBAAiB,KAAK,eAChE,cACA,MACA,QACD;EAEA,OAAO;GACN;GACA,SAAS;IACR,GAAI,mBACD,CAAC;KAAE,MAAM;KAAsB,MAAM;IAAiB,CAAC,IACvD,CAAC;IACJ;KAAE,MAAM;KAAiB;IAAK;IAC9B,GAAG;GACJ;GACA,OAAO,kBAAkB,MAAiC;GAC1D;EACD;CACD;CAEA,MAAM,SACL,SAC4D;EAC5D,MAAM,EAAE,MAAM,aAAa,KAAK,QAAQ,OAAO;EAC/C,MAAM,EAAE,aAAa,+BAA+B,QAAQ,MAAM;EAElE,MAAM,SAAS,KAAK,eAAe,MAAM,UAAU;GAClD,QAAQ;GACR,iBAAiB,QAAQ;EAC1B,CAAC;EACD,MAAM,aAAa,KAAK,cAAc;EAEtC,MAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,IAC1C,KAAK,OACL,QACA;GACC,GAAG;GACH,QAAQ,QAAQ;EACjB,CACD;EAGA,IAAI,oBAAoB,gBACvB,OAAO,EACN,QAAQ,mBACP,gBAAgB,UAAU;GACzB,OAAO,KAAK;GACZ,YAAY,KAAK;EAClB,CAAC,GACD,QACD,EACD;EAKD,MAAM,eAAe;EACrB,MAAM,EAAE,kBAAkB,MAAM,WAAW,iBAAiB,KAAK,eAChE,cACA,MACA,QACD;EAEA,IAAI,SAAwB;EAC5B,IAAI,cAA6B;EAEjC,OAAO,EACN,QAAQ,IAAI,eAA0C,EACrD,MAAM,YAAY;GACjB,WAAW,QAAQ;IAClB,MAAM;IACI;GACX,CAAC;GAED,IAAI,kBAAkB;IACrB,cAAc,WAAW;IACzB,WAAW,QAAQ;KAAE,MAAM;KAAmB,IAAI;IAAY,CAAC;IAC/D,WAAW,QAAQ;KAClB,MAAM;KACN,IAAI;KACJ,OAAO;IACR,CAAC;IACD,WAAW,QAAQ;KAAE,MAAM;KAAiB,IAAI;IAAY,CAAC;GAC9D;GAEA,IAAI,MAAM;IACT,SAAS,WAAW;IACpB,WAAW,QAAQ;KAAE,MAAM;KAAc,IAAI;IAAO,CAAC;IACrD,WAAW,QAAQ;KAAE,MAAM;KAAc,IAAI;KAAQ,OAAO;IAAK,CAAC;IAClE,WAAW,QAAQ;KAAE,MAAM;KAAY,IAAI;IAAO,CAAC;GACpD;GAEA,KAAK,MAAM,YAAY,WACtB,WAAW,QAAQ,QAAQ;GAG5B,WAAW,QAAQ;IAClB,MAAM;IACN;IACA,OAAO,kBAAkB,QAAmC;GAC7D,CAAC;GACD,WAAW,MAAM;EAClB,EACD,CAAC,EACF;CACD;AACD;;;ACvYA,IAAa,sBAAb,MAAyD;CAGxD,IAAI,mBAA2B;EAC9B,OAAO,KAAK,SAAS,oBAAoB;CAC1C;CAEA,IAAI,WAAmB;EACtB,OAAO,KAAK,OAAO;CACpB;CAEA,YACC,SACA,UACA,QACC;EAHQ,KAAA,UAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;wBAbD,wBAAuB,IAAA;CAc7B;CAEH,MAAM,WAAW,EAChB,QACA,GACA,MACA,aACA,MACA,eAGC;EACD,MAAM,EAAE,OAAO,WAAW,4BAA4B,IAAI;EAE1D,MAAM,WAAmC,CAAC;EAE1C,IAAI,eAAe,MAClB,SAAS,KAAK;GACb,SAAS;GACT,SAAS;GACT,MAAM;EACP,CAAC;EAGF,MAAM,gBAAgB,YAAY;GAejC,OAAOC,eAAa,MAdE,KAAK,OAAO,QAAQ,IACzC,KAAK,SACL;IACC;IACA,QAAQ,UAAU;IAClB;IACA;GACD,GACA;IACC,SAAS,KAAK,OAAO;IACrB,QAAQ;GACT,CACD,CAE0B;EAC3B;EAMA,OAAO;GACN,QAAA,MALkC,QAAQ,IAC1C,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,cAAc,CAAC,CAChD;GAIC,UAAU;IACT,SAAS,CAAC;IACV,SAAS,KAAK;IACd,2BAAW,IAAI,KAAK;GACrB;GACA;EACD;CACD;AACD;AAEA,SAAS,4BAA4B,MAA0B;CAC9D,MAAM,CAAC,OAAO,UAAU,MAAM,MAAM,GAAG,KAAK,CAAC,KAAA,GAAW,KAAA,CAAS;CAEjE,OAAO;EACN,QAAQ,aAAa,MAAM;EAC3B,OAAO,aAAa,KAAK;CAC1B;AACD;AAEA,SAAS,aAAa,OAAgB;CACrC,IAAI,UAAU,MAAM,CAAC,OAAO,OAAO,KAAA;CACnC,MAAM,SAAS,OAAO,KAAK;CAC3B,OAAO,OAAO,UAAU,MAAM,IAAI,SAAS,KAAA;AAC5C;;;;;;;;;AAUA,eAAeA,eAAa,QAAsC;CACjE,IAAI,kBAAkB,YACrB,OAAO;CAER,IAAI,kBAAkB,aACrB,OAAO,IAAI,WAAW,MAAM;CAE7B,IAAI,kBAAkB,gBAAgB;EACrC,MAAM,SAAU,OAAsC,UAAU;EAChE,MAAM,SAAuB,CAAC;EAC9B,IAAI,cAAc;EAClB,OAAO,MAAM;GACZ,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GACV,OAAO,KAAK,KAAK;GACjB,eAAe,MAAM;EACtB;EACA,MAAM,SAAS,IAAI,WAAW,WAAW;EACzC,IAAI,SAAS;EACb,KAAK,MAAM,SAAS,QAAQ;GAC3B,OAAO,IAAI,OAAO,MAAM;GACxB,UAAU,MAAM;EACjB;EACA,OAAO;CACR;CAEA,IAAI,kBAAkB,UACrB,OAAO,IAAI,WAAW,MAAM,OAAO,YAAY,CAAC;CAGjD,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM;EAClD,MAAM,MAAM;EAEZ,IAAI,OAAO,IAAI,UAAU,UACxB,OAAO,WAAW,KAAK,KAAK,IAAI,KAAK,IAAI,MAAM,EAAE,WAAW,CAAC,CAAC;EAG/D,IAAI,IAAI,gBAAgB,YACvB,OAAO,IAAI;EAGZ,IAAI,IAAI,gBAAgB,aACvB,OAAO,IAAI,WAAW,IAAI,IAAI;EAG/B,IAAI,OAAO,IAAI,gBAAgB,YAC9B,OAAO,IAAI,WAAW,MAAO,IAA4B,YAAY,CAAC;CAExE;CACA,MAAM,IAAI,MACT,gDAAgD,OAAO,UAAU,SAAS,KAAK,MAAM,EAAE,cACtF,OAAO,WAAW,YAAY,WAAW,OACtC,KAAK,UAAU,OAAO,KAAK,MAAM,CAAC,IAClC,OAEL;AACD;;;;;;;;;;ACtIA,IAAa,8BAAb,MAAyE;CAGxE,IAAI,WAAmB;EACtB,OAAO,KAAK,OAAO;CACpB;CAEA,YACC,SACA,UACA,QACC;EAHQ,KAAA,UAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;wBATD,wBAAuB,IAAA;CAU7B;CAEH,MAAM,WACL,SACmE;EACnE,MAAM,EAAE,OAAO,WAAW,gBAAgB;EAE1C,MAAM,WAAmC,CAAC;EAI1C,MAAM,aACL,OAAO,UAAU,WACd,WAAW,KAAK,KAAK,KAAK,IAAI,MAAM,EAAE,WAAW,CAAC,CAAC,IACnD;EAEJ,MAAM,UAAU,KAAK,YAAY;EAEjC,IAAI;EAEJ,IAAI,SACH,YAAY,MAAM,KAAK,SAAS,YAAY,WAAW,WAAW;OAElE,YAAY,MAAM,KAAK,WAAW,YAAY,WAAW;EAG1D,MAAM,SAAS;EAGf,IAAI,SACH,OAAO,KAAK,uBAAuB,QAAQ,QAAQ;EAEpD,OAAO,KAAK,yBAAyB,QAAQ,QAAQ;CACtD;CAMA,MAAc,WAAW,YAAwB,aAA6C;EAS7F,MAAM,SAAkC,EAAE,OANzB,KAAK,YAER,sCACV,mBAAmB,UAAU,IAC7B,MAAM,KAAK,UAAU,EAEuB;EAEhD,IAAI,KAAK,SAAS,UACjB,OAAO,WAAW,KAAK,SAAS;EAEjC,IAAI,KAAK,SAAS,QACjB,OAAO,iBAAiB,KAAK,SAAS;EAGvC,OAAO,KAAK,OAAO,QAAQ,IAC1B,KAAK,SACL,QACA;GAAE,SAAS,KAAK,OAAO;GAAS,QAAQ;EAAY,CACrD;CACD;CAEA,yBACC,KACA,UAC0D;EAC1D,MAAM,OAAQ,IAAI,QAAmB;EAGrC,MAAM,WAA4E,CAAC;EAGnF,IAAI,IAAI,YAAY,MAAM,QAAQ,IAAI,QAAQ,GAC7C,KAAK,MAAM,OAAO,IAAI,UACrB,SAAS,KAAK;GACb,MAAQ,IAAgC,QAAmB;GAC3D,aAAe,IAAgC,SAAoB;GACnE,WAAa,IAAgC,OAAkB;EAChE,CAAC;OAIE,IAAI,IAAI,SAAS,MAAM,QAAQ,IAAI,KAAK,GAC5C,KAAK,MAAM,KAAK,IAAI,OACnB,SAAS,KAAK;GACb,MAAQ,EAA8B,QAAmB;GACzD,aAAe,EAA8B,SAAoB;GACjE,WAAa,EAA8B,OAAkB;EAC9D,CAAC;EAKH,MAAM,OAAO,IAAI;EAEjB,OAAO;GACN;GACA;GACA,UAAW,MAAM,YAAuB,KAAA;GACxC,mBAAoB,MAAM,YAAuB,KAAA;GACjD;GACA,UAAU;IACT,2BAAW,IAAI,KAAK;IACpB,SAAS,KAAK;IACd,SAAS,CAAC;GACX;EACD;CACD;CAMA,MAAc,SACb,YACA,WACA,aACmB;EACnB,IAAI,KAAK,OAAO,WAEf,OAAO,KAAK,OAAO,QAAQ,IAC1B,KAAK,SACL,EACC,OAAO;GAAE,MAAM,mBAAmB,UAAU;GAAG,aAAa;EAAU,EACvE,GACA;GAAE,SAAS,KAAK,OAAO;GAAS,QAAQ;EAAY,CACrD;EAMD,IAAI,CAAC,KAAK,OAAO,aAChB,MAAM,IAAI,MACT,wIAED;EAED,OAAO,gBACN,KAAK,OAAO,aACZ,KAAK,SACL,YACA,WACA,WACD;CACD;CAEA,uBACC,KACA,UAC0D;EAY1D,MAAM,OAVU,IAAI,SACM,SAAA,GASH,EAAE,EAAE,eAAe;EAE1C,MAAM,OAAO,KAAK,cAAc;EAChC,MAAM,WAA4E,CAAC;EAEnF,IAAI,KAAK,SAAS,MAAM,QAAQ,IAAI,KAAK,GACxC,KAAK,MAAM,KAAK,IAAI,OACnB,SAAS,KAAK;GACb,MAAM,EAAE,QAAQ;GAChB,aAAa,EAAE,SAAS;GACxB,WAAW,EAAE,OAAO;EACrB,CAAC;EAIH,OAAO;GACN;GACA;GACA,UAAU,KAAA;GACV,mBAAmB,KAAA;GACnB;GACA,UAAU;IACT,2BAAW,IAAI,KAAK;IACpB,SAAS,KAAK;IACd,SAAS,CAAC;GACX;EACD;CACD;AACD;AAMA,SAAS,mBAAmB,OAA2B;CACtD,IAAI,SAAS;CACb,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KACjC,UAAU,OAAO,aAAa,MAAM,EAAG;CAExC,OAAO,KAAK,MAAM;AACnB;;;;;;;;;ACnOA,IAAa,uBAAb,MAA2D;CAG1D,IAAI,WAAmB;EACtB,OAAO,KAAK,OAAO;CACpB;CAEA,YACC,SACA,UACA,QACC;EAHQ,KAAA,UAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;wBATD,wBAAuB,IAAA;CAU7B;CAEH,MAAM,WACL,SAC4D;EAC5D,MAAM,EAAE,MAAM,OAAO,OAAO,gBAAgB;EAE5C,MAAM,WAAmC,CAAC;EAE1C,IAAI,QAAQ,cACX,SAAS,KAAK;GACb,SAAS;GACT,SAAS;GACT,MAAM;EACP,CAAC;EAGF,IAAI,QAAQ,cACX,SAAS,KAAK;GACb,SACC;GACD,SAAS;GACT,MAAM;EACP,CAAC;EAIF,MAAM,SAAkC,EAAE,KAAK;EAC/C,IAAI,OAAO,OAAO,QAAQ;EAC1B,IAAI,SAAS,MAAM,OAAO,QAAQ;EAqBlC,OAAO;GACN,OAAA,MAHmB,aAAa,MAjBZ,KAAK,OAAO,QAAQ,IACxC,KAAK,SACL,QACA;IACC,SAAS,KAAK,OAAO;IACrB,QAAQ;IAKR,mBAAmB;GACpB,CACD,CAKuC;GAItC;GACA,UAAU;IACT,2BAAW,IAAI,KAAK;IACpB,SAAS,KAAK;IACd,SAAS,CAAC;GACX;EACD;CACD;AACD;;;;;;;;;AAcA,eAAe,aAAa,QAAsC;CAEjE,IAAI,kBAAkB,UACrB,OAAO,IAAI,WAAW,MAAM,OAAO,YAAY,CAAC;CAEjD,IAAI,kBAAkB,YACrB,OAAO;CAER,IAAI,kBAAkB,aACrB,OAAO,IAAI,WAAW,MAAM;CAE7B,IAAI,kBAAkB,gBAAgB;EACrC,MAAM,SAAU,OAAsC,UAAU;EAChE,MAAM,SAAuB,CAAC;EAC9B,IAAI,cAAc;EAClB,OAAO,MAAM;GACZ,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;GAC1C,IAAI,MAAM;GACV,OAAO,KAAK,KAAK;GACjB,eAAe,MAAM;EACtB;EACA,MAAM,SAAS,IAAI,WAAW,WAAW;EACzC,IAAI,SAAS;EACb,KAAK,MAAM,SAAS,QAAQ;GAC3B,OAAO,IAAI,OAAO,MAAM;GACxB,UAAU,MAAM;EACjB;EACA,OAAO;CACR;CAEA,IAAI,OAAO,WAAW,YAAY,WAAW,MAAM;EAClD,MAAM,MAAM;EACZ,IAAI,OAAO,IAAI,UAAU,UACxB,OAAO,WAAW,KAAK,KAAK,IAAI,KAAK,IAAI,MAAM,EAAE,WAAW,CAAC,CAAC;CAEhE;CACA,MAAM,IAAI,MACT,8CAA8C,OAAO,UAAU,SAAS,KAAK,MAAM,GACpF;AACD;;;;;;;;;;;;ACzHA,IAAa,0BAAb,MAAiE;CAGhE,IAAI,WAAmB;EACtB,OAAO,KAAK,OAAO;CACpB;CAEA,YACC,SACA,UACA,QACC;EAHQ,KAAA,UAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;wBATD,wBAAuB,IAAA;CAU7B;CAEH,MAAM,SACL,SAC6D;EAC7D,MAAM,EAAE,WAAW,OAAO,MAAM,gBAAgB;EAEhD,MAAM,WAAmC,CAAC;EAM1C,MAAM,SAAkC;GACvC;GACA,UALgB,oBAAoB,WAAW,QAKxC;EACR;EACA,IAAI,QAAQ,MACX,OAAO,QAAQ;EAmBhB,OAAO;GACN,WAVgB,MAPK,KAAK,OAAO,QAAQ,IACzC,KAAK,SACL,QACA;IAAE,SAAS,KAAK,OAAO;IAAS,QAAQ;GAAY,CACrD,EAAA,CAGwB,YAEK,CAAC,EAAA,CAC5B,KAAK,UAAU;IACf,OAAO,KAAK,MAAM;IAClB,gBAAgB,KAAK,SAAS;GAC/B,EAAE,CAAC,CACF,MAAM,GAAG,MAAM,EAAE,iBAAiB,EAAE,cAG/B;GACN;GACA,UAAU;IACT,2BAAW,IAAI,KAAK;IACpB,SAAS,KAAK;IACd,SAAS,CAAC;GACX;EACD;CACD;AACD;;;;;;;;AAaA,SAAS,oBACR,WACA,UAC0B;CAC1B,IAAI,UAAU,SAAS,QACtB,OAAO,UAAU,OAAO,KAAK,UAAU,EAAE,KAAK,EAAE;CAIjD,SAAS,KAAK;EACb,SAAS;EACT,MAAM;CACP,CAAC;CAED,OAAO,UAAU,OAAO,KAAK,SAAS,EAAE,MAAM,KAAK,UAAU,GAAG,EAAE,EAAE;AACrE;;;;;;;ACnGA,IAAa,2BAAb,cAA8C,0BAA0B,CAAC;;;;;;;;;;;;ACsBzE,SAAgB,0BAA0B,MAAsC;CAC/E,IAAI,KAAK,WAAW,GACnB,MAAM,IAAI,MAAM,4DAA4D;CAE7E,MAAM,UAAU,KAAK,EAAE,CAAC;CAExB,eAAe,QAAW,KAA6D;EACtF,MAAM,WAA8B,CAAC;EACrC,KAAK,MAAM,OAAO,MACjB,IAAI;GACH,MAAM,SAAS,MAAM,IAAI,IAAI,KAAK;GAClC,SAAS,KAAK;IAAE,OAAO,IAAI;IAAM,WAAW,IAAI;IAAW,IAAI;GAAK,CAAC;GACrE,OAAO;EACR,SAAS,GAAG;GACX,MAAM,MAAM,sBAAsB,YAAY,CAAC;GAC/C,SAAS,KAAK;IACb,OAAO,IAAI;IACX,WAAW,IAAI;IACf,IAAI;IACJ,QAAQ,IAAI;IACZ,OAAO;GACR,CAAC;EACF;EAED,MAAM,IAAI,uBAAuB,QAAQ;CAC1C;CAEA,OAAO;EACN,sBAAsB;EACtB,UAAU,QAAQ;EAClB,SAAS,QAAQ;EACjB,eAAe,QAAQ;EACvB,WACC,SAC6C;GAC7C,OAAO,SAAS,MAAM,EAAE,WAAW,OAAO,CAAC;EAC5C;EACA,SAAS,SAA+E;GACvF,OAAO,SAAS,MAAM,EAAE,SAAS,OAAO,CAAC;EAC1C;CACD;AACD;;;ACHA,SAAS,OAAO,GAAe,GAAwC;CACtE,MAAM,MAAM,IAAI,WAAW,IAAI,YAAY,EAAE,SAAS,EAAE,MAAM,CAAC;CAC/D,IAAI,IAAI,GAAG,CAAC;CACZ,IAAI,IAAI,GAAG,EAAE,MAAM;CACnB,OAAO;AACR;;AAGA,SAAS,kBAAkB,KAAyB;CACnD,KAAK,IAAI,IAAI,IAAI,SAAS,GAAG,KAAK,GAAG,KACpC,IAAI,IAAI,OAAO,MAAQ,IAAI,IAAI,OAAO,IAAM,OAAO,IAAI;CAExD,OAAO;AACR;;AAGA,SAAS,YAAY,KAAyB;CAC7C,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,QAAQ,KACnC,IAAI,IAAI,OAAO,MAAQ,IAAI,IAAI,OAAO,IAAM;EAC3C;EACA;CACD;CAED,OAAO;AACR;AAEA,SAAS,UAAU,SAAiB,OAAe,MAAsB;CACxE,OAAO,kDAAkD,QAAQ,OAAO,MAAM,eAAe;AAC9F;AAEA,SAAgB,sBAAsB,SAA6D;CAClG,MAAM,EAAE,SAAS,SAAS,UAAU;CACpC,MAAM,gBAAgB,QAAQ,iBAAiB;CAC/C,MAAM,YAAY,QAAQ,mBAAmB;CAE7C,IAAI,gBAAgB,QAAQ,aAAa;CACzC,IAAI,UAAmC,IAAI,2BAAW,IAAI,YAAY,CAAC,CAAC;CACxE,IAAI,aAAa;CAIjB,eAAe,YACd,YAC6C;EAC7C,IAAI;EACJ,IAAI;GACH,MAAM,MAAO,QAAwB,MAAM,UAAU,SAAS,OAAO,aAAa,GAAG,EACpF,QAAQ,MACT,CAAC;EACF,SAAS,UAAU;GAClB,WAAW,MACV,IAAI,qBACH,YACA,iCAAiC,cAAc,IAC/C,QACD,CACD;GACA,OAAO;EACR;EAEA,IAAI,IAAI,WAAW,KAAK;GACvB,IAAI,cAAc,kBAAkB;IACnC,WAAW,MAAM;IACjB,OAAO;GACR;GACA,WAAW,MACV,IAAI,qBACH,kBACA,wCAAwC,cAAc,wFAEvD,CACD;GACA,OAAO;EACR;EACA,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM;GACzB,WAAW,MACV,IAAI,qBACH,YACA,kBAAkB,IAAI,OAAO,aAAa,cAAc,EACzD,CACD;GACA,OAAO;EACR;EACA,OAAO,IAAI;CACZ;CAEA,OAAO,IAAI,eAA2B,EACrC,MAAM,MAAM,YAAY;EAIvB,IAAI;EACJ,IAAI,QAAQ,SACX,UAAU,QAAQ;OACZ;GACN,MAAM,OAAO,MAAM,YAAY,UAAU;GACzC,IAAI,CAAC,MAAM;GACX,UAAU;EACX;EAEA,SAAS;GACR,MAAM,SAAS,QAAQ,UAAU;GACjC,IAAI;IACH,SAAS;KACR,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;KAC1C,IAAI,MAAM;MACT,IAAI,QAAQ,SAAS,GAAG;OACvB,WAAW,QAAQ,OAAO;OAC1B,UAAU,IAAI,2BAAW,IAAI,YAAY,CAAC,CAAC;MAC5C;MACA,WAAW,MAAM;MACjB;KACD;KACA,IAAI,CAAC,SAAS,MAAM,WAAW,GAAG;KAElC,UAAU,OAAO,SAAS,KAAK;KAC/B,MAAM,WAAW,kBAAkB,OAAO;KAC1C,IAAI,WAAW,GAAG;MACjB,MAAM,WAAW,QAAQ,MAAM,GAAG,QAAQ;MAC1C,WAAW,QAAQ,QAAQ;MAC3B,iBAAiB,YAAY,QAAQ;MACrC,QAAQ,aAAa,aAAa;MAClC,UAAU,QAAQ,MAAM,QAAQ;KACjC;IACD;GACD,SAAS,KAAK;IACb,IAAI;KACH,OAAO,YAAY;IACpB,QAAQ,CAER;IAEA,IAAI,cAAc,eAAe;KAChC,WAAW,MACV,IAAI,qBACH,kBACA,YAAY,cAAc,+BAA+B,cAAc,IACvE,GACD,CACD;KACA;IACD;IAGA,UAAU,IAAI,2BAAW,IAAI,YAAY,CAAC,CAAC;IAC3C;IACA,QAAQ,cAAc,eAAe,UAAU;IAE/C,MAAM,OAAO,MAAM,YAAY,UAAU;IACzC,IAAI,CAAC,MAAM;IACX,UAAU;GACX;EACD;CACD,EACD,CAAC;AACF;;;;;;;;AChJA,SAAgB,UAAU,MAA0B;CACnD,MAAM,QAAQ,KAAK,QAAQ,GAAG;CAC9B,IAAI,UAAU,IACb,MAAM,IAAI,qBACT,UACA,eAAe,KAAK,uEACrB;CAED,MAAM,cAAc,KAAK,MAAM,GAAG,KAAK;CACvC,MAAM,UAAU,KAAK,MAAM,QAAQ,CAAC;CACpC,IAAI,CAAC,eAAe,CAAC,SACpB,MAAM,IAAI,qBACT,UACA,eAAe,KAAK,gEACrB;CAED,OAAO;EAAE;EAAa;CAAQ;AAC/B;;;;;AAMA,SAAgB,gBAAgB,MAAc,QAAyC;CACtF,MAAM,OAAO,mBAAmB,OAAO,WAAW;CAClD,IAAI,CAAC,MACJ,MAAM,IAAI,qBACT,UACA,6BAA6B,OAAO,YAAY,gBAAgB,KAAK,4HAGtE;CAED,IAAI,CAAC,KAAK,YACT,MAAM,IAAI,qBACT,UACA,aAAa,OAAO,YAAY,oIAEjC;CAED,OAAO;AACR;;;;;;;AAmHA,SAAgB,gBACf,MACA,sBACA,aAAa,MACb,mBAAmB,MACP;CACZ,MAAM,WAAqB,CAAC;CAC5B,MAAM,sBAAsB,KAAK,UAAU,SAAS;CACpD,MAAM,eAAe,KAAK,aAAa,KAAA,KAAa,KAAK,cAAc;CACvE,MAAM,cAAc,uBAAuB;CAC3C,MAAM,UAAU,sBAAsB,6BAA2B;CAKjE,IAAI,cAAc,CAAC,qBAAqB,KAAK,cAAc,aAAa,cAEvE,MAAM,IAAI,qBACT,UACA,GAHY,KAAK,cAAc,YAAY,0BAAwB,QAG3D,8OAGT;CAKD,IAAI,CAAC,YAAY;EAChB,IAAI,KAAK,cAAc,OACtB,MAAM,IAAI,qBACT,UACA,uJAED;EAED,IAAI,sBACH,MAAM,IAAI,qBACT,UACA,sIAED;EAED,OAAO;GAAE,WAAW;GAAW,eAAe;GAAO;EAAS;CAC/D;CAEA,IAAI,KAAK,cAAc,SAAS,aAC/B,MAAM,IAAI,qBACT,UACA,kCAAkC,QAAQ,+GAE3C;CAED,IAAI,KAAK,cAAc,aAAa,sBACnC,MAAM,IAAI,qBACT,UACA,sFACD;CAGD,IAAI,aAAa;EAChB,IAAI,sBACH,MAAM,IAAI,qBACT,UACA,8BAA8B,QAAQ,2EACX,sBAAsB,yBAAyB,UAAU,6DAErF;EAED,SAAS,KACR,0CAA0C,QAAQ,0HAEnD;EACA,OAAO;GAAE,WAAW;GAAW,eAAe;GAAO;EAAS;CAC/D;CAEA,MAAM,YAAY,KAAK,aAAa;CACpC,OAAO;EACN;EACA,eAAe,cAAc,SAAS,KAAK,WAAW;EACtD;CACD;AACD;AAQA,IAAa,uBAAb,cAA0C,MAAM;CAI/C,YAAY,MAAgC,SAAiB,OAAiB;EAC7E,MAAM,OAAO;wBAJL,QAAA,KAAA,CAAA;wBACS,SAAA,KAAA,CAAA;EAIjB,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,QAAQ;CACd;AACD;AAOA,MAAM,qBAAqB,IAAI,IAAI,CAAC,kBAAkB,MAAM,CAAC;AAa7D,SAAS,OAAO,MAA2C;CAC1D,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,gBAAgB,YAAY,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI;CACpE,IAAI,gBAAgB,aAAa,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,IAAI;CACrE,OAAO;AACR;AAEA,SAAS,gBAAgB,GAAoD;CAC5E,MAAM,MAA8B,CAAC;CACrC,IAAI,CAAC,GAAG,OAAO;CACf,IAAI,aAAa,SAChB,KAAK,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,KAAK;MAC3B,IAAI,MAAM,QAAQ,CAAC,GACzB,KAAK,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,KAAK;MAEjC,OAAO,OAAO,KAAK,CAAC;CAErB,OAAO;AACR;AAEA,SAAS,iBAAiB,SAGxB;CACD,IAAI,CAAC,SACJ,MAAM,IAAI,qBACT,UACA,yIAED;CAED,IAAI,OAAO,YAAY,UAAU,OAAO;EAAE,IAAI;EAAS,SAAS,EAAE,IAAI,QAAQ;CAAE;CAChF,OAAO;EAAE,IAAI,QAAQ;EAAI,SAAS;CAAQ;AAC3C;;;;;;AAwBA,SAAgB,sBAAsB,QAAgD;CACrF,IAAI,CAAC,QAAQ,SACZ,MAAM,IAAI,qBACT,UACA,wEACD;CAED,IAAI,CAAC,OAAO,WAAW,QACtB,MAAM,IAAI,qBACT,UACA,8HAED;CAGD,MAAM,0BAAU,IAAI,IAAgC;CACpD,KAAK,MAAM,KAAK,OAAO,WAAW,QAAQ,IAAI,EAAE,YAAY,CAAC;CAC7D,MAAM,gBAAgB,OAAO,UAAU;CAEvC,MAAM,YACL,MACA,YACsD;EACtD,MAAM,SAAS,UAAU,IAAI;EAC7B,MAAM,OAAO,gBAAgB,MAAM,MAAM;EAEzC,MAAM,uBAAuB,QAAQ,WAAW;EAChD,MAAM,mBAAwC;GAC7C,GAAG;GACH,QAAQ,QAAQ,UAAU;GAC1B,iBAAiB,QAAQ,mBAAmB,OAAO;EACpD;EACA,MAAM,YAAY,gBACjB,kBACA,sBACA,KAAK,YACL,KAAK,gBAAgB,KACtB;EACA,KAAK,MAAM,KAAK,UAAU,UAAU,QAAQ,KAAK,CAAC;EAQlD,MAAM,OACL,UAAU,cAAc,QACpB,KAAK,iBAAiB,WACtB,KAAK;EACV,MAAM,SAAS,QAAQ,IAAI,IAAI;EAC/B,IAAI,CAAC,QACJ,MAAM,IAAI,qBACT,UACA,UAAU,cAAc,QACrB,qBAAqB,OAAO,YAAY,gBAAgB,KAAK,cACzD,KAAK,qCAAqC,KAAK,wDACJ,KAAK,iBACrC,CAAC,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,SAAS,KAC1D,uCAAuC,KAAK,gBAAgB,OAAO,YAAY,mCAC7C,KAAK,kBACxB,CAAC,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,SAAS,iEACM,KAAK,GACzE;EAGD,MAAM,EAAE,IAAI,WAAW,SAAS,mBAAmB,iBAClD,QAAQ,WAAW,OAAO,OAC3B;EAEA,MAAM,YACL,UAAU,cAAc,QACrB,aACA,OAAO,SAGP,GAAG,KAAK,YAAY,GAAG,OAAO,WAC9B,gBACA,kBACA,WACA,OACD,IACC,iBACA,OAAO,SACP,MACA,WACA,gBACA,kBACA,WACA,OACD;EAEH,OAAO;GACN,OAAO,OAAO,OAAO;IACpB,SAAS,OAAO;IAChB,OAAO;IAGP,GAAI,UAAU,cAAc,aAAa,KAAK,UAC3C,EAAE,SAAS,KAAK,QAAQ,IACxB,CAAC;GACL,CAAC;GACD,WAAW,UAAU;EACtB;CACD;CAEA,QAAQ,MAAM,UAAU,CAAC,MAAM;EAK9B,IAAI,QAAQ,UAAU,SAAS,UAAU;GACxC,MAAM,EAAE,UAAU,GAAG,SAAS;GAM9B,OAAO,0BAJM,CADE,MAAM,GAAG,SAAS,MAChB,CAAC,CAAC,KAAK,MAAM;IAC7B,MAAM,EAAE,OAAO,cAAc,SAAS,GAAG,IAAI;IAC7C,OAAO;KAAE,MAAM;KAAG;KAAO;IAAU;GACpC,CACoC,CAAC;EACtC;EACA,OAAO,SAAS,MAAM,OAAO,CAAC,CAAC;CAChC;AACD;AAEA,SAAS,aAAa,MAAgB,WAAsB,SAAoC;CAC/F,IAAI,CAAC,QAAQ,YAAY;CACzB,QAAQ,WAAW;EAClB,WAAW,UAAU;EACrB,eAAe,UAAU;EACzB,UAAU,UAAU;EACpB,QAAQ,KAAK;EACb,OAAO,KAAK,QAAQ,IAAI,eAAe;EACvC,QAAQ,KAAK,QAAQ,IAAI,aAAa;EACtC,aAAa,KAAK,QAAQ,IAAI,qBAAqB;EACnD,OAAO,KAAK,QAAQ,IAAI,eAAe;CACxC,CAAC;AACF;;AAKA,SAAS,cACR,MACA,UAC8B;CAC9B,IAAI,CAAC,QAAQ,CAAC,UAAU,OAAO,KAAA;CAC/B,OAAO;EAAE,GAAG;EAAM,GAAG;CAAS;AAC/B;;AAGA,SAAS,kBAAkB,UAAmC;CAC7D,OAAO,KAAK,UAAU,WAAW,IAAI,MAAO,OAAO,MAAM,WAAW,EAAE,SAAS,IAAI,CAAE;AACtF;AAEA,SAAS,aACR,SACA,MACA,gBACA,MACA,WACA,aAC0B;CAC1B,QAAQ,OAAO,QAA2B,SAA0C;EACnF,MAAM,OAAO,KAAK,MAAM,OAAO,MAAM,IAAI,CAAC;EAE1C,OAAO,KAAK;EAIZ,MAAM,gBAAgC,EAAE,GAAG,eAAe;EAC1D,MAAM,aAAa,cAAc,eAAe,UAAU,KAAK,QAAQ;EACvE,IAAI,YAAY,cAAc,WAAW;EACzC,IAAI,KAAK,eAAe,KAAA,GAAW,cAAc,aAAa,KAAK;EAEnE,MAAM,aAAa;GAClB,SAAS;GACT,mBAAmB;GACnB,GAAI,KAAK,eAAe,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;GAC/D,GAAI,MAAM,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;EAC/C;EAaA,MAAM,OAAO,MAAMC,QAAG,IAAI,MAAM,MAAM,UAAU;EAChD,aAAa,MAAM,WAAW,WAAW;EAIzC,MAAM,QAAQ,KAAK,QAAQ,IAAI,eAAe;EAC9C,IAAI,UAAU,iBAAiB,SAAS,KAAK,MAAM;GAClD,MAAM,YAAY,sBAAsB;IACvC;IACA,SAAS,eAAe;IACxB;IACA,SAAS,KAAK;IACd,iBAAiB,KAAK;IACtB,GAAI,KAAK,aAAa,EAAE,YAAY,KAAK,WAAW,IAAI,CAAC;GAC1D,CAAC;GACD,OAAO,IAAI,SAAS,WAAW;IAAE,QAAQ,KAAK;IAAQ,SAAS,KAAK;GAAQ,CAAC;EAC9E;EACA,OAAO;CACR;AACD;AAEA,SAAS,iBACR,SACA,MACA,WACA,gBACA,MACA,WACA,aAC0B;CAG1B,MAAM,QAAQ,IAAI,IAAI,kBAAkB;CACxC,IAAI,CAAC,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK,aAAa,MAAM,IAAI,EAAE,YAAY,CAAC;CAE3E,QAAQ,OAAO,OAA0B,SAA0C;EAClF,MAAM,SAAS,OAAO,UAAU,WAAW,QAAQ,MAAM,SAAS;EAIlE,MAAM,WAAW,KAAK,oBACnB,KAAK,kBAAkB,MAAM,IAC7B,IAAI,IAAI,MAAM,CAAC,CAAC,SAAS,QAAQ,OAAO,EAAE,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC,UAAU;EAC5E,MAAM,OAAO,KAAK,MAAM,OAAO,MAAM,IAAI,CAAC;EAE1C,MAAM,UAAkC,CAAC;EACzC,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,gBAAgB,MAAM,OAAO,CAAC,GACjE,IAAI,CAAC,MAAM,IAAI,EAAE,YAAY,CAAC,GAAG,QAAQ,KAAK;EAE/C,IAAI,KAAK,cAAc,OAAO,OAAO,SAAS,KAAK,YAAY;EAE/D,IAAI,KAAK,aAAa,KAAA,GAAW,QAAQ,sBAAsB,OAAO,KAAK,QAAQ;EACnF,IAAI,KAAK,WAAW,QAAQ,uBAAuB;EAEnD,MAAM,WAAW,cAAc,eAAe,UAAU,KAAK,QAAQ;EACrE,IAAI,UAAU,QAAQ,qBAAqB,kBAAkB,QAAQ;EACrE,IAAI,KAAK,eAAe,KAAA,GACvB,QAAQ,wBAAwB,OAAO,KAAK,UAAU;EAGvD,MAAM,UAAwB;GAC7B,UAAU,KAAK;GACf;GACA;GACA,OAAO;EACR;EACA,MAAM,UAA0B,CAAC,OAAO;EAExC,IAAI,KAAK,UAAU,SAAS,UAC3B,KAAK,MAAM,MAAM,KAAK,SAAS,QAAQ;GACtC,MAAM,WAAW,UAAU,EAAE;GAC7B,MAAM,SAAS,gBAAgB,IAAI,QAAQ;GAC3C,IAAI,OAAO,sBAAsB,KAAK,mBACrC,MAAM,IAAI,qBACT,UACA,sCAAsC,KAAK,kBAAkB,KACzD,OAAO,kBAAkB,oFAE9B;GAED,QAAQ,KAAK;IAAE,GAAG;IAAS,OAAO;KAAE,GAAG;KAAM,OAAO,SAAS;IAAQ;GAAE,CAAC;EACzE;EAGD,MAAM,KAAM,QAAgE,QAC3E,SACD;EACA,MAAM,aAAsC,CAAC;EAC7C,IAAI,MAAM,QAAQ,WAAW,SAAS,KAAK;EAC3C,MAAM,OAAO,MAAM,GAAG,IAAI,SAAS,UAAU;EAC7C,aAAa,MAAM,WAAW,WAAW;EACzC,OAAO;CACR;AACD;;;;;;;AC/kBA,MAAM,qBAAqB;;;;AAiK3B,SAAgB,gBAAgB,SAAuC;CACtE,IAAI,CAAC,QAAQ,WAAW,EAAE,eAAe,WAAW,YAAY,UAC/D,MAAM,IAAI,MACT,wIAED;CAGD,IAAI;CACJ,MAAM,YAAY,CAAC,CAAC,QAAQ;CAE5B,IAAI,QAAQ,SACX,UAAU,QAAQ;MACZ;EACN,MAAM,EAAE,WAAW,WAAW;EAC9B,UAAU,EACT,KAAK,UAAU;GAAE;GAAW;GAAQ,OAAO,QAAQ;EAAM,CAAC,EAC3D;CACD;CAEA,MAAM,mBAAmB,SAA+B,WAAkC,CAAC,MAC1F,IAAI,2BAA2B,SAAS,UAAU;EACjD;EACA,SAAS,QAAQ;EACjB,UAAU;EACV;CACD,CAAC;CAMF,IAAI;CACJ,MAAM,eAAe,SAAkC;EACtD,IAAI,CAAC,QAAQ,WAAW,QACvB,MAAM,IAAI,MACT,IAAI,KAAK;;;6IAMV;EAED,aAAA,WAAa,sBAAsB;GAClC;GAKA,SAAS,QAAQ,WAAW,EAAE,IAAI,mBAAmB;GACrD,WAAW,QAAQ;GACnB,QAAQ,QAAQ;GAChB,iBAAiB,QAAQ;EAC1B,CAAC;EACD,OAAO;CACR;CAKA,MAAM,iBAAiB,OACtB,OAAO,OAAO,YAAY,CAAC,GAAG,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG;CAKjE,MAAM,aACL,SACA,aACgC;EAChC,IAAI,cAAc,OAAO,GAIxB,OAAO,YAAY,OAAO,CAAC,CAC1B,SACA,QACD;EAED,OAAO,gBAAgB,SAAS,QAA6C;CAC9E;CAEA,MAAM,oBACL,SACA,WAAmC,CAAC,MAEpC,IAAI,oBAAoB,SAAS,UAAU;EAC1C;EACA,SAAS,QAAQ;EACjB,UAAU;CACX,CAAC;CACF,MAAM,wBACL,SACA,WAAuC,CAAC,MAExC,IAAI,wBAAwB,SAAS,UAAU;EAC9C;EACA,SAAS,QAAQ;EACjB,UAAU;CACX,CAAC;CAEF,MAAM,4BACL,SACA,WAA2C,CAAC,MAE5C,IAAI,4BAA4B,SAAS,UAAU;EAClD;EACA,SAAS,QAAQ;EACjB,UAAU;EACV;EACA,aACC,CAAC,aAAa,eAAe,UAC1B;GAAE,WAAW,QAAQ;GAAW,QAAQ,QAAQ;EAAO,IACvD,KAAA;CACL,CAAC;CAEF,MAAM,qBAAqB,SAAuB,WAAoC,CAAC,MACtF,IAAI,qBAAqB,SAAS,UAAU;EAC3C;EACA,SAAS,QAAQ;EACjB,UAAU;CACX,CAAC;CAEF,MAAM,wBACL,SACA,WAAuC,CAAC,MAExC,IAAI,wBAAwB,SAAS,UAAU;EAC9C;EACA,SAAS,QAAQ;EACjB,UAAU;CACX,CAAC;CAEF,MAAM,YACL,SACA,aACI;EACJ,IAAI,IAAI,QACP,MAAM,IAAI,MAAM,qEAAqE;EAEtF,OAAO,UAAU,SAAS,QAAQ;CACnC;CAEA,SAAS,OAAO;CAChB,SAAS,YAAY;CACrB,SAAS,gBAAgB;CACzB,SAAS,qBAAqB;CAC9B,SAAS,QAAQ;CACjB,SAAS,aAAa;CACtB,SAAS,gBAAgB;CACzB,SAAS,qBAAqB;CAC9B,SAAS,SAAS;CAClB,SAAS,cAAc;CACvB,SAAS,YAAY;CACrB,SAAS,iBAAiB;CAE1B,OAAO;AACR;;;;;;;AAwBA,SAAgB,eACf,SAEA,eAAe,iBACI;CACnB,MAAM,UAAU,QAAQ;CAExB,MAAM,mBAAmB,WAAiC,CAAC,MAC1D,IAAI,0BAA0B,4CAA4C,UAAU;EACnF;EACA,UAAU;CACX,CAAC;CAEF,MAAM,YAAY,aAAoC;EACrD,IAAI,IAAI,QACP,MAAM,IAAI,MAAM,oEAAoE;EAErF,OAAO,gBAAgB,QAAQ;CAChC;CAEA,SAAS,OAAO;CAEhB,OAAO;AACR;AAkBA,IAAI,gBAAgB;;;;;AAMpB,SAAgB,cAAc,SAA6C;CAC1E,IAAI,CAAC,eAAe;EACnB,gBAAgB;EAChB,QAAQ,KACP,wKAGD;CACD;CACA,OAAO,eAAe,SAAS,cAAc;AAC9C"}
|