@ai-sdk/openai-compatible 3.0.81 → 3.0.83
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/CHANGELOG.md +25 -0
- package/dist/index.d.ts +8 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -24
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +2 -2
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +13 -4
- package/dist/internal/index.js.map +1 -1
- package/docs/index.mdx +4 -1
- package/package.json +3 -3
- package/src/chat/convert-to-openai-compatible-chat-messages.ts +17 -3
- package/src/chat/openai-compatible-chat-language-model-options.ts +4 -1
- package/src/chat/openai-compatible-chat-language-model.ts +26 -10
- package/src/completion/openai-compatible-completion-language-model.ts +11 -3
- package/src/embedding/openai-compatible-embedding-model.ts +4 -2
- package/src/image/openai-compatible-image-model.ts +14 -6
- package/src/openai-compatible-provider.ts +13 -7
package/dist/internal/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JSONValue, LanguageModelV4, LanguageModelV4CallOptions, LanguageModelV4FinishReason, LanguageModelV4Prompt, LanguageModelV4Usage, SharedV4ProviderMetadata, SharedV4Warning } from "@ai-sdk/provider";
|
|
2
|
-
import { FetchFunction } from "@ai-sdk/provider-utils";
|
|
2
|
+
import { FetchFunction, Resolvable } from "@ai-sdk/provider-utils";
|
|
3
3
|
import { ZodType, z } from "zod/v4";
|
|
4
4
|
//#region src/chat/openai-compatible-api-types.d.ts
|
|
5
5
|
type OpenAICompatibleChatPrompt = Array<OpenAICompatibleMessage>;
|
|
@@ -181,7 +181,7 @@ type MetadataExtractor = {
|
|
|
181
181
|
//#region src/chat/openai-compatible-chat-language-model.d.ts
|
|
182
182
|
type OpenAICompatibleChatConfig = {
|
|
183
183
|
provider: string;
|
|
184
|
-
headers?:
|
|
184
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
185
185
|
url: (options: {
|
|
186
186
|
modelId: string;
|
|
187
187
|
path: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/chat/openai-compatible-api-types.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","../../src/openai-compatible-error.ts","../../src/chat/openai-compatible-metadata-extractor.ts","../../src/chat/openai-compatible-chat-language-model.ts"],"mappings":";;;;KAEY,6BAA6B,MAAM;KAEnC,0BACR,gCACA,8BACA,mCACA;KAIC,WAAW,aAAa,eAE3B,YAAY,cAAc,IAAI;UAGf,sCAAsC;EACrD;EACA;;UAGe,oCAAoC,WAAW;EAC9D;EACA,kBAAkB,MAAM;;KAGd,8BACR,kCACA,mCACA,mCACA,wCACA;UAEa,wCAAwC;EACvD;EACA;;UAGe,yCAAyC;EACxD;EACA;IAAa;;;UAIE,yCAAyC;EACxD;EACA;IAAa;;;UAIE,8CAA8C;EAC7D;EACA;IAAe;IAAc;;;UAGd,wCAAwC;EACvD;EACA;IAAQ;IAAkB;;IAAwB;;;UAGnC,yCAAyC,WAAW;EACnE;EACA;EACA;EACA,aAAa,MAAM;;UAGJ,wCAAwC;EACvD;EACA;EACA;IACE;IACA;;;;;;EAMF;IACE;MACE;;;;UAKW,oCAAoC;EACnD;EACA,kBAAkB,MAAM;EACxB;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/chat/openai-compatible-api-types.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","../../src/openai-compatible-error.ts","../../src/chat/openai-compatible-metadata-extractor.ts","../../src/chat/openai-compatible-chat-language-model.ts"],"mappings":";;;;KAEY,6BAA6B,MAAM;KAEnC,0BACR,gCACA,8BACA,mCACA;KAIC,WAAW,aAAa,eAE3B,YAAY,cAAc,IAAI;UAGf,sCAAsC;EACrD;EACA;;UAGe,oCAAoC,WAAW;EAC9D;EACA,kBAAkB,MAAM;;KAGd,8BACR,kCACA,mCACA,mCACA,wCACA;UAEa,wCAAwC;EACvD;EACA;;UAGe,yCAAyC;EACxD;EACA;IAAa;;;UAIE,yCAAyC;EACxD;EACA;IAAa;;;UAIE,8CAA8C;EAC7D;EACA;IAAe;IAAc;;;UAGd,wCAAwC;EACvD;EACA;IAAQ;IAAkB;;IAAwB;;;UAGnC,yCAAyC,WAAW;EACnE;EACA;EACA;EACA,aAAa,MAAM;;UAGJ,wCAAwC;EACvD;EACA;EACA;IACE;IACA;;;;;;EAMF;IACE;MACE;;;;UAKW,oCAAoC;EACnD;EACA,kBAAkB,MAAM;EACxB;;;;wBCiHc,sCACd,QAAQ,yBAEN,UACA,oBACA;EAEA;EACA;EACA;IAED;;;wBClNa,iCACd;EAEM;EACA;EACA;IACE;;EAEF;IACE;;uBAKP;;;wBCfa,gCACd,0CACC;;;wBCFa,sBACd,IACA,OACA;EAEA;EACA;EACA;+BACD;;;wBCLe,eACd,OACA;EAEA,OAAO;EACP,aAAa;;EAEb,mBAEI;IACE;IACA;MACE;MACA;MACA;MACA;;;EAGR;IACM;IAAkB;MAAY;;;EAKpC,cAAc;;;;KCXJ,uBAAuB;EACjC,aAAa,QAAQ;EACrB,iBAAiB,OAAO;EACxB,eAAe,UAAU,UAAU,QAAQ;;;;;;;;;KCdjC;;;;;;;;;EASV,oBACE;IAEA;QACI,QAAQ;;;;;;;;EASd;;;;;;;IAOE,aAAa;;;;;;;;IASb,iBAAiB;;;;;KCoBT;EACV;EACA,UAAU,WAAW;EACrB,MAAM;IAAW;IAAiB;;EAClC,QAAQ;EACR;EACA,iBAAiB;EACjB,oBAAoB;;;;EAKpB;;;;EAKA;;;;EAKA,sBAAsB;;;;;;;EAQtB,wBACE,MAAM,qBACN,WAAW,sBACR;;;;;;;EAQL,gBAAgB;IACd,WAAW,QACT;IAGF,UAAU;;;;;;EAOZ,gBACE,OAAO,EAAE,MAAM,kBAAkB,uCAC9B;;cAmsBD,wCAAgC,EAAA,YAAA,EAAA,YAAA,EAAA;;;;;;;;;;;;GAmBxB,EAAA,KAAA"}
|
package/dist/internal/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UnsupportedFunctionalityError } from "@ai-sdk/provider";
|
|
2
|
-
import { convertBase64ToUint8Array, convertToBase64, createLanguageModelResponseMetadata, createNullLanguageModelUsage, getTopLevelMediaType, resolveFullMediaType, resolveProviderReference } from "@ai-sdk/provider-utils";
|
|
2
|
+
import { convertBase64ToUint8Array, convertToBase64, createLanguageModelResponseMetadata, createNullLanguageModelUsage, getTopLevelMediaType, resolveFullMediaType, resolveProviderReference, secureJsonParse, stringifyWithBigIntAndCycles } from "@ai-sdk/provider-utils";
|
|
3
3
|
//#region src/chat/convert-to-openai-compatible-chat-messages.ts
|
|
4
4
|
function getOpenAIMetadata(message) {
|
|
5
5
|
return message?.providerOptions?.openaiCompatible ?? {};
|
|
@@ -84,6 +84,15 @@ function convertToolContentPart(part, provider) {
|
|
|
84
84
|
if (part.type === "custom") throw new UnsupportedFunctionalityError({ functionality: "custom tool content parts" });
|
|
85
85
|
return convertToOpenAICompatibleContentPart(part, provider);
|
|
86
86
|
}
|
|
87
|
+
function serializeToolCallArguments(input) {
|
|
88
|
+
if (typeof input === "string") try {
|
|
89
|
+
secureJsonParse(input);
|
|
90
|
+
return input;
|
|
91
|
+
} catch {
|
|
92
|
+
return JSON.stringify(input);
|
|
93
|
+
}
|
|
94
|
+
return stringifyWithBigIntAndCycles(input);
|
|
95
|
+
}
|
|
87
96
|
function convertToOpenAICompatibleChatMessages(prompt, { provider = "openaiCompatible", providerOptionsKey = "google", supportsMultiPartToolContent = false } = {}) {
|
|
88
97
|
const messages = [];
|
|
89
98
|
for (const { role, content, ...message } of prompt) {
|
|
@@ -131,7 +140,7 @@ function convertToOpenAICompatibleChatMessages(prompt, { provider = "openaiCompa
|
|
|
131
140
|
type: "function",
|
|
132
141
|
function: {
|
|
133
142
|
name: part.toolName,
|
|
134
|
-
arguments:
|
|
143
|
+
arguments: serializeToolCallArguments(part.input)
|
|
135
144
|
},
|
|
136
145
|
...partMetadata,
|
|
137
146
|
...thoughtSignature ? { extra_content: { google: { thought_signature: String(thoughtSignature) } } } : {}
|
|
@@ -164,9 +173,9 @@ function convertToOpenAICompatibleChatMessages(prompt, { provider = "openaiCompa
|
|
|
164
173
|
break;
|
|
165
174
|
case "json":
|
|
166
175
|
case "error-json":
|
|
167
|
-
contentValue =
|
|
176
|
+
contentValue = stringifyWithBigIntAndCycles(output.value);
|
|
168
177
|
break;
|
|
169
|
-
case "content": contentValue = supportsMultiPartToolContent ? output.value.map((part) => convertToolContentPart(part, provider)) :
|
|
178
|
+
case "content": contentValue = supportsMultiPartToolContent ? output.value.map((part) => convertToolContentPart(part, provider)) : stringifyWithBigIntAndCycles(output.value);
|
|
170
179
|
}
|
|
171
180
|
const toolResponseMetadata = getOpenAIMetadata(toolResponse);
|
|
172
181
|
messages.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_exhaustiveCheck","_exhaustiveCheck"],"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 LanguageModelV4FilePart,\n type LanguageModelV4Prompt,\n type LanguageModelV4TextPart,\n type LanguageModelV4ToolResultOutput,\n type SharedV4ProviderMetadata,\n} from '@ai-sdk/provider';\nimport type {\n OpenAICompatibleChatPrompt,\n OpenAICompatibleContentPart,\n} from './openai-compatible-api-types';\nimport {\n convertBase64ToUint8Array,\n convertToBase64,\n getTopLevelMediaType,\n resolveFullMediaType,\n resolveProviderReference,\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\nfunction convertToOpenAICompatibleContentPart(\n part: LanguageModelV4TextPart | LanguageModelV4FilePart,\n provider: string,\n): OpenAICompatibleContentPart {\n const partMetadata = getOpenAIMetadata(part);\n\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 return {\n type: 'file',\n file: {\n file_id: resolveProviderReference({\n reference: part.data.reference,\n provider,\n }),\n },\n ...partMetadata,\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 === 'video') {\n return {\n type: 'video_url',\n video_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\nfunction convertToolContentPart(\n part: Extract<\n LanguageModelV4ToolResultOutput,\n { type: 'content' }\n >['value'][number],\n provider: string,\n): OpenAICompatibleContentPart {\n if (part.type === 'custom') {\n throw new UnsupportedFunctionalityError({\n functionality: 'custom tool content parts',\n });\n }\n\n return convertToOpenAICompatibleContentPart(part, provider);\n}\n\nexport function convertToOpenAICompatibleChatMessages(\n prompt: LanguageModelV4Prompt,\n {\n provider = 'openaiCompatible',\n providerOptionsKey = 'google',\n supportsMultiPartToolContent = false,\n }: {\n provider?: string;\n providerOptionsKey?: string;\n supportsMultiPartToolContent?: boolean;\n } = {},\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 convertToOpenAICompatibleContentPart(part, provider),\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?.[providerOptionsKey]?.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 | Array<OpenAICompatibleContentPart>;\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 'json':\n case 'error-json':\n contentValue = JSON.stringify(output.value);\n break;\n case 'content':\n contentValue = supportsMultiPartToolContent\n ? output.value.map(part =>\n convertToolContentPart(part, provider),\n )\n : 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';\nimport { createNullLanguageModelUsage } from '@ai-sdk/provider-utils';\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 createNullLanguageModelUsage();\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: Math.max(0, 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","import { createLanguageModelResponseMetadata } from '@ai-sdk/provider-utils';\n\nexport function getResponseMetadata({\n id,\n model,\n created,\n}: {\n id?: string | null;\n model?: string | null;\n created?: number | null;\n}) {\n return createLanguageModelResponseMetadata({\n id,\n model,\n // Some OpenAI-compatible providers use 0 as a placeholder timestamp.\n created: created || 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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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_exhaustiveCheck","_exhaustiveCheck"],"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 LanguageModelV4FilePart,\n type LanguageModelV4Prompt,\n type LanguageModelV4TextPart,\n type LanguageModelV4ToolResultOutput,\n type SharedV4ProviderMetadata,\n} from '@ai-sdk/provider';\nimport type {\n OpenAICompatibleChatPrompt,\n OpenAICompatibleContentPart,\n} from './openai-compatible-api-types';\nimport {\n secureJsonParse,\n stringifyWithBigIntAndCycles,\n convertBase64ToUint8Array,\n convertToBase64,\n getTopLevelMediaType,\n resolveFullMediaType,\n resolveProviderReference,\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\nfunction convertToOpenAICompatibleContentPart(\n part: LanguageModelV4TextPart | LanguageModelV4FilePart,\n provider: string,\n): OpenAICompatibleContentPart {\n const partMetadata = getOpenAIMetadata(part);\n\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 return {\n type: 'file',\n file: {\n file_id: resolveProviderReference({\n reference: part.data.reference,\n provider,\n }),\n },\n ...partMetadata,\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 === 'video') {\n return {\n type: 'video_url',\n video_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\nfunction convertToolContentPart(\n part: Extract<\n LanguageModelV4ToolResultOutput,\n { type: 'content' }\n >['value'][number],\n provider: string,\n): OpenAICompatibleContentPart {\n if (part.type === 'custom') {\n throw new UnsupportedFunctionalityError({\n functionality: 'custom tool content parts',\n });\n }\n\n return convertToOpenAICompatibleContentPart(part, provider);\n}\n\nfunction serializeToolCallArguments(input: unknown): string {\n if (typeof input === 'string') {\n try {\n secureJsonParse(input);\n return input;\n } catch {\n return JSON.stringify(input);\n }\n }\n return stringifyWithBigIntAndCycles(input);\n}\n\nexport function convertToOpenAICompatibleChatMessages(\n prompt: LanguageModelV4Prompt,\n {\n provider = 'openaiCompatible',\n providerOptionsKey = 'google',\n supportsMultiPartToolContent = false,\n }: {\n provider?: string;\n providerOptionsKey?: string;\n supportsMultiPartToolContent?: boolean;\n } = {},\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 convertToOpenAICompatibleContentPart(part, provider),\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?.[providerOptionsKey]?.thoughtSignature ??\n part.providerOptions?.google?.thoughtSignature;\n toolCalls.push({\n id: part.toolCallId,\n type: 'function',\n function: {\n name: part.toolName,\n arguments: serializeToolCallArguments(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 | Array<OpenAICompatibleContentPart>;\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 'json':\n case 'error-json':\n contentValue = stringifyWithBigIntAndCycles(output.value);\n break;\n case 'content':\n contentValue = supportsMultiPartToolContent\n ? output.value.map(part =>\n convertToolContentPart(part, provider),\n )\n : stringifyWithBigIntAndCycles(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';\nimport { createNullLanguageModelUsage } from '@ai-sdk/provider-utils';\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 createNullLanguageModelUsage();\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: Math.max(0, 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","import { createLanguageModelResponseMetadata } from '@ai-sdk/provider-utils';\n\nexport function getResponseMetadata({\n id,\n model,\n created,\n}: {\n id?: string | null;\n model?: string | null;\n created?: number | null;\n}) {\n return createLanguageModelResponseMetadata({\n id,\n model,\n // Some OpenAI-compatible providers use 0 as a placeholder timestamp.\n created: created || 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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"}
|
package/docs/index.mdx
CHANGED
|
@@ -50,12 +50,15 @@ You can use the following optional settings to customize the provider instance:
|
|
|
50
50
|
|
|
51
51
|
Set the URL prefix for API calls.
|
|
52
52
|
|
|
53
|
-
- **apiKey**
|
|
53
|
+
- **apiKey** _string | PromiseLike<string> | (() => string | PromiseLike<string>)_
|
|
54
54
|
|
|
55
55
|
API key for authenticating requests. If specified, adds an `Authorization`
|
|
56
56
|
header to request headers with the value `Bearer <apiKey>`. This will be added
|
|
57
57
|
before any headers potentially specified in the `headers` option.
|
|
58
58
|
|
|
59
|
+
A function is called before each request and may return a promise. Use it to
|
|
60
|
+
supply refreshed credentials; a promise value resolves to the same key each time.
|
|
61
|
+
|
|
59
62
|
- **headers** _Record<string,string>_
|
|
60
63
|
|
|
61
64
|
Optional custom headers to include in requests. These will be added to request headers
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/openai-compatible",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.83",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ai-sdk/provider": "4.0.
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
38
|
+
"@ai-sdk/provider": "4.0.35",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.73"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.4",
|
|
@@ -11,6 +11,8 @@ import type {
|
|
|
11
11
|
OpenAICompatibleContentPart,
|
|
12
12
|
} from './openai-compatible-api-types';
|
|
13
13
|
import {
|
|
14
|
+
secureJsonParse,
|
|
15
|
+
stringifyWithBigIntAndCycles,
|
|
14
16
|
convertBase64ToUint8Array,
|
|
15
17
|
convertToBase64,
|
|
16
18
|
getTopLevelMediaType,
|
|
@@ -186,6 +188,18 @@ function convertToolContentPart(
|
|
|
186
188
|
return convertToOpenAICompatibleContentPart(part, provider);
|
|
187
189
|
}
|
|
188
190
|
|
|
191
|
+
function serializeToolCallArguments(input: unknown): string {
|
|
192
|
+
if (typeof input === 'string') {
|
|
193
|
+
try {
|
|
194
|
+
secureJsonParse(input);
|
|
195
|
+
return input;
|
|
196
|
+
} catch {
|
|
197
|
+
return JSON.stringify(input);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return stringifyWithBigIntAndCycles(input);
|
|
201
|
+
}
|
|
202
|
+
|
|
189
203
|
export function convertToOpenAICompatibleChatMessages(
|
|
190
204
|
prompt: LanguageModelV4Prompt,
|
|
191
205
|
{
|
|
@@ -263,7 +277,7 @@ export function convertToOpenAICompatibleChatMessages(
|
|
|
263
277
|
type: 'function',
|
|
264
278
|
function: {
|
|
265
279
|
name: part.toolName,
|
|
266
|
-
arguments:
|
|
280
|
+
arguments: serializeToolCallArguments(part.input),
|
|
267
281
|
},
|
|
268
282
|
...partMetadata,
|
|
269
283
|
// Include extra_content for Google Gemini thought signatures
|
|
@@ -312,14 +326,14 @@ export function convertToOpenAICompatibleChatMessages(
|
|
|
312
326
|
break;
|
|
313
327
|
case 'json':
|
|
314
328
|
case 'error-json':
|
|
315
|
-
contentValue =
|
|
329
|
+
contentValue = stringifyWithBigIntAndCycles(output.value);
|
|
316
330
|
break;
|
|
317
331
|
case 'content':
|
|
318
332
|
contentValue = supportsMultiPartToolContent
|
|
319
333
|
? output.value.map(part =>
|
|
320
334
|
convertToolContentPart(part, provider),
|
|
321
335
|
)
|
|
322
|
-
:
|
|
336
|
+
: stringifyWithBigIntAndCycles(output.value);
|
|
323
337
|
break;
|
|
324
338
|
}
|
|
325
339
|
|
|
@@ -11,8 +11,11 @@ export const openaiCompatibleLanguageModelChatOptions = z.object({
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Reasoning effort for reasoning models. Defaults to `medium`.
|
|
14
|
+
*
|
|
15
|
+
* Set to `null` to send `"reasoning_effort": null`, for providers that treat
|
|
16
|
+
* an explicit `null` differently from an omitted field.
|
|
14
17
|
*/
|
|
15
|
-
reasoningEffort: z.string().
|
|
18
|
+
reasoningEffort: z.string().nullish(),
|
|
16
19
|
|
|
17
20
|
/**
|
|
18
21
|
* Controls the verbosity of the generated text. Defaults to `medium`.
|
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
type SharedV4Warning,
|
|
14
14
|
} from '@ai-sdk/provider';
|
|
15
15
|
import {
|
|
16
|
+
type Resolvable,
|
|
17
|
+
resolve,
|
|
16
18
|
lazySchema,
|
|
17
19
|
zodSchema,
|
|
18
20
|
combineHeaders,
|
|
@@ -63,7 +65,7 @@ type OpenAICompatibleStreamingToolCallDelta = StreamingToolCallDelta & {
|
|
|
63
65
|
|
|
64
66
|
export type OpenAICompatibleChatConfig = {
|
|
65
67
|
provider: string;
|
|
66
|
-
headers?:
|
|
68
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
67
69
|
url: (options: { modelId: string; path: string }) => string;
|
|
68
70
|
fetch?: FetchFunction;
|
|
69
71
|
includeUsage?: boolean;
|
|
@@ -290,6 +292,15 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
290
292
|
providerOptions,
|
|
291
293
|
);
|
|
292
294
|
|
|
295
|
+
const reasoningEffort =
|
|
296
|
+
compatibleOptions.reasoningEffort !== undefined
|
|
297
|
+
? compatibleOptions.reasoningEffort
|
|
298
|
+
: isCustomReasoning(reasoning)
|
|
299
|
+
? this.config.mapReasoning != null
|
|
300
|
+
? this.config.mapReasoning({ reasoning, warnings })
|
|
301
|
+
: reasoning
|
|
302
|
+
: undefined;
|
|
303
|
+
|
|
293
304
|
return {
|
|
294
305
|
metadataKey,
|
|
295
306
|
args: {
|
|
@@ -335,13 +346,12 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
335
346
|
),
|
|
336
347
|
),
|
|
337
348
|
|
|
338
|
-
reasoning_effort:
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
: undefined),
|
|
349
|
+
// only write reasoning_effort when it has a value: an explicit `null` must be
|
|
350
|
+
// sent as `null`, and an unset option must not overwrite a raw
|
|
351
|
+
// `reasoning_effort` passed through provider options:
|
|
352
|
+
...(reasoningEffort !== undefined
|
|
353
|
+
? { reasoning_effort: reasoningEffort }
|
|
354
|
+
: {}),
|
|
345
355
|
verbosity: compatibleOptions.textVerbosity,
|
|
346
356
|
|
|
347
357
|
// messages:
|
|
@@ -377,7 +387,10 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
377
387
|
path: '/chat/completions',
|
|
378
388
|
modelId: this.modelId,
|
|
379
389
|
}),
|
|
380
|
-
headers: combineHeaders(
|
|
390
|
+
headers: combineHeaders(
|
|
391
|
+
await resolve(this.config.headers),
|
|
392
|
+
options.headers,
|
|
393
|
+
),
|
|
381
394
|
body: transformedBody,
|
|
382
395
|
failedResponseHandler: this.failedResponseHandler,
|
|
383
396
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -494,7 +507,10 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
494
507
|
path: '/chat/completions',
|
|
495
508
|
modelId: this.modelId,
|
|
496
509
|
}),
|
|
497
|
-
headers: combineHeaders(
|
|
510
|
+
headers: combineHeaders(
|
|
511
|
+
await resolve(this.config.headers),
|
|
512
|
+
options.headers,
|
|
513
|
+
),
|
|
498
514
|
body,
|
|
499
515
|
failedResponseHandler: this.failedResponseHandler,
|
|
500
516
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -10,6 +10,8 @@ import type {
|
|
|
10
10
|
SharedV4Warning,
|
|
11
11
|
} from '@ai-sdk/provider';
|
|
12
12
|
import {
|
|
13
|
+
type Resolvable,
|
|
14
|
+
resolve,
|
|
13
15
|
lazySchema,
|
|
14
16
|
zodSchema,
|
|
15
17
|
combineHeaders,
|
|
@@ -45,7 +47,7 @@ import {
|
|
|
45
47
|
type OpenAICompatibleCompletionConfig = {
|
|
46
48
|
provider: string;
|
|
47
49
|
includeUsage?: boolean;
|
|
48
|
-
headers?:
|
|
50
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
49
51
|
url: (options: { modelId: string; path: string }) => string;
|
|
50
52
|
fetch?: FetchFunction;
|
|
51
53
|
errorStructure?: ProviderErrorStructure<any>;
|
|
@@ -217,7 +219,10 @@ export class OpenAICompatibleCompletionLanguageModel implements LanguageModelV4
|
|
|
217
219
|
path: '/completions',
|
|
218
220
|
modelId: this.modelId,
|
|
219
221
|
}),
|
|
220
|
-
headers: combineHeaders(
|
|
222
|
+
headers: combineHeaders(
|
|
223
|
+
await resolve(this.config.headers),
|
|
224
|
+
options.headers,
|
|
225
|
+
),
|
|
221
226
|
body: args,
|
|
222
227
|
failedResponseHandler: this.failedResponseHandler,
|
|
223
228
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -272,7 +277,10 @@ export class OpenAICompatibleCompletionLanguageModel implements LanguageModelV4
|
|
|
272
277
|
path: '/completions',
|
|
273
278
|
modelId: this.modelId,
|
|
274
279
|
}),
|
|
275
|
-
headers: combineHeaders(
|
|
280
|
+
headers: combineHeaders(
|
|
281
|
+
await resolve(this.config.headers),
|
|
282
|
+
options.headers,
|
|
283
|
+
),
|
|
276
284
|
body,
|
|
277
285
|
failedResponseHandler: this.failedResponseHandler,
|
|
278
286
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
type SharedV4Warning,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import {
|
|
7
|
+
type Resolvable,
|
|
8
|
+
resolve,
|
|
7
9
|
lazySchema,
|
|
8
10
|
zodSchema,
|
|
9
11
|
combineHeaders,
|
|
@@ -40,7 +42,7 @@ type OpenAICompatibleEmbeddingConfig = {
|
|
|
40
42
|
|
|
41
43
|
provider: string;
|
|
42
44
|
url: (options: { modelId: string; path: string }) => string;
|
|
43
|
-
headers?:
|
|
45
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
44
46
|
fetch?: FetchFunction;
|
|
45
47
|
errorStructure?: ProviderErrorStructure<any>;
|
|
46
48
|
};
|
|
@@ -154,7 +156,7 @@ export class OpenAICompatibleEmbeddingModel implements EmbeddingModelV4 {
|
|
|
154
156
|
path: '/embeddings',
|
|
155
157
|
modelId: this.modelId,
|
|
156
158
|
}),
|
|
157
|
-
headers: combineHeaders(this.config.headers
|
|
159
|
+
headers: combineHeaders(await resolve(this.config.headers), headers),
|
|
158
160
|
body: {
|
|
159
161
|
model: this.modelId,
|
|
160
162
|
input: values,
|
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
warnIfDeprecatedProviderOptionsKey,
|
|
12
12
|
} from '../utils/to-camel-case';
|
|
13
13
|
import {
|
|
14
|
+
type Resolvable,
|
|
15
|
+
resolve,
|
|
14
16
|
lazySchema,
|
|
15
17
|
zodSchema,
|
|
16
18
|
type InferSchema,
|
|
@@ -39,7 +41,7 @@ import type { OpenAICompatibleImageModelId } from './openai-compatible-image-set
|
|
|
39
41
|
|
|
40
42
|
export type OpenAICompatibleImageModelConfig = {
|
|
41
43
|
provider: string;
|
|
42
|
-
headers?:
|
|
44
|
+
headers?: Resolvable<Record<string, string | undefined>>;
|
|
43
45
|
url: (options: { modelId: string; path: string }) => string;
|
|
44
46
|
fetch?: FetchFunction;
|
|
45
47
|
errorStructure?: ProviderErrorStructure<any>;
|
|
@@ -136,7 +138,10 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
136
138
|
path: isEditing ? '/images/edits' : '/images/generations',
|
|
137
139
|
modelId: this.modelId,
|
|
138
140
|
});
|
|
139
|
-
const requestHeaders = combineHeaders(
|
|
141
|
+
const requestHeaders = combineHeaders(
|
|
142
|
+
await resolve(this.config.headers),
|
|
143
|
+
headers,
|
|
144
|
+
);
|
|
140
145
|
|
|
141
146
|
// Image editing mode - use form data and /images/edits endpoint
|
|
142
147
|
if (isEditing) {
|
|
@@ -165,7 +170,7 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
165
170
|
return {
|
|
166
171
|
images: await this.getImages(response.data, {
|
|
167
172
|
url,
|
|
168
|
-
headers
|
|
173
|
+
headers,
|
|
169
174
|
abortSignal,
|
|
170
175
|
}),
|
|
171
176
|
warnings,
|
|
@@ -202,7 +207,7 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
202
207
|
return {
|
|
203
208
|
images: await this.getImages(response.data, {
|
|
204
209
|
url,
|
|
205
|
-
headers
|
|
210
|
+
headers,
|
|
206
211
|
abortSignal,
|
|
207
212
|
}),
|
|
208
213
|
warnings,
|
|
@@ -219,7 +224,7 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
219
224
|
data: InferSchema<typeof openaiCompatibleImageResponseSchema>['data'],
|
|
220
225
|
options: {
|
|
221
226
|
url: string;
|
|
222
|
-
headers: Record<string, string | undefined
|
|
227
|
+
headers: Record<string, string | undefined> | undefined;
|
|
223
228
|
abortSignal: AbortSignal | undefined;
|
|
224
229
|
},
|
|
225
230
|
): Promise<string[] | Uint8Array[]> {
|
|
@@ -246,7 +251,10 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
246
251
|
validateUrl: true,
|
|
247
252
|
trustedOrigin: options.url,
|
|
248
253
|
credentialedOrigin: options.url,
|
|
249
|
-
headers:
|
|
254
|
+
headers: combineHeaders(
|
|
255
|
+
await resolve(this.config.headers),
|
|
256
|
+
options.headers,
|
|
257
|
+
),
|
|
250
258
|
abortSignal: options.abortSignal,
|
|
251
259
|
fetch: this.config.fetch,
|
|
252
260
|
successfulResponseHandler: createBinaryResponseHandler(),
|
|
@@ -5,6 +5,8 @@ import type {
|
|
|
5
5
|
ProviderV4,
|
|
6
6
|
} from '@ai-sdk/provider';
|
|
7
7
|
import {
|
|
8
|
+
resolveWith,
|
|
9
|
+
type Resolvable,
|
|
8
10
|
withoutTrailingSlash,
|
|
9
11
|
withUserAgentSuffix,
|
|
10
12
|
type FetchFunction,
|
|
@@ -61,8 +63,9 @@ export interface OpenAICompatibleProviderSettings {
|
|
|
61
63
|
* API key for authenticating requests. If specified, adds an `Authorization`
|
|
62
64
|
* header to request headers with the value `Bearer <apiKey>`. This will be added
|
|
63
65
|
* before any headers potentially specified in the `headers` option.
|
|
66
|
+
* A function is called before each request and may return a promise.
|
|
64
67
|
*/
|
|
65
|
-
apiKey?: string
|
|
68
|
+
apiKey?: Resolvable<string>;
|
|
66
69
|
|
|
67
70
|
/**
|
|
68
71
|
* Optional custom headers to include in requests. These will be added to request headers
|
|
@@ -148,17 +151,20 @@ export function createOpenAICompatible<
|
|
|
148
151
|
interface CommonModelConfig {
|
|
149
152
|
provider: string;
|
|
150
153
|
url: ({ path }: { path: string }) => string;
|
|
151
|
-
headers:
|
|
154
|
+
headers: Resolvable<Record<string, string>>;
|
|
152
155
|
fetch?: FetchFunction;
|
|
153
156
|
}
|
|
154
157
|
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
...options.headers,
|
|
158
|
-
};
|
|
158
|
+
const configuredApiKey = options.apiKey;
|
|
159
|
+
const headers = { ...options.headers };
|
|
159
160
|
|
|
160
161
|
const getHeaders = () =>
|
|
161
|
-
|
|
162
|
+
resolveWith(configuredApiKey, apiKey =>
|
|
163
|
+
withUserAgentSuffix(
|
|
164
|
+
{ ...(apiKey && { Authorization: `Bearer ${apiKey}` }), ...headers },
|
|
165
|
+
`ai-sdk-openai-compatible/${VERSION}`,
|
|
166
|
+
),
|
|
167
|
+
);
|
|
162
168
|
|
|
163
169
|
const getCommonModelConfig = (modelType: string): CommonModelConfig => ({
|
|
164
170
|
provider: `${providerName}.${modelType}`,
|