workers-ai-provider 3.1.3 → 3.1.4
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 +23 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +80 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/convert-to-workersai-chat-messages.ts +78 -22
- package/src/utils.ts +1 -1
- package/src/workersai-chat-language-model.ts +17 -21
- package/src/workersai-chat-prompt.ts +5 -1
package/README.md
CHANGED
|
@@ -111,6 +111,29 @@ for await (const chunk of result.textStream) {
|
|
|
111
111
|
}
|
|
112
112
|
```
|
|
113
113
|
|
|
114
|
+
## Vision (Image Inputs)
|
|
115
|
+
|
|
116
|
+
Send images to vision-capable models like Llama 4 Scout and Kimi K2.5:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { generateText } from "ai";
|
|
120
|
+
|
|
121
|
+
const { text } = await generateText({
|
|
122
|
+
model: workersai("@cf/meta/llama-4-scout-17b-16e-instruct"),
|
|
123
|
+
messages: [
|
|
124
|
+
{
|
|
125
|
+
role: "user",
|
|
126
|
+
content: [
|
|
127
|
+
{ type: "text", text: "What's in this image?" },
|
|
128
|
+
{ type: "image", image: imageUint8Array },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Images can be provided as `Uint8Array`, base64 strings, or data URLs. Multiple images per message are supported. Works with both the binding and REST API configurations.
|
|
136
|
+
|
|
114
137
|
## Tool Calling
|
|
115
138
|
|
|
116
139
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -142,6 +142,12 @@ declare class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
142
142
|
private getArgs;
|
|
143
143
|
/**
|
|
144
144
|
* Build the inputs object for `binding.run()`, shared by doGenerate and doStream.
|
|
145
|
+
*
|
|
146
|
+
* Images are embedded inline in messages as OpenAI-compatible content
|
|
147
|
+
* arrays with `image_url` parts. Both the REST API and the binding
|
|
148
|
+
* accept this format at runtime.
|
|
149
|
+
*
|
|
150
|
+
* The binding path additionally normalises null content to empty strings.
|
|
145
151
|
*/
|
|
146
152
|
private buildRunInputs;
|
|
147
153
|
/**
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,43 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
|
|
5
5
|
// src/convert-to-workersai-chat-messages.ts
|
|
6
|
+
function toUint8Array(data) {
|
|
7
|
+
if (data instanceof Uint8Array) {
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
if (typeof data === "string") {
|
|
11
|
+
let base64 = data;
|
|
12
|
+
if (base64.startsWith("data:")) {
|
|
13
|
+
const commaIndex = base64.indexOf(",");
|
|
14
|
+
if (commaIndex >= 0) {
|
|
15
|
+
base64 = base64.slice(commaIndex + 1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const binaryString = atob(base64);
|
|
19
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
20
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
21
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
22
|
+
}
|
|
23
|
+
return bytes;
|
|
24
|
+
}
|
|
25
|
+
if (data instanceof URL) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
"URL image sources are not supported by Workers AI. Provide image data as a Uint8Array or base64 string instead."
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function uint8ArrayToBase64(bytes) {
|
|
33
|
+
let binary = "";
|
|
34
|
+
const chunkSize = 8192;
|
|
35
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
36
|
+
const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));
|
|
37
|
+
binary += String.fromCharCode(...chunk);
|
|
38
|
+
}
|
|
39
|
+
return btoa(binary);
|
|
40
|
+
}
|
|
6
41
|
function convertToWorkersAIChatMessages(prompt) {
|
|
7
42
|
const messages = [];
|
|
8
|
-
const images = [];
|
|
9
43
|
for (const { role, content } of prompt) {
|
|
10
44
|
switch (role) {
|
|
11
45
|
case "system": {
|
|
@@ -14,6 +48,7 @@ function convertToWorkersAIChatMessages(prompt) {
|
|
|
14
48
|
}
|
|
15
49
|
case "user": {
|
|
16
50
|
const textParts = [];
|
|
51
|
+
const imageParts = [];
|
|
17
52
|
for (const part of content) {
|
|
18
53
|
switch (part.type) {
|
|
19
54
|
case "text": {
|
|
@@ -21,21 +56,34 @@ function convertToWorkersAIChatMessages(prompt) {
|
|
|
21
56
|
break;
|
|
22
57
|
}
|
|
23
58
|
case "file": {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
59
|
+
const imageBytes = toUint8Array(part.data);
|
|
60
|
+
if (imageBytes) {
|
|
61
|
+
imageParts.push({
|
|
62
|
+
image: imageBytes,
|
|
63
|
+
mediaType: part.mediaType
|
|
29
64
|
});
|
|
30
65
|
}
|
|
31
66
|
break;
|
|
32
67
|
}
|
|
33
68
|
}
|
|
34
69
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
70
|
+
if (imageParts.length > 0) {
|
|
71
|
+
const contentArray = [];
|
|
72
|
+
if (textParts.length > 0) {
|
|
73
|
+
contentArray.push({ type: "text", text: textParts.join("\n") });
|
|
74
|
+
}
|
|
75
|
+
for (const img of imageParts) {
|
|
76
|
+
const base64 = uint8ArrayToBase64(img.image);
|
|
77
|
+
const mediaType = img.mediaType || "image/png";
|
|
78
|
+
contentArray.push({
|
|
79
|
+
type: "image_url",
|
|
80
|
+
image_url: { url: `data:${mediaType};base64,${base64}` }
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
messages.push({ content: contentArray, role: "user" });
|
|
84
|
+
} else {
|
|
85
|
+
messages.push({ content: textParts.join("\n"), role: "user" });
|
|
86
|
+
}
|
|
39
87
|
break;
|
|
40
88
|
}
|
|
41
89
|
case "assistant": {
|
|
@@ -106,7 +154,7 @@ function convertToWorkersAIChatMessages(prompt) {
|
|
|
106
154
|
}
|
|
107
155
|
}
|
|
108
156
|
}
|
|
109
|
-
return {
|
|
157
|
+
return { messages };
|
|
110
158
|
}
|
|
111
159
|
|
|
112
160
|
// src/map-workersai-usage.ts
|
|
@@ -862,22 +910,21 @@ var WorkersAIChatLanguageModel = class {
|
|
|
862
910
|
}
|
|
863
911
|
/**
|
|
864
912
|
* Build the inputs object for `binding.run()`, shared by doGenerate and doStream.
|
|
913
|
+
*
|
|
914
|
+
* Images are embedded inline in messages as OpenAI-compatible content
|
|
915
|
+
* arrays with `image_url` parts. Both the REST API and the binding
|
|
916
|
+
* accept this format at runtime.
|
|
917
|
+
*
|
|
918
|
+
* The binding path additionally normalises null content to empty strings.
|
|
865
919
|
*/
|
|
866
|
-
buildRunInputs(args, messages,
|
|
867
|
-
if (images.length > 1) {
|
|
868
|
-
throw new Error("Multiple images are not yet supported as input");
|
|
869
|
-
}
|
|
870
|
-
const imagePart = images[0];
|
|
871
|
-
const finalMessages = this.config.isBinding ? normalizeMessagesForBinding(messages) : messages;
|
|
920
|
+
buildRunInputs(args, messages, options) {
|
|
872
921
|
return {
|
|
873
922
|
max_tokens: args.max_tokens,
|
|
874
|
-
messages:
|
|
923
|
+
messages: this.config.isBinding ? normalizeMessagesForBinding(messages) : messages,
|
|
875
924
|
temperature: args.temperature,
|
|
876
925
|
tools: args.tools,
|
|
877
926
|
...args.tool_choice ? { tool_choice: args.tool_choice } : {},
|
|
878
927
|
top_p: args.top_p,
|
|
879
|
-
...imagePart ? { image: Array.from(imagePart.image) } : {},
|
|
880
|
-
// Only include response_format when actually set
|
|
881
928
|
...args.response_format ? { response_format: args.response_format } : {},
|
|
882
929
|
...options?.stream ? { stream: true } : {}
|
|
883
930
|
};
|
|
@@ -905,11 +952,13 @@ var WorkersAIChatLanguageModel = class {
|
|
|
905
952
|
}
|
|
906
953
|
async doGenerate(options) {
|
|
907
954
|
const { args, warnings } = this.getArgs(options);
|
|
908
|
-
const { messages
|
|
909
|
-
const inputs = this.buildRunInputs(args, messages
|
|
955
|
+
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
956
|
+
const inputs = this.buildRunInputs(args, messages);
|
|
910
957
|
const runOptions = this.getRunOptions();
|
|
911
958
|
const output = await this.config.binding.run(
|
|
912
959
|
args.model,
|
|
960
|
+
// Content arrays for vision are valid at runtime but not in the
|
|
961
|
+
// binding's strict TypeScript definitions (which expect string content).
|
|
913
962
|
inputs,
|
|
914
963
|
runOptions
|
|
915
964
|
);
|
|
@@ -937,8 +986,8 @@ var WorkersAIChatLanguageModel = class {
|
|
|
937
986
|
}
|
|
938
987
|
async doStream(options) {
|
|
939
988
|
const { args, warnings } = this.getArgs(options);
|
|
940
|
-
const { messages
|
|
941
|
-
const inputs = this.buildRunInputs(args, messages,
|
|
989
|
+
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
990
|
+
const inputs = this.buildRunInputs(args, messages, { stream: true });
|
|
942
991
|
const runOptions = this.getRunOptions();
|
|
943
992
|
const response = await this.config.binding.run(
|
|
944
993
|
args.model,
|
|
@@ -1031,7 +1080,7 @@ var WorkersAIImageModel = class {
|
|
|
1031
1080
|
seed,
|
|
1032
1081
|
width
|
|
1033
1082
|
});
|
|
1034
|
-
return
|
|
1083
|
+
return toUint8Array2(output);
|
|
1035
1084
|
};
|
|
1036
1085
|
const images = await Promise.all(
|
|
1037
1086
|
Array.from({ length: n }, () => generateImage())
|
|
@@ -1059,7 +1108,7 @@ function parseInteger(value) {
|
|
|
1059
1108
|
const number = Number(value);
|
|
1060
1109
|
return Number.isInteger(number) ? number : void 0;
|
|
1061
1110
|
}
|
|
1062
|
-
async function
|
|
1111
|
+
async function toUint8Array2(output) {
|
|
1063
1112
|
if (output instanceof Uint8Array) {
|
|
1064
1113
|
return output;
|
|
1065
1114
|
}
|
|
@@ -1140,7 +1189,7 @@ var WorkersAITranscriptionModel = class {
|
|
|
1140
1189
|
// ---------------------------------------------------------------------------
|
|
1141
1190
|
async runWhisper(audioBytes, abortSignal) {
|
|
1142
1191
|
const modelStr = this.modelId;
|
|
1143
|
-
const audio = modelStr === "@cf/openai/whisper-large-v3-turbo" ?
|
|
1192
|
+
const audio = modelStr === "@cf/openai/whisper-large-v3-turbo" ? uint8ArrayToBase642(audioBytes) : Array.from(audioBytes);
|
|
1144
1193
|
const inputs = { audio };
|
|
1145
1194
|
if (this.settings.language) {
|
|
1146
1195
|
inputs.language = this.settings.language;
|
|
@@ -1196,7 +1245,7 @@ var WorkersAITranscriptionModel = class {
|
|
|
1196
1245
|
return this.config.binding.run(
|
|
1197
1246
|
this.modelId,
|
|
1198
1247
|
{
|
|
1199
|
-
audio: { body:
|
|
1248
|
+
audio: { body: uint8ArrayToBase642(audioBytes), contentType: mediaType }
|
|
1200
1249
|
},
|
|
1201
1250
|
{ gateway: this.config.gateway, signal: abortSignal }
|
|
1202
1251
|
);
|
|
@@ -1243,7 +1292,7 @@ var WorkersAITranscriptionModel = class {
|
|
|
1243
1292
|
};
|
|
1244
1293
|
}
|
|
1245
1294
|
};
|
|
1246
|
-
function
|
|
1295
|
+
function uint8ArrayToBase642(bytes) {
|
|
1247
1296
|
let binary = "";
|
|
1248
1297
|
for (let i = 0; i < bytes.length; i++) {
|
|
1249
1298
|
binary += String.fromCharCode(bytes[i]);
|
|
@@ -1295,7 +1344,7 @@ var WorkersAISpeechModel = class {
|
|
|
1295
1344
|
returnRawResponse: true
|
|
1296
1345
|
}
|
|
1297
1346
|
);
|
|
1298
|
-
const audio = await
|
|
1347
|
+
const audio = await toUint8Array3(result);
|
|
1299
1348
|
return {
|
|
1300
1349
|
audio,
|
|
1301
1350
|
warnings,
|
|
@@ -1307,7 +1356,7 @@ var WorkersAISpeechModel = class {
|
|
|
1307
1356
|
};
|
|
1308
1357
|
}
|
|
1309
1358
|
};
|
|
1310
|
-
async function
|
|
1359
|
+
async function toUint8Array3(output) {
|
|
1311
1360
|
if (output instanceof Response) {
|
|
1312
1361
|
return new Uint8Array(await output.arrayBuffer());
|
|
1313
1362
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/convert-to-workersai-chat-messages.ts","../src/map-workersai-usage.ts","../src/streaming.ts","../src/map-workersai-finish-reason.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 { LanguageModelV3Prompt, SharedV3ProviderOptions } from \"@ai-sdk/provider\";\nimport type { WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\nexport function convertToWorkersAIChatMessages(prompt: LanguageModelV3Prompt): {\n\tmessages: WorkersAIChatPrompt;\n\timages: {\n\t\tmediaType: string | undefined;\n\t\timage: Uint8Array;\n\t\tproviderOptions: SharedV3ProviderOptions | undefined;\n\t}[];\n} {\n\tconst messages: WorkersAIChatPrompt = [];\n\tconst images: {\n\t\tmediaType: string | undefined;\n\t\timage: Uint8Array;\n\t\tproviderOptions: SharedV3ProviderOptions | undefined;\n\t}[] = [];\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\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\tif (part.data instanceof Uint8Array) {\n\t\t\t\t\t\t\t\timages.push({\n\t\t\t\t\t\t\t\t\timage: part.data,\n\t\t\t\t\t\t\t\t\tmediaType: part.mediaType,\n\t\t\t\t\t\t\t\t\tproviderOptions: part.providerOptions,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Don't push empty strings for image parts\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\tmessages.push({\n\t\t\t\t\tcontent: textParts.join(\"\\n\"),\n\t\t\t\t\trole: \"user\",\n\t\t\t\t});\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\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 passed through to text for the message conversion,\n\t\t\t\t\t\t\t// since Workers AI doesn't have a separate reasoning field in messages\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 \"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\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\tmessages.push({\n\t\t\t\t\t\t\tcontent: JSON.stringify(toolResponse.output),\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 { images, 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 */\nexport function mapWorkersAIUsage(\n\toutput: Record<string, unknown> | AiTextGenerationOutput | AiTextToImageOutput,\n): LanguageModelV3Usage {\n\tconst usage = (\n\t\toutput as {\n\t\t\tusage?: { prompt_tokens?: number; completion_tokens?: number };\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\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: undefined,\n\t\t\tcacheRead: undefined,\n\t\t\tcacheWrite: undefined,\n\t\t},\n\t\traw: { total: promptTokens + completionTokens },\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// All open tool calls are closed with tool-input-end in flush().\n\tconst activeToolCalls = new Map<number, { id: string; toolName: string; args: string }>();\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 (!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\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 (!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\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 all open tool call inputs and emit complete tool-call events\n\t\t\t\tfor (const [, tc] of activeToolCalls) {\n\t\t\t\t\tcontroller.enqueue({ type: \"tool-input-end\", id: tc.id });\n\t\t\t\t\t// Emit the complete tool-call event — the AI SDK expects both\n\t\t\t\t\t// incremental tool-input-* events AND a final tool-call event,\n\t\t\t\t\t// matching how @ai-sdk/openai-compatible works.\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"tool-call\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.toolName,\n\t\t\t\t\t\tinput: tc.args,\n\t\t\t\t\t});\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 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 (skip)\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 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)) continue;\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// First chunk for this tool call — emit tool-input-start\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\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\t// If arguments arrived in the same chunk as the start, emit them\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\t// Subsequent chunks — emit argument deltas\n\t\t\t\tconst active = activeToolCalls.get(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 { 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 { 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 be a string (not 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}\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\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 fetch(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 fetch(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,\n\t\t\tname: tool.name,\n\t\t\tparameters: tool.type === \"function\" && tool.inputSchema,\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: \"any\", 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 'any'\n\t\tcase \"tool\":\n\t\t\treturn {\n\t\t\t\ttool_choice: \"any\",\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({ values }: 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\t...passthroughOptions,\n\t\t\t},\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\tprivate buildRunInputs(\n\t\targs: ReturnType<typeof this.getArgs>[\"args\"],\n\t\tmessages: ReturnType<typeof convertToWorkersAIChatMessages>[\"messages\"],\n\t\timages: ReturnType<typeof convertToWorkersAIChatMessages>[\"images\"],\n\t\toptions?: { stream?: boolean },\n\t) {\n\t\tif (images.length > 1) {\n\t\t\tthrow new Error(\"Multiple images are not yet supported as input\");\n\t\t}\n\n\t\tconst imagePart = images[0];\n\n\t\t// Only normalize messages for the binding path (REST API doesn't need it)\n\t\tconst finalMessages = this.config.isBinding\n\t\t\t? normalizeMessagesForBinding(messages)\n\t\t\t: messages;\n\n\t\treturn {\n\t\t\tmax_tokens: args.max_tokens,\n\t\t\tmessages: finalMessages,\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...(imagePart ? { image: Array.from(imagePart.image) } : {}),\n\t\t\t// Only include response_format when actually set\n\t\t\t...(args.response_format ? { response_format: args.response_format } : {}),\n\t\t\t...(options?.stream ? { stream: true } : {}),\n\t\t};\n\t}\n\n\t/**\n\t * Get passthrough options for binding.run() from settings.\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\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, images } = convertToWorkersAIChatMessages(options.prompt);\n\n\t\tconst inputs = this.buildRunInputs(args, messages, images);\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,\n\t\t\trunOptions,\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, images } = convertToWorkersAIChatMessages(options.prompt);\n\n\t\tconst inputs = this.buildRunInputs(args, messages, images, { stream: true });\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,\n\t\t\trunOptions,\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}: 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(this.modelId as keyof AiModels, {\n\t\t\t\theight,\n\t\t\t\tprompt: prompt ?? \"\",\n\t\t\t\tseed,\n\t\t\t\twidth,\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\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 }),\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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","names":["generateId","generateId","generateId","generateId","toUint8Array"]}
|
|
1
|
+
{"version":3,"sources":["../src/convert-to-workersai-chat-messages.ts","../src/map-workersai-usage.ts","../src/streaming.ts","../src/map-workersai-finish-reason.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 {\n\tLanguageModelV3DataContent,\n\tLanguageModelV3Prompt,\n} 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\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 passed through to text for the message conversion,\n\t\t\t\t\t\t\t// since Workers AI doesn't have a separate reasoning field in messages\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 \"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\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\tmessages.push({\n\t\t\t\t\t\t\tcontent: JSON.stringify(toolResponse.output),\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 */\nexport function mapWorkersAIUsage(\n\toutput: Record<string, unknown> | AiTextGenerationOutput | AiTextToImageOutput,\n): LanguageModelV3Usage {\n\tconst usage = (\n\t\toutput as {\n\t\t\tusage?: { prompt_tokens?: number; completion_tokens?: number };\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\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: undefined,\n\t\t\tcacheRead: undefined,\n\t\t\tcacheWrite: undefined,\n\t\t},\n\t\traw: { total: promptTokens + completionTokens },\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// All open tool calls are closed with tool-input-end in flush().\n\tconst activeToolCalls = new Map<number, { id: string; toolName: string; args: string }>();\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 (!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\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 (!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\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 all open tool call inputs and emit complete tool-call events\n\t\t\t\tfor (const [, tc] of activeToolCalls) {\n\t\t\t\t\tcontroller.enqueue({ type: \"tool-input-end\", id: tc.id });\n\t\t\t\t\t// Emit the complete tool-call event — the AI SDK expects both\n\t\t\t\t\t// incremental tool-input-* events AND a final tool-call event,\n\t\t\t\t\t// matching how @ai-sdk/openai-compatible works.\n\t\t\t\t\tcontroller.enqueue({\n\t\t\t\t\t\ttype: \"tool-call\",\n\t\t\t\t\t\ttoolCallId: tc.id,\n\t\t\t\t\t\ttoolName: tc.toolName,\n\t\t\t\t\t\tinput: tc.args,\n\t\t\t\t\t});\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 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 (skip)\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 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)) continue;\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// First chunk for this tool call — emit tool-input-start\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\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\t// If arguments arrived in the same chunk as the start, emit them\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\t// Subsequent chunks — emit argument deltas\n\t\t\t\tconst active = activeToolCalls.get(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 { 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 { 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}\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\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 fetch(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 fetch(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,\n\t\t\tname: tool.name,\n\t\t\tparameters: tool.type === \"function\" && tool.inputSchema,\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: \"any\", 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 'any'\n\t\tcase \"tool\":\n\t\t\treturn {\n\t\t\t\ttool_choice: \"any\",\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({ values }: 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\t...passthroughOptions,\n\t\t\t},\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\tprivate buildRunInputs(\n\t\targs: ReturnType<typeof this.getArgs>[\"args\"],\n\t\tmessages: ReturnType<typeof convertToWorkersAIChatMessages>[\"messages\"],\n\t\toptions?: { stream?: boolean },\n\t) {\n\t\treturn {\n\t\t\tmax_tokens: args.max_tokens,\n\t\t\tmessages: this.config.isBinding\n\t\t\t\t? normalizeMessagesForBinding(messages)\n\t\t\t\t: 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};\n\t}\n\n\t/**\n\t * Get passthrough options for binding.run() from settings.\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\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\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\t// Content arrays for vision are valid at runtime but not in the\n\t\t\t// binding's strict TypeScript definitions (which expect string content).\n\t\t\tinputs as AiModels[keyof AiModels][\"inputs\"],\n\t\t\trunOptions,\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, { stream: true });\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\trunOptions,\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}: 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(this.modelId as keyof AiModels, {\n\t\t\t\theight,\n\t\t\t\tprompt: prompt ?? \"\",\n\t\t\t\tseed,\n\t\t\t\twidth,\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\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 }),\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":";;;;;AAcA,SAAS,aAAa,MAAqD;AAC1E,MAAI,gBAAgB,YAAY;AAC/B,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,SAAS,UAAU;AAC7B,QAAI,SAAS;AACb,QAAI,OAAO,WAAW,OAAO,GAAG;AAC/B,YAAM,aAAa,OAAO,QAAQ,GAAG;AACrC,UAAI,cAAc,GAAG;AACpB,iBAAS,OAAO,MAAM,aAAa,CAAC;AAAA,MACrC;AAAA,IACD;AACA,UAAM,eAAe,KAAK,MAAM;AAChC,UAAM,QAAQ,IAAI,WAAW,aAAa,MAAM;AAChD,aAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,YAAM,CAAC,IAAI,aAAa,WAAW,CAAC;AAAA,IACrC;AACA,WAAO;AAAA,EACR;AAEA,MAAI,gBAAgB,KAAK;AACxB,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AAEA,SAAO;AACR;AAEA,SAAS,mBAAmB,OAA2B;AACtD,MAAI,SAAS;AACb,QAAM,YAAY;AAClB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,WAAW;AACjD,UAAM,QAAQ,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,WAAW,MAAM,MAAM,CAAC;AACrE,cAAU,OAAO,aAAa,GAAG,KAAK;AAAA,EACvC;AACA,SAAO,KAAK,MAAM;AACnB;AAEO,SAAS,+BAA+B,QAE7C;AACD,QAAM,WAAgC,CAAC;AAEvC,aAAW,EAAE,MAAM,QAAQ,KAAK,QAAQ;AACvC,YAAQ,MAAM;AAAA,MACb,KAAK,UAAU;AACd,iBAAS,KAAK,EAAE,SAAS,MAAM,SAAS,CAAC;AACzC;AAAA,MACD;AAAA,MAEA,KAAK,QAAQ;AACZ,cAAM,YAAsB,CAAC;AAC7B,cAAM,aAAqE,CAAC;AAE5E,mBAAW,QAAQ,SAAS;AAC3B,kBAAQ,KAAK,MAAM;AAAA,YAClB,KAAK,QAAQ;AACZ,wBAAU,KAAK,KAAK,IAAI;AACxB;AAAA,YACD;AAAA,YACA,KAAK,QAAQ;AACZ,oBAAM,aAAa,aAAa,KAAK,IAAI;AACzC,kBAAI,YAAY;AACf,2BAAW,KAAK;AAAA,kBACf,OAAO;AAAA,kBACP,WAAW,KAAK;AAAA,gBACjB,CAAC;AAAA,cACF;AACA;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAEA,YAAI,WAAW,SAAS,GAAG;AAC1B,gBAAM,eAAuC,CAAC;AAC9C,cAAI,UAAU,SAAS,GAAG;AACzB,yBAAa,KAAK,EAAE,MAAM,QAAQ,MAAM,UAAU,KAAK,IAAI,EAAE,CAAC;AAAA,UAC/D;AACA,qBAAW,OAAO,YAAY;AAC7B,kBAAM,SAAS,mBAAmB,IAAI,KAAK;AAC3C,kBAAM,YAAY,IAAI,aAAa;AACnC,yBAAa,KAAK;AAAA,cACjB,MAAM;AAAA,cACN,WAAW,EAAE,KAAK,QAAQ,SAAS,WAAW,MAAM,GAAG;AAAA,YACxD,CAAC;AAAA,UACF;AACA,mBAAS,KAAK,EAAE,SAAS,cAAc,MAAM,OAAO,CAAC;AAAA,QACtD,OAAO;AACN,mBAAS,KAAK,EAAE,SAAS,UAAU,KAAK,IAAI,GAAG,MAAM,OAAO,CAAC;AAAA,QAC9D;AAEA;AAAA,MACD;AAAA,MAEA,KAAK,aAAa;AACjB,YAAI,OAAO;AACX,cAAM,YAID,CAAC;AAEN,mBAAW,QAAQ,SAAS;AAC3B,kBAAQ,KAAK,MAAM;AAAA,YAClB,KAAK,QAAQ;AACZ,sBAAQ,KAAK;AACb;AAAA,YACD;AAAA,YAEA,KAAK,aAAa;AAGjB,sBAAQ,KAAK;AACb;AAAA,YACD;AAAA,YAEA,KAAK,QAAQ;AAEZ;AAAA,YACD;AAAA,YAEA,KAAK,aAAa;AACjB,wBAAU,KAAK;AAAA,gBACd,UAAU;AAAA,kBACT,WAAW,KAAK,UAAU,KAAK,KAAK;AAAA,kBACpC,MAAM,KAAK;AAAA,gBACZ;AAAA,gBACA,IAAI,KAAK;AAAA,gBACT,MAAM;AAAA,cACP,CAAC;AACD;AAAA,YACD;AAAA,YAEA,KAAK,eAAe;AAEnB;AAAA,YACD;AAAA,YAEA,SAAS;AACR,oBAAM,kBAAkB;AACxB,oBAAM,IAAI;AAAA,gBACT,0BAA2B,gBAAqC,IAAI;AAAA,cACrE;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAEA,iBAAS,KAAK;AAAA,UACb,SAAS;AAAA,UACT,MAAM;AAAA,UACN,YACC,UAAU,SAAS,IAChB,UAAU,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,WAAW,KAAK,GAAG,GAAG,OAAO;AAAA,YAChE,UAAU,EAAE,WAAW,MAAM,KAAK;AAAA,YAClC;AAAA,YACA,MAAM;AAAA,UACP,EAAE,IACD;AAAA,QACL,CAAC;AAED;AAAA,MACD;AAAA,MAEA,KAAK,QAAQ;AACZ,mBAAW,gBAAgB,SAAS;AACnC,cAAI,aAAa,SAAS,eAAe;AACxC,qBAAS,KAAK;AAAA,cACb,SAAS,KAAK,UAAU,aAAa,MAAM;AAAA,cAC3C,MAAM,aAAa;AAAA,cACnB,cAAc,aAAa;AAAA,cAC3B,MAAM;AAAA,YACP,CAAC;AAAA,UACF;AAAA,QAED;AACA;AAAA,MACD;AAAA,MAEA,SAAS;AACR,cAAM,kBAAkB;AACxB,cAAM,IAAI,MAAM,qBAAqB,eAAe,EAAE;AAAA,MACvD;AAAA,IACD;AAAA,EACD;AAEA,SAAO,EAAE,SAAS;AACnB;;;ACrMO,SAAS,kBACf,QACuB;AACvB,QAAM,QACL,OAGC,SAAS;AAAA,IACV,mBAAmB;AAAA,IACnB,eAAe;AAAA,EAChB;AAEA,QAAM,eAAe,MAAM,iBAAiB;AAC5C,QAAM,mBAAmB,MAAM,qBAAqB;AAEpD,SAAO;AAAA,IACN,cAAc;AAAA,MACb,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW;AAAA,IACZ;AAAA,IACA,aAAa;AAAA,MACZ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,IACb;AAAA,IACA,KAAK,EAAE,OAAO,eAAe,iBAAiB;AAAA,EAC/C;AACD;;;AC9BA,SAAS,kBAAkB;;;ACIpB,SAAS,yBACf,wBAC8B;AAC9B,MAAI;AAEJ,MACC,OAAO,2BAA2B,YAClC,2BAA2B,QAC3B,2BAA2B,QAC1B;AACD,mBAAe;AAAA,EAChB,WAAW,OAAO,2BAA2B,YAAY,2BAA2B,MAAM;AACzF,UAAM,WAAW;AAGjB,UAAM,UAAU,SAAS;AACzB,QAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,GAAG;AACjD,qBAAe,QAAQ,CAAC,EAAE;AAAA,IAC3B,WAAW,mBAAmB,UAAU;AACvC,qBAAe,SAAS;AAAA,IACzB,OAAO;AACN,qBAAe;AAAA,IAChB;AAAA,EACD,OAAO;AAEN,mBAAe;AAAA,EAChB;AAEA,QAAM,MAAM,gBAAgB;AAE5B,UAAQ,cAAc;AAAA,IACrB,KAAK;AACJ,aAAO,EAAE,SAAS,QAAQ,IAAI;AAAA,IAC/B,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,EAAE,SAAS,UAAU,IAAI;AAAA,IACjC,KAAK;AACJ,aAAO,EAAE,SAAS,cAAc,IAAI;AAAA,IACrC,KAAK;AACJ,aAAO,EAAE,SAAS,SAAS,IAAI;AAAA,IAChC,KAAK;AAAA,IACL,KAAK;AACJ,aAAO,EAAE,SAAS,SAAS,IAAI;AAAA,IAChC;AACC,aAAO,EAAE,SAAS,QAAQ,IAAI;AAAA,EAChC;AACD;;;AD1CO,SAAS,mBACf,QACA,UAC4C;AAC5C,MAAI,YAAY;AAChB,SAAO,OAAO;AAAA,IACb,IAAI,gBAAsE;AAAA,MACzE,UAAU,OAAO,YAAY;AAC5B,YAAI,CAAC,WAAW;AACf,sBAAY;AACZ,qBAAW,QAAQ;AAAA,YAClB,MAAM;AAAA,YACN;AAAA,UACD,CAAC;AAAA,QACF;AACA,mBAAW,QAAQ,KAAK;AAAA,MACzB;AAAA,MACA,MAAM,YAAY;AACjB,YAAI,CAAC,WAAW;AACf,qBAAW,QAAQ;AAAA,YAClB,MAAM;AAAA,YACN;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AACD;AAKA,SAAS,wBAAwB,IAAsC;AACtE,QAAM,KAAK,GAAG;AACd,QAAM,OAAO,IAAI,QAAQ,GAAG,QAAQ;AACpC,QAAM,OAAO,IAAI,aAAa,GAAG,aAAa;AAC9C,QAAM,KAAK,GAAG,MAAM;AACpB,SAAO,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,SAAS;AAC3C;AAYO,SAAS,gBACf,UAC4C;AAC5C,QAAM,YACL,oBAAoB,iBACjB,WACC,SAAS;AAEd,MAAI,CAAC,WAAW;AACf,UAAM,IAAI,MAAM,+CAA+C;AAAA,EAChE;AAGA,MAAI,QAA8B;AAAA,IACjC,cAAc,EAAE,OAAO,GAAG,MAAM,QAAW,WAAW,OAAU;AAAA,IAChE,aAAa;AAAA,MACZ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,IACb;AAAA,IACA,KAAK,EAAE,aAAa,EAAE;AAAA,EACvB;AACA,MAAI,SAAwB;AAC5B,MAAI,cAA6B;AACjC,MAAI,eAAmD;AACvD,MAAI,eAAe;AACnB,MAAI,kBAAkB;AAMtB,QAAM,kBAAkB,oBAAI,IAA4D;AAGxF,QAAM,YAAY,UAAU,YAAY,IAAI,WAAW,CAAC;AAGxD,SAAO,UAAU;AAAA,IAChB,IAAI,gBAAmD;AAAA,MACtD,UAAU,MAAM,YAAY;AAC3B,YAAI,CAAC,QAAQ,SAAS,UAAU;AAC/B,cAAI,SAAS,SAAU,gBAAe;AACtC;AAAA,QACD;AAEA,0BAAkB;AAClB,YAAI;AACJ,YAAI;AACH,kBAAQ,KAAK,MAAM,IAAI;AAAA,QACxB,QAAQ;AACP,kBAAQ,KAAK,oDAAoD,IAAI;AACrE;AAAA,QACD;AAEA,YAAI,MAAM,OAAO;AAChB,kBAAQ,kBAAkB,KAAgD;AAAA,QAC3E;AAGA,cAAM,UAAU,MAAM;AAMtB,cAAM,qBAAqB,UAAU,CAAC,GAAG;AACzC,cAAM,qBAAqB,MAAM;AAEjC,YAAI,sBAAsB,MAAM;AAC/B,yBAAe,yBAAyB,kBAAkB;AAAA,QAC3D,WAAW,sBAAsB,MAAM;AACtC,yBAAe,yBAAyB,kBAAkB;AAAA,QAC3D;AAGA,cAAM,iBAAiB,MAAM;AAC7B,YAAI,kBAAkB,QAAQ,mBAAmB,IAAI;AACpD,gBAAM,eAAe,OAAO,cAAc;AAC1C,cAAI,aAAa,SAAS,GAAG;AAC5B,gBAAI,CAAC,QAAQ;AACZ,uBAAS,WAAW;AACpB,yBAAW,QAAQ,EAAE,MAAM,cAAc,IAAI,OAAO,CAAC;AAAA,YACtD;AACA,uBAAW,QAAQ;AAAA,cAClB,MAAM;AAAA,cACN,IAAI;AAAA,cACJ,OAAO;AAAA,YACR,CAAC;AAAA,UACF;AAAA,QACD;AAGA,YAAI,MAAM,QAAQ,MAAM,UAAU,GAAG;AACpC,6BAAmB,MAAM,YAAyC,UAAU;AAAA,QAC7E;AAGA,YAAI,UAAU,CAAC,GAAG,OAAO;AACxB,gBAAM,QAAQ,QAAQ,CAAC,EAAE;AAEzB,gBAAM,iBAAkB,MAAM,qBAAqB,MAAM;AAGzD,cAAI,kBAAkB,eAAe,SAAS,GAAG;AAChD,gBAAI,CAAC,aAAa;AACjB,4BAAc,WAAW;AACzB,yBAAW,QAAQ;AAAA,gBAClB,MAAM;AAAA,gBACN,IAAI;AAAA,cACL,CAAC;AAAA,YACF;AACA,uBAAW,QAAQ;AAAA,cAClB,MAAM;AAAA,cACN,IAAI;AAAA,cACJ,OAAO;AAAA,YACR,CAAC;AAAA,UACF;AAEA,gBAAM,YAAY,MAAM;AACxB,cAAI,aAAa,UAAU,SAAS,GAAG;AACtC,gBAAI,CAAC,QAAQ;AACZ,uBAAS,WAAW;AACpB,yBAAW,QAAQ,EAAE,MAAM,cAAc,IAAI,OAAO,CAAC;AAAA,YACtD;AACA,uBAAW,QAAQ;AAAA,cAClB,MAAM;AAAA,cACN,IAAI;AAAA,cACJ,OAAO;AAAA,YACR,CAAC;AAAA,UACF;AAEA,gBAAM,iBAAiB,MAAM;AAG7B,cAAI,MAAM,QAAQ,cAAc,GAAG;AAClC,+BAAmB,gBAAgB,UAAU;AAAA,UAC9C;AAAA,QACD;AAAA,MACD;AAAA,MAEA,MAAM,YAAY;AAEjB,mBAAW,CAAC,EAAE,EAAE,KAAK,iBAAiB;AACrC,qBAAW,QAAQ,EAAE,MAAM,kBAAkB,IAAI,GAAG,GAAG,CAAC;AAIxD,qBAAW,QAAQ;AAAA,YAClB,MAAM;AAAA,YACN,YAAY,GAAG;AAAA,YACf,UAAU,GAAG;AAAA,YACb,OAAO,GAAG;AAAA,UACX,CAAC;AAAA,QACF;AAGA,YAAI,aAAa;AAChB,qBAAW,QAAQ,EAAE,MAAM,iBAAiB,IAAI,YAAY,CAAC;AAAA,QAC9D;AACA,YAAI,QAAQ;AACX,qBAAW,QAAQ,EAAE,MAAM,YAAY,IAAI,OAAO,CAAC;AAAA,QACpD;AAGA,cAAM,wBACL,CAAC,gBAAgB,mBAAmB,CAAC,eACjC;AAAA,UACD,SAAS;AAAA,UACT,KAAK;AAAA,QACN,IACE,gBAAgB,EAAE,SAAS,QAAQ,KAAK,OAAO;AAEpD,mBAAW,QAAQ;AAAA,UAClB,cAAc;AAAA,UACd,MAAM;AAAA,UACN;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,CAAC;AAAA,EACF;AAcA,WAAS,mBACR,WACA,YACC;AACD,eAAW,MAAM,WAAW;AAC3B,UAAI,wBAAwB,EAAE,EAAG;AAEjC,YAAM,UAAW,GAAG,SAAoB;AACxC,YAAM,KAAK,GAAG;AACd,YAAM,SAAU,IAAI,QAAQ,GAAG,QAAQ;AACvC,YAAM,SAAU,IAAI,aAAa,GAAG,aAAa;AACjD,YAAM,OAAO,GAAG;AAEhB,UAAI,CAAC,gBAAgB,IAAI,OAAO,GAAG;AAElC,cAAM,KAAK,QAAQ,WAAW;AAC9B,cAAM,WAAW,UAAU;AAC3B,wBAAgB,IAAI,SAAS,EAAE,IAAI,UAAU,MAAM,GAAG,CAAC;AAEvD,mBAAW,QAAQ;AAAA,UAClB,MAAM;AAAA,UACN;AAAA,UACA;AAAA,QACD,CAAC;AAGD,YAAI,UAAU,QAAQ,WAAW,IAAI;AACpC,gBAAM,QAAQ,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,MAAM;AACzE,0BAAgB,IAAI,OAAO,EAAG,QAAQ;AACtC,qBAAW,QAAQ;AAAA,YAClB,MAAM;AAAA,YACN;AAAA,YACA;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD,OAAO;AAEN,cAAM,SAAS,gBAAgB,IAAI,OAAO;AAC1C,YAAI,UAAU,QAAQ,WAAW,IAAI;AACpC,gBAAM,QAAQ,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,MAAM;AACzE,iBAAO,QAAQ;AACf,qBAAW,QAAQ;AAAA,YAClB,MAAM;AAAA,YACN,IAAI,OAAO;AAAA,YACX;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAOA,IAAM,aAAN,cAAyB,gBAAoC;AAAA,EAC5D,cAAc;AACb,QAAI,SAAS;AACb,UAAM,UAAU,IAAI,YAAY;AAEhC,UAAM;AAAA,MACL,UAAU,OAAO,YAAY;AAC5B,kBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAChD,cAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,iBAAS,MAAM,IAAI,KAAK;AAExB,mBAAW,QAAQ,OAAO;AACzB,gBAAM,UAAU,KAAK,KAAK;AAC1B,cAAI,CAAC,QAAS;AACd,cAAI,QAAQ,WAAW,QAAQ,GAAG;AACjC,uBAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;AAAA,UACpC,WAAW,QAAQ,WAAW,OAAO,GAAG;AACvC,uBAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;AAAA,UACpC;AAAA,QACD;AAAA,MACD;AAAA,MAEA,MAAM,YAAY;AACjB,YAAI,OAAO,KAAK,GAAG;AAClB,gBAAM,UAAU,OAAO,KAAK;AAC5B,cAAI,QAAQ,WAAW,QAAQ,GAAG;AACjC,uBAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;AAAA,UACpC,WAAW,QAAQ,WAAW,OAAO,GAAG;AACvC,uBAAW,QAAQ,QAAQ,MAAM,CAAC,CAAC;AAAA,UACpC;AAAA,QACD;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AACD;;;AE5VA,SAAS,cAAAA,mBAAkB;AAapB,SAAS,4BAA4B,UAAoD;AAC/F,SAAO,SAAS,IAAI,CAAC,QAAQ;AAC5B,UAAM,aAAa,EAAE,GAAG,IAAI;AAG5B,QAAI,WAAW,YAAY,QAAQ,WAAW,YAAY,QAAW;AACpE,MAAC,WAAmC,UAAU;AAAA,IAC/C;AAEA,WAAO;AAAA,EACR,CAAC;AACF;AA2CO,SAAS,UAAU,QAAgC;AACzD,QAAM,EAAE,WAAW,OAAO,IAAI;AAE9B,SAAO,eAAe,IACrB,OACA,QACA,SAC0F;AAC1F,UAAM;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MACA,GAAG;AAAA,IACJ,IAAI,WAAW,CAAC;AAEhB,UAAM,YAAY,IAAI,gBAAgB;AACtC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,kBAAkB,GAAG;AAC9D,UAAI,UAAU,UAAa,UAAU,MAAM;AAC1C,cAAM,IAAI;AAAA,UACT,qBAAqB,GAAG;AAAA,QACzB;AAAA,MACD;AACA,UAAI;AACH,cAAM,WAAW,OAAO,KAAK;AAC7B,YAAI,CAAC,UAAU;AACd;AAAA,QACD;AACA,kBAAU,OAAO,KAAK,QAAQ;AAAA,MAC/B,QAAQ;AACP,cAAM,IAAI;AAAA,UACT,qBAAqB,GAAG;AAAA,QACzB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,cAAc,UAAU,SAAS;AAEvC,UAAM,YAAY,OAAO,KAAK,EAAE,WAAW,MAAM,IAAI,QAAQ,OAAO,KAAK;AAGzE,UAAM,MAAM,SAAS,KAClB,wCAAwC,SAAS,IAAI,QAAQ,EAAE,eAAe,SAAS,GACvF,cAAc,IAAI,WAAW,KAAK,EACnC,KACC,iDAAiD,SAAS,OAAO,SAAS,GAC1E,cAAc,IAAI,WAAW,KAAK,EACnC;AAEF,UAAM,UAAkC;AAAA,MACvC,eAAe,UAAU,MAAM;AAAA,MAC/B,gBAAgB;AAAA,MAChB,GAAI,gBAAgB,OAAO,iBAAiB,WACxC,eACD,CAAC;AAAA,IACL;AAEA,QAAI,SAAS;AACZ,UAAI,QAAQ,WAAW;AACtB,gBAAQ,mBAAmB,IAAI;AAAA,MAChC;AACA,UAAI,OAAO,QAAQ,aAAa,UAAU;AACzC,gBAAQ,kBAAkB,IAAI,OAAO,QAAQ,QAAQ;AAAA,MACtD;AACA,UAAI,QAAQ,UAAU;AACrB,gBAAQ,kBAAkB,IAAI,QAAQ;AAAA,MACvC;AACA,UAAI,QAAQ,UAAU;AACrB,gBAAQ,iBAAiB,IAAI,KAAK,UAAU,QAAQ,QAAQ;AAAA,MAC7D;AAAA,IACD;AAEA,UAAM,OAAO,KAAK,UAAU,MAAM;AAElC,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MACjC;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACD,CAAC;AAGD,QAAI,CAAC,SAAS,MAAM,CAAC,mBAAmB;AACvC,UAAI;AACJ,UAAI;AACH,oBAAY,MAAM,SAAS,KAAK;AAAA,MACjC,QAAQ;AACP,oBAAY;AAAA,MACb;AACA,YAAM,IAAI;AAAA,QACT,yBAAyB,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS;AAAA,MAC/E;AAAA,IACD;AAEA,QAAI,mBAAmB;AACtB,aAAO;AAAA,IACR;AAEA,QAAK,OAAiC,WAAW,MAAM;AACtD,YAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,UAAI,YAAY,SAAS,cAAc,KAAK,SAAS,MAAM;AAC1D,eAAO,SAAS;AAAA,MACjB;AACA,UAAI,SAAS,QAAQ,CAAC,YAAY,SAAS,MAAM,GAAG;AAEnD,eAAO,SAAS;AAAA,MACjB;AAOA,YAAM,gBAAgB,MAAM,MAAM,KAAK;AAAA,QACtC,MAAM,KAAK,UAAU;AAAA,UACpB,GAAI;AAAA,UACJ,QAAQ;AAAA,QACT,CAAC;AAAA,QACD;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,MACD,CAAC;AAED,UAAI,CAAC,cAAc,IAAI;AACtB,YAAI;AACJ,YAAI;AACH,sBAAY,MAAM,cAAc,KAAK;AAAA,QACtC,QAAQ;AACP,sBAAY;AAAA,QACb;AACA,cAAM,IAAI;AAAA,UACT,yBAAyB,cAAc,MAAM,IAAI,cAAc,UAAU,MAAM,SAAS;AAAA,QACzF;AAAA,MACD;AAEA,YAAM,YAAY,MAAM,cAAc,KAEnC;AACH,aAAO,UAAU;AAAA,IAClB;AAEA,UAAM,OAAO,MAAM,SAAS,KAEzB;AACH,WAAO,KAAK;AAAA,EACb;AACD;AAeA,eAAsB,gBACrB,QACA,OACA,YACA,aACA,QACmC;AACnC,QAAM,MAAM,iDAAiD,OAAO,SAAS,WAAW,KAAK;AAE7F,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IACjC,QAAQ;AAAA,IACR,SAAS;AAAA,MACR,eAAe,UAAU,OAAO,MAAM;AAAA,MACtC,gBAAgB;AAAA,IACjB;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EACD,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AACjB,QAAI;AACJ,QAAI;AACH,kBAAY,MAAM,SAAS,KAAK;AAAA,IACjC,QAAQ;AACP,kBAAY;AAAA,IACb;AACA,UAAM,IAAI;AAAA,MACT,yBAAyB,SAAS,MAAM,IAAI,SAAS,UAAU,MAAM,SAAS;AAAA,IAC/E;AAAA,EACD;AAEA,QAAM,OAAO,MAAM,SAAS,KAA2C;AACvE,SAAQ,KAAK,UAAU;AACxB;AAMO,SAAS,0BACf,OACA,YACC;AACD,MAAI,SAAS,MAAM;AAClB,WAAO,EAAE,aAAa,QAAW,OAAO,OAAU;AAAA,EACnD;AAEA,QAAM,cAAc,MAAM,IAAI,CAAC,UAAU;AAAA,IACxC,UAAU;AAAA,MACT,aAAa,KAAK,SAAS,cAAc,KAAK;AAAA,MAC9C,MAAM,KAAK;AAAA,MACX,YAAY,KAAK,SAAS,cAAc,KAAK;AAAA,IAC9C;AAAA,IACA,MAAM;AAAA,EACP,EAAE;AAEF,MAAI,cAAc,MAAM;AACvB,WAAO,EAAE,aAAa,QAAW,OAAO,YAAY;AAAA,EACrD;AAEA,QAAM,OAAO,WAAW;AAExB,UAAQ,MAAM;AAAA,IACb,KAAK;AACJ,aAAO,EAAE,aAAa,MAAM,OAAO,YAAY;AAAA,IAChD,KAAK;AACJ,aAAO,EAAE,aAAa,MAAM,OAAO,YAAY;AAAA,IAChD,KAAK;AACJ,aAAO,EAAE,aAAa,OAAO,OAAO,YAAY;AAAA;AAAA;AAAA,IAIjD,KAAK;AACJ,aAAO;AAAA,QACN,aAAa;AAAA,QACb,OAAO,YAAY,OAAO,CAAC,SAAS,KAAK,SAAS,SAAS,WAAW,QAAQ;AAAA,MAC/E;AAAA,IACD,SAAS;AACR,YAAM,kBAAkB;AACxB,YAAM,IAAI,MAAM,iCAAiC,eAAe,EAAE;AAAA,IACnE;AAAA,EACD;AACD;AAgFA,SAAS,gBAAgB,UAAkE;AAE1F,QAAM,KACL,cAAc,YAAY,OAAO,SAAS,aAAa,YAAY,SAAS,WACxE,SAAS,WACV;AAEJ,MAAI,IAAI,MAAM;AACb,WAAO;AAAA,MACN,OACC,OAAO,GAAG,cAAc,WACrB,GAAG,YACH,KAAK,UAAU,GAAG,aAAa,CAAC,CAAC;AAAA,MACrC,YAAY,SAAS,MAAMC,YAAW;AAAA,MACtC,MAAM;AAAA,MACN,UAAU,GAAG;AAAA,IACd;AAAA,EACD;AAGA,QAAM,OAAO;AACb,SAAO;AAAA,IACN,OACC,OAAO,KAAK,cAAc,WACvB,KAAK,YACL,KAAK,UAAU,KAAK,aAAa,CAAC,CAAC;AAAA,IACvC,YAAY,KAAK,MAAMA,YAAW;AAAA,IAClC,MAAM;AAAA,IACN,UAAU,KAAK;AAAA,EAChB;AACD;AAEO,SAAS,iBAAiB,QAA4D;AAC5F,MAAI,OAAO,cAAc,MAAM,QAAQ,OAAO,UAAU,GAAG;AAC1D,WAAO,OAAO,WAAW;AAAA,MAAI,CAAC,aAC7B,gBAAgB,QAAQ;AAAA,IACzB;AAAA,EACD;AAEA,QAAM,UAAU,OAAO;AAGvB,MAAI,UAAU,CAAC,GAAG,SAAS,cAAc,MAAM,QAAQ,QAAQ,CAAC,EAAE,QAAQ,UAAU,GAAG;AACtF,WAAO,QAAQ,CAAC,EAAE,QAAQ,WAAW,IAAI,CAAC,aAAa,gBAAgB,QAAQ,CAAC;AAAA,EACjF;AAEA,SAAO,CAAC;AACT;AAkBO,SAAS,YAAY,QAAqD;AAEhF,QAAM,UAAU,OAAO;AACvB,QAAM,gBAAgB,UAAU,CAAC,GAAG,SAAS;AAC7C,MAAI,iBAAiB,QAAQ,OAAO,aAAa,EAAE,SAAS,GAAG;AAC9D,WAAO,OAAO,aAAa;AAAA,EAC5B;AAEA,MAAI,cAAc,QAAQ;AACzB,UAAM,WAAW,OAAO;AAExB,QAAI,OAAO,aAAa,YAAY,aAAa,MAAM;AACtD,aAAO,KAAK,UAAU,QAAQ;AAAA,IAC/B;AAEA,QAAI,OAAO,aAAa,UAAU;AACjC,aAAO,OAAO,QAAQ;AAAA,IACvB;AAEA,QAAI,aAAa,QAAQ,aAAa,QAAW;AAChD,aAAO;AAAA,IACR;AACA,WAAO,OAAO,QAAQ;AAAA,EACvB;AACA,SAAO;AACR;;;ACndO,IAAM,4BAAN,MAA2D;AAAA,EAWjE,YACC,SACA,UACA,QACC;AAdF,wBAAS,wBAAuB;AAChC,wBAAS,+BAA8B;AAEvC,wBAAS,iBAAkF,CAAC;AAE5F,wBAAS;AACT,wBAAS;AAET,wBAAiB;AAOhB,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,SAAS;AAAA,EACf;AAAA,EAEA,IAAI,WAAmB;AACtB,WAAO,KAAK,OAAO;AAAA,EACpB;AAAA,EAEQ,YAAY;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,GAAoE;AACnE,UAAM,WAA8B,CAAC;AAErC,QAAI,SAAS,QAAQ,MAAM,SAAS,GAAG;AACtC,cAAQ;AAAA,QACP;AAAA,MACD;AACA,eAAS,KAAK,EAAE,SAAS,SAAS,MAAM,cAAc,CAAC;AAAA,IACxD;AAEA,QAAI,oBAAoB,MAAM;AAC7B,eAAS,KAAK,EAAE,SAAS,oBAAoB,MAAM,cAAc,CAAC;AAAA,IACnE;AAEA,QAAI,mBAAmB,MAAM;AAC5B,eAAS,KAAK,EAAE,SAAS,mBAAmB,MAAM,cAAc,CAAC;AAAA,IAClE;AAEA,QAAI,gBAAgB,SAAS,QAAQ;AACpC,eAAS,KAAK,EAAE,SAAS,kBAAkB,MAAM,cAAc,CAAC;AAAA,IACjE;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,QAAwE;AAC1F,UAAM,EAAE,SAAS,IAAI,+BAA+B,MAAM;AAC1D,WAAO,SAAS,IAAI,CAAC,EAAE,SAAS,KAAK,MAAM,GAAG,IAAI,KAAK,OAAO,EAAE,EAAE,KAAK,MAAM;AAAA,EAC9E;AAAA,EAEA,MAAM,WACL,SAC8D;AAC9D,UAAM,WAAW,KAAK,YAAY,OAAO;AACzC,UAAM,QAAQ,KAAK,WAAW,QAAQ,MAAM;AAE5C,UAAM,SAAS,MAAM,KAAK,OAAO,QAAQ,SAAS,EAAE,MAAM,CAAC;AAE3D,WAAO;AAAA,MACN,cAAc,EAAE,SAAS,QAAQ,KAAK,OAAO;AAAA,MAC7C,SAAS;AAAA,QACR,GAAG,OAAO,KAAK,IAAI,CAAC,EAAE,SAAS,UAAU,MAAM,OAAO;AAAA,UACrD,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,IAAI;AAAA,UACJ,KAAK;AAAA,UACL,kBAAkB;AAAA,YACjB,YAAY,EAAE,MAAM;AAAA,UACrB;AAAA,QACD,EAAE;AAAA,QACF;AAAA,UACC,MAAM;AAAA,UACN,MAAM,OAAO;AAAA,QACd;AAAA,QACA,GAAG,iBAAiB,MAA4C;AAAA,MACjE;AAAA,MACA,OAAO,kBAAkB,MAA4C;AAAA,MACrE;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,SACL,SAC4D;AAC5D,UAAM,WAAW,KAAK,YAAY,OAAO;AACzC,UAAM,QAAQ,KAAK,WAAW,QAAQ,MAAM;AAE5C,UAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,SAAS;AAAA,MACnD;AAAA,MACA,QAAQ;AAAA,IACT,CAAC;AAED,WAAO;AAAA,MACN,QAAQ;AAAA,QACP,gBAAgB,QAA4D;AAAA,QAC5E;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;;;AC3HA,SAAS,0CAA0C;AAoB5C,IAAM,0BAAN,MAA0D;AAAA,EAmBhE,YACC,SACA,UACA,QACC;AAtBF,wBAAS,wBAAuB;AAChC,wBAAS;AACT,wBAAiB;AACjB,wBAAiB;AAoBhB,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,SAAS;AAAA,EACf;AAAA,EArBA,IAAI,WAAmB;AACtB,WAAO,KAAK,OAAO;AAAA,EACpB;AAAA,EAEA,IAAI,uBAA+B;AAElC,WAAO,KAAK,SAAS,wBAAwB;AAAA,EAC9C;AAAA,EAEA,IAAI,wBAAiC;AACpC,WAAO,KAAK,SAAS,yBAAyB;AAAA,EAC/C;AAAA,EAYA,MAAM,QAAQ,EAAE,OAAO,GAAiE;AACvF,QAAI,OAAO,SAAS,KAAK,sBAAsB;AAC9C,YAAM,IAAI,mCAAmC;AAAA,QAC5C,sBAAsB,KAAK;AAAA,QAC3B,SAAS,KAAK;AAAA,QACd,UAAU,KAAK;AAAA,QACf;AAAA,MACD,CAAC;AAAA,IACF;AAEA,UAAM;AAAA,MACL;AAAA,MACA,sBAAsB;AAAA,MACtB,uBAAuB;AAAA,MACvB,GAAG;AAAA,IACJ,IAAI,KAAK;AAET,UAAM,WAAW,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC1C,KAAK;AAAA,MACL;AAAA,QACC,MAAM;AAAA,MACP;AAAA,MACA;AAAA,QACC,SAAS,KAAK,OAAO,WAAW;AAAA,QAChC,GAAG;AAAA,MACJ;AAAA,IACD;AAEA,WAAO;AAAA,MACN,YAAa,SAAkC;AAAA,MAC/C,UAAU,CAAC;AAAA,IACZ;AAAA,EACD;AACD;;;ACtFA,SAAS,cAAAC,mBAAkB;AAsBpB,IAAM,6BAAN,MAA4D;AAAA,EAWlE,YACC,SACA,UACA,QACC;AAdF,wBAAS,wBAAuB;AAChC,wBAAS,+BAA8B;AAEvC,wBAAS,iBAAkF,CAAC;AAE5F,wBAAS;AACT,wBAAS;AAET,wBAAiB;AAOhB,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,SAAS;AAAA,EACf;AAAA,EAEA,IAAI,WAAmB;AACtB,WAAO,KAAK,OAAO;AAAA,EACpB;AAAA,EAEQ,QAAQ;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,GAAiD;AAChD,UAAM,OAAO,gBAAgB,QAAQ;AAErC,UAAM,WAA8B,CAAC;AAErC,QAAI,oBAAoB,MAAM;AAC7B,eAAS,KAAK,EAAE,SAAS,oBAAoB,MAAM,cAAc,CAAC;AAAA,IACnE;AAEA,QAAI,mBAAmB,MAAM;AAC5B,eAAS,KAAK,EAAE,SAAS,mBAAmB,MAAM,cAAc,CAAC;AAAA,IAClE;AAEA,UAAM,WAAW;AAAA,MAChB,YAAY;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,aAAa;AAAA,MACb,aAAa,KAAK,SAAS;AAAA,MAC3B;AAAA,MACA,OAAO;AAAA,IACR;AAEA,YAAQ,MAAM;AAAA,MACb,KAAK,QAAQ;AACZ,eAAO;AAAA,UACN,MAAM;AAAA,YACL,GAAG;AAAA,YACH,iBAAiB;AAAA,YAGjB,GAAG,0BAA0B,OAAO,UAAU;AAAA,UAC/C;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,MAEA,KAAK,QAAQ;AACZ,eAAO;AAAA,UACN,MAAM;AAAA,YACL,GAAG;AAAA,YACH,iBAAiB;AAAA,cAChB,MAAM;AAAA,cACN,aACC,gBAAgB,SAAS,SAAS,eAAe,SAAS;AAAA,YAC5D;AAAA,YACA,OAAO;AAAA,YACP,aAAa;AAAA,UACd;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,MAEA,SAAS;AACR,cAAM,kBAAkB;AACxB,cAAM,IAAI,MAAM,qBAAqB,eAAe,EAAE;AAAA,MACvD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,eACP,MACA,UACA,SACC;AACD,WAAO;AAAA,MACN,YAAY,KAAK;AAAA,MACjB,UAAU,KAAK,OAAO,YACnB,4BAA4B,QAAQ,IACpC;AAAA,MACH,aAAa,KAAK;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;AAAA,MAC5D,OAAO,KAAK;AAAA,MACZ,GAAI,KAAK,kBAAkB,EAAE,iBAAiB,KAAK,gBAAgB,IAAI,CAAC;AAAA,MACxE,GAAI,SAAS,SAAS,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC3C;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB;AACvB,UAAM;AAAA,MACL;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACJ,IAAI,KAAK;AAET,UAAM,gBAAgB;AAAA,MACrB,GAAI,gBAAgB,OAAO,iBAAiB,WACxC,eACD,CAAC;AAAA,MACJ,GAAI,kBAAkB,EAAE,sBAAsB,gBAAgB,IAAI,CAAC;AAAA,IACpE;AAEA,WAAO;AAAA,MACN,SAAS,KAAK,OAAO,WAAW;AAAA,MAChC,GAAI,OAAO,KAAK,aAAa,EAAE,SAAS,IAAI,EAAE,cAAc,cAAc,IAAI,CAAC;AAAA,MAC/E,GAAG;AAAA,IACJ;AAAA,EACD;AAAA,EAEA,MAAM,WACL,SAC8D;AAC9D,UAAM,EAAE,MAAM,SAAS,IAAI,KAAK,QAAQ,OAAO;AAC/C,UAAM,EAAE,SAAS,IAAI,+BAA+B,QAAQ,MAAM;AAElE,UAAM,SAAS,KAAK,eAAe,MAAM,QAAQ;AACjD,UAAM,aAAa,KAAK,cAAc;AAEtC,UAAM,SAAS,MAAM,KAAK,OAAO,QAAQ;AAAA,MACxC,KAAK;AAAA;AAAA;AAAA,MAGL;AAAA,MACA;AAAA,IACD;AAEA,QAAI,kBAAkB,gBAAgB;AACrC,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAEA,UAAM,eAAe;AACrB,UAAM,UAAU,aAAa;AAK7B,UAAM,mBACL,UAAU,CAAC,GAAG,SAAS,qBAAqB,UAAU,CAAC,GAAG,SAAS;AAEpE,WAAO;AAAA,MACN,cAAc,yBAAyB,YAAY;AAAA,MACnD,SAAS;AAAA,QACR,GAAI,mBACD,CAAC,EAAE,MAAM,aAAsB,MAAM,iBAAiB,CAAC,IACvD,CAAC;AAAA,QACJ;AAAA,UACC,MAAM;AAAA,UACN,MAAM,YAAY,YAAY,KAAK;AAAA,QACpC;AAAA,QACA,GAAG,iBAAiB,YAAY;AAAA,MACjC;AAAA,MACA,OAAO,kBAAkB,MAAiC;AAAA,MAC1D;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,SACL,SAC4D;AAC5D,UAAM,EAAE,MAAM,SAAS,IAAI,KAAK,QAAQ,OAAO;AAC/C,UAAM,EAAE,SAAS,IAAI,+BAA+B,QAAQ,MAAM;AAElE,UAAM,SAAS,KAAK,eAAe,MAAM,UAAU,EAAE,QAAQ,KAAK,CAAC;AACnE,UAAM,aAAa,KAAK,cAAc;AAEtC,UAAM,WAAW,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC1C,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACD;AAGA,QAAI,oBAAoB,gBAAgB;AACvC,aAAO;AAAA,QACN,QAAQ,mBAAmB,gBAAgB,QAAQ,GAAG,QAAQ;AAAA,MAC/D;AAAA,IACD;AAIA,UAAM,eAAe;AACrB,UAAM,UAAU,aAAa;AAK7B,UAAM,mBACL,UAAU,CAAC,GAAG,SAAS,qBAAqB,UAAU,CAAC,GAAG,SAAS;AAEpE,QAAI,SAAwB;AAC5B,QAAI,cAA6B;AAEjC,WAAO;AAAA,MACN,QAAQ,IAAI,eAA0C;AAAA,QACrD,MAAM,YAAY;AACjB,qBAAW,QAAQ;AAAA,YAClB,MAAM;AAAA,YACN;AAAA,UACD,CAAC;AAED,cAAI,kBAAkB;AACrB,0BAAcC,YAAW;AACzB,uBAAW,QAAQ,EAAE,MAAM,mBAAmB,IAAI,YAAY,CAAC;AAC/D,uBAAW,QAAQ;AAAA,cAClB,MAAM;AAAA,cACN,IAAI;AAAA,cACJ,OAAO;AAAA,YACR,CAAC;AACD,uBAAW,QAAQ,EAAE,MAAM,iBAAiB,IAAI,YAAY,CAAC;AAAA,UAC9D;AAEA,gBAAM,OAAO,YAAY,YAAY;AACrC,cAAI,MAAM;AACT,qBAASA,YAAW;AACpB,uBAAW,QAAQ,EAAE,MAAM,cAAc,IAAI,OAAO,CAAC;AACrD,uBAAW,QAAQ,EAAE,MAAM,cAAc,IAAI,QAAQ,OAAO,KAAK,CAAC;AAClE,uBAAW,QAAQ,EAAE,MAAM,YAAY,IAAI,OAAO,CAAC;AAAA,UACpD;AAEA,qBAAW,YAAY,iBAAiB,YAAY,GAAG;AACtD,uBAAW,QAAQ,QAAQ;AAAA,UAC5B;AAEA,qBAAW,QAAQ;AAAA,YAClB,MAAM;AAAA,YACN,cAAc,yBAAyB,YAAY;AAAA,YACnD,OAAO,kBAAkB,QAAmC;AAAA,UAC7D,CAAC;AACD,qBAAW,MAAM;AAAA,QAClB;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AACD;;;AC/RO,IAAM,sBAAN,MAAkD;AAAA,EAWxD,YACU,SACA,UACA,QACR;AAHQ;AACA;AACA;AAbV,wBAAS,wBAAuB;AAAA,EAc7B;AAAA,EAZH,IAAI,mBAA2B;AAC9B,WAAO,KAAK,SAAS,oBAAoB;AAAA,EAC1C;AAAA,EAEA,IAAI,WAAmB;AACtB,WAAO,KAAK,OAAO;AAAA,EACpB;AAAA,EAQA,MAAM,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,GAEE;AACD,UAAM,EAAE,OAAO,OAAO,IAAI,4BAA4B,IAAI;AAE1D,UAAM,WAAmC,CAAC;AAE1C,QAAI,eAAe,MAAM;AACxB,eAAS,KAAK;AAAA,QACb,SAAS;AAAA,QACT,SAAS;AAAA,QACT,MAAM;AAAA,MACP,CAAC;AAAA,IACF;AAEA,UAAM,gBAAgB,YAAY;AACjC,YAAM,SAAU,MAAM,KAAK,OAAO,QAAQ,IAAI,KAAK,SAA2B;AAAA,QAC7E;AAAA,QACA,QAAQ,UAAU;AAAA,QAClB;AAAA,QACA;AAAA,MACD,CAAC;AAED,aAAOC,cAAa,MAAM;AAAA,IAC3B;AAEA,UAAM,SAAuB,MAAM,QAAQ;AAAA,MAC1C,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,cAAc,CAAC;AAAA,IAChD;AAEA,WAAO;AAAA,MACN;AAAA,MACA,UAAU;AAAA,QACT,SAAS,CAAC;AAAA,QACV,SAAS,KAAK;AAAA,QACd,WAAW,oBAAI,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;AAEA,SAAS,4BAA4B,MAA0B;AAC9D,QAAM,CAAC,OAAO,MAAM,IAAI,MAAM,MAAM,GAAG,KAAK,CAAC,QAAW,MAAS;AAEjE,SAAO;AAAA,IACN,QAAQ,aAAa,MAAM;AAAA,IAC3B,OAAO,aAAa,KAAK;AAAA,EAC1B;AACD;AAEA,SAAS,aAAa,OAAgB;AACrC,MAAI,UAAU,MAAM,CAAC,MAAO,QAAO;AACnC,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,UAAU,MAAM,IAAI,SAAS;AAC5C;AAUA,eAAeA,cAAa,QAAsC;AACjE,MAAI,kBAAkB,YAAY;AACjC,WAAO;AAAA,EACR;AACA,MAAI,kBAAkB,aAAa;AAClC,WAAO,IAAI,WAAW,MAAM;AAAA,EAC7B;AACA,MAAI,kBAAkB,gBAAgB;AACrC,UAAM,SAAU,OAAsC,UAAU;AAChE,UAAM,SAAuB,CAAC;AAC9B,QAAI,cAAc;AAClB,WAAO,MAAM;AACZ,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,aAAO,KAAK,KAAK;AACjB,qBAAe,MAAM;AAAA,IACtB;AACA,UAAM,SAAS,IAAI,WAAW,WAAW;AACzC,QAAI,SAAS;AACb,eAAW,SAAS,QAAQ;AAC3B,aAAO,IAAI,OAAO,MAAM;AACxB,gBAAU,MAAM;AAAA,IACjB;AACA,WAAO;AAAA,EACR;AAEA,MAAI,kBAAkB,UAAU;AAC/B,WAAO,IAAI,WAAW,MAAM,OAAO,YAAY,CAAC;AAAA,EACjD;AAEA,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AAClD,UAAM,MAAM;AAEZ,QAAI,OAAO,IAAI,UAAU,UAAU;AAClC,aAAO,WAAW,KAAK,KAAK,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAAA,IAC/D;AAEA,QAAI,IAAI,gBAAgB,YAAY;AACnC,aAAO,IAAI;AAAA,IACZ;AAEA,QAAI,IAAI,gBAAgB,aAAa;AACpC,aAAO,IAAI,WAAW,IAAI,IAAI;AAAA,IAC/B;AAEA,QAAI,OAAO,IAAI,gBAAgB,YAAY;AAC1C,aAAO,IAAI,WAAW,MAAO,IAA4B,YAAY,CAAC;AAAA,IACvE;AAAA,EACD;AACA,QAAM,IAAI;AAAA,IACT,gDAAgD,OAAO,UAAU,SAAS,KAAK,MAAM,CAAC,eACrF,OAAO,WAAW,YAAY,WAAW,OACtC,KAAK,UAAU,OAAO,KAAK,MAAM,CAAC,IAClC,KACJ;AAAA,EACD;AACD;;;AC9HO,IAAM,8BAAN,MAAkE;AAAA,EAOxE,YACU,SACA,UACA,QACR;AAHQ;AACA;AACA;AATV,wBAAS,wBAAuB;AAAA,EAU7B;AAAA,EARH,IAAI,WAAmB;AACtB,WAAO,KAAK,OAAO;AAAA,EACpB;AAAA,EAQA,MAAM,WACL,SACmE;AACnE,UAAM,EAAE,OAAO,WAAW,YAAY,IAAI;AAE1C,UAAM,WAAmC,CAAC;AAI1C,UAAM,aACL,OAAO,UAAU,WACd,WAAW,KAAK,KAAK,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IACnD;AAEJ,UAAM,UAAU,KAAK,YAAY;AAEjC,QAAI;AAEJ,QAAI,SAAS;AACZ,kBAAY,MAAM,KAAK,SAAS,YAAY,WAAW,WAAW;AAAA,IACnE,OAAO;AACN,kBAAY,MAAM,KAAK,WAAW,YAAY,WAAW;AAAA,IAC1D;AAEA,UAAM,SAAS;AAGf,QAAI,SAAS;AACZ,aAAO,KAAK,uBAAuB,QAAQ,QAAQ;AAAA,IACpD;AACA,WAAO,KAAK,yBAAyB,QAAQ,QAAQ;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,WAAW,YAAwB,aAA6C;AAG7F,UAAM,WAAW,KAAK;AACtB,UAAM,QACL,aAAa,sCACVC,oBAAmB,UAAU,IAC7B,MAAM,KAAK,UAAU;AAEzB,UAAM,SAAkC,EAAE,MAAM;AAEhD,QAAI,KAAK,SAAS,UAAU;AAC3B,aAAO,WAAW,KAAK,SAAS;AAAA,IACjC;AACA,QAAI,KAAK,SAAS,QAAQ;AACzB,aAAO,iBAAiB,KAAK,SAAS;AAAA,IACvC;AAEA,WAAO,KAAK,OAAO,QAAQ;AAAA,MAC1B,KAAK;AAAA,MACL;AAAA,MACA,EAAE,SAAS,KAAK,OAAO,SAAS,QAAQ,YAAY;AAAA,IACrD;AAAA,EACD;AAAA,EAEQ,yBACP,KACA,UAC0D;AAC1D,UAAM,OAAQ,IAAI,QAAmB;AAGrC,UAAM,WAA4E,CAAC;AAGnF,QAAI,IAAI,YAAY,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAChD,iBAAW,OAAO,IAAI,UAAU;AAC/B,iBAAS,KAAK;AAAA,UACb,MAAQ,IAAgC,QAAmB;AAAA,UAC3D,aAAe,IAAgC,SAAoB;AAAA,UACnE,WAAa,IAAgC,OAAkB;AAAA,QAChE,CAAC;AAAA,MACF;AAAA,IACD,WAES,IAAI,SAAS,MAAM,QAAQ,IAAI,KAAK,GAAG;AAC/C,iBAAW,KAAK,IAAI,OAAO;AAC1B,iBAAS,KAAK;AAAA,UACb,MAAQ,EAA8B,QAAmB;AAAA,UACzD,aAAe,EAA8B,SAAoB;AAAA,UACjE,WAAa,EAA8B,OAAkB;AAAA,QAC9D,CAAC;AAAA,MACF;AAAA,IACD;AAGA,UAAM,OAAO,IAAI;AAEjB,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAW,MAAM,YAAuB;AAAA,MACxC,mBAAoB,MAAM,YAAuB;AAAA,MACjD;AAAA,MACA,UAAU;AAAA,QACT,WAAW,oBAAI,KAAK;AAAA,QACpB,SAAS,KAAK;AAAA,QACd,SAAS,CAAC;AAAA,MACX;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,SACb,YACA,WACA,aACmB;AACnB,QAAI,KAAK,OAAO,WAAW;AAE1B,aAAO,KAAK,OAAO,QAAQ;AAAA,QAC1B,KAAK;AAAA,QACL;AAAA,UACC,OAAO,EAAE,MAAMA,oBAAmB,UAAU,GAAG,aAAa,UAAU;AAAA,QACvE;AAAA,QACA,EAAE,SAAS,KAAK,OAAO,SAAS,QAAQ,YAAY;AAAA,MACrD;AAAA,IACD;AAKA,QAAI,CAAC,KAAK,OAAO,aAAa;AAC7B,YAAM,IAAI;AAAA,QACT;AAAA,MAED;AAAA,IACD;AACA,WAAO;AAAA,MACN,KAAK,OAAO;AAAA,MACZ,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,uBACP,KACA,UAC0D;AAE1D,UAAM,UAAU,IAAI;AACpB,UAAM,WAAW,SAAS;AAS1B,UAAM,MAAM,WAAW,CAAC,GAAG,eAAe,CAAC;AAE3C,UAAM,OAAO,KAAK,cAAc;AAChC,UAAM,WAA4E,CAAC;AAEnF,QAAI,KAAK,SAAS,MAAM,QAAQ,IAAI,KAAK,GAAG;AAC3C,iBAAW,KAAK,IAAI,OAAO;AAC1B,iBAAS,KAAK;AAAA,UACb,MAAM,EAAE,QAAQ;AAAA,UAChB,aAAa,EAAE,SAAS;AAAA,UACxB,WAAW,EAAE,OAAO;AAAA,QACrB,CAAC;AAAA,MACF;AAAA,IACD;AAEA,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,mBAAmB;AAAA,MACnB;AAAA,MACA,UAAU;AAAA,QACT,WAAW,oBAAI,KAAK;AAAA,QACpB,SAAS,KAAK;AAAA,QACd,SAAS,CAAC;AAAA,MACX;AAAA,IACD;AAAA,EACD;AACD;AAMA,SAASA,oBAAmB,OAA2B;AACtD,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,cAAU,OAAO,aAAa,MAAM,CAAC,CAAE;AAAA,EACxC;AACA,SAAO,KAAK,MAAM;AACnB;;;ACnOO,IAAM,uBAAN,MAAoD;AAAA,EAO1D,YACU,SACA,UACA,QACR;AAHQ;AACA;AACA;AATV,wBAAS,wBAAuB;AAAA,EAU7B;AAAA,EARH,IAAI,WAAmB;AACtB,WAAO,KAAK,OAAO;AAAA,EACpB;AAAA,EAQA,MAAM,WACL,SAC4D;AAC5D,UAAM,EAAE,MAAM,OAAO,OAAO,YAAY,IAAI;AAE5C,UAAM,WAAmC,CAAC;AAE1C,QAAI,QAAQ,cAAc;AACzB,eAAS,KAAK;AAAA,QACb,SAAS;AAAA,QACT,SAAS;AAAA,QACT,MAAM;AAAA,MACP,CAAC;AAAA,IACF;AAEA,QAAI,QAAQ,cAAc;AACzB,eAAS,KAAK;AAAA,QACb,SACC;AAAA,QACD,SAAS;AAAA,QACT,MAAM;AAAA,MACP,CAAC;AAAA,IACF;AAGA,UAAM,SAAkC,EAAE,KAAK;AAC/C,QAAI,MAAO,QAAO,QAAQ;AAC1B,QAAI,SAAS,KAAM,QAAO,QAAQ;AAElC,UAAM,SAAS,MAAM,KAAK,OAAO,QAAQ;AAAA,MACxC,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACC,SAAS,KAAK,OAAO;AAAA,QACrB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,QAKR,mBAAmB;AAAA,MACpB;AAAA,IACD;AAKA,UAAM,QAAQ,MAAMC,cAAa,MAAM;AAEvC,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA,QACT,WAAW,oBAAI,KAAK;AAAA,QACpB,SAAS,KAAK;AAAA,QACd,SAAS,CAAC;AAAA,MACX;AAAA,IACD;AAAA,EACD;AACD;AAcA,eAAeA,cAAa,QAAsC;AAEjE,MAAI,kBAAkB,UAAU;AAC/B,WAAO,IAAI,WAAW,MAAM,OAAO,YAAY,CAAC;AAAA,EACjD;AACA,MAAI,kBAAkB,YAAY;AACjC,WAAO;AAAA,EACR;AACA,MAAI,kBAAkB,aAAa;AAClC,WAAO,IAAI,WAAW,MAAM;AAAA,EAC7B;AACA,MAAI,kBAAkB,gBAAgB;AACrC,UAAM,SAAU,OAAsC,UAAU;AAChE,UAAM,SAAuB,CAAC;AAC9B,QAAI,cAAc;AAClB,WAAO,MAAM;AACZ,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,aAAO,KAAK,KAAK;AACjB,qBAAe,MAAM;AAAA,IACtB;AACA,UAAM,SAAS,IAAI,WAAW,WAAW;AACzC,QAAI,SAAS;AACb,eAAW,SAAS,QAAQ;AAC3B,aAAO,IAAI,OAAO,MAAM;AACxB,gBAAU,MAAM;AAAA,IACjB;AACA,WAAO;AAAA,EACR;AAEA,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AAClD,UAAM,MAAM;AACZ,QAAI,OAAO,IAAI,UAAU,UAAU;AAClC,aAAO,WAAW,KAAK,KAAK,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAAA,IAC/D;AAAA,EACD;AACA,QAAM,IAAI;AAAA,IACT,8CAA8C,OAAO,UAAU,SAAS,KAAK,MAAM,CAAC;AAAA,EACrF;AACD;;;ACzHO,IAAM,0BAAN,MAA0D;AAAA,EAOhE,YACU,SACA,UACA,QACR;AAHQ;AACA;AACA;AATV,wBAAS,wBAAuB;AAAA,EAU7B;AAAA,EARH,IAAI,WAAmB;AACtB,WAAO,KAAK,OAAO;AAAA,EACpB;AAAA,EAQA,MAAM,SACL,SAC6D;AAC7D,UAAM,EAAE,WAAW,OAAO,MAAM,YAAY,IAAI;AAEhD,UAAM,WAAmC,CAAC;AAG1C,UAAM,WAAW,oBAAoB,WAAW,QAAQ;AAGxD,UAAM,SAAkC;AAAA,MACvC;AAAA,MACA;AAAA,IACD;AACA,QAAI,QAAQ,MAAM;AACjB,aAAO,QAAQ;AAAA,IAChB;AAEA,UAAM,SAAU,MAAM,KAAK,OAAO,QAAQ;AAAA,MACzC,KAAK;AAAA,MACL;AAAA,MACA,EAAE,SAAS,KAAK,OAAO,SAAS,QAAQ,YAAY;AAAA,IACrD;AAGA,UAAM,WAAW,OAAO;AAExB,UAAM,WAAW,YAAY,CAAC,GAC5B,IAAI,CAAC,UAAU;AAAA,MACf,OAAO,KAAK,MAAM;AAAA,MAClB,gBAAgB,KAAK,SAAS;AAAA,IAC/B,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,iBAAiB,EAAE,cAAc;AAEpD,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA,QACT,WAAW,oBAAI,KAAK;AAAA,QACpB,SAAS,KAAK;AAAA,QACd,SAAS,CAAC;AAAA,MACX;AAAA,IACD;AAAA,EACD;AACD;AAaA,SAAS,oBACR,WACA,UAC0B;AAC1B,MAAI,UAAU,SAAS,QAAQ;AAC9B,WAAO,UAAU,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE;AAAA,EACjD;AAGA,WAAS,KAAK;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,EACP,CAAC;AAED,SAAO,UAAU,OAAO,IAAI,CAAC,SAAS,EAAE,MAAM,KAAK,UAAU,GAAG,EAAE,EAAE;AACrE;;;ACnGO,IAAM,2BAAN,cAAuC,0BAA0B;AAAC;;;AC2IlE,SAAS,gBAAgB,SAAuC;AACtE,MAAI,CAAC,QAAQ,WAAW,EAAE,eAAe,WAAW,YAAY,UAAU;AACzE,UAAM,IAAI;AAAA,MACT;AAAA,IAED;AAAA,EACD;AAEA,MAAI;AACJ,QAAM,YAAY,CAAC,CAAC,QAAQ;AAE5B,MAAI,QAAQ,SAAS;AACpB,cAAU,QAAQ;AAAA,EACnB,OAAO;AACN,UAAM,EAAE,WAAW,OAAO,IAAI;AAC9B,cAAU;AAAA,MACT,KAAK,UAAU,EAAE,WAAW,OAAO,CAAC;AAAA,IACrC;AAAA,EACD;AAEA,QAAM,kBAAkB,CAAC,SAA+B,WAAkC,CAAC,MAC1F,IAAI,2BAA2B,SAAS,UAAU;AAAA,IACjD;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,UAAU;AAAA,IACV;AAAA,EACD,CAAC;AAEF,QAAM,mBAAmB,CACxB,SACA,WAAmC,CAAC,MAEpC,IAAI,oBAAoB,SAAS,UAAU;AAAA,IAC1C;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,UAAU;AAAA,EACX,CAAC;AACF,QAAM,uBAAuB,CAC5B,SACA,WAAuC,CAAC,MAExC,IAAI,wBAAwB,SAAS,UAAU;AAAA,IAC9C;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,UAAU;AAAA,EACX,CAAC;AAEF,QAAM,2BAA2B,CAChC,SACA,WAA2C,CAAC,MAE5C,IAAI,4BAA4B,SAAS,UAAU;AAAA,IAClD;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,UAAU;AAAA,IACV;AAAA,IACA,aACC,CAAC,aAAa,eAAe,UAC1B,EAAE,WAAW,QAAQ,WAAW,QAAQ,QAAQ,OAAO,IACvD;AAAA,EACL,CAAC;AAEF,QAAM,oBAAoB,CAAC,SAAuB,WAAoC,CAAC,MACtF,IAAI,qBAAqB,SAAS,UAAU;AAAA,IAC3C;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,UAAU;AAAA,EACX,CAAC;AAEF,QAAM,uBAAuB,CAC5B,SACA,WAAuC,CAAC,MAExC,IAAI,wBAAwB,SAAS,UAAU;AAAA,IAC9C;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,UAAU;AAAA,EACX,CAAC;AAEF,QAAM,WAAW,CAAC,SAA+B,aAAqC;AACrF,QAAI,YAAY;AACf,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACtF;AACA,WAAO,gBAAgB,SAAS,QAAQ;AAAA,EACzC;AAEA,WAAS,OAAO;AAChB,WAAS,YAAY;AACrB,WAAS,gBAAgB;AACzB,WAAS,qBAAqB;AAC9B,WAAS,QAAQ;AACjB,WAAS,aAAa;AACtB,WAAS,gBAAgB;AACzB,WAAS,qBAAqB;AAC9B,WAAS,SAAS;AAClB,WAAS,cAAc;AACvB,WAAS,YAAY;AACrB,WAAS,iBAAiB;AAE1B,SAAO;AACR;AAwBO,SAAS,eACf,SAEA,eAAe,iBACI;AACnB,QAAM,UAAU,QAAQ;AAExB,QAAM,kBAAkB,CAAC,WAAiC,CAAC,MAC1D,IAAI,0BAA0B,4CAA4C,UAAU;AAAA,IACnF;AAAA,IACA,UAAU;AAAA,EACX,CAAC;AAEF,QAAM,WAAW,CAAC,aAAoC;AACrD,QAAI,YAAY;AACf,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACrF;AACA,WAAO,gBAAgB,QAAQ;AAAA,EAChC;AAEA,WAAS,OAAO;AAEhB,SAAO;AACR;AAkBA,IAAI,gBAAgB;AAMb,SAAS,cAAc,SAA6C;AAC1E,MAAI,CAAC,eAAe;AACnB,oBAAgB;AAChB,YAAQ;AAAA,MACP;AAAA,IAGD;AAAA,EACD;AACA,SAAO,eAAe,SAAS,cAAc;AAC9C;","names":["generateId","generateId","generateId","generateId","toUint8Array","uint8ArrayToBase64","toUint8Array"]}
|
package/package.json
CHANGED
|
@@ -1,20 +1,62 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
LanguageModelV3DataContent,
|
|
3
|
+
LanguageModelV3Prompt,
|
|
4
|
+
} from "@ai-sdk/provider";
|
|
5
|
+
import type { WorkersAIContentPart, WorkersAIChatPrompt } from "./workersai-chat-prompt";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Normalise any LanguageModelV3DataContent value to a Uint8Array.
|
|
9
|
+
*
|
|
10
|
+
* Handles:
|
|
11
|
+
* - Uint8Array → returned as-is
|
|
12
|
+
* - string → decoded from base64 (with or without data-URL prefix)
|
|
13
|
+
* - URL → not supported (Workers AI needs raw bytes, not a reference)
|
|
14
|
+
*/
|
|
15
|
+
function toUint8Array(data: LanguageModelV3DataContent): Uint8Array | null {
|
|
16
|
+
if (data instanceof Uint8Array) {
|
|
17
|
+
return data;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (typeof data === "string") {
|
|
21
|
+
let base64 = data;
|
|
22
|
+
if (base64.startsWith("data:")) {
|
|
23
|
+
const commaIndex = base64.indexOf(",");
|
|
24
|
+
if (commaIndex >= 0) {
|
|
25
|
+
base64 = base64.slice(commaIndex + 1);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const binaryString = atob(base64);
|
|
29
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
30
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
31
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
32
|
+
}
|
|
33
|
+
return bytes;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (data instanceof URL) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"URL image sources are not supported by Workers AI. " +
|
|
39
|
+
"Provide image data as a Uint8Array or base64 string instead.",
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function uint8ArrayToBase64(bytes: Uint8Array): string {
|
|
47
|
+
let binary = "";
|
|
48
|
+
const chunkSize = 8192;
|
|
49
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
50
|
+
const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));
|
|
51
|
+
binary += String.fromCharCode(...chunk);
|
|
52
|
+
}
|
|
53
|
+
return btoa(binary);
|
|
54
|
+
}
|
|
3
55
|
|
|
4
56
|
export function convertToWorkersAIChatMessages(prompt: LanguageModelV3Prompt): {
|
|
5
57
|
messages: WorkersAIChatPrompt;
|
|
6
|
-
images: {
|
|
7
|
-
mediaType: string | undefined;
|
|
8
|
-
image: Uint8Array;
|
|
9
|
-
providerOptions: SharedV3ProviderOptions | undefined;
|
|
10
|
-
}[];
|
|
11
58
|
} {
|
|
12
59
|
const messages: WorkersAIChatPrompt = [];
|
|
13
|
-
const images: {
|
|
14
|
-
mediaType: string | undefined;
|
|
15
|
-
image: Uint8Array;
|
|
16
|
-
providerOptions: SharedV3ProviderOptions | undefined;
|
|
17
|
-
}[] = [];
|
|
18
60
|
|
|
19
61
|
for (const { role, content } of prompt) {
|
|
20
62
|
switch (role) {
|
|
@@ -25,6 +67,7 @@ export function convertToWorkersAIChatMessages(prompt: LanguageModelV3Prompt): {
|
|
|
25
67
|
|
|
26
68
|
case "user": {
|
|
27
69
|
const textParts: string[] = [];
|
|
70
|
+
const imageParts: { image: Uint8Array; mediaType: string | undefined }[] = [];
|
|
28
71
|
|
|
29
72
|
for (const part of content) {
|
|
30
73
|
switch (part.type) {
|
|
@@ -33,23 +76,36 @@ export function convertToWorkersAIChatMessages(prompt: LanguageModelV3Prompt): {
|
|
|
33
76
|
break;
|
|
34
77
|
}
|
|
35
78
|
case "file": {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
79
|
+
const imageBytes = toUint8Array(part.data);
|
|
80
|
+
if (imageBytes) {
|
|
81
|
+
imageParts.push({
|
|
82
|
+
image: imageBytes,
|
|
39
83
|
mediaType: part.mediaType,
|
|
40
|
-
providerOptions: part.providerOptions,
|
|
41
84
|
});
|
|
42
85
|
}
|
|
43
|
-
// Don't push empty strings for image parts
|
|
44
86
|
break;
|
|
45
87
|
}
|
|
46
88
|
}
|
|
47
89
|
}
|
|
48
90
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
91
|
+
if (imageParts.length > 0) {
|
|
92
|
+
const contentArray: WorkersAIContentPart[] = [];
|
|
93
|
+
if (textParts.length > 0) {
|
|
94
|
+
contentArray.push({ type: "text", text: textParts.join("\n") });
|
|
95
|
+
}
|
|
96
|
+
for (const img of imageParts) {
|
|
97
|
+
const base64 = uint8ArrayToBase64(img.image);
|
|
98
|
+
const mediaType = img.mediaType || "image/png";
|
|
99
|
+
contentArray.push({
|
|
100
|
+
type: "image_url",
|
|
101
|
+
image_url: { url: `data:${mediaType};base64,${base64}` },
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
messages.push({ content: contentArray, role: "user" });
|
|
105
|
+
} else {
|
|
106
|
+
messages.push({ content: textParts.join("\n"), role: "user" });
|
|
107
|
+
}
|
|
108
|
+
|
|
53
109
|
break;
|
|
54
110
|
}
|
|
55
111
|
|
|
@@ -144,5 +200,5 @@ export function convertToWorkersAIChatMessages(prompt: LanguageModelV3Prompt): {
|
|
|
144
200
|
}
|
|
145
201
|
}
|
|
146
202
|
|
|
147
|
-
return {
|
|
203
|
+
return { messages };
|
|
148
204
|
}
|
package/src/utils.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { WorkersAIChatPrompt } from "./workersai-chat-prompt";
|
|
|
10
10
|
* Normalize messages before passing to the Workers AI binding.
|
|
11
11
|
*
|
|
12
12
|
* The binding has strict schema validation that differs from the OpenAI API:
|
|
13
|
-
* - `content` must be
|
|
13
|
+
* - `content` must not be null
|
|
14
14
|
*/
|
|
15
15
|
export function normalizeMessagesForBinding(messages: WorkersAIChatPrompt): WorkersAIChatPrompt {
|
|
16
16
|
return messages.map((msg) => {
|
|
@@ -117,33 +117,27 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
119
|
* Build the inputs object for `binding.run()`, shared by doGenerate and doStream.
|
|
120
|
+
*
|
|
121
|
+
* Images are embedded inline in messages as OpenAI-compatible content
|
|
122
|
+
* arrays with `image_url` parts. Both the REST API and the binding
|
|
123
|
+
* accept this format at runtime.
|
|
124
|
+
*
|
|
125
|
+
* The binding path additionally normalises null content to empty strings.
|
|
120
126
|
*/
|
|
121
127
|
private buildRunInputs(
|
|
122
128
|
args: ReturnType<typeof this.getArgs>["args"],
|
|
123
129
|
messages: ReturnType<typeof convertToWorkersAIChatMessages>["messages"],
|
|
124
|
-
images: ReturnType<typeof convertToWorkersAIChatMessages>["images"],
|
|
125
130
|
options?: { stream?: boolean },
|
|
126
131
|
) {
|
|
127
|
-
if (images.length > 1) {
|
|
128
|
-
throw new Error("Multiple images are not yet supported as input");
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const imagePart = images[0];
|
|
132
|
-
|
|
133
|
-
// Only normalize messages for the binding path (REST API doesn't need it)
|
|
134
|
-
const finalMessages = this.config.isBinding
|
|
135
|
-
? normalizeMessagesForBinding(messages)
|
|
136
|
-
: messages;
|
|
137
|
-
|
|
138
132
|
return {
|
|
139
133
|
max_tokens: args.max_tokens,
|
|
140
|
-
messages:
|
|
134
|
+
messages: this.config.isBinding
|
|
135
|
+
? normalizeMessagesForBinding(messages)
|
|
136
|
+
: messages,
|
|
141
137
|
temperature: args.temperature,
|
|
142
138
|
tools: args.tools,
|
|
143
139
|
...(args.tool_choice ? { tool_choice: args.tool_choice } : {}),
|
|
144
140
|
top_p: args.top_p,
|
|
145
|
-
...(imagePart ? { image: Array.from(imagePart.image) } : {}),
|
|
146
|
-
// Only include response_format when actually set
|
|
147
141
|
...(args.response_format ? { response_format: args.response_format } : {}),
|
|
148
142
|
...(options?.stream ? { stream: true } : {}),
|
|
149
143
|
};
|
|
@@ -179,14 +173,16 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
179
173
|
options: Parameters<LanguageModelV3["doGenerate"]>[0],
|
|
180
174
|
): Promise<Awaited<ReturnType<LanguageModelV3["doGenerate"]>>> {
|
|
181
175
|
const { args, warnings } = this.getArgs(options);
|
|
182
|
-
const { messages
|
|
176
|
+
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
183
177
|
|
|
184
|
-
const inputs = this.buildRunInputs(args, messages
|
|
178
|
+
const inputs = this.buildRunInputs(args, messages);
|
|
185
179
|
const runOptions = this.getRunOptions();
|
|
186
180
|
|
|
187
181
|
const output = await this.config.binding.run(
|
|
188
182
|
args.model as keyof AiModels,
|
|
189
|
-
|
|
183
|
+
// Content arrays for vision are valid at runtime but not in the
|
|
184
|
+
// binding's strict TypeScript definitions (which expect string content).
|
|
185
|
+
inputs as AiModels[keyof AiModels]["inputs"],
|
|
190
186
|
runOptions,
|
|
191
187
|
);
|
|
192
188
|
|
|
@@ -226,14 +222,14 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
226
222
|
options: Parameters<LanguageModelV3["doStream"]>[0],
|
|
227
223
|
): Promise<Awaited<ReturnType<LanguageModelV3["doStream"]>>> {
|
|
228
224
|
const { args, warnings } = this.getArgs(options);
|
|
229
|
-
const { messages
|
|
225
|
+
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
230
226
|
|
|
231
|
-
const inputs = this.buildRunInputs(args, messages,
|
|
227
|
+
const inputs = this.buildRunInputs(args, messages, { stream: true });
|
|
232
228
|
const runOptions = this.getRunOptions();
|
|
233
229
|
|
|
234
230
|
const response = await this.config.binding.run(
|
|
235
231
|
args.model as keyof AiModels,
|
|
236
|
-
inputs,
|
|
232
|
+
inputs as AiModels[keyof AiModels]["inputs"],
|
|
237
233
|
runOptions,
|
|
238
234
|
);
|
|
239
235
|
|
|
@@ -6,6 +6,10 @@ export type WorkersAIChatMessage =
|
|
|
6
6
|
| WorkersAIAssistantMessage
|
|
7
7
|
| WorkersAIToolMessage;
|
|
8
8
|
|
|
9
|
+
export type WorkersAIContentPart =
|
|
10
|
+
| { type: "text"; text: string }
|
|
11
|
+
| { type: "image_url"; image_url: { url: string } };
|
|
12
|
+
|
|
9
13
|
export interface WorkersAISystemMessage {
|
|
10
14
|
role: "system";
|
|
11
15
|
content: string;
|
|
@@ -13,7 +17,7 @@ export interface WorkersAISystemMessage {
|
|
|
13
17
|
|
|
14
18
|
export interface WorkersAIUserMessage {
|
|
15
19
|
role: "user";
|
|
16
|
-
content: string;
|
|
20
|
+
content: string | WorkersAIContentPart[];
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
export interface WorkersAIAssistantMessage {
|