@ai-sdk/openai-compatible 3.0.60 → 3.0.62
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 +15 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +77 -66
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +7 -2
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +71 -64
- package/dist/internal/index.js.map +1 -1
- package/docs/index.mdx +24 -0
- package/package.json +3 -3
- package/src/chat/convert-to-openai-compatible-chat-messages.ts +162 -126
- package/src/chat/openai-compatible-api-types.ts +1 -1
- package/src/chat/openai-compatible-chat-language-model.ts +7 -0
- package/src/openai-compatible-provider.ts +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @ai-sdk/openai-compatible
|
|
2
2
|
|
|
3
|
+
## 3.0.62
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 04be48f: fix(openai-compatible): support multipart tool results for compatible providers
|
|
8
|
+
|
|
9
|
+
## 3.0.61
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [8c65988]
|
|
14
|
+
- Updated dependencies [527a163]
|
|
15
|
+
- @ai-sdk/provider@4.0.21
|
|
16
|
+
- @ai-sdk/provider-utils@5.0.53
|
|
17
|
+
|
|
3
18
|
## 3.0.60
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -87,6 +87,10 @@ type OpenAICompatibleChatConfig = {
|
|
|
87
87
|
* Whether the model supports structured outputs.
|
|
88
88
|
*/
|
|
89
89
|
supportsStructuredOutputs?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Whether the model supports multi-part content in tool results.
|
|
92
|
+
*/
|
|
93
|
+
supportsMultiPartToolContent?: boolean;
|
|
90
94
|
/**
|
|
91
95
|
* The supported URLs for the model.
|
|
92
96
|
*/
|
|
@@ -368,6 +372,13 @@ interface OpenAICompatibleProviderSettings {
|
|
|
368
372
|
* Whether the provider supports structured outputs in chat models.
|
|
369
373
|
*/
|
|
370
374
|
supportsStructuredOutputs?: boolean;
|
|
375
|
+
/**
|
|
376
|
+
* Whether chat models support multi-part content in tool results.
|
|
377
|
+
*
|
|
378
|
+
* Enable this for providers that extend the OpenAI Chat Completions API with
|
|
379
|
+
* structured tool-result content. Defaults to `false`.
|
|
380
|
+
*/
|
|
381
|
+
supportsMultiPartToolContent?: boolean;
|
|
371
382
|
/**
|
|
372
383
|
* Optional function to transform the request body before sending it to the API.
|
|
373
384
|
* This is useful for proxy providers that may require a different request format
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/openai-compatible-error.ts","../src/chat/openai-compatible-chat-language-model-options.ts","../src/chat/openai-compatible-metadata-extractor.ts","../src/chat/openai-compatible-chat-language-model.ts","../src/completion/openai-compatible-completion-language-model-options.ts","../src/completion/openai-compatible-completion-language-model.ts","../src/embedding/openai-compatible-embedding-model-options.ts","../src/embedding/openai-compatible-embedding-model.ts","../src/image/openai-compatible-image-settings.ts","../src/image/openai-compatible-image-model.ts","../src/image/openai-compatible-image-model-options.ts","../src/openai-compatible-provider.ts","../src/version.ts"],"mappings":";;;;cACa,iCAA+B,EAAA;;;;;;;GAW1C,EAAA,KAAA;KAEU,4BAA4B,EAAE,aACjC;KAGG,uBAAuB;EACjC,aAAa,QAAQ;EACrB,iBAAiB,OAAO;EACxB,eAAe,UAAU,UAAU,QAAQ;;;;KCnBjC;cAEC,0CAAwC,EAAA;;;;;GAyBnD,EAAA,KAAA;KAEU,2CAA2C,EAAE,aAChD;;;;;;;;KCzBG;;;;;;;;;EASV,oBACE;IAEA;QACI,QAAQ;;;;;;;;EASd;;;;;;;IAOE,aAAa;;;;;;;;IASb,iBAAiB;;;;;KCgBT;EACV;EACA,gBAAgB;EAChB,MAAM;IAAW;IAAiB;;EAClC,QAAQ;EACR;EACA,iBAAiB;EACjB,oBAAoB;;;;EAKpB;;;;EAKA,sBAAsB;;;;;;EAOtB,wBAAwB,MAAM,wBAAwB;;;;;EAMtD,gBACE,OAAO,EAAE,aAAa,sCACnB;;qBASM,6CAA6C;WAC/C;WAEA;WAEA,SAAS;qBACC,QAAQ;mBACV;mBACA;UAET,oBAAoB,OAAO;;;;UAO3B,sBAAsB;IAC5B;IACA,QAAQ;MACT;EAQC,YAAA,SAAS,6BACT,QAAQ;MAgBN;cAIQ;MAIR,iBAAa,eAAA,YAAA,YAAA,eAAA;UAIT;UAIA;UASM;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/openai-compatible-error.ts","../src/chat/openai-compatible-chat-language-model-options.ts","../src/chat/openai-compatible-metadata-extractor.ts","../src/chat/openai-compatible-chat-language-model.ts","../src/completion/openai-compatible-completion-language-model-options.ts","../src/completion/openai-compatible-completion-language-model.ts","../src/embedding/openai-compatible-embedding-model-options.ts","../src/embedding/openai-compatible-embedding-model.ts","../src/image/openai-compatible-image-settings.ts","../src/image/openai-compatible-image-model.ts","../src/image/openai-compatible-image-model-options.ts","../src/openai-compatible-provider.ts","../src/version.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -71,7 +71,72 @@ function getAudioFormat(mediaType) {
|
|
|
71
71
|
default: return null;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
function
|
|
74
|
+
function convertToOpenAICompatibleContentPart(part) {
|
|
75
|
+
const partMetadata = getOpenAIMetadata(part);
|
|
76
|
+
switch (part.type) {
|
|
77
|
+
case "text": return {
|
|
78
|
+
type: "text",
|
|
79
|
+
text: part.text,
|
|
80
|
+
...partMetadata
|
|
81
|
+
};
|
|
82
|
+
case "file": switch (part.data.type) {
|
|
83
|
+
case "reference": throw new UnsupportedFunctionalityError({ functionality: "file parts with provider references" });
|
|
84
|
+
case "text": throw new UnsupportedFunctionalityError({ functionality: "text file parts" });
|
|
85
|
+
case "url":
|
|
86
|
+
case "data": {
|
|
87
|
+
const topLevel = getTopLevelMediaType(part.mediaType);
|
|
88
|
+
if (topLevel === "image") return {
|
|
89
|
+
type: "image_url",
|
|
90
|
+
image_url: { url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}` },
|
|
91
|
+
...partMetadata
|
|
92
|
+
};
|
|
93
|
+
if (topLevel === "video") return {
|
|
94
|
+
type: "video_url",
|
|
95
|
+
video_url: { url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}` },
|
|
96
|
+
...partMetadata
|
|
97
|
+
};
|
|
98
|
+
if (topLevel === "audio") {
|
|
99
|
+
if (part.data.type === "url") throw new UnsupportedFunctionalityError({ functionality: "audio file parts with URLs" });
|
|
100
|
+
const fullMediaType = resolveFullMediaType({ part });
|
|
101
|
+
const format = getAudioFormat(fullMediaType);
|
|
102
|
+
if (format === null) throw new UnsupportedFunctionalityError({ functionality: `audio media type ${fullMediaType}` });
|
|
103
|
+
return {
|
|
104
|
+
type: "input_audio",
|
|
105
|
+
input_audio: {
|
|
106
|
+
data: convertToBase64(part.data.data),
|
|
107
|
+
format
|
|
108
|
+
},
|
|
109
|
+
...partMetadata
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (topLevel === "application") {
|
|
113
|
+
if (part.data.type === "url") throw new UnsupportedFunctionalityError({ functionality: "PDF file parts with URLs" });
|
|
114
|
+
const fullMediaType = resolveFullMediaType({ part });
|
|
115
|
+
if (fullMediaType !== "application/pdf") throw new UnsupportedFunctionalityError({ functionality: `file part media type ${fullMediaType}` });
|
|
116
|
+
return {
|
|
117
|
+
type: "file",
|
|
118
|
+
file: {
|
|
119
|
+
filename: part.filename ?? "document.pdf",
|
|
120
|
+
file_data: `data:application/pdf;base64,${convertToBase64(part.data.data)}`
|
|
121
|
+
},
|
|
122
|
+
...partMetadata
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (topLevel === "text") return {
|
|
126
|
+
type: "text",
|
|
127
|
+
text: part.data.type === "url" ? part.data.url.toString() : typeof part.data.data === "string" ? new TextDecoder().decode(convertBase64ToUint8Array(part.data.data)) : new TextDecoder().decode(part.data.data),
|
|
128
|
+
...partMetadata
|
|
129
|
+
};
|
|
130
|
+
throw new UnsupportedFunctionalityError({ functionality: `file part media type ${part.mediaType}` });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function convertToolContentPart(part) {
|
|
136
|
+
if (part.type === "custom") throw new UnsupportedFunctionalityError({ functionality: "custom tool content parts" });
|
|
137
|
+
return convertToOpenAICompatibleContentPart(part);
|
|
138
|
+
}
|
|
139
|
+
function convertToOpenAICompatibleChatMessages(prompt, { providerOptionsKey = "google", supportsMultiPartToolContent = false } = {}) {
|
|
75
140
|
const messages = [];
|
|
76
141
|
for (const { role, content, ...message } of prompt) {
|
|
77
142
|
const metadata = getOpenAIMetadata({ ...message });
|
|
@@ -94,67 +159,7 @@ function convertToOpenAICompatibleChatMessages(prompt, { providerOptionsKey = "g
|
|
|
94
159
|
}
|
|
95
160
|
messages.push({
|
|
96
161
|
role: "user",
|
|
97
|
-
content: content.map(
|
|
98
|
-
const partMetadata = getOpenAIMetadata(part);
|
|
99
|
-
switch (part.type) {
|
|
100
|
-
case "text": return {
|
|
101
|
-
type: "text",
|
|
102
|
-
text: part.text,
|
|
103
|
-
...partMetadata
|
|
104
|
-
};
|
|
105
|
-
case "file": switch (part.data.type) {
|
|
106
|
-
case "reference": throw new UnsupportedFunctionalityError({ functionality: "file parts with provider references" });
|
|
107
|
-
case "text": throw new UnsupportedFunctionalityError({ functionality: "text file parts" });
|
|
108
|
-
case "url":
|
|
109
|
-
case "data": {
|
|
110
|
-
const topLevel = getTopLevelMediaType(part.mediaType);
|
|
111
|
-
if (topLevel === "image") return {
|
|
112
|
-
type: "image_url",
|
|
113
|
-
image_url: { url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}` },
|
|
114
|
-
...partMetadata
|
|
115
|
-
};
|
|
116
|
-
if (topLevel === "video") return {
|
|
117
|
-
type: "video_url",
|
|
118
|
-
video_url: { url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}` },
|
|
119
|
-
...partMetadata
|
|
120
|
-
};
|
|
121
|
-
if (topLevel === "audio") {
|
|
122
|
-
if (part.data.type === "url") throw new UnsupportedFunctionalityError({ functionality: "audio file parts with URLs" });
|
|
123
|
-
const fullMediaType = resolveFullMediaType({ part });
|
|
124
|
-
const format = getAudioFormat(fullMediaType);
|
|
125
|
-
if (format === null) throw new UnsupportedFunctionalityError({ functionality: `audio media type ${fullMediaType}` });
|
|
126
|
-
return {
|
|
127
|
-
type: "input_audio",
|
|
128
|
-
input_audio: {
|
|
129
|
-
data: convertToBase64(part.data.data),
|
|
130
|
-
format
|
|
131
|
-
},
|
|
132
|
-
...partMetadata
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
if (topLevel === "application") {
|
|
136
|
-
if (part.data.type === "url") throw new UnsupportedFunctionalityError({ functionality: "PDF file parts with URLs" });
|
|
137
|
-
const fullMediaType = resolveFullMediaType({ part });
|
|
138
|
-
if (fullMediaType !== "application/pdf") throw new UnsupportedFunctionalityError({ functionality: `file part media type ${fullMediaType}` });
|
|
139
|
-
return {
|
|
140
|
-
type: "file",
|
|
141
|
-
file: {
|
|
142
|
-
filename: part.filename ?? "document.pdf",
|
|
143
|
-
file_data: `data:application/pdf;base64,${convertToBase64(part.data.data)}`
|
|
144
|
-
},
|
|
145
|
-
...partMetadata
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
if (topLevel === "text") return {
|
|
149
|
-
type: "text",
|
|
150
|
-
text: part.data.type === "url" ? part.data.url.toString() : typeof part.data.data === "string" ? new TextDecoder().decode(convertBase64ToUint8Array(part.data.data)) : new TextDecoder().decode(part.data.data),
|
|
151
|
-
...partMetadata
|
|
152
|
-
};
|
|
153
|
-
throw new UnsupportedFunctionalityError({ functionality: `file part media type ${part.mediaType}` });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}),
|
|
162
|
+
content: content.map(convertToOpenAICompatibleContentPart),
|
|
158
163
|
...metadata
|
|
159
164
|
});
|
|
160
165
|
break;
|
|
@@ -209,9 +214,11 @@ function convertToOpenAICompatibleChatMessages(prompt, { providerOptionsKey = "g
|
|
|
209
214
|
case "execution-denied":
|
|
210
215
|
contentValue = output.reason ?? "Tool call execution denied.";
|
|
211
216
|
break;
|
|
212
|
-
case "content":
|
|
213
217
|
case "json":
|
|
214
|
-
case "error-json":
|
|
218
|
+
case "error-json":
|
|
219
|
+
contentValue = JSON.stringify(output.value);
|
|
220
|
+
break;
|
|
221
|
+
case "content": contentValue = supportsMultiPartToolContent ? output.value.map(convertToolContentPart) : JSON.stringify(output.value);
|
|
215
222
|
}
|
|
216
223
|
const toolResponseMetadata = getOpenAIMetadata(toolResponse);
|
|
217
224
|
messages.push({
|
|
@@ -430,7 +437,10 @@ var OpenAICompatibleChatLanguageModel = class OpenAICompatibleChatLanguageModel
|
|
|
430
437
|
}).filter(([key]) => !Object.keys(openaiCompatibleLanguageModelChatOptions.shape).includes(key))),
|
|
431
438
|
reasoning_effort: compatibleOptions.reasoningEffort ?? (isCustomReasoning(reasoning) ? reasoning : void 0),
|
|
432
439
|
verbosity: compatibleOptions.textVerbosity,
|
|
433
|
-
messages: convertToOpenAICompatibleChatMessages(prompt, {
|
|
440
|
+
messages: convertToOpenAICompatibleChatMessages(prompt, {
|
|
441
|
+
providerOptionsKey: metadataKey,
|
|
442
|
+
supportsMultiPartToolContent: this.config.supportsMultiPartToolContent
|
|
443
|
+
}),
|
|
434
444
|
tools: openaiTools,
|
|
435
445
|
tool_choice: openaiToolChoice
|
|
436
446
|
},
|
|
@@ -1407,7 +1417,7 @@ async function fileToBlob(file) {
|
|
|
1407
1417
|
}
|
|
1408
1418
|
//#endregion
|
|
1409
1419
|
//#region src/version.ts
|
|
1410
|
-
const VERSION = "3.0.
|
|
1420
|
+
const VERSION = "3.0.62";
|
|
1411
1421
|
//#endregion
|
|
1412
1422
|
//#region src/openai-compatible-provider.ts
|
|
1413
1423
|
/**
|
|
@@ -1436,6 +1446,7 @@ function createOpenAICompatible(options) {
|
|
|
1436
1446
|
...getCommonModelConfig("chat"),
|
|
1437
1447
|
includeUsage: options.includeUsage,
|
|
1438
1448
|
supportsStructuredOutputs: options.supportsStructuredOutputs,
|
|
1449
|
+
supportsMultiPartToolContent: options.supportsMultiPartToolContent,
|
|
1439
1450
|
supportedUrls: options.supportedUrls,
|
|
1440
1451
|
transformRequestBody: options.transformRequestBody,
|
|
1441
1452
|
metadataExtractor: options.metadataExtractor,
|