@ai-sdk/openai-compatible 3.0.0-beta.4 → 3.0.0-beta.57

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +440 -8
  2. package/README.md +2 -0
  3. package/dist/index.d.ts +69 -8
  4. package/dist/index.js +548 -428
  5. package/dist/index.js.map +1 -1
  6. package/dist/internal/index.d.ts +20 -2
  7. package/dist/internal/index.js +91 -91
  8. package/dist/internal/index.js.map +1 -1
  9. package/docs/index.mdx +1 -0
  10. package/package.json +16 -17
  11. package/src/chat/convert-openai-compatible-chat-usage.ts +1 -1
  12. package/src/chat/convert-to-openai-compatible-chat-messages.ts +94 -73
  13. package/src/chat/map-openai-compatible-finish-reason.ts +1 -1
  14. package/src/chat/openai-compatible-api-types.ts +3 -5
  15. package/src/chat/openai-compatible-chat-language-model.ts +205 -191
  16. package/src/chat/openai-compatible-metadata-extractor.ts +1 -1
  17. package/src/chat/openai-compatible-prepare-tools.ts +2 -3
  18. package/src/completion/convert-openai-compatible-completion-usage.ts +1 -1
  19. package/src/completion/convert-to-openai-compatible-completion-prompt.ts +1 -2
  20. package/src/completion/map-openai-compatible-finish-reason.ts +1 -1
  21. package/src/completion/openai-compatible-completion-language-model.ts +52 -17
  22. package/src/embedding/openai-compatible-embedding-model.ts +36 -10
  23. package/src/image/openai-compatible-image-model.ts +35 -13
  24. package/src/index.ts +3 -3
  25. package/src/openai-compatible-error.ts +1 -2
  26. package/src/openai-compatible-provider.ts +18 -5
  27. package/src/utils/to-camel-case.ts +43 -0
  28. package/dist/index.d.mts +0 -290
  29. package/dist/index.mjs +0 -1742
  30. package/dist/index.mjs.map +0 -1
  31. package/dist/internal/index.d.mts +0 -193
  32. package/dist/internal/index.mjs +0 -340
  33. package/dist/internal/index.mjs.map +0 -1
  34. /package/src/chat/{openai-compatible-chat-options.ts → openai-compatible-chat-language-model-options.ts} +0 -0
  35. /package/src/completion/{openai-compatible-completion-options.ts → openai-compatible-completion-language-model-options.ts} +0 -0
  36. /package/src/embedding/{openai-compatible-embedding-options.ts → openai-compatible-embedding-model-options.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { JSONValue, LanguageModelV4Prompt, LanguageModelV4Usage, LanguageModelV4FinishReason, LanguageModelV4CallOptions, SharedV4Warning, SharedV4ProviderMetadata, LanguageModelV4 } from '@ai-sdk/provider';
2
2
  import { FetchFunction } from '@ai-sdk/provider-utils';
3
- import { ZodType } from 'zod/v4';
3
+ import { ZodType, z } from 'zod/v4';
4
4
 
5
5
  type OpenAICompatibleChatPrompt = Array<OpenAICompatibleMessage>;
6
6
  type OpenAICompatibleMessage = OpenAICompatibleSystemMessage | OpenAICompatibleUserMessage | OpenAICompatibleAssistantMessage | OpenAICompatibleToolMessage;
@@ -165,7 +165,7 @@ type MetadataExtractor = {
165
165
 
166
166
  type OpenAICompatibleChatConfig = {
167
167
  provider: string;
168
- headers: () => Record<string, string | undefined>;
168
+ headers?: () => Record<string, string | undefined>;
169
169
  url: (options: {
170
170
  modelId: string;
171
171
  path: string;
@@ -188,6 +188,24 @@ type OpenAICompatibleChatConfig = {
188
188
  * than the official OpenAI API.
189
189
  */
190
190
  transformRequestBody?: (args: Record<string, any>) => Record<string, any>;
191
+ /**
192
+ * Optional usage converter for OpenAI-compatible providers with different
193
+ * token accounting semantics.
194
+ */
195
+ convertUsage?: (usage: z.infer<typeof openaiCompatibleTokenUsageSchema>) => LanguageModelV4Usage;
191
196
  };
197
+ declare const openaiCompatibleTokenUsageSchema: z.ZodOptional<z.ZodNullable<z.ZodObject<{
198
+ prompt_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
199
+ completion_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
200
+ total_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
201
+ prompt_tokens_details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
202
+ cached_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
203
+ }, z.core.$strip>>>;
204
+ completion_tokens_details: z.ZodOptional<z.ZodNullable<z.ZodObject<{
205
+ reasoning_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
206
+ accepted_prediction_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
207
+ rejected_prediction_tokens: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
208
+ }, z.core.$strip>>>;
209
+ }, z.core.$loose>>>;
192
210
 
193
211
  export { type OpenAICompatibleChatConfig, convertOpenAICompatibleChatUsage, convertToOpenAICompatibleChatMessages, getResponseMetadata, mapOpenAICompatibleFinishReason, prepareTools };
@@ -1,36 +1,13 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/internal/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- convertOpenAICompatibleChatUsage: () => convertOpenAICompatibleChatUsage,
24
- convertToOpenAICompatibleChatMessages: () => convertToOpenAICompatibleChatMessages,
25
- getResponseMetadata: () => getResponseMetadata,
26
- mapOpenAICompatibleFinishReason: () => mapOpenAICompatibleFinishReason,
27
- prepareTools: () => prepareTools
28
- });
29
- module.exports = __toCommonJS(index_exports);
30
-
31
1
  // src/chat/convert-to-openai-compatible-chat-messages.ts
32
- var import_provider = require("@ai-sdk/provider");
33
- var import_provider_utils = require("@ai-sdk/provider-utils");
2
+ import {
3
+ UnsupportedFunctionalityError
4
+ } from "@ai-sdk/provider";
5
+ import {
6
+ convertBase64ToUint8Array,
7
+ convertToBase64,
8
+ getTopLevelMediaType,
9
+ resolveFullMediaType
10
+ } from "@ai-sdk/provider-utils";
34
11
  function getOpenAIMetadata(message) {
35
12
  var _a, _b;
36
13
  return (_b = (_a = message == null ? void 0 : message.providerOptions) == null ? void 0 : _a.openaiCompatible) != null ? _b : {};
@@ -75,65 +52,87 @@ function convertToOpenAICompatibleChatMessages(prompt) {
75
52
  return { type: "text", text: part.text, ...partMetadata };
76
53
  }
77
54
  case "file": {
78
- if (part.mediaType.startsWith("image/")) {
79
- const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType;
80
- return {
81
- type: "image_url",
82
- image_url: {
83
- url: part.data instanceof URL ? part.data.toString() : `data:${mediaType};base64,${(0, import_provider_utils.convertToBase64)(part.data)}`
84
- },
85
- ...partMetadata
86
- };
87
- }
88
- if (part.mediaType.startsWith("audio/")) {
89
- if (part.data instanceof URL) {
90
- throw new import_provider.UnsupportedFunctionalityError({
91
- functionality: "audio file parts with URLs"
55
+ switch (part.data.type) {
56
+ case "reference": {
57
+ throw new UnsupportedFunctionalityError({
58
+ functionality: "file parts with provider references"
92
59
  });
93
60
  }
94
- const format = getAudioFormat(part.mediaType);
95
- if (format === null) {
96
- throw new import_provider.UnsupportedFunctionalityError({
97
- functionality: `audio media type ${part.mediaType}`
61
+ case "text": {
62
+ throw new UnsupportedFunctionalityError({
63
+ functionality: "text file parts"
98
64
  });
99
65
  }
100
- return {
101
- type: "input_audio",
102
- input_audio: {
103
- data: (0, import_provider_utils.convertToBase64)(part.data),
104
- format
105
- },
106
- ...partMetadata
107
- };
108
- }
109
- if (part.mediaType === "application/pdf") {
110
- if (part.data instanceof URL) {
111
- throw new import_provider.UnsupportedFunctionalityError({
112
- functionality: "PDF file parts with URLs"
66
+ case "url":
67
+ case "data": {
68
+ const topLevel = getTopLevelMediaType(part.mediaType);
69
+ if (topLevel === "image") {
70
+ return {
71
+ type: "image_url",
72
+ image_url: {
73
+ url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`
74
+ },
75
+ ...partMetadata
76
+ };
77
+ }
78
+ if (topLevel === "audio") {
79
+ if (part.data.type === "url") {
80
+ throw new UnsupportedFunctionalityError({
81
+ functionality: "audio file parts with URLs"
82
+ });
83
+ }
84
+ const fullMediaType = resolveFullMediaType({ part });
85
+ const format = getAudioFormat(fullMediaType);
86
+ if (format === null) {
87
+ throw new UnsupportedFunctionalityError({
88
+ functionality: `audio media type ${fullMediaType}`
89
+ });
90
+ }
91
+ return {
92
+ type: "input_audio",
93
+ input_audio: {
94
+ data: convertToBase64(part.data.data),
95
+ format
96
+ },
97
+ ...partMetadata
98
+ };
99
+ }
100
+ if (topLevel === "application") {
101
+ if (part.data.type === "url") {
102
+ throw new UnsupportedFunctionalityError({
103
+ functionality: "PDF file parts with URLs"
104
+ });
105
+ }
106
+ const fullMediaType = resolveFullMediaType({ part });
107
+ if (fullMediaType !== "application/pdf") {
108
+ throw new UnsupportedFunctionalityError({
109
+ functionality: `file part media type ${fullMediaType}`
110
+ });
111
+ }
112
+ return {
113
+ type: "file",
114
+ file: {
115
+ filename: (_a2 = part.filename) != null ? _a2 : "document.pdf",
116
+ file_data: `data:application/pdf;base64,${convertToBase64(part.data.data)}`
117
+ },
118
+ ...partMetadata
119
+ };
120
+ }
121
+ if (topLevel === "text") {
122
+ const textContent = part.data.type === "url" ? part.data.url.toString() : typeof part.data.data === "string" ? new TextDecoder().decode(
123
+ convertBase64ToUint8Array(part.data.data)
124
+ ) : new TextDecoder().decode(part.data.data);
125
+ return {
126
+ type: "text",
127
+ text: textContent,
128
+ ...partMetadata
129
+ };
130
+ }
131
+ throw new UnsupportedFunctionalityError({
132
+ functionality: `file part media type ${part.mediaType}`
113
133
  });
114
134
  }
115
- return {
116
- type: "file",
117
- file: {
118
- filename: (_a2 = part.filename) != null ? _a2 : "document.pdf",
119
- file_data: `data:application/pdf;base64,${(0, import_provider_utils.convertToBase64)(part.data)}`
120
- },
121
- ...partMetadata
122
- };
123
- }
124
- if (part.mediaType.startsWith("text/")) {
125
- const textContent = part.data instanceof URL ? part.data.toString() : typeof part.data === "string" ? new TextDecoder().decode(
126
- (0, import_provider_utils.convertBase64ToUint8Array)(part.data)
127
- ) : new TextDecoder().decode(part.data);
128
- return {
129
- type: "text",
130
- text: textContent,
131
- ...partMetadata
132
- };
133
135
  }
134
- throw new import_provider.UnsupportedFunctionalityError({
135
- functionality: `file part media type ${part.mediaType}`
136
- });
137
136
  }
138
137
  }
139
138
  }),
@@ -181,7 +180,7 @@ function convertToOpenAICompatibleChatMessages(prompt) {
181
180
  }
182
181
  messages.push({
183
182
  role: "assistant",
184
- content: text,
183
+ content: toolCalls.length > 0 ? text || null : text,
185
184
  ...reasoning.length > 0 ? { reasoning_content: reasoning } : {},
186
185
  tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
187
186
  ...metadata
@@ -201,7 +200,7 @@ function convertToOpenAICompatibleChatMessages(prompt) {
201
200
  contentValue = output.value;
202
201
  break;
203
202
  case "execution-denied":
204
- contentValue = (_c = output.reason) != null ? _c : "Tool execution denied.";
203
+ contentValue = (_c = output.reason) != null ? _c : "Tool call execution denied.";
205
204
  break;
206
205
  case "content":
207
206
  case "json":
@@ -298,7 +297,9 @@ function getResponseMetadata({
298
297
  }
299
298
 
300
299
  // src/chat/openai-compatible-prepare-tools.ts
301
- var import_provider2 = require("@ai-sdk/provider");
300
+ import {
301
+ UnsupportedFunctionalityError as UnsupportedFunctionalityError2
302
+ } from "@ai-sdk/provider";
302
303
  function prepareTools({
303
304
  tools,
304
305
  toolChoice
@@ -347,18 +348,17 @@ function prepareTools({
347
348
  };
348
349
  default: {
349
350
  const _exhaustiveCheck = type;
350
- throw new import_provider2.UnsupportedFunctionalityError({
351
+ throw new UnsupportedFunctionalityError2({
351
352
  functionality: `tool choice type: ${_exhaustiveCheck}`
352
353
  });
353
354
  }
354
355
  }
355
356
  }
356
- // Annotate the CommonJS export names for ESM import in node:
357
- 0 && (module.exports = {
357
+ export {
358
358
  convertOpenAICompatibleChatUsage,
359
359
  convertToOpenAICompatibleChatMessages,
360
360
  getResponseMetadata,
361
361
  mapOpenAICompatibleFinishReason,
362
362
  prepareTools
363
- });
363
+ };
364
364
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/internal/index.ts","../../src/chat/convert-to-openai-compatible-chat-messages.ts","../../src/chat/convert-openai-compatible-chat-usage.ts","../../src/chat/map-openai-compatible-finish-reason.ts","../../src/chat/get-response-metadata.ts","../../src/chat/openai-compatible-prepare-tools.ts"],"sourcesContent":["export { convertToOpenAICompatibleChatMessages } from '../chat/convert-to-openai-compatible-chat-messages';\nexport { convertOpenAICompatibleChatUsage } from '../chat/convert-openai-compatible-chat-usage';\nexport { mapOpenAICompatibleFinishReason } from '../chat/map-openai-compatible-finish-reason';\nexport { getResponseMetadata } from '../chat/get-response-metadata';\nexport { prepareTools } from '../chat/openai-compatible-prepare-tools';\nexport type { OpenAICompatibleChatConfig } from '../chat/openai-compatible-chat-language-model';\n","import {\n LanguageModelV4Prompt,\n SharedV4ProviderMetadata,\n UnsupportedFunctionalityError,\n} from '@ai-sdk/provider';\nimport { OpenAICompatibleChatPrompt } from './openai-compatible-api-types';\nimport {\n convertBase64ToUint8Array,\n convertToBase64,\n} from '@ai-sdk/provider-utils';\n\nfunction getOpenAIMetadata(message: {\n providerOptions?: SharedV4ProviderMetadata;\n}) {\n return message?.providerOptions?.openaiCompatible ?? {};\n}\n\nfunction getAudioFormat(mediaType: string): 'wav' | 'mp3' | null {\n switch (mediaType) {\n case 'audio/wav':\n return 'wav';\n case 'audio/mp3':\n case 'audio/mpeg':\n return 'mp3';\n default:\n return null;\n }\n}\n\nexport function convertToOpenAICompatibleChatMessages(\n prompt: LanguageModelV4Prompt,\n): OpenAICompatibleChatPrompt {\n const messages: OpenAICompatibleChatPrompt = [];\n for (const { role, content, ...message } of prompt) {\n const metadata = getOpenAIMetadata({ ...message });\n switch (role) {\n case 'system': {\n messages.push({ role: 'system', content, ...metadata });\n break;\n }\n\n case 'user': {\n if (content.length === 1 && content[0].type === 'text') {\n messages.push({\n role: 'user',\n content: content[0].text,\n ...getOpenAIMetadata(content[0]),\n });\n break;\n }\n\n messages.push({\n role: 'user',\n content: content.map(part => {\n const partMetadata = getOpenAIMetadata(part);\n switch (part.type) {\n case 'text': {\n return { type: 'text', text: part.text, ...partMetadata };\n }\n case 'file': {\n if (part.mediaType.startsWith('image/')) {\n const mediaType =\n part.mediaType === 'image/*'\n ? 'image/jpeg'\n : part.mediaType;\n\n return {\n type: 'image_url',\n image_url: {\n url:\n part.data instanceof URL\n ? part.data.toString()\n : `data:${mediaType};base64,${convertToBase64(part.data)}`,\n },\n ...partMetadata,\n };\n }\n\n if (part.mediaType.startsWith('audio/')) {\n if (part.data instanceof URL) {\n throw new UnsupportedFunctionalityError({\n functionality: 'audio file parts with URLs',\n });\n }\n\n const format = getAudioFormat(part.mediaType);\n if (format === null) {\n throw new UnsupportedFunctionalityError({\n functionality: `audio media type ${part.mediaType}`,\n });\n }\n\n return {\n type: 'input_audio',\n input_audio: {\n data: convertToBase64(part.data),\n format,\n },\n ...partMetadata,\n };\n }\n\n if (part.mediaType === 'application/pdf') {\n if (part.data instanceof URL) {\n throw new UnsupportedFunctionalityError({\n functionality: 'PDF file parts with URLs',\n });\n }\n\n return {\n type: 'file',\n file: {\n filename: part.filename ?? 'document.pdf',\n file_data: `data:application/pdf;base64,${convertToBase64(part.data)}`,\n },\n ...partMetadata,\n };\n }\n\n if (part.mediaType.startsWith('text/')) {\n const textContent =\n part.data instanceof URL\n ? part.data.toString()\n : typeof part.data === 'string'\n ? new TextDecoder().decode(\n convertBase64ToUint8Array(part.data),\n )\n : new TextDecoder().decode(part.data);\n\n return {\n type: 'text',\n text: textContent,\n ...partMetadata,\n };\n }\n\n // Unsupported type\n throw new UnsupportedFunctionalityError({\n functionality: `file part media type ${part.mediaType}`,\n });\n }\n }\n }),\n ...metadata,\n });\n\n break;\n }\n\n case 'assistant': {\n let text = '';\n let reasoning = '';\n const toolCalls: Array<{\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n extra_content?: {\n google?: {\n thought_signature?: string;\n };\n };\n }> = [];\n\n for (const part of content) {\n const partMetadata = getOpenAIMetadata(part);\n switch (part.type) {\n case 'text': {\n text += part.text;\n break;\n }\n case 'reasoning': {\n reasoning += part.text;\n break;\n }\n case 'tool-call': {\n // TODO: thoughtSignature should be abstracted once we add support for other providers\n const thoughtSignature =\n part.providerOptions?.google?.thoughtSignature;\n toolCalls.push({\n id: part.toolCallId,\n type: 'function',\n function: {\n name: part.toolName,\n arguments: JSON.stringify(part.input),\n },\n ...partMetadata,\n // Include extra_content for Google Gemini thought signatures\n ...(thoughtSignature\n ? {\n extra_content: {\n google: {\n thought_signature: String(thoughtSignature),\n },\n },\n }\n : {}),\n });\n break;\n }\n }\n }\n\n messages.push({\n role: 'assistant',\n content: text,\n ...(reasoning.length > 0 ? { reasoning_content: reasoning } : {}),\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\n ...metadata,\n });\n\n break;\n }\n\n case 'tool': {\n for (const toolResponse of content) {\n if (toolResponse.type === 'tool-approval-response') {\n continue;\n }\n\n const output = toolResponse.output;\n\n let contentValue: string;\n switch (output.type) {\n case 'text':\n case 'error-text':\n contentValue = output.value;\n break;\n case 'execution-denied':\n contentValue = output.reason ?? 'Tool execution denied.';\n break;\n case 'content':\n case 'json':\n case 'error-json':\n contentValue = JSON.stringify(output.value);\n break;\n }\n\n const toolResponseMetadata = getOpenAIMetadata(toolResponse);\n messages.push({\n role: 'tool',\n tool_call_id: toolResponse.toolCallId,\n content: contentValue,\n ...toolResponseMetadata,\n });\n }\n break;\n }\n\n default: {\n const _exhaustiveCheck: never = role;\n throw new Error(`Unsupported role: ${_exhaustiveCheck}`);\n }\n }\n }\n\n return messages;\n}\n","import { LanguageModelV4Usage } from '@ai-sdk/provider';\n\nexport function convertOpenAICompatibleChatUsage(\n usage:\n | {\n prompt_tokens?: number | null;\n completion_tokens?: number | null;\n prompt_tokens_details?: {\n cached_tokens?: number | null;\n } | null;\n completion_tokens_details?: {\n reasoning_tokens?: number | null;\n } | null;\n }\n | undefined\n | null,\n): LanguageModelV4Usage {\n if (usage == null) {\n return {\n inputTokens: {\n total: undefined,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: undefined,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n }\n\n const promptTokens = usage.prompt_tokens ?? 0;\n const completionTokens = usage.completion_tokens ?? 0;\n const cacheReadTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;\n const reasoningTokens =\n usage.completion_tokens_details?.reasoning_tokens ?? 0;\n\n return {\n inputTokens: {\n total: promptTokens,\n noCache: promptTokens - cacheReadTokens,\n cacheRead: cacheReadTokens,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: completionTokens,\n text: completionTokens - reasoningTokens,\n reasoning: reasoningTokens,\n },\n raw: usage,\n };\n}\n","import { LanguageModelV4FinishReason } from '@ai-sdk/provider';\n\nexport function mapOpenAICompatibleFinishReason(\n finishReason: string | null | undefined,\n): LanguageModelV4FinishReason['unified'] {\n switch (finishReason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content-filter';\n case 'function_call':\n case 'tool_calls':\n return 'tool-calls';\n default:\n return 'other';\n }\n}\n","export function getResponseMetadata({\n id,\n model,\n created,\n}: {\n id?: string | undefined | null;\n created?: number | undefined | null;\n model?: string | undefined | null;\n}) {\n return {\n id: id ?? undefined,\n modelId: model ?? undefined,\n timestamp: created != null ? new Date(created * 1000) : undefined,\n };\n}\n","import {\n LanguageModelV4CallOptions,\n SharedV4Warning,\n UnsupportedFunctionalityError,\n} from '@ai-sdk/provider';\n\nexport function prepareTools({\n tools,\n toolChoice,\n}: {\n tools: LanguageModelV4CallOptions['tools'];\n toolChoice?: LanguageModelV4CallOptions['toolChoice'];\n}): {\n tools:\n | undefined\n | Array<{\n type: 'function';\n function: {\n name: string;\n description: string | undefined;\n parameters: unknown;\n strict?: boolean;\n };\n }>;\n toolChoice:\n | { type: 'function'; function: { name: string } }\n | 'auto'\n | 'none'\n | 'required'\n | undefined;\n toolWarnings: SharedV4Warning[];\n} {\n // when the tools array is empty, change it to undefined to prevent errors:\n tools = tools?.length ? tools : undefined;\n\n const toolWarnings: SharedV4Warning[] = [];\n\n if (tools == null) {\n return { tools: undefined, toolChoice: undefined, toolWarnings };\n }\n\n const openaiCompatTools: Array<{\n type: 'function';\n function: {\n name: string;\n description: string | undefined;\n parameters: unknown;\n strict?: boolean;\n };\n }> = [];\n\n for (const tool of tools) {\n if (tool.type === 'provider') {\n toolWarnings.push({\n type: 'unsupported',\n feature: `provider-defined tool ${tool.id}`,\n });\n } else {\n openaiCompatTools.push({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema,\n ...(tool.strict != null ? { strict: tool.strict } : {}),\n },\n });\n }\n }\n\n if (toolChoice == null) {\n return { tools: openaiCompatTools, toolChoice: undefined, toolWarnings };\n }\n\n const type = toolChoice.type;\n\n switch (type) {\n case 'auto':\n case 'none':\n case 'required':\n return { tools: openaiCompatTools, toolChoice: type, toolWarnings };\n case 'tool':\n return {\n tools: openaiCompatTools,\n toolChoice: {\n type: 'function',\n function: { name: toolChoice.toolName },\n },\n toolWarnings,\n };\n default: {\n const _exhaustiveCheck: never = type;\n throw new UnsupportedFunctionalityError({\n functionality: `tool choice type: ${_exhaustiveCheck}`,\n });\n }\n }\n}\n"],"mappings":"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","names":["_a","import_provider"]}
1
+ {"version":3,"sources":["../../src/chat/convert-to-openai-compatible-chat-messages.ts","../../src/chat/convert-openai-compatible-chat-usage.ts","../../src/chat/map-openai-compatible-finish-reason.ts","../../src/chat/get-response-metadata.ts","../../src/chat/openai-compatible-prepare-tools.ts"],"sourcesContent":["import {\n UnsupportedFunctionalityError,\n type LanguageModelV4Prompt,\n type SharedV4ProviderMetadata,\n} from '@ai-sdk/provider';\nimport type { OpenAICompatibleChatPrompt } from './openai-compatible-api-types';\nimport {\n convertBase64ToUint8Array,\n convertToBase64,\n getTopLevelMediaType,\n resolveFullMediaType,\n} from '@ai-sdk/provider-utils';\n\nfunction getOpenAIMetadata(message: {\n providerOptions?: SharedV4ProviderMetadata;\n}) {\n return message?.providerOptions?.openaiCompatible ?? {};\n}\n\nfunction getAudioFormat(mediaType: string): 'wav' | 'mp3' | null {\n switch (mediaType) {\n case 'audio/wav':\n return 'wav';\n case 'audio/mp3':\n case 'audio/mpeg':\n return 'mp3';\n default:\n return null;\n }\n}\n\nexport function convertToOpenAICompatibleChatMessages(\n prompt: LanguageModelV4Prompt,\n): OpenAICompatibleChatPrompt {\n const messages: OpenAICompatibleChatPrompt = [];\n for (const { role, content, ...message } of prompt) {\n const metadata = getOpenAIMetadata({ ...message });\n switch (role) {\n case 'system': {\n messages.push({ role: 'system', content, ...metadata });\n break;\n }\n\n case 'user': {\n if (content.length === 1 && content[0].type === 'text') {\n messages.push({\n role: 'user',\n content: content[0].text,\n ...getOpenAIMetadata(content[0]),\n });\n break;\n }\n\n messages.push({\n role: 'user',\n content: content.map(part => {\n const partMetadata = getOpenAIMetadata(part);\n switch (part.type) {\n case 'text': {\n return { type: 'text', text: part.text, ...partMetadata };\n }\n case 'file': {\n switch (part.data.type) {\n case 'reference': {\n throw new UnsupportedFunctionalityError({\n functionality: 'file parts with provider references',\n });\n }\n case 'text': {\n throw new UnsupportedFunctionalityError({\n functionality: 'text file parts',\n });\n }\n case 'url':\n case 'data': {\n const topLevel = getTopLevelMediaType(part.mediaType);\n\n if (topLevel === 'image') {\n return {\n type: 'image_url',\n image_url: {\n url:\n part.data.type === 'url'\n ? part.data.url.toString()\n : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`,\n },\n ...partMetadata,\n };\n }\n\n if (topLevel === 'audio') {\n if (part.data.type === 'url') {\n throw new UnsupportedFunctionalityError({\n functionality: 'audio file parts with URLs',\n });\n }\n\n const fullMediaType = resolveFullMediaType({ part });\n const format = getAudioFormat(fullMediaType);\n if (format === null) {\n throw new UnsupportedFunctionalityError({\n functionality: `audio media type ${fullMediaType}`,\n });\n }\n\n return {\n type: 'input_audio',\n input_audio: {\n data: convertToBase64(part.data.data),\n format,\n },\n ...partMetadata,\n };\n }\n\n if (topLevel === 'application') {\n if (part.data.type === 'url') {\n throw new UnsupportedFunctionalityError({\n functionality: 'PDF file parts with URLs',\n });\n }\n\n const fullMediaType = resolveFullMediaType({ part });\n if (fullMediaType !== 'application/pdf') {\n throw new UnsupportedFunctionalityError({\n functionality: `file part media type ${fullMediaType}`,\n });\n }\n\n return {\n type: 'file',\n file: {\n filename: part.filename ?? 'document.pdf',\n file_data: `data:application/pdf;base64,${convertToBase64(part.data.data)}`,\n },\n ...partMetadata,\n };\n }\n\n if (topLevel === 'text') {\n const textContent =\n part.data.type === 'url'\n ? part.data.url.toString()\n : typeof part.data.data === 'string'\n ? new TextDecoder().decode(\n convertBase64ToUint8Array(part.data.data),\n )\n : new TextDecoder().decode(part.data.data);\n\n return {\n type: 'text',\n text: textContent,\n ...partMetadata,\n };\n }\n\n throw new UnsupportedFunctionalityError({\n functionality: `file part media type ${part.mediaType}`,\n });\n }\n }\n }\n }\n }),\n ...metadata,\n });\n\n break;\n }\n\n case 'assistant': {\n let text = '';\n let reasoning = '';\n const toolCalls: Array<{\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n extra_content?: {\n google?: {\n thought_signature?: string;\n };\n };\n }> = [];\n\n for (const part of content) {\n const partMetadata = getOpenAIMetadata(part);\n switch (part.type) {\n case 'text': {\n text += part.text;\n break;\n }\n case 'reasoning': {\n reasoning += part.text;\n break;\n }\n case 'tool-call': {\n // TODO: thoughtSignature should be abstracted once we add support for other providers\n const thoughtSignature =\n part.providerOptions?.google?.thoughtSignature;\n toolCalls.push({\n id: part.toolCallId,\n type: 'function',\n function: {\n name: part.toolName,\n arguments: JSON.stringify(part.input),\n },\n ...partMetadata,\n // Include extra_content for Google Gemini thought signatures\n ...(thoughtSignature\n ? {\n extra_content: {\n google: {\n thought_signature: String(thoughtSignature),\n },\n },\n }\n : {}),\n });\n break;\n }\n }\n }\n\n messages.push({\n role: 'assistant',\n content: toolCalls.length > 0 ? text || null : text,\n ...(reasoning.length > 0 ? { reasoning_content: reasoning } : {}),\n tool_calls: toolCalls.length > 0 ? toolCalls : undefined,\n ...metadata,\n });\n\n break;\n }\n\n case 'tool': {\n for (const toolResponse of content) {\n if (toolResponse.type === 'tool-approval-response') {\n continue;\n }\n\n const output = toolResponse.output;\n\n let contentValue: string;\n switch (output.type) {\n case 'text':\n case 'error-text':\n contentValue = output.value;\n break;\n case 'execution-denied':\n contentValue = output.reason ?? 'Tool call execution denied.';\n break;\n case 'content':\n case 'json':\n case 'error-json':\n contentValue = JSON.stringify(output.value);\n break;\n }\n\n const toolResponseMetadata = getOpenAIMetadata(toolResponse);\n messages.push({\n role: 'tool',\n tool_call_id: toolResponse.toolCallId,\n content: contentValue,\n ...toolResponseMetadata,\n });\n }\n break;\n }\n\n default: {\n const _exhaustiveCheck: never = role;\n throw new Error(`Unsupported role: ${_exhaustiveCheck}`);\n }\n }\n }\n\n return messages;\n}\n","import type { LanguageModelV4Usage } from '@ai-sdk/provider';\n\nexport function convertOpenAICompatibleChatUsage(\n usage:\n | {\n prompt_tokens?: number | null;\n completion_tokens?: number | null;\n prompt_tokens_details?: {\n cached_tokens?: number | null;\n } | null;\n completion_tokens_details?: {\n reasoning_tokens?: number | null;\n } | null;\n }\n | undefined\n | null,\n): LanguageModelV4Usage {\n if (usage == null) {\n return {\n inputTokens: {\n total: undefined,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: undefined,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n }\n\n const promptTokens = usage.prompt_tokens ?? 0;\n const completionTokens = usage.completion_tokens ?? 0;\n const cacheReadTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;\n const reasoningTokens =\n usage.completion_tokens_details?.reasoning_tokens ?? 0;\n\n return {\n inputTokens: {\n total: promptTokens,\n noCache: promptTokens - cacheReadTokens,\n cacheRead: cacheReadTokens,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: completionTokens,\n text: completionTokens - reasoningTokens,\n reasoning: reasoningTokens,\n },\n raw: usage,\n };\n}\n","import type { LanguageModelV4FinishReason } from '@ai-sdk/provider';\n\nexport function mapOpenAICompatibleFinishReason(\n finishReason: string | null | undefined,\n): LanguageModelV4FinishReason['unified'] {\n switch (finishReason) {\n case 'stop':\n return 'stop';\n case 'length':\n return 'length';\n case 'content_filter':\n return 'content-filter';\n case 'function_call':\n case 'tool_calls':\n return 'tool-calls';\n default:\n return 'other';\n }\n}\n","export function getResponseMetadata({\n id,\n model,\n created,\n}: {\n id?: string | undefined | null;\n created?: number | undefined | null;\n model?: string | undefined | null;\n}) {\n return {\n id: id ?? undefined,\n modelId: model ?? undefined,\n timestamp: created != null ? new Date(created * 1000) : undefined,\n };\n}\n","import {\n UnsupportedFunctionalityError,\n type LanguageModelV4CallOptions,\n type SharedV4Warning,\n} from '@ai-sdk/provider';\nexport function prepareTools({\n tools,\n toolChoice,\n}: {\n tools: LanguageModelV4CallOptions['tools'];\n toolChoice?: LanguageModelV4CallOptions['toolChoice'];\n}): {\n tools:\n | undefined\n | Array<{\n type: 'function';\n function: {\n name: string;\n description: string | undefined;\n parameters: unknown;\n strict?: boolean;\n };\n }>;\n toolChoice:\n | { type: 'function'; function: { name: string } }\n | 'auto'\n | 'none'\n | 'required'\n | undefined;\n toolWarnings: SharedV4Warning[];\n} {\n // when the tools array is empty, change it to undefined to prevent errors:\n tools = tools?.length ? tools : undefined;\n\n const toolWarnings: SharedV4Warning[] = [];\n\n if (tools == null) {\n return { tools: undefined, toolChoice: undefined, toolWarnings };\n }\n\n const openaiCompatTools: Array<{\n type: 'function';\n function: {\n name: string;\n description: string | undefined;\n parameters: unknown;\n strict?: boolean;\n };\n }> = [];\n\n for (const tool of tools) {\n if (tool.type === 'provider') {\n toolWarnings.push({\n type: 'unsupported',\n feature: `provider-defined tool ${tool.id}`,\n });\n } else {\n openaiCompatTools.push({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema,\n ...(tool.strict != null ? { strict: tool.strict } : {}),\n },\n });\n }\n }\n\n if (toolChoice == null) {\n return { tools: openaiCompatTools, toolChoice: undefined, toolWarnings };\n }\n\n const type = toolChoice.type;\n\n switch (type) {\n case 'auto':\n case 'none':\n case 'required':\n return { tools: openaiCompatTools, toolChoice: type, toolWarnings };\n case 'tool':\n return {\n tools: openaiCompatTools,\n toolChoice: {\n type: 'function',\n function: { name: toolChoice.toolName },\n },\n toolWarnings,\n };\n default: {\n const _exhaustiveCheck: never = type;\n throw new UnsupportedFunctionalityError({\n functionality: `tool choice type: ${_exhaustiveCheck}`,\n });\n }\n }\n}\n"],"mappings":"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","names":["_a","UnsupportedFunctionalityError"]}
package/docs/index.mdx CHANGED
@@ -15,6 +15,7 @@ We provide detailed documentation for the following OpenAI compatible providers:
15
15
  - [NIM](/providers/openai-compatible-providers/nim)
16
16
  - [Heroku](/providers/openai-compatible-providers/heroku)
17
17
  - [Clarifai](/providers/openai-compatible-providers/clarifai)
18
+ - [NEAR AI Cloud](/providers/openai-compatible-providers/nearai)
18
19
 
19
20
  The general setup and provider instance creation is the same for all of these providers.
20
21
 
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@ai-sdk/openai-compatible",
3
- "version": "3.0.0-beta.4",
3
+ "version": "3.0.0-beta.57",
4
+ "type": "module",
4
5
  "license": "Apache-2.0",
5
6
  "sideEffects": false,
6
7
  "main": "./dist/index.js",
7
- "module": "./dist/index.mjs",
8
8
  "types": "./dist/index.d.ts",
9
9
  "files": [
10
10
  "dist/**/*",
@@ -25,41 +25,42 @@
25
25
  "./package.json": "./package.json",
26
26
  ".": {
27
27
  "types": "./dist/index.d.ts",
28
- "import": "./dist/index.mjs",
29
- "require": "./dist/index.js"
28
+ "import": "./dist/index.js",
29
+ "default": "./dist/index.js"
30
30
  },
31
31
  "./internal": {
32
32
  "types": "./dist/internal/index.d.ts",
33
- "import": "./dist/internal/index.mjs",
34
- "module": "./dist/internal/index.mjs",
35
- "require": "./dist/internal/index.js"
33
+ "import": "./dist/internal/index.js",
34
+ "default": "./dist/internal/index.js"
36
35
  }
37
36
  },
38
37
  "dependencies": {
39
- "@ai-sdk/provider": "4.0.0-beta.1",
40
- "@ai-sdk/provider-utils": "5.0.0-beta.2"
38
+ "@ai-sdk/provider": "4.0.0-beta.19",
39
+ "@ai-sdk/provider-utils": "5.0.0-beta.49"
41
40
  },
42
41
  "devDependencies": {
43
- "@types/node": "20.17.24",
44
- "tsup": "^8",
42
+ "@types/node": "22.19.19",
43
+ "tsup": "^8.5.1",
45
44
  "typescript": "5.8.3",
46
45
  "zod": "3.25.76",
47
- "@ai-sdk/test-server": "2.0.0-beta.0",
46
+ "@ai-sdk/test-server": "2.0.0-beta.7",
48
47
  "@vercel/ai-tsconfig": "0.0.0"
49
48
  },
50
49
  "peerDependencies": {
51
50
  "zod": "^3.25.76 || ^4.1.8"
52
51
  },
53
52
  "engines": {
54
- "node": ">=18"
53
+ "node": ">=22"
55
54
  },
56
55
  "publishConfig": {
57
- "access": "public"
56
+ "access": "public",
57
+ "provenance": true
58
58
  },
59
59
  "homepage": "https://ai-sdk.dev/docs",
60
60
  "repository": {
61
61
  "type": "git",
62
- "url": "git+https://github.com/vercel/ai.git"
62
+ "url": "https://github.com/vercel/ai",
63
+ "directory": "packages/openai-compatible"
63
64
  },
64
65
  "bugs": {
65
66
  "url": "https://github.com/vercel/ai/issues"
@@ -71,9 +72,7 @@
71
72
  "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
72
73
  "build:watch": "pnpm clean && tsup --watch",
73
74
  "clean": "del-cli dist docs *.tsbuildinfo",
74
- "lint": "eslint \"./**/*.ts*\"",
75
75
  "type-check": "tsc --build",
76
- "prettier-check": "prettier --check \"./**/*.ts*\"",
77
76
  "test": "pnpm test:node && pnpm test:edge",
78
77
  "test:update": "pnpm test:node -u",
79
78
  "test:watch": "vitest --config vitest.node.config.js",
@@ -1,4 +1,4 @@
1
- import { LanguageModelV4Usage } from '@ai-sdk/provider';
1
+ import type { LanguageModelV4Usage } from '@ai-sdk/provider';
2
2
 
3
3
  export function convertOpenAICompatibleChatUsage(
4
4
  usage: