@ai-sdk/openai-compatible 3.0.61 → 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 CHANGED
@@ -1,5 +1,11 @@
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
+
3
9
  ## 3.0.61
4
10
 
5
11
  ### 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
@@ -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":"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"}
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 convertToOpenAICompatibleChatMessages(prompt, { providerOptionsKey = "google" } = {}) {
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((part) => {
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": contentValue = JSON.stringify(output.value);
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, { providerOptionsKey: metadataKey }),
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.61";
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,