workers-ai-provider 0.0.11 → 0.0.13

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/dist/index.d.ts CHANGED
@@ -9,21 +9,31 @@ interface WorkersAIChatSettings {
9
9
  safePrompt?: boolean;
10
10
  /**
11
11
  * Optionally set Cloudflare AI Gateway options.
12
+ * @deprecated
12
13
  */
13
14
  gateway?: GatewayOptions;
14
15
  }
15
16
 
17
+ /**
18
+ * The names of the BaseAiTextGeneration models.
19
+ */
20
+ type TextGenerationModels = Exclude<value2key<AiModels, BaseAiTextGeneration>, value2key<AiModels, BaseAiTextToImage>>;
21
+ type value2key<T, V> = {
22
+ [K in keyof T]: T[K] extends V ? K : never;
23
+ }[keyof T];
24
+
16
25
  type WorkersAIChatConfig = {
17
26
  provider: string;
18
27
  binding: Ai;
28
+ gateway?: GatewayOptions;
19
29
  };
20
30
  declare class WorkersAIChatLanguageModel implements LanguageModelV1 {
21
31
  readonly specificationVersion = "v1";
22
32
  readonly defaultObjectGenerationMode = "json";
23
- readonly modelId: BaseAiTextGenerationModels;
33
+ readonly modelId: TextGenerationModels;
24
34
  readonly settings: WorkersAIChatSettings;
25
35
  private readonly config;
26
- constructor(modelId: BaseAiTextGenerationModels, settings: WorkersAIChatSettings, config: WorkersAIChatConfig);
36
+ constructor(modelId: TextGenerationModels, settings: WorkersAIChatSettings, config: WorkersAIChatConfig);
27
37
  get provider(): string;
28
38
  private getArgs;
29
39
  doGenerate(options: Parameters<LanguageModelV1["doGenerate"]>[0]): Promise<Awaited<ReturnType<LanguageModelV1["doGenerate"]>>>;
@@ -31,24 +41,28 @@ declare class WorkersAIChatLanguageModel implements LanguageModelV1 {
31
41
  }
32
42
 
33
43
  interface WorkersAI {
34
- (modelId: BaseAiTextGenerationModels, settings?: WorkersAIChatSettings): WorkersAIChatLanguageModel;
44
+ (modelId: TextGenerationModels, settings?: WorkersAIChatSettings): WorkersAIChatLanguageModel;
35
45
  /**
36
46
  * Creates a model for text generation.
37
47
  **/
38
- chat(modelId: BaseAiTextGenerationModels, settings?: WorkersAIChatSettings): WorkersAIChatLanguageModel;
48
+ chat(modelId: TextGenerationModels, settings?: WorkersAIChatSettings): WorkersAIChatLanguageModel;
39
49
  }
40
50
  interface WorkersAISettings {
41
51
  /**
42
52
  * Provide an `env.AI` binding to use for the AI inference.
43
53
  * You can set up an AI bindings in your Workers project
44
54
  * by adding the following this to `wrangler.toml`:
45
-
55
+
46
56
  ```toml
47
57
  [ai]
48
58
  binding = "AI"
49
59
  ```
50
60
  **/
51
61
  binding: Ai;
62
+ /**
63
+ * Optionally set Cloudflare AI Gateway options.
64
+ */
65
+ gateway?: GatewayOptions;
52
66
  }
53
67
  /**
54
68
  * Create a Workers AI provider instance.
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
6
6
  import {
7
7
  UnsupportedFunctionalityError as UnsupportedFunctionalityError2
8
8
  } from "@ai-sdk/provider";
9
- import { z as z2 } from "zod";
9
+ import { z } from "zod";
10
10
 
11
11
  // src/convert-to-workersai-chat-messages.ts
12
12
  import {
@@ -94,25 +94,22 @@ function convertToWorkersAIChatMessages(prompt) {
94
94
  return messages;
95
95
  }
96
96
 
97
- // src/workersai-error.ts
98
- import {
99
- createJsonErrorResponseHandler
100
- } from "@ai-sdk/provider-utils";
101
- import { z } from "zod";
102
- var workersAIErrorDataSchema = z.object({
103
- object: z.literal("error"),
104
- message: z.string(),
105
- type: z.string(),
106
- param: z.string().nullable(),
107
- code: z.string().nullable()
108
- });
109
- var workersAIFailedResponseHandler = createJsonErrorResponseHandler({
110
- errorSchema: workersAIErrorDataSchema,
111
- errorToMessage: (data) => data.message
112
- });
113
-
114
97
  // src/workersai-chat-language-model.ts
115
98
  import { events } from "fetch-event-stream";
99
+
100
+ // src/map-workersai-usage.ts
101
+ function mapWorkersAIUsage(output) {
102
+ const usage = output.usage ?? {
103
+ prompt_tokens: 0,
104
+ completion_tokens: 0
105
+ };
106
+ return {
107
+ promptTokens: usage.prompt_tokens,
108
+ completionTokens: usage.completion_tokens
109
+ };
110
+ }
111
+
112
+ // src/workersai-chat-language-model.ts
116
113
  var WorkersAIChatLanguageModel = class {
117
114
  constructor(modelId, settings, config) {
118
115
  __publicField(this, "specificationVersion", "v1");
@@ -175,7 +172,8 @@ var WorkersAIChatLanguageModel = class {
175
172
  return {
176
173
  args: {
177
174
  ...baseArgs,
178
- response_format: { type: "json_object" }
175
+ response_format: { type: "json_object" },
176
+ tools: void 0
179
177
  },
180
178
  warnings
181
179
  };
@@ -205,95 +203,90 @@ var WorkersAIChatLanguageModel = class {
205
203
  }
206
204
  async doGenerate(options) {
207
205
  const { args, warnings } = this.getArgs(options);
208
- const response = await this.config.binding.run(
206
+ const output = await this.config.binding.run(
209
207
  args.model,
210
208
  {
211
- messages: args.messages
209
+ messages: args.messages,
210
+ max_tokens: args.max_tokens,
211
+ temperature: args.temperature,
212
+ tools: args.tools,
213
+ top_p: args.top_p
212
214
  },
213
- {
214
- gateway: this.settings.gateway
215
- }
215
+ { gateway: this.config.gateway ?? this.settings.gateway }
216
216
  );
217
- if (response instanceof ReadableStream) {
217
+ if (output instanceof ReadableStream) {
218
218
  throw new Error("This shouldn't happen");
219
219
  }
220
220
  return {
221
- text: response.response,
222
- // TODO: tool calls
223
- // toolCalls: response.tool_calls?.map((toolCall) => ({
224
- // toolCallType: "function",
225
- // toolCallId: toolCall.name, // TODO: what can the id be?
226
- // toolName: toolCall.name,
227
- // args: JSON.stringify(toolCall.arguments || {}),
228
- // })),
221
+ text: output.response,
222
+ toolCalls: output.tool_calls?.map((toolCall) => ({
223
+ toolCallType: "function",
224
+ toolCallId: toolCall.name,
225
+ toolName: toolCall.name,
226
+ args: JSON.stringify(toolCall.arguments || {})
227
+ })),
229
228
  finishReason: "stop",
230
229
  // TODO: mapWorkersAIFinishReason(response.finish_reason),
231
230
  rawCall: { rawPrompt: args.messages, rawSettings: args },
232
- usage: {
233
- // TODO: mapWorkersAIUsage(response.usage),
234
- promptTokens: 0,
235
- completionTokens: 0
236
- },
231
+ usage: mapWorkersAIUsage(output),
237
232
  warnings
238
233
  };
239
234
  }
240
235
  async doStream(options) {
241
236
  const { args, warnings } = this.getArgs(options);
242
- const decoder = new TextDecoder();
243
- const response = await this.config.binding.run(args.model, {
244
- messages: args.messages,
245
- stream: true
246
- });
237
+ const response = await this.config.binding.run(
238
+ args.model,
239
+ {
240
+ messages: args.messages,
241
+ max_tokens: args.max_tokens,
242
+ stream: true,
243
+ temperature: args.temperature,
244
+ tools: args.tools,
245
+ top_p: args.top_p
246
+ },
247
+ { gateway: this.config.gateway ?? this.settings.gateway }
248
+ );
247
249
  if (!(response instanceof ReadableStream)) {
248
250
  throw new Error("This shouldn't happen");
249
251
  }
252
+ const chunkEvent = events(new Response(response));
253
+ let usage = { promptTokens: 0, completionTokens: 0 };
250
254
  return {
251
- stream: response.pipeThrough(
252
- new TransformStream({
253
- async transform(chunk, controller) {
254
- const chunkToText = decoder.decode(chunk);
255
- const chunks = events(new Response(chunkToText));
256
- for await (const singleChunk of chunks) {
257
- if (!singleChunk.data) {
258
- continue;
259
- }
260
- if (singleChunk.data === "[DONE]") {
261
- controller.enqueue({
262
- type: "finish",
263
- finishReason: "stop",
264
- usage: {
265
- promptTokens: 0,
266
- completionTokens: 0
267
- }
268
- });
269
- return;
270
- }
271
- const data = JSON.parse(singleChunk.data);
272
- controller.enqueue({
273
- type: "text-delta",
274
- textDelta: data.response ?? "DATALOSS"
275
- });
255
+ stream: new ReadableStream({
256
+ async start(controller) {
257
+ for await (const event of chunkEvent) {
258
+ if (!event.data) {
259
+ continue;
276
260
  }
277
- controller.enqueue({
278
- type: "finish",
279
- finishReason: "stop",
280
- usage: {
281
- promptTokens: 0,
282
- completionTokens: 0
283
- }
261
+ if (event.data === "[DONE]") {
262
+ break;
263
+ }
264
+ const chunk = JSON.parse(event.data);
265
+ if (chunk.usage) {
266
+ usage = mapWorkersAIUsage(chunk);
267
+ }
268
+ chunk.response.length && controller.enqueue({
269
+ type: "text-delta",
270
+ textDelta: chunk.response
284
271
  });
285
272
  }
286
- })
287
- ),
273
+ controller.enqueue({
274
+ type: "finish",
275
+ finishReason: "stop",
276
+ usage
277
+ });
278
+ controller.close();
279
+ }
280
+ }),
288
281
  rawCall: { rawPrompt: args.messages, rawSettings: args },
289
282
  warnings
290
283
  };
291
284
  }
292
285
  };
293
- var workersAIChatResponseSchema = z2.object({
294
- response: z2.string()
286
+ var workersAIChatResponseSchema = z.object({
287
+ response: z.string()
295
288
  });
296
- var workersAIChatChunkSchema = z2.instanceof(Uint8Array);
289
+ var workersAIChatChunkSchema = z.instanceof(Uint8Array);
297
290
  function prepareToolsAndToolChoice(mode) {
298
291
  const tools = mode.tools?.length ? mode.tools : void 0;
299
292
  if (tools == null) {
@@ -341,7 +334,8 @@ function prepareToolsAndToolChoice(mode) {
341
334
  function createWorkersAI(options) {
342
335
  const createChatModel = (modelId, settings = {}) => new WorkersAIChatLanguageModel(modelId, settings, {
343
336
  provider: "workersai.chat",
344
- binding: options.binding
337
+ binding: options.binding,
338
+ gateway: options.gateway
345
339
  });
346
340
  const provider = function(modelId, settings) {
347
341
  if (new.target) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/workersai-chat-language-model.ts","../src/convert-to-workersai-chat-messages.ts","../src/workersai-error.ts","../src/index.ts"],"sourcesContent":["import {\n type LanguageModelV1,\n type LanguageModelV1CallWarning,\n type LanguageModelV1FinishReason,\n type LanguageModelV1StreamPart,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport type {\n ParseResult,\n createEventSourceResponseHandler,\n createJsonResponseHandler,\n postJsonToApi,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport { mapWorkersAIFinishReason } from \"./map-workersai-finish-reason\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport { workersAIFailedResponseHandler } from \"./workersai-error\";\n\nimport { events } from \"fetch-event-stream\";\n\ntype WorkersAIChatConfig = {\n provider: string;\n binding: Ai;\n};\n\nexport class WorkersAIChatLanguageModel implements LanguageModelV1 {\n readonly specificationVersion = \"v1\";\n readonly defaultObjectGenerationMode = \"json\";\n\n readonly modelId: BaseAiTextGenerationModels;\n readonly settings: WorkersAIChatSettings;\n\n private readonly config: WorkersAIChatConfig;\n\n constructor(\n modelId: BaseAiTextGenerationModels,\n settings: WorkersAIChatSettings,\n config: WorkersAIChatConfig\n ) {\n this.modelId = modelId;\n this.settings = settings;\n this.config = config;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private getArgs({\n mode,\n prompt,\n maxTokens,\n temperature,\n topP,\n frequencyPenalty,\n presencePenalty,\n seed,\n }: Parameters<LanguageModelV1[\"doGenerate\"]>[0]) {\n const type = mode.type;\n\n const warnings: LanguageModelV1CallWarning[] = [];\n\n if (frequencyPenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"frequencyPenalty\",\n });\n }\n\n if (presencePenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"presencePenalty\",\n });\n }\n\n const baseArgs = {\n // model id:\n model: this.modelId,\n\n // model specific settings:\n safe_prompt: this.settings.safePrompt,\n\n // standardized settings:\n max_tokens: maxTokens,\n temperature,\n top_p: topP,\n random_seed: seed,\n\n // messages:\n messages: convertToWorkersAIChatMessages(prompt),\n };\n\n switch (type) {\n case \"regular\": {\n return {\n args: { ...baseArgs, ...prepareToolsAndToolChoice(mode) },\n warnings,\n };\n }\n\n case \"object-json\": {\n return {\n args: {\n ...baseArgs,\n response_format: { type: \"json_object\" },\n },\n warnings,\n };\n }\n\n case \"object-tool\": {\n return {\n args: {\n ...baseArgs,\n tool_choice: \"any\",\n tools: [{ type: \"function\", function: mode.tool }],\n },\n warnings,\n };\n }\n\n // @ts-expect-error - this is unreachable code\n // TODO: fixme\n case \"object-grammar\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"object-grammar mode\",\n });\n }\n\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported type: ${exhaustiveCheck}`);\n }\n }\n }\n\n async doGenerate(\n options: Parameters<LanguageModelV1[\"doGenerate\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doGenerate\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const response = await this.config.binding.run(args.model, {\n messages: args.messages,\n }, \n {\n gateway: this.settings.gateway\n });\n\n if (response instanceof ReadableStream) {\n throw new Error(\"This shouldn't happen\");\n }\n\n return {\n text: response.response,\n // TODO: tool calls\n // toolCalls: response.tool_calls?.map((toolCall) => ({\n // toolCallType: \"function\",\n // toolCallId: toolCall.name, // TODO: what can the id be?\n // toolName: toolCall.name,\n // args: JSON.stringify(toolCall.arguments || {}),\n // })),\n finishReason: \"stop\", // TODO: mapWorkersAIFinishReason(response.finish_reason),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n usage: {\n // TODO: mapWorkersAIUsage(response.usage),\n promptTokens: 0,\n completionTokens: 0,\n },\n warnings,\n };\n }\n\n async doStream(\n options: Parameters<LanguageModelV1[\"doStream\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doStream\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const decoder = new TextDecoder();\n\n const response = await this.config.binding.run(args.model, {\n messages: args.messages,\n stream: true,\n });\n\n if (!(response instanceof ReadableStream)) {\n throw new Error(\"This shouldn't happen\");\n }\n\n return {\n stream: response.pipeThrough(\n new TransformStream<\n ParseResult<z.infer<typeof workersAIChatChunkSchema>>,\n LanguageModelV1StreamPart\n >({\n async transform(chunk, controller) {\n const chunkToText = decoder.decode(chunk as unknown as Uint8Array);\n const chunks = events(new Response(chunkToText));\n for await (const singleChunk of chunks) {\n if (!singleChunk.data) {\n continue;\n }\n if (singleChunk.data === \"[DONE]\") {\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: {\n promptTokens: 0,\n completionTokens: 0,\n },\n });\n return;\n }\n const data = JSON.parse(singleChunk.data);\n\n controller.enqueue({\n type: \"text-delta\",\n textDelta: data.response ?? \"DATALOSS\",\n });\n }\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: {\n promptTokens: 0,\n completionTokens: 0,\n },\n });\n },\n })\n ),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n warnings,\n };\n }\n}\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatResponseSchema = z.object({\n response: z.string(),\n});\n\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatChunkSchema = z.instanceof(Uint8Array);\n\nfunction prepareToolsAndToolChoice(\n mode: Parameters<LanguageModelV1[\"doGenerate\"]>[0][\"mode\"] & {\n type: \"regular\";\n }\n) {\n // when the tools array is empty, change it to undefined to prevent errors:\n const tools = mode.tools?.length ? mode.tools : undefined;\n\n if (tools == null) {\n return { tools: undefined, tool_choice: undefined };\n }\n\n const mappedTools = tools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n // @ts-expect-error - description is not a property of tool\n description: tool.description,\n // @ts-expect-error - parameters is not a property of tool\n parameters: tool.parameters,\n },\n }));\n\n const toolChoice = mode.toolChoice;\n\n if (toolChoice == null) {\n return { tools: mappedTools, tool_choice: undefined };\n }\n\n const type = toolChoice.type;\n\n switch (type) {\n case \"auto\":\n return { tools: mappedTools, tool_choice: type };\n case \"none\":\n return { tools: mappedTools, tool_choice: type };\n case \"required\":\n return { tools: mappedTools, tool_choice: \"any\" };\n\n // workersAI does not support tool mode directly,\n // so we filter the tools and force the tool choice through 'any'\n case \"tool\":\n return {\n tools: mappedTools.filter(\n (tool) => tool.function.name === toolChoice.toolName\n ),\n tool_choice: \"any\",\n };\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported tool choice type: ${exhaustiveCheck}`);\n }\n }\n}\n","import {\n type LanguageModelV1Prompt,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport type { WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n// TODO\nexport function convertToWorkersAIChatMessages(\n prompt: LanguageModelV1Prompt\n): WorkersAIChatPrompt {\n const messages: WorkersAIChatPrompt = [];\n\n for (const { role, content } of prompt) {\n switch (role) {\n case \"system\": {\n messages.push({ role: \"system\", content });\n break;\n }\n\n case \"user\": {\n messages.push({\n role: \"user\",\n content: content\n .map((part) => {\n switch (part.type) {\n case \"text\": {\n return part.text;\n }\n case \"image\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"image-part\",\n });\n }\n }\n })\n .join(\"\"),\n });\n break;\n }\n\n case \"assistant\": {\n let text = \"\";\n const toolCalls: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }> = [];\n\n for (const part of content) {\n switch (part.type) {\n case \"text\": {\n text += part.text;\n break;\n }\n case \"tool-call\": {\n toolCalls.push({\n id: part.toolCallId,\n type: \"function\",\n function: {\n name: part.toolName,\n arguments: JSON.stringify(part.args),\n },\n });\n break;\n }\n default: {\n const exhaustiveCheck = part satisfies never;\n throw new Error(`Unsupported part: ${exhaustiveCheck}`);\n }\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: text,\n tool_calls:\n toolCalls.length > 0\n ? toolCalls.map(({ function: { name, arguments: args } }) => ({\n id: \"null\",\n type: \"function\",\n function: { name, arguments: args },\n }))\n : undefined,\n });\n\n break;\n }\n case \"tool\": {\n for (const toolResponse of content) {\n messages.push({\n role: \"tool\",\n name: toolResponse.toolName,\n content: JSON.stringify(toolResponse.result),\n });\n }\n break;\n }\n default: {\n const exhaustiveCheck = role satisfies never;\n throw new Error(`Unsupported role: ${exhaustiveCheck}`);\n }\n }\n }\n\n return messages;\n}\n","import {\n createJsonErrorResponseHandler,\n type ResponseHandler,\n} from \"@ai-sdk/provider-utils\";\nimport type { APICallError } from \"ai\";\nimport { z } from \"zod\";\n\nconst workersAIErrorDataSchema = z.object({\n object: z.literal(\"error\"),\n message: z.string(),\n type: z.string(),\n param: z.string().nullable(),\n code: z.string().nullable(),\n});\n\nexport type WorkersAIErrorData = z.infer<typeof workersAIErrorDataSchema>;\n\nexport const workersAIFailedResponseHandler: ResponseHandler<APICallError> =\n createJsonErrorResponseHandler({\n errorSchema: workersAIErrorDataSchema,\n errorToMessage: (data) => data.message,\n });\n","import { WorkersAIChatLanguageModel } from \"./workersai-chat-language-model\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\n\nexport interface WorkersAI {\n (\n modelId: BaseAiTextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n\n /**\n * Creates a model for text generation.\n **/\n chat(\n modelId: BaseAiTextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n}\n\nexport interface WorkersAISettings {\n /**\n * Provide an `env.AI` binding to use for the AI inference. \n * You can set up an AI bindings in your Workers project \n * by adding the following this to `wrangler.toml`: \n \n ```toml\n[ai]\nbinding = \"AI\"\n ``` \n **/\n binding: Ai;\n}\n\n/**\n * Create a Workers AI provider instance.\n **/\nexport function createWorkersAI(options: WorkersAISettings): WorkersAI {\n const createChatModel = (\n modelId: BaseAiTextGenerationModels,\n settings: WorkersAIChatSettings = {}\n ) =>\n new WorkersAIChatLanguageModel(modelId, settings, {\n provider: \"workersai.chat\",\n binding: options.binding,\n });\n\n const provider = function (\n modelId: BaseAiTextGenerationModels,\n settings?: WorkersAIChatSettings\n ) {\n if (new.target) {\n throw new Error(\n \"The WorkersAI model function cannot be called with the new keyword.\"\n );\n }\n\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n\n return provider;\n}\n"],"mappings":"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","names":["UnsupportedFunctionalityError","z","UnsupportedFunctionalityError","z"]}
1
+ {"version":3,"sources":["../src/workersai-chat-language-model.ts","../src/convert-to-workersai-chat-messages.ts","../src/map-workersai-usage.ts","../src/index.ts"],"sourcesContent":["import {\n type LanguageModelV1,\n type LanguageModelV1CallWarning,\n type LanguageModelV1StreamPart,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport { z } from \"zod\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\nimport { events } from \"fetch-event-stream\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\n\ntype WorkersAIChatConfig = {\n provider: string;\n binding: Ai;\n gateway?: GatewayOptions;\n};\n\nexport class WorkersAIChatLanguageModel implements LanguageModelV1 {\n readonly specificationVersion = \"v1\";\n readonly defaultObjectGenerationMode = \"json\";\n\n readonly modelId: TextGenerationModels;\n readonly settings: WorkersAIChatSettings;\n\n private readonly config: WorkersAIChatConfig;\n\n constructor(\n modelId: TextGenerationModels,\n settings: WorkersAIChatSettings,\n config: WorkersAIChatConfig\n ) {\n this.modelId = modelId;\n this.settings = settings;\n this.config = config;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private getArgs({\n mode,\n prompt,\n maxTokens,\n temperature,\n topP,\n frequencyPenalty,\n presencePenalty,\n seed,\n }: Parameters<LanguageModelV1[\"doGenerate\"]>[0]) {\n const type = mode.type;\n\n const warnings: LanguageModelV1CallWarning[] = [];\n\n if (frequencyPenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"frequencyPenalty\",\n });\n }\n\n if (presencePenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"presencePenalty\",\n });\n }\n\n const baseArgs = {\n // model id:\n model: this.modelId,\n\n // model specific settings:\n safe_prompt: this.settings.safePrompt,\n\n // standardized settings:\n max_tokens: maxTokens,\n temperature,\n top_p: topP,\n random_seed: seed,\n\n // messages:\n messages: convertToWorkersAIChatMessages(prompt),\n };\n\n switch (type) {\n case \"regular\": {\n return {\n args: { ...baseArgs, ...prepareToolsAndToolChoice(mode) },\n warnings,\n };\n }\n\n case \"object-json\": {\n return {\n args: {\n ...baseArgs,\n response_format: { type: \"json_object\" },\n tools: undefined,\n },\n warnings,\n };\n }\n\n case \"object-tool\": {\n return {\n args: {\n ...baseArgs,\n tool_choice: \"any\",\n tools: [{ type: \"function\", function: mode.tool }],\n },\n warnings,\n };\n }\n\n // @ts-expect-error - this is unreachable code\n // TODO: fixme\n case \"object-grammar\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"object-grammar mode\",\n });\n }\n\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported type: ${exhaustiveCheck}`);\n }\n }\n }\n\n async doGenerate(\n options: Parameters<LanguageModelV1[\"doGenerate\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doGenerate\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const output = await this.config.binding.run(\n args.model,\n {\n messages: args.messages,\n max_tokens: args.max_tokens,\n temperature: args.temperature,\n tools: args.tools,\n top_p: args.top_p,\n },\n { gateway: this.config.gateway ?? this.settings.gateway }\n );\n\n if (output instanceof ReadableStream) {\n throw new Error(\"This shouldn't happen\");\n }\n\n return {\n text: output.response,\n toolCalls: output.tool_calls?.map((toolCall) => ({\n toolCallType: \"function\",\n toolCallId: toolCall.name,\n toolName: toolCall.name,\n args: JSON.stringify(toolCall.arguments || {}),\n })),\n finishReason: \"stop\", // TODO: mapWorkersAIFinishReason(response.finish_reason),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n usage: mapWorkersAIUsage(output),\n warnings,\n };\n }\n\n async doStream(\n options: Parameters<LanguageModelV1[\"doStream\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doStream\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const response = await this.config.binding.run(\n args.model,\n {\n messages: args.messages,\n max_tokens: args.max_tokens,\n stream: true,\n temperature: args.temperature,\n tools: args.tools,\n top_p: args.top_p,\n },\n { gateway: this.config.gateway ?? this.settings.gateway }\n );\n\n if (!(response instanceof ReadableStream)) {\n throw new Error(\"This shouldn't happen\");\n }\n\n const chunkEvent = events(new Response(response));\n let usage = { promptTokens: 0, completionTokens: 0 };\n\n return {\n stream: new ReadableStream<LanguageModelV1StreamPart>({\n async start(controller) {\n for await (const event of chunkEvent) {\n if (!event.data) {\n continue;\n }\n if (event.data === \"[DONE]\") {\n break;\n }\n const chunk = JSON.parse(event.data);\n if (chunk.usage) {\n usage = mapWorkersAIUsage(chunk);\n }\n chunk.response.length &&\n controller.enqueue({\n type: \"text-delta\",\n textDelta: chunk.response,\n });\n }\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: usage,\n });\n controller.close();\n },\n }),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n warnings,\n };\n }\n}\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatResponseSchema = z.object({\n response: z.string(),\n});\n\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatChunkSchema = z.instanceof(Uint8Array);\n\nfunction prepareToolsAndToolChoice(\n mode: Parameters<LanguageModelV1[\"doGenerate\"]>[0][\"mode\"] & {\n type: \"regular\";\n }\n) {\n // when the tools array is empty, change it to undefined to prevent errors:\n const tools = mode.tools?.length ? mode.tools : undefined;\n\n if (tools == null) {\n return { tools: undefined, tool_choice: undefined };\n }\n\n const mappedTools = tools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n // @ts-expect-error - description is not a property of tool\n description: tool.description,\n // @ts-expect-error - parameters is not a property of tool\n parameters: tool.parameters,\n },\n }));\n\n const toolChoice = mode.toolChoice;\n\n if (toolChoice == null) {\n return { tools: mappedTools, tool_choice: undefined };\n }\n\n const type = toolChoice.type;\n\n switch (type) {\n case \"auto\":\n return { tools: mappedTools, tool_choice: type };\n case \"none\":\n return { tools: mappedTools, tool_choice: type };\n case \"required\":\n return { tools: mappedTools, tool_choice: \"any\" };\n\n // workersAI does not support tool mode directly,\n // so we filter the tools and force the tool choice through 'any'\n case \"tool\":\n return {\n tools: mappedTools.filter(\n (tool) => tool.function.name === toolChoice.toolName\n ),\n tool_choice: \"any\",\n };\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported tool choice type: ${exhaustiveCheck}`);\n }\n }\n}\n","import {\n type LanguageModelV1Prompt,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport type { WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n// TODO\nexport function convertToWorkersAIChatMessages(\n prompt: LanguageModelV1Prompt\n): WorkersAIChatPrompt {\n const messages: WorkersAIChatPrompt = [];\n\n for (const { role, content } of prompt) {\n switch (role) {\n case \"system\": {\n messages.push({ role: \"system\", content });\n break;\n }\n\n case \"user\": {\n messages.push({\n role: \"user\",\n content: content\n .map((part) => {\n switch (part.type) {\n case \"text\": {\n return part.text;\n }\n case \"image\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"image-part\",\n });\n }\n }\n })\n .join(\"\"),\n });\n break;\n }\n\n case \"assistant\": {\n let text = \"\";\n const toolCalls: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }> = [];\n\n for (const part of content) {\n switch (part.type) {\n case \"text\": {\n text += part.text;\n break;\n }\n case \"tool-call\": {\n toolCalls.push({\n id: part.toolCallId,\n type: \"function\",\n function: {\n name: part.toolName,\n arguments: JSON.stringify(part.args),\n },\n });\n break;\n }\n default: {\n const exhaustiveCheck = part satisfies never;\n throw new Error(`Unsupported part: ${exhaustiveCheck}`);\n }\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: text,\n tool_calls:\n toolCalls.length > 0\n ? toolCalls.map(({ function: { name, arguments: args } }) => ({\n id: \"null\",\n type: \"function\",\n function: { name, arguments: args },\n }))\n : undefined,\n });\n\n break;\n }\n case \"tool\": {\n for (const toolResponse of content) {\n messages.push({\n role: \"tool\",\n name: toolResponse.toolName,\n content: JSON.stringify(toolResponse.result),\n });\n }\n break;\n }\n default: {\n const exhaustiveCheck = role satisfies never;\n throw new Error(`Unsupported role: ${exhaustiveCheck}`);\n }\n }\n }\n\n return messages;\n}\n","export function mapWorkersAIUsage(output: AiTextGenerationOutput | AiTextToImageOutput) {\n\tconst usage = (output as { usage: { prompt_tokens: number, completion_tokens: number} }).usage ?? {\n\t\tprompt_tokens: 0,\n\t\tcompletion_tokens: 0,\n\t};\n\n\treturn {\n\t\tpromptTokens: usage.prompt_tokens,\n\t\tcompletionTokens: usage.completion_tokens\n\t}\n}\n","import { WorkersAIChatLanguageModel } from \"./workersai-chat-language-model\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\nexport interface WorkersAI {\n (\n modelId: TextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n\n /**\n * Creates a model for text generation.\n **/\n chat(\n modelId: TextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n}\n\nexport interface WorkersAISettings {\n /**\n * Provide an `env.AI` binding to use for the AI inference.\n * You can set up an AI bindings in your Workers project\n * by adding the following this to `wrangler.toml`:\n\n ```toml\n[ai]\nbinding = \"AI\"\n ```\n **/\n binding: Ai;\n /**\n * Optionally set Cloudflare AI Gateway options.\n */\n gateway?: GatewayOptions;\n}\n\n/**\n * Create a Workers AI provider instance.\n **/\nexport function createWorkersAI(options: WorkersAISettings): WorkersAI {\n const createChatModel = (\n modelId: TextGenerationModels,\n settings: WorkersAIChatSettings = {}\n ) =>\n new WorkersAIChatLanguageModel(modelId, settings, {\n provider: \"workersai.chat\",\n binding: options.binding,\n gateway: options.gateway,\n });\n\n const provider = function (\n modelId: TextGenerationModels,\n settings?: WorkersAIChatSettings\n ) {\n if (new.target) {\n throw new Error(\n \"The WorkersAI model function cannot be called with the new keyword.\"\n );\n }\n\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n\n return provider;\n}\n"],"mappings":"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","names":["UnsupportedFunctionalityError","UnsupportedFunctionalityError"]}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "workers-ai-provider",
3
3
  "description": "Workers AI Provider for the vercel AI SDK",
4
4
  "type": "module",
5
- "version": "0.0.11",
5
+ "version": "0.0.13",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "repository": {
@@ -41,6 +41,6 @@
41
41
  "serverless"
42
42
  ],
43
43
  "devDependencies": {
44
- "@cloudflare/workers-types": "^4.20241205.0"
44
+ "@cloudflare/workers-types": "^4.20250214.0"
45
45
  }
46
46
  }
package/src/index.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { WorkersAIChatLanguageModel } from "./workersai-chat-language-model";
2
2
  import type { WorkersAIChatSettings } from "./workersai-chat-settings";
3
+ import type { TextGenerationModels } from "./workersai-models";
3
4
 
4
5
  export interface WorkersAI {
5
6
  (
6
- modelId: BaseAiTextGenerationModels,
7
+ modelId: TextGenerationModels,
7
8
  settings?: WorkersAIChatSettings
8
9
  ): WorkersAIChatLanguageModel;
9
10
 
@@ -11,23 +12,27 @@ export interface WorkersAI {
11
12
  * Creates a model for text generation.
12
13
  **/
13
14
  chat(
14
- modelId: BaseAiTextGenerationModels,
15
+ modelId: TextGenerationModels,
15
16
  settings?: WorkersAIChatSettings
16
17
  ): WorkersAIChatLanguageModel;
17
18
  }
18
19
 
19
20
  export interface WorkersAISettings {
20
21
  /**
21
- * Provide an `env.AI` binding to use for the AI inference.
22
- * You can set up an AI bindings in your Workers project
23
- * by adding the following this to `wrangler.toml`:
24
-
22
+ * Provide an `env.AI` binding to use for the AI inference.
23
+ * You can set up an AI bindings in your Workers project
24
+ * by adding the following this to `wrangler.toml`:
25
+
25
26
  ```toml
26
27
  [ai]
27
28
  binding = "AI"
28
- ```
29
+ ```
29
30
  **/
30
31
  binding: Ai;
32
+ /**
33
+ * Optionally set Cloudflare AI Gateway options.
34
+ */
35
+ gateway?: GatewayOptions;
31
36
  }
32
37
 
33
38
  /**
@@ -35,16 +40,17 @@ binding = "AI"
35
40
  **/
36
41
  export function createWorkersAI(options: WorkersAISettings): WorkersAI {
37
42
  const createChatModel = (
38
- modelId: BaseAiTextGenerationModels,
43
+ modelId: TextGenerationModels,
39
44
  settings: WorkersAIChatSettings = {}
40
45
  ) =>
41
46
  new WorkersAIChatLanguageModel(modelId, settings, {
42
47
  provider: "workersai.chat",
43
48
  binding: options.binding,
49
+ gateway: options.gateway,
44
50
  });
45
51
 
46
52
  const provider = function (
47
- modelId: BaseAiTextGenerationModels,
53
+ modelId: TextGenerationModels,
48
54
  settings?: WorkersAIChatSettings
49
55
  ) {
50
56
  if (new.target) {
@@ -0,0 +1,11 @@
1
+ export function mapWorkersAIUsage(output: AiTextGenerationOutput | AiTextToImageOutput) {
2
+ const usage = (output as { usage: { prompt_tokens: number, completion_tokens: number} }).usage ?? {
3
+ prompt_tokens: 0,
4
+ completion_tokens: 0,
5
+ };
6
+
7
+ return {
8
+ promptTokens: usage.prompt_tokens,
9
+ completionTokens: usage.completion_tokens
10
+ }
11
+ }
@@ -1,40 +1,34 @@
1
1
  import {
2
2
  type LanguageModelV1,
3
3
  type LanguageModelV1CallWarning,
4
- type LanguageModelV1FinishReason,
5
4
  type LanguageModelV1StreamPart,
6
5
  UnsupportedFunctionalityError,
7
6
  } from "@ai-sdk/provider";
8
- import type {
9
- ParseResult,
10
- createEventSourceResponseHandler,
11
- createJsonResponseHandler,
12
- postJsonToApi,
13
- } from "@ai-sdk/provider-utils";
14
7
  import { z } from "zod";
15
8
  import { convertToWorkersAIChatMessages } from "./convert-to-workersai-chat-messages";
16
- import { mapWorkersAIFinishReason } from "./map-workersai-finish-reason";
17
9
  import type { WorkersAIChatSettings } from "./workersai-chat-settings";
18
- import { workersAIFailedResponseHandler } from "./workersai-error";
10
+ import type { TextGenerationModels } from "./workersai-models";
19
11
 
20
12
  import { events } from "fetch-event-stream";
13
+ import { mapWorkersAIUsage } from "./map-workersai-usage";
21
14
 
22
15
  type WorkersAIChatConfig = {
23
16
  provider: string;
24
17
  binding: Ai;
18
+ gateway?: GatewayOptions;
25
19
  };
26
20
 
27
21
  export class WorkersAIChatLanguageModel implements LanguageModelV1 {
28
22
  readonly specificationVersion = "v1";
29
23
  readonly defaultObjectGenerationMode = "json";
30
24
 
31
- readonly modelId: BaseAiTextGenerationModels;
25
+ readonly modelId: TextGenerationModels;
32
26
  readonly settings: WorkersAIChatSettings;
33
27
 
34
28
  private readonly config: WorkersAIChatConfig;
35
29
 
36
30
  constructor(
37
- modelId: BaseAiTextGenerationModels,
31
+ modelId: TextGenerationModels,
38
32
  settings: WorkersAIChatSettings,
39
33
  config: WorkersAIChatConfig
40
34
  ) {
@@ -105,6 +99,7 @@ export class WorkersAIChatLanguageModel implements LanguageModelV1 {
105
99
  args: {
106
100
  ...baseArgs,
107
101
  response_format: { type: "json_object" },
102
+ tools: undefined,
108
103
  },
109
104
  warnings,
110
105
  };
@@ -141,33 +136,33 @@ export class WorkersAIChatLanguageModel implements LanguageModelV1 {
141
136
  ): Promise<Awaited<ReturnType<LanguageModelV1["doGenerate"]>>> {
142
137
  const { args, warnings } = this.getArgs(options);
143
138
 
144
- const response = await this.config.binding.run(args.model, {
145
- messages: args.messages,
146
- },
147
- {
148
- gateway: this.settings.gateway
149
- });
139
+ const output = await this.config.binding.run(
140
+ args.model,
141
+ {
142
+ messages: args.messages,
143
+ max_tokens: args.max_tokens,
144
+ temperature: args.temperature,
145
+ tools: args.tools,
146
+ top_p: args.top_p,
147
+ },
148
+ { gateway: this.config.gateway ?? this.settings.gateway }
149
+ );
150
150
 
151
- if (response instanceof ReadableStream) {
151
+ if (output instanceof ReadableStream) {
152
152
  throw new Error("This shouldn't happen");
153
153
  }
154
154
 
155
155
  return {
156
- text: response.response,
157
- // TODO: tool calls
158
- // toolCalls: response.tool_calls?.map((toolCall) => ({
159
- // toolCallType: "function",
160
- // toolCallId: toolCall.name, // TODO: what can the id be?
161
- // toolName: toolCall.name,
162
- // args: JSON.stringify(toolCall.arguments || {}),
163
- // })),
156
+ text: output.response,
157
+ toolCalls: output.tool_calls?.map((toolCall) => ({
158
+ toolCallType: "function",
159
+ toolCallId: toolCall.name,
160
+ toolName: toolCall.name,
161
+ args: JSON.stringify(toolCall.arguments || {}),
162
+ })),
164
163
  finishReason: "stop", // TODO: mapWorkersAIFinishReason(response.finish_reason),
165
164
  rawCall: { rawPrompt: args.messages, rawSettings: args },
166
- usage: {
167
- // TODO: mapWorkersAIUsage(response.usage),
168
- promptTokens: 0,
169
- completionTokens: 0,
170
- },
165
+ usage: mapWorkersAIUsage(output),
171
166
  warnings,
172
167
  };
173
168
  }
@@ -177,59 +172,54 @@ export class WorkersAIChatLanguageModel implements LanguageModelV1 {
177
172
  ): Promise<Awaited<ReturnType<LanguageModelV1["doStream"]>>> {
178
173
  const { args, warnings } = this.getArgs(options);
179
174
 
180
- const decoder = new TextDecoder();
181
-
182
- const response = await this.config.binding.run(args.model, {
183
- messages: args.messages,
184
- stream: true,
185
- });
175
+ const response = await this.config.binding.run(
176
+ args.model,
177
+ {
178
+ messages: args.messages,
179
+ max_tokens: args.max_tokens,
180
+ stream: true,
181
+ temperature: args.temperature,
182
+ tools: args.tools,
183
+ top_p: args.top_p,
184
+ },
185
+ { gateway: this.config.gateway ?? this.settings.gateway }
186
+ );
186
187
 
187
188
  if (!(response instanceof ReadableStream)) {
188
189
  throw new Error("This shouldn't happen");
189
190
  }
190
191
 
191
- return {
192
- stream: response.pipeThrough(
193
- new TransformStream<
194
- ParseResult<z.infer<typeof workersAIChatChunkSchema>>,
195
- LanguageModelV1StreamPart
196
- >({
197
- async transform(chunk, controller) {
198
- const chunkToText = decoder.decode(chunk as unknown as Uint8Array);
199
- const chunks = events(new Response(chunkToText));
200
- for await (const singleChunk of chunks) {
201
- if (!singleChunk.data) {
202
- continue;
203
- }
204
- if (singleChunk.data === "[DONE]") {
205
- controller.enqueue({
206
- type: "finish",
207
- finishReason: "stop",
208
- usage: {
209
- promptTokens: 0,
210
- completionTokens: 0,
211
- },
212
- });
213
- return;
214
- }
215
- const data = JSON.parse(singleChunk.data);
192
+ const chunkEvent = events(new Response(response));
193
+ let usage = { promptTokens: 0, completionTokens: 0 };
216
194
 
195
+ return {
196
+ stream: new ReadableStream<LanguageModelV1StreamPart>({
197
+ async start(controller) {
198
+ for await (const event of chunkEvent) {
199
+ if (!event.data) {
200
+ continue;
201
+ }
202
+ if (event.data === "[DONE]") {
203
+ break;
204
+ }
205
+ const chunk = JSON.parse(event.data);
206
+ if (chunk.usage) {
207
+ usage = mapWorkersAIUsage(chunk);
208
+ }
209
+ chunk.response.length &&
217
210
  controller.enqueue({
218
211
  type: "text-delta",
219
- textDelta: data.response ?? "DATALOSS",
212
+ textDelta: chunk.response,
220
213
  });
221
- }
222
- controller.enqueue({
223
- type: "finish",
224
- finishReason: "stop",
225
- usage: {
226
- promptTokens: 0,
227
- completionTokens: 0,
228
- },
229
- });
230
- },
231
- })
232
- ),
214
+ }
215
+ controller.enqueue({
216
+ type: "finish",
217
+ finishReason: "stop",
218
+ usage: usage,
219
+ });
220
+ controller.close();
221
+ },
222
+ }),
233
223
  rawCall: { rawPrompt: args.messages, rawSettings: args },
234
224
  warnings,
235
225
  };
@@ -7,6 +7,7 @@ export interface WorkersAIChatSettings {
7
7
  safePrompt?: boolean;
8
8
  /**
9
9
  * Optionally set Cloudflare AI Gateway options.
10
+ * @deprecated
10
11
  */
11
- gateway?: GatewayOptions
12
+ gateway?: GatewayOptions;
12
13
  }
@@ -1,8 +1,6 @@
1
1
  import {
2
2
  createJsonErrorResponseHandler,
3
- type ResponseHandler,
4
3
  } from "@ai-sdk/provider-utils";
5
- import type { APICallError } from "ai";
6
4
  import { z } from "zod";
7
5
 
8
6
  const workersAIErrorDataSchema = z.object({
@@ -13,9 +11,7 @@ const workersAIErrorDataSchema = z.object({
13
11
  code: z.string().nullable(),
14
12
  });
15
13
 
16
- export type WorkersAIErrorData = z.infer<typeof workersAIErrorDataSchema>;
17
-
18
- export const workersAIFailedResponseHandler: ResponseHandler<APICallError> =
14
+ export const workersAIFailedResponseHandler =
19
15
  createJsonErrorResponseHandler({
20
16
  errorSchema: workersAIErrorDataSchema,
21
17
  errorToMessage: (data) => data.message,
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The names of the BaseAiTextGeneration models.
3
+ */
4
+ export type TextGenerationModels = Exclude<
5
+ value2key<AiModels, BaseAiTextGeneration>,
6
+ value2key<AiModels, BaseAiTextToImage>
7
+ >;
8
+
9
+ type value2key<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];