@ai-sdk/openai-compatible 3.0.58 → 3.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,1878 +1,1463 @@
1
- // src/chat/openai-compatible-chat-language-model.ts
2
- import {
3
- InvalidResponseDataError
4
- } from "@ai-sdk/provider";
5
- import {
6
- combineHeaders,
7
- createEventSourceResponseHandler,
8
- createJsonErrorResponseHandler,
9
- createJsonResponseHandler,
10
- generateId,
11
- isCustomReasoning,
12
- parseProviderOptions,
13
- postJsonToApi,
14
- serializeModelOptions,
15
- StreamingToolCallTracker,
16
- WORKFLOW_SERIALIZE,
17
- WORKFLOW_DESERIALIZE
18
- } from "@ai-sdk/provider-utils";
19
- import { z as z3 } from "zod/v4";
20
-
21
- // src/utils/to-camel-case.ts
1
+ import { InvalidPromptError, InvalidResponseDataError, TooManyEmbeddingValuesForCallError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
2
+ import { StreamingToolCallTracker, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, convertBase64ToUint8Array, convertToBase64, convertToFormData, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonResponseHandler, createLanguageModelResponseMetadata, createLanguageModelResponseMetadata as getResponseMetadata, createNullLanguageModelUsage, downloadBlob, generateId, getTopLevelMediaType, isCustomReasoning, parseProviderOptions, postFormDataToApi, postJsonToApi, resolveFullMediaType, serializeModelOptions, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils";
3
+ import { z } from "zod/v4";
4
+ //#region src/utils/to-camel-case.ts
22
5
  function toCamelCase(str) {
23
- return str.replace(/[_-]([a-z])/g, (g) => g[1].toUpperCase());
6
+ return str.replace(/[_-]([a-z])/g, (g) => g[1].toUpperCase());
24
7
  }
8
+ /**
9
+ Resolves which key to use for providerMetadata based on what the caller
10
+ passed in providerOptions. Returns the camelCase variant when the caller
11
+ supplied it, otherwise falls back to the raw name.
12
+ */
25
13
  function resolveProviderOptionsKey(rawName, providerOptions) {
26
- const camelName = toCamelCase(rawName);
27
- if (camelName !== rawName && providerOptions?.[camelName] != null) {
28
- return camelName;
29
- }
30
- return rawName;
14
+ const camelName = toCamelCase(rawName);
15
+ if (camelName !== rawName && providerOptions?.[camelName] != null) return camelName;
16
+ return rawName;
31
17
  }
32
- function warnIfDeprecatedProviderOptionsKey({
33
- rawName,
34
- providerOptions,
35
- warnings
36
- }) {
37
- const camelName = toCamelCase(rawName);
38
- if (camelName !== rawName && providerOptions?.[rawName] != null) {
39
- warnings.push({
40
- type: "deprecated",
41
- setting: `providerOptions key '${rawName}'`,
42
- message: `Use '${camelName}' instead.`
43
- });
44
- }
18
+ /**
19
+ Pushes a deprecation warning when the user supplies providerOptions under a non-camelCase key
20
+ */
21
+ function warnIfDeprecatedProviderOptionsKey({ rawName, providerOptions, warnings }) {
22
+ const camelName = toCamelCase(rawName);
23
+ if (camelName !== rawName && providerOptions?.[rawName] != null) warnings.push({
24
+ type: "deprecated",
25
+ setting: `providerOptions key '${rawName}'`,
26
+ message: `Use '${camelName}' instead.`
27
+ });
45
28
  }
46
-
47
- // src/openai-compatible-error.ts
48
- import { z } from "zod/v4";
49
- var openaiCompatibleErrorDataSchema = z.object({
50
- error: z.object({
51
- message: z.string(),
52
- // The additional information below is handled loosely to support
53
- // OpenAI-compatible providers that have slightly different error
54
- // responses:
55
- type: z.string().nullish(),
56
- param: z.any().nullish(),
57
- code: z.union([z.string(), z.number()]).nullish()
58
- })
59
- });
60
- var defaultOpenAICompatibleErrorStructure = {
61
- errorSchema: openaiCompatibleErrorDataSchema,
62
- errorToMessage: (data) => data.error.message
29
+ const defaultOpenAICompatibleErrorStructure = {
30
+ errorSchema: z.object({ error: z.object({
31
+ message: z.string(),
32
+ type: z.string().nullish(),
33
+ param: z.any().nullish(),
34
+ code: z.union([z.string(), z.number()]).nullish()
35
+ }) }),
36
+ errorToMessage: (data) => data.error.message
63
37
  };
64
-
65
- // src/chat/convert-openai-compatible-chat-usage.ts
66
- import { createNullLanguageModelUsage } from "@ai-sdk/provider-utils";
38
+ //#endregion
39
+ //#region src/chat/convert-openai-compatible-chat-usage.ts
67
40
  function convertOpenAICompatibleChatUsage(usage) {
68
- if (usage == null) {
69
- return createNullLanguageModelUsage();
70
- }
71
- const promptTokens = usage.prompt_tokens ?? 0;
72
- const completionTokens = usage.completion_tokens ?? 0;
73
- const cacheReadTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;
74
- const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0;
75
- return {
76
- inputTokens: {
77
- total: promptTokens,
78
- noCache: promptTokens - cacheReadTokens,
79
- cacheRead: cacheReadTokens,
80
- cacheWrite: void 0
81
- },
82
- outputTokens: {
83
- total: completionTokens,
84
- text: Math.max(0, completionTokens - reasoningTokens),
85
- reasoning: reasoningTokens
86
- },
87
- raw: usage
88
- };
41
+ if (usage == null) return createNullLanguageModelUsage();
42
+ const promptTokens = usage.prompt_tokens ?? 0;
43
+ const completionTokens = usage.completion_tokens ?? 0;
44
+ const cacheReadTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;
45
+ const reasoningTokens = usage.completion_tokens_details?.reasoning_tokens ?? 0;
46
+ return {
47
+ inputTokens: {
48
+ total: promptTokens,
49
+ noCache: promptTokens - cacheReadTokens,
50
+ cacheRead: cacheReadTokens,
51
+ cacheWrite: void 0
52
+ },
53
+ outputTokens: {
54
+ total: completionTokens,
55
+ text: Math.max(0, completionTokens - reasoningTokens),
56
+ reasoning: reasoningTokens
57
+ },
58
+ raw: usage
59
+ };
89
60
  }
90
-
91
- // src/chat/convert-to-openai-compatible-chat-messages.ts
92
- import {
93
- UnsupportedFunctionalityError
94
- } from "@ai-sdk/provider";
95
- import {
96
- convertBase64ToUint8Array,
97
- convertToBase64,
98
- getTopLevelMediaType,
99
- resolveFullMediaType
100
- } from "@ai-sdk/provider-utils";
61
+ //#endregion
62
+ //#region src/chat/convert-to-openai-compatible-chat-messages.ts
101
63
  function getOpenAIMetadata(message) {
102
- return message?.providerOptions?.openaiCompatible ?? {};
64
+ return message?.providerOptions?.openaiCompatible ?? {};
103
65
  }
104
66
  function getAudioFormat(mediaType) {
105
- switch (mediaType) {
106
- case "audio/wav":
107
- return "wav";
108
- case "audio/mp3":
109
- case "audio/mpeg":
110
- return "mp3";
111
- default:
112
- return null;
113
- }
67
+ switch (mediaType) {
68
+ case "audio/wav": return "wav";
69
+ case "audio/mp3":
70
+ case "audio/mpeg": return "mp3";
71
+ default: return null;
72
+ }
114
73
  }
115
74
  function convertToOpenAICompatibleChatMessages(prompt, { providerOptionsKey = "google" } = {}) {
116
- const messages = [];
117
- for (const { role, content, ...message } of prompt) {
118
- const metadata = getOpenAIMetadata({ ...message });
119
- switch (role) {
120
- case "system": {
121
- messages.push({ role: "system", content, ...metadata });
122
- break;
123
- }
124
- case "user": {
125
- if (content.length === 1 && content[0].type === "text") {
126
- messages.push({
127
- role: "user",
128
- content: content[0].text,
129
- ...getOpenAIMetadata(content[0])
130
- });
131
- break;
132
- }
133
- messages.push({
134
- role: "user",
135
- content: content.map((part) => {
136
- const partMetadata = getOpenAIMetadata(part);
137
- switch (part.type) {
138
- case "text": {
139
- return { type: "text", text: part.text, ...partMetadata };
140
- }
141
- case "file": {
142
- switch (part.data.type) {
143
- case "reference": {
144
- throw new UnsupportedFunctionalityError({
145
- functionality: "file parts with provider references"
146
- });
147
- }
148
- case "text": {
149
- throw new UnsupportedFunctionalityError({
150
- functionality: "text file parts"
151
- });
152
- }
153
- case "url":
154
- case "data": {
155
- const topLevel = getTopLevelMediaType(part.mediaType);
156
- if (topLevel === "image") {
157
- return {
158
- type: "image_url",
159
- image_url: {
160
- url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`
161
- },
162
- ...partMetadata
163
- };
164
- }
165
- if (topLevel === "video") {
166
- return {
167
- type: "video_url",
168
- video_url: {
169
- url: part.data.type === "url" ? part.data.url.toString() : `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`
170
- },
171
- ...partMetadata
172
- };
173
- }
174
- if (topLevel === "audio") {
175
- if (part.data.type === "url") {
176
- throw new UnsupportedFunctionalityError({
177
- functionality: "audio file parts with URLs"
178
- });
179
- }
180
- const fullMediaType = resolveFullMediaType({ part });
181
- const format = getAudioFormat(fullMediaType);
182
- if (format === null) {
183
- throw new UnsupportedFunctionalityError({
184
- functionality: `audio media type ${fullMediaType}`
185
- });
186
- }
187
- return {
188
- type: "input_audio",
189
- input_audio: {
190
- data: convertToBase64(part.data.data),
191
- format
192
- },
193
- ...partMetadata
194
- };
195
- }
196
- if (topLevel === "application") {
197
- if (part.data.type === "url") {
198
- throw new UnsupportedFunctionalityError({
199
- functionality: "PDF file parts with URLs"
200
- });
201
- }
202
- const fullMediaType = resolveFullMediaType({ part });
203
- if (fullMediaType !== "application/pdf") {
204
- throw new UnsupportedFunctionalityError({
205
- functionality: `file part media type ${fullMediaType}`
206
- });
207
- }
208
- return {
209
- type: "file",
210
- file: {
211
- filename: part.filename ?? "document.pdf",
212
- file_data: `data:application/pdf;base64,${convertToBase64(part.data.data)}`
213
- },
214
- ...partMetadata
215
- };
216
- }
217
- if (topLevel === "text") {
218
- const textContent = part.data.type === "url" ? part.data.url.toString() : typeof part.data.data === "string" ? new TextDecoder().decode(
219
- convertBase64ToUint8Array(part.data.data)
220
- ) : new TextDecoder().decode(part.data.data);
221
- return {
222
- type: "text",
223
- text: textContent,
224
- ...partMetadata
225
- };
226
- }
227
- throw new UnsupportedFunctionalityError({
228
- functionality: `file part media type ${part.mediaType}`
229
- });
230
- }
231
- }
232
- }
233
- }
234
- }),
235
- ...metadata
236
- });
237
- break;
238
- }
239
- case "assistant": {
240
- let text = "";
241
- let reasoning = "";
242
- const toolCalls = [];
243
- for (const part of content) {
244
- const partMetadata = getOpenAIMetadata(part);
245
- switch (part.type) {
246
- case "text": {
247
- text += part.text;
248
- break;
249
- }
250
- case "reasoning": {
251
- reasoning += part.text;
252
- break;
253
- }
254
- case "tool-call": {
255
- const thoughtSignature = part.providerOptions?.[providerOptionsKey]?.thoughtSignature ?? part.providerOptions?.google?.thoughtSignature;
256
- toolCalls.push({
257
- id: part.toolCallId,
258
- type: "function",
259
- function: {
260
- name: part.toolName,
261
- arguments: JSON.stringify(part.input)
262
- },
263
- ...partMetadata,
264
- // Include extra_content for Google Gemini thought signatures
265
- ...thoughtSignature ? {
266
- extra_content: {
267
- google: {
268
- thought_signature: String(thoughtSignature)
269
- }
270
- }
271
- } : {}
272
- });
273
- break;
274
- }
275
- }
276
- }
277
- messages.push({
278
- role: "assistant",
279
- content: toolCalls.length > 0 ? text || null : text,
280
- ...reasoning.length > 0 ? { reasoning_content: reasoning } : {},
281
- tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
282
- ...metadata
283
- });
284
- break;
285
- }
286
- case "tool": {
287
- for (const toolResponse of content) {
288
- if (toolResponse.type === "tool-approval-response") {
289
- continue;
290
- }
291
- const output = toolResponse.output;
292
- let contentValue;
293
- switch (output.type) {
294
- case "text":
295
- case "error-text":
296
- contentValue = output.value;
297
- break;
298
- case "execution-denied":
299
- contentValue = output.reason ?? "Tool call execution denied.";
300
- break;
301
- case "content":
302
- case "json":
303
- case "error-json":
304
- contentValue = JSON.stringify(output.value);
305
- break;
306
- }
307
- const toolResponseMetadata = getOpenAIMetadata(toolResponse);
308
- messages.push({
309
- role: "tool",
310
- tool_call_id: toolResponse.toolCallId,
311
- content: contentValue,
312
- ...toolResponseMetadata
313
- });
314
- }
315
- break;
316
- }
317
- default: {
318
- const _exhaustiveCheck = role;
319
- throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
320
- }
321
- }
322
- }
323
- return messages;
75
+ const messages = [];
76
+ for (const { role, content, ...message } of prompt) {
77
+ const metadata = getOpenAIMetadata({ ...message });
78
+ switch (role) {
79
+ case "system":
80
+ messages.push({
81
+ role: "system",
82
+ content,
83
+ ...metadata
84
+ });
85
+ break;
86
+ case "user":
87
+ if (content.length === 1 && content[0].type === "text") {
88
+ messages.push({
89
+ role: "user",
90
+ content: content[0].text,
91
+ ...getOpenAIMetadata(content[0])
92
+ });
93
+ break;
94
+ }
95
+ messages.push({
96
+ 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
+ }),
158
+ ...metadata
159
+ });
160
+ break;
161
+ case "assistant": {
162
+ let text = "";
163
+ let reasoning = "";
164
+ const toolCalls = [];
165
+ for (const part of content) {
166
+ const partMetadata = getOpenAIMetadata(part);
167
+ switch (part.type) {
168
+ case "text":
169
+ text += part.text;
170
+ break;
171
+ case "reasoning":
172
+ reasoning += part.text;
173
+ break;
174
+ case "tool-call": {
175
+ const thoughtSignature = part.providerOptions?.[providerOptionsKey]?.thoughtSignature ?? part.providerOptions?.google?.thoughtSignature;
176
+ toolCalls.push({
177
+ id: part.toolCallId,
178
+ type: "function",
179
+ function: {
180
+ name: part.toolName,
181
+ arguments: JSON.stringify(part.input)
182
+ },
183
+ ...partMetadata,
184
+ ...thoughtSignature ? { extra_content: { google: { thought_signature: String(thoughtSignature) } } } : {}
185
+ });
186
+ break;
187
+ }
188
+ }
189
+ }
190
+ messages.push({
191
+ role: "assistant",
192
+ content: toolCalls.length > 0 ? text || null : text,
193
+ ...reasoning.length > 0 ? { reasoning_content: reasoning } : {},
194
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
195
+ ...metadata
196
+ });
197
+ break;
198
+ }
199
+ case "tool":
200
+ for (const toolResponse of content) {
201
+ if (toolResponse.type === "tool-approval-response") continue;
202
+ const output = toolResponse.output;
203
+ let contentValue;
204
+ switch (output.type) {
205
+ case "text":
206
+ case "error-text":
207
+ contentValue = output.value;
208
+ break;
209
+ case "execution-denied":
210
+ contentValue = output.reason ?? "Tool call execution denied.";
211
+ break;
212
+ case "content":
213
+ case "json":
214
+ case "error-json": contentValue = JSON.stringify(output.value);
215
+ }
216
+ const toolResponseMetadata = getOpenAIMetadata(toolResponse);
217
+ messages.push({
218
+ role: "tool",
219
+ tool_call_id: toolResponse.toolCallId,
220
+ content: contentValue,
221
+ ...toolResponseMetadata
222
+ });
223
+ }
224
+ break;
225
+ default: throw new Error(`Unsupported role: ${role}`);
226
+ }
227
+ }
228
+ return messages;
324
229
  }
325
-
326
- // src/chat/get-response-metadata.ts
327
- import { createLanguageModelResponseMetadata } from "@ai-sdk/provider-utils";
328
- function getResponseMetadata({
329
- id,
330
- model,
331
- created
332
- }) {
333
- return createLanguageModelResponseMetadata({
334
- id,
335
- model,
336
- // Some OpenAI-compatible providers use 0 as a placeholder timestamp.
337
- created: created || void 0
338
- });
230
+ //#endregion
231
+ //#region src/chat/get-response-metadata.ts
232
+ function getResponseMetadata$1({ id, model, created }) {
233
+ return createLanguageModelResponseMetadata({
234
+ id,
235
+ model,
236
+ created: created || void 0
237
+ });
339
238
  }
340
-
341
- // src/chat/map-openai-compatible-finish-reason.ts
342
- function mapOpenAICompatibleFinishReason(finishReason) {
343
- switch (finishReason) {
344
- case "stop":
345
- return "stop";
346
- case "length":
347
- return "length";
348
- case "content_filter":
349
- return "content-filter";
350
- case "function_call":
351
- case "tool_calls":
352
- return "tool-calls";
353
- default:
354
- return "other";
355
- }
239
+ //#endregion
240
+ //#region src/chat/map-openai-compatible-finish-reason.ts
241
+ function mapOpenAICompatibleFinishReason$1(finishReason) {
242
+ switch (finishReason) {
243
+ case "stop": return "stop";
244
+ case "length": return "length";
245
+ case "content_filter": return "content-filter";
246
+ case "function_call":
247
+ case "tool_calls": return "tool-calls";
248
+ default: return "other";
249
+ }
356
250
  }
357
-
358
- // src/chat/openai-compatible-chat-language-model-options.ts
359
- import { z as z2 } from "zod/v4";
360
- var openaiCompatibleLanguageModelChatOptions = z2.object({
361
- /**
362
- * A unique identifier representing your end-user, which can help the provider to
363
- * monitor and detect abuse.
364
- */
365
- user: z2.string().optional(),
366
- /**
367
- * Reasoning effort for reasoning models. Defaults to `medium`.
368
- */
369
- reasoningEffort: z2.string().optional(),
370
- /**
371
- * Controls the verbosity of the generated text. Defaults to `medium`.
372
- */
373
- textVerbosity: z2.string().optional(),
374
- /**
375
- * Whether to use strict JSON schema validation.
376
- * When true, the model uses constrained decoding to guarantee schema compliance.
377
- * Only used when the provider supports structured outputs and a schema is provided.
378
- *
379
- * @default true
380
- */
381
- strictJsonSchema: z2.boolean().optional()
251
+ //#endregion
252
+ //#region src/chat/openai-compatible-chat-language-model-options.ts
253
+ const openaiCompatibleLanguageModelChatOptions = z.object({
254
+ /**
255
+ * A unique identifier representing your end-user, which can help the provider to
256
+ * monitor and detect abuse.
257
+ */
258
+ user: z.string().optional(),
259
+ /**
260
+ * Reasoning effort for reasoning models. Defaults to `medium`.
261
+ */
262
+ reasoningEffort: z.string().optional(),
263
+ /**
264
+ * Controls the verbosity of the generated text. Defaults to `medium`.
265
+ */
266
+ textVerbosity: z.string().optional(),
267
+ /**
268
+ * Whether to use strict JSON schema validation.
269
+ * When true, the model uses constrained decoding to guarantee schema compliance.
270
+ * Only used when the provider supports structured outputs and a schema is provided.
271
+ *
272
+ * @default true
273
+ */
274
+ strictJsonSchema: z.boolean().optional()
382
275
  });
383
-
384
- // src/chat/openai-compatible-prepare-tools.ts
385
- import {
386
- UnsupportedFunctionalityError as UnsupportedFunctionalityError2
387
- } from "@ai-sdk/provider";
388
- function prepareTools({
389
- tools,
390
- toolChoice
391
- }) {
392
- tools = tools?.length ? tools : void 0;
393
- const toolWarnings = [];
394
- if (tools == null) {
395
- return { tools: void 0, toolChoice: void 0, toolWarnings };
396
- }
397
- const openaiCompatTools = [];
398
- for (const tool of tools) {
399
- if (tool.type === "provider") {
400
- toolWarnings.push({
401
- type: "unsupported",
402
- feature: `provider-defined tool ${tool.id}`
403
- });
404
- } else {
405
- openaiCompatTools.push({
406
- type: "function",
407
- function: {
408
- name: tool.name,
409
- description: tool.description,
410
- parameters: tool.inputSchema,
411
- ...tool.strict != null ? { strict: tool.strict } : {}
412
- }
413
- });
414
- }
415
- }
416
- if (toolChoice == null) {
417
- return { tools: openaiCompatTools, toolChoice: void 0, toolWarnings };
418
- }
419
- const type = toolChoice.type;
420
- switch (type) {
421
- case "auto":
422
- case "none":
423
- case "required":
424
- return { tools: openaiCompatTools, toolChoice: type, toolWarnings };
425
- case "tool":
426
- return {
427
- tools: openaiCompatTools,
428
- toolChoice: {
429
- type: "function",
430
- function: { name: toolChoice.toolName }
431
- },
432
- toolWarnings
433
- };
434
- default: {
435
- const _exhaustiveCheck = type;
436
- throw new UnsupportedFunctionalityError2({
437
- functionality: `tool choice type: ${_exhaustiveCheck}`
438
- });
439
- }
440
- }
276
+ //#endregion
277
+ //#region src/chat/openai-compatible-prepare-tools.ts
278
+ function prepareTools({ tools, toolChoice }) {
279
+ tools = tools?.length ? tools : void 0;
280
+ const toolWarnings = [];
281
+ if (tools == null) return {
282
+ tools: void 0,
283
+ toolChoice: void 0,
284
+ toolWarnings
285
+ };
286
+ const openaiCompatTools = [];
287
+ for (const tool of tools) if (tool.type === "provider") toolWarnings.push({
288
+ type: "unsupported",
289
+ feature: `provider-defined tool ${tool.id}`
290
+ });
291
+ else openaiCompatTools.push({
292
+ type: "function",
293
+ function: {
294
+ name: tool.name,
295
+ description: tool.description,
296
+ parameters: tool.inputSchema,
297
+ ...tool.strict != null ? { strict: tool.strict } : {}
298
+ }
299
+ });
300
+ if (toolChoice == null) return {
301
+ tools: openaiCompatTools,
302
+ toolChoice: void 0,
303
+ toolWarnings
304
+ };
305
+ const type = toolChoice.type;
306
+ switch (type) {
307
+ case "auto":
308
+ case "none":
309
+ case "required": return {
310
+ tools: openaiCompatTools,
311
+ toolChoice: type,
312
+ toolWarnings
313
+ };
314
+ case "tool": return {
315
+ tools: openaiCompatTools,
316
+ toolChoice: {
317
+ type: "function",
318
+ function: { name: toolChoice.toolName }
319
+ },
320
+ toolWarnings
321
+ };
322
+ default: throw new UnsupportedFunctionalityError({ functionality: `tool choice type: ${type}` });
323
+ }
441
324
  }
442
-
443
- // src/chat/openai-compatible-chat-language-model.ts
444
- var OpenAICompatibleChatLanguageModel = class _OpenAICompatibleChatLanguageModel {
445
- constructor(modelId, config) {
446
- this.specificationVersion = "v4";
447
- this.modelId = modelId;
448
- this.config = config;
449
- const errorStructure = config.errorStructure ?? defaultOpenAICompatibleErrorStructure;
450
- this.chunkSchema = createOpenAICompatibleChatChunkSchema(
451
- errorStructure.errorSchema
452
- );
453
- this.failedResponseHandler = createJsonErrorResponseHandler(errorStructure);
454
- this.supportsStructuredOutputs = config.supportsStructuredOutputs ?? false;
455
- }
456
- // type inferred via constructor
457
- static [WORKFLOW_SERIALIZE](model) {
458
- return serializeModelOptions({
459
- modelId: model.modelId,
460
- config: model.config
461
- });
462
- }
463
- static [WORKFLOW_DESERIALIZE](options) {
464
- return new _OpenAICompatibleChatLanguageModel(
465
- options.modelId,
466
- options.config
467
- );
468
- }
469
- get provider() {
470
- return this.config.provider;
471
- }
472
- get providerOptionsName() {
473
- return this.config.provider.split(".")[0].trim();
474
- }
475
- get supportedUrls() {
476
- return this.config.supportedUrls?.() ?? {};
477
- }
478
- transformRequestBody(args) {
479
- return this.config.transformRequestBody?.(args) ?? args;
480
- }
481
- convertUsage(usage) {
482
- return this.config.convertUsage?.(usage) ?? convertOpenAICompatibleChatUsage(usage);
483
- }
484
- async getArgs({
485
- prompt,
486
- maxOutputTokens,
487
- temperature,
488
- topP,
489
- topK,
490
- frequencyPenalty,
491
- presencePenalty,
492
- reasoning,
493
- providerOptions,
494
- stopSequences,
495
- responseFormat,
496
- seed,
497
- toolChoice,
498
- tools
499
- }) {
500
- const warnings = [];
501
- const deprecatedOptions = await parseProviderOptions({
502
- provider: "openai-compatible",
503
- providerOptions,
504
- schema: openaiCompatibleLanguageModelChatOptions
505
- });
506
- if (deprecatedOptions != null) {
507
- warnings.push({
508
- type: "deprecated",
509
- setting: "providerOptions key 'openai-compatible'",
510
- message: "Use 'openaiCompatible' instead."
511
- });
512
- }
513
- warnIfDeprecatedProviderOptionsKey({
514
- rawName: this.providerOptionsName,
515
- providerOptions,
516
- warnings
517
- });
518
- const compatibleOptions = Object.assign(
519
- deprecatedOptions ?? {},
520
- await parseProviderOptions({
521
- provider: "openaiCompatible",
522
- providerOptions,
523
- schema: openaiCompatibleLanguageModelChatOptions
524
- }) ?? {},
525
- await parseProviderOptions({
526
- provider: this.providerOptionsName,
527
- providerOptions,
528
- schema: openaiCompatibleLanguageModelChatOptions
529
- }) ?? {},
530
- await parseProviderOptions({
531
- provider: toCamelCase(this.providerOptionsName),
532
- providerOptions,
533
- schema: openaiCompatibleLanguageModelChatOptions
534
- }) ?? {}
535
- );
536
- const strictJsonSchema = compatibleOptions?.strictJsonSchema ?? true;
537
- if (topK != null) {
538
- warnings.push({ type: "unsupported", feature: "topK" });
539
- }
540
- if (responseFormat?.type === "json" && responseFormat.schema != null && !this.supportsStructuredOutputs) {
541
- warnings.push({
542
- type: "unsupported",
543
- feature: "responseFormat",
544
- details: "JSON response format schema is only supported with structuredOutputs"
545
- });
546
- }
547
- const {
548
- tools: openaiTools,
549
- toolChoice: openaiToolChoice,
550
- toolWarnings
551
- } = prepareTools({
552
- tools,
553
- toolChoice
554
- });
555
- const metadataKey = resolveProviderOptionsKey(
556
- this.providerOptionsName,
557
- providerOptions
558
- );
559
- return {
560
- metadataKey,
561
- args: {
562
- // model id:
563
- model: this.modelId,
564
- // model specific settings:
565
- user: compatibleOptions.user,
566
- // standardized settings:
567
- max_tokens: maxOutputTokens,
568
- temperature,
569
- top_p: topP,
570
- frequency_penalty: frequencyPenalty,
571
- presence_penalty: presencePenalty,
572
- response_format: responseFormat?.type === "json" ? this.supportsStructuredOutputs === true && responseFormat.schema != null ? {
573
- type: "json_schema",
574
- json_schema: {
575
- schema: responseFormat.schema,
576
- strict: strictJsonSchema,
577
- name: responseFormat.name ?? "response",
578
- description: responseFormat.description
579
- }
580
- } : { type: "json_object" } : void 0,
581
- stop: stopSequences,
582
- seed,
583
- ...Object.fromEntries(
584
- Object.entries({
585
- ...providerOptions?.[this.providerOptionsName],
586
- ...providerOptions?.[toCamelCase(this.providerOptionsName)]
587
- }).filter(
588
- ([key]) => !Object.keys(
589
- openaiCompatibleLanguageModelChatOptions.shape
590
- ).includes(key)
591
- )
592
- ),
593
- reasoning_effort: compatibleOptions.reasoningEffort ?? (isCustomReasoning(reasoning) ? reasoning : void 0),
594
- verbosity: compatibleOptions.textVerbosity,
595
- // messages:
596
- messages: convertToOpenAICompatibleChatMessages(prompt, {
597
- providerOptionsKey: metadataKey
598
- }),
599
- // tools:
600
- tools: openaiTools,
601
- tool_choice: openaiToolChoice
602
- },
603
- warnings: [...warnings, ...toolWarnings]
604
- };
605
- }
606
- async doGenerate(options) {
607
- const { args, warnings, metadataKey } = await this.getArgs({ ...options });
608
- const transformedBody = this.transformRequestBody(args);
609
- const body = JSON.stringify(transformedBody);
610
- const {
611
- responseHeaders,
612
- value: responseBody,
613
- rawValue: rawResponse
614
- } = await postJsonToApi({
615
- url: this.config.url({
616
- path: "/chat/completions",
617
- modelId: this.modelId
618
- }),
619
- headers: combineHeaders(this.config.headers?.(), options.headers),
620
- body: transformedBody,
621
- failedResponseHandler: this.failedResponseHandler,
622
- successfulResponseHandler: createJsonResponseHandler(
623
- OpenAICompatibleChatResponseSchema
624
- ),
625
- abortSignal: options.abortSignal,
626
- fetch: this.config.fetch
627
- });
628
- const choice = responseBody.choices[0];
629
- if (choice == null) {
630
- throw new InvalidResponseDataError({
631
- data: rawResponse,
632
- message: "Response did not contain any choices."
633
- });
634
- }
635
- const content = [];
636
- content.push(...convertOpenAICompatibleContent(choice.message.content));
637
- const reasoning = choice.message.reasoning_content ?? choice.message.reasoning;
638
- if (reasoning != null && reasoning.length > 0) {
639
- content.push({
640
- type: "reasoning",
641
- text: reasoning
642
- });
643
- }
644
- if (choice.message.tool_calls != null) {
645
- for (const toolCall of choice.message.tool_calls) {
646
- const thoughtSignature = toolCall.extra_content?.google?.thought_signature;
647
- content.push({
648
- type: "tool-call",
649
- toolCallId: toolCall.id || generateId(),
650
- toolName: toolCall.function.name,
651
- input: toolCall.function.arguments,
652
- ...thoughtSignature ? {
653
- providerMetadata: {
654
- [metadataKey]: { thoughtSignature }
655
- }
656
- } : {}
657
- });
658
- }
659
- }
660
- const providerMetadata = {
661
- [metadataKey]: {},
662
- ...await this.config.metadataExtractor?.extractMetadata?.({
663
- parsedBody: rawResponse
664
- })
665
- };
666
- const completionTokenDetails = responseBody.usage?.completion_tokens_details;
667
- if (completionTokenDetails?.accepted_prediction_tokens != null) {
668
- providerMetadata[metadataKey].acceptedPredictionTokens = completionTokenDetails?.accepted_prediction_tokens;
669
- }
670
- if (completionTokenDetails?.rejected_prediction_tokens != null) {
671
- providerMetadata[metadataKey].rejectedPredictionTokens = completionTokenDetails?.rejected_prediction_tokens;
672
- }
673
- return {
674
- content,
675
- finishReason: {
676
- unified: mapOpenAICompatibleFinishReason(choice.finish_reason),
677
- raw: choice.finish_reason ?? void 0
678
- },
679
- usage: this.convertUsage(responseBody.usage),
680
- providerMetadata,
681
- request: { body },
682
- response: {
683
- ...getResponseMetadata(responseBody),
684
- headers: responseHeaders,
685
- body: rawResponse
686
- },
687
- warnings
688
- };
689
- }
690
- async doStream(options) {
691
- const { args, warnings, metadataKey } = await this.getArgs({
692
- ...options
693
- });
694
- const body = this.transformRequestBody({
695
- ...args,
696
- stream: true,
697
- // only include stream_options when in strict compatibility mode:
698
- stream_options: this.config.includeUsage ? { include_usage: true } : void 0
699
- });
700
- const metadataExtractor = this.config.metadataExtractor?.createStreamExtractor();
701
- const { responseHeaders, value: response } = await postJsonToApi({
702
- url: this.config.url({
703
- path: "/chat/completions",
704
- modelId: this.modelId
705
- }),
706
- headers: combineHeaders(this.config.headers?.(), options.headers),
707
- body,
708
- failedResponseHandler: this.failedResponseHandler,
709
- successfulResponseHandler: createEventSourceResponseHandler(
710
- this.chunkSchema
711
- ),
712
- abortSignal: options.abortSignal,
713
- fetch: this.config.fetch
714
- });
715
- const providerOptionsName = metadataKey;
716
- let toolCallTracker;
717
- const pendingToolCalls = /* @__PURE__ */ new Map();
718
- const forwardedToolCallIndices = /* @__PURE__ */ new Set();
719
- const processToolCallDelta = (toolCallDelta) => {
720
- const index = toolCallDelta.index;
721
- if (index == null || forwardedToolCallIndices.has(index)) {
722
- toolCallTracker.processDelta(toolCallDelta);
723
- return;
724
- }
725
- let pending = pendingToolCalls.get(index);
726
- if (pending == null) {
727
- pending = {
728
- id: toolCallDelta.id ?? null,
729
- bufferedArguments: "",
730
- extraContent: toolCallDelta.extra_content ?? null
731
- };
732
- pendingToolCalls.set(index, pending);
733
- } else {
734
- if (pending.id == null && toolCallDelta.id != null) {
735
- pending.id = toolCallDelta.id;
736
- }
737
- if (pending.extraContent == null && toolCallDelta.extra_content != null) {
738
- pending.extraContent = toolCallDelta.extra_content;
739
- }
740
- }
741
- const argumentsDelta = toolCallDelta.function?.arguments;
742
- if (argumentsDelta != null) {
743
- pending.bufferedArguments += argumentsDelta;
744
- }
745
- const name = toolCallDelta.function?.name;
746
- if (name != null) {
747
- const forwardDelta = {
748
- index,
749
- id: pending.id,
750
- function: {
751
- name,
752
- arguments: pending.bufferedArguments
753
- },
754
- extra_content: pending.extraContent ?? void 0
755
- };
756
- toolCallTracker.processDelta(forwardDelta);
757
- pendingToolCalls.delete(index);
758
- forwardedToolCallIndices.add(index);
759
- }
760
- };
761
- let finishReason;
762
- let usage = void 0;
763
- let metadataExtracted = false;
764
- let isActiveReasoning = false;
765
- let isActiveText = false;
766
- const convertUsage = (usage2) => this.convertUsage(usage2);
767
- return {
768
- stream: response.pipeThrough(
769
- new TransformStream({
770
- start(controller) {
771
- toolCallTracker = new StreamingToolCallTracker(
772
- controller,
773
- {
774
- generateId,
775
- extractMetadata: (delta) => {
776
- const thoughtSignature = delta.extra_content?.google?.thought_signature;
777
- return thoughtSignature ? { [providerOptionsName]: { thoughtSignature } } : void 0;
778
- },
779
- buildToolCallProviderMetadata: (metadata) => metadata
780
- }
781
- );
782
- controller.enqueue({ type: "stream-start", warnings });
783
- },
784
- transform(chunk, controller) {
785
- if (options.includeRawChunks) {
786
- controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
787
- }
788
- if (!chunk.success) {
789
- finishReason = { unified: "error", raw: void 0 };
790
- controller.enqueue({ type: "error", error: chunk.error });
791
- return;
792
- }
793
- metadataExtractor?.processChunk(chunk.rawValue);
794
- if ("error" in chunk.value) {
795
- finishReason = { unified: "error", raw: void 0 };
796
- controller.enqueue({
797
- type: "error",
798
- error: chunk.value.error
799
- });
800
- return;
801
- }
802
- const value = chunk.value;
803
- if (!metadataExtracted) {
804
- const metadata = getResponseMetadata(value);
805
- if (Object.values(metadata).some(Boolean)) {
806
- metadataExtracted = true;
807
- controller.enqueue({
808
- type: "response-metadata",
809
- ...metadata
810
- });
811
- }
812
- }
813
- if (value.usage != null) {
814
- usage = value.usage;
815
- }
816
- const choice = value.choices[0];
817
- if (choice?.finish_reason != null) {
818
- finishReason = {
819
- unified: mapOpenAICompatibleFinishReason(choice.finish_reason),
820
- raw: choice.finish_reason ?? void 0
821
- };
822
- }
823
- if (choice?.delta == null) {
824
- return;
825
- }
826
- const delta = choice.delta;
827
- const enqueueReasoningDelta = (reasoningDelta) => {
828
- if (isActiveText) {
829
- controller.enqueue({ type: "text-end", id: "txt-0" });
830
- isActiveText = false;
831
- }
832
- if (!isActiveReasoning) {
833
- controller.enqueue({
834
- type: "reasoning-start",
835
- id: "reasoning-0"
836
- });
837
- isActiveReasoning = true;
838
- }
839
- controller.enqueue({
840
- type: "reasoning-delta",
841
- id: "reasoning-0",
842
- delta: reasoningDelta
843
- });
844
- };
845
- const enqueueTextDelta = (textDelta) => {
846
- if (isActiveReasoning) {
847
- controller.enqueue({
848
- type: "reasoning-end",
849
- id: "reasoning-0"
850
- });
851
- isActiveReasoning = false;
852
- }
853
- if (!isActiveText) {
854
- controller.enqueue({ type: "text-start", id: "txt-0" });
855
- isActiveText = true;
856
- }
857
- controller.enqueue({
858
- type: "text-delta",
859
- id: "txt-0",
860
- delta: textDelta
861
- });
862
- };
863
- const reasoningContent = delta.reasoning_content ?? delta.reasoning;
864
- if (reasoningContent) {
865
- enqueueReasoningDelta(reasoningContent);
866
- }
867
- for (const contentPart of convertOpenAICompatibleContent(
868
- delta.content
869
- )) {
870
- if (contentPart.type === "reasoning") {
871
- enqueueReasoningDelta(contentPart.text);
872
- } else {
873
- enqueueTextDelta(contentPart.text);
874
- }
875
- }
876
- if (delta.tool_calls != null && delta.tool_calls.length > 0) {
877
- if (isActiveReasoning) {
878
- controller.enqueue({
879
- type: "reasoning-end",
880
- id: "reasoning-0"
881
- });
882
- isActiveReasoning = false;
883
- }
884
- for (const toolCallDelta of delta.tool_calls) {
885
- processToolCallDelta(toolCallDelta);
886
- }
887
- }
888
- },
889
- flush(controller) {
890
- if (isActiveReasoning) {
891
- controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
892
- }
893
- if (isActiveText) {
894
- controller.enqueue({ type: "text-end", id: "txt-0" });
895
- }
896
- for (const [index, pending] of pendingToolCalls) {
897
- toolCallTracker.processDelta({
898
- index,
899
- id: pending.id,
900
- function: { arguments: pending.bufferedArguments }
901
- });
902
- }
903
- pendingToolCalls.clear();
904
- toolCallTracker.flush();
905
- if (finishReason == null) {
906
- finishReason = { unified: "error", raw: void 0 };
907
- controller.enqueue({
908
- type: "error",
909
- error: new InvalidResponseDataError({
910
- data: void 0,
911
- message: "Response stream ended without a finish reason."
912
- })
913
- });
914
- }
915
- const providerMetadata = {
916
- [providerOptionsName]: {},
917
- ...metadataExtractor?.buildMetadata()
918
- };
919
- if (usage?.completion_tokens_details?.accepted_prediction_tokens != null) {
920
- providerMetadata[providerOptionsName].acceptedPredictionTokens = usage?.completion_tokens_details?.accepted_prediction_tokens;
921
- }
922
- if (usage?.completion_tokens_details?.rejected_prediction_tokens != null) {
923
- providerMetadata[providerOptionsName].rejectedPredictionTokens = usage?.completion_tokens_details?.rejected_prediction_tokens;
924
- }
925
- controller.enqueue({
926
- type: "finish",
927
- finishReason,
928
- usage: convertUsage(usage),
929
- providerMetadata
930
- });
931
- }
932
- })
933
- ),
934
- request: { body },
935
- response: { headers: responseHeaders }
936
- };
937
- }
325
+ //#endregion
326
+ //#region src/chat/openai-compatible-chat-language-model.ts
327
+ var OpenAICompatibleChatLanguageModel = class OpenAICompatibleChatLanguageModel {
328
+ static [WORKFLOW_SERIALIZE](model) {
329
+ return serializeModelOptions({
330
+ modelId: model.modelId,
331
+ config: model.config
332
+ });
333
+ }
334
+ static [WORKFLOW_DESERIALIZE](options) {
335
+ return new OpenAICompatibleChatLanguageModel(options.modelId, options.config);
336
+ }
337
+ constructor(modelId, config) {
338
+ this.specificationVersion = "v4";
339
+ this.modelId = modelId;
340
+ this.config = config;
341
+ const errorStructure = config.errorStructure ?? defaultOpenAICompatibleErrorStructure;
342
+ this.chunkSchema = createOpenAICompatibleChatChunkSchema(errorStructure.errorSchema);
343
+ this.failedResponseHandler = createJsonErrorResponseHandler(errorStructure);
344
+ this.supportsStructuredOutputs = config.supportsStructuredOutputs ?? false;
345
+ }
346
+ get provider() {
347
+ return this.config.provider;
348
+ }
349
+ get providerOptionsName() {
350
+ return this.config.provider.split(".")[0].trim();
351
+ }
352
+ get supportedUrls() {
353
+ return this.config.supportedUrls?.() ?? {};
354
+ }
355
+ transformRequestBody(args) {
356
+ return this.config.transformRequestBody?.(args) ?? args;
357
+ }
358
+ convertUsage(usage) {
359
+ return this.config.convertUsage?.(usage) ?? convertOpenAICompatibleChatUsage(usage);
360
+ }
361
+ async getArgs({ prompt, maxOutputTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, reasoning, providerOptions, stopSequences, responseFormat, seed, toolChoice, tools }) {
362
+ const warnings = [];
363
+ const deprecatedOptions = await parseProviderOptions({
364
+ provider: "openai-compatible",
365
+ providerOptions,
366
+ schema: openaiCompatibleLanguageModelChatOptions
367
+ });
368
+ if (deprecatedOptions != null) warnings.push({
369
+ type: "deprecated",
370
+ setting: "providerOptions key 'openai-compatible'",
371
+ message: "Use 'openaiCompatible' instead."
372
+ });
373
+ warnIfDeprecatedProviderOptionsKey({
374
+ rawName: this.providerOptionsName,
375
+ providerOptions,
376
+ warnings
377
+ });
378
+ const compatibleOptions = Object.assign(deprecatedOptions ?? {}, await parseProviderOptions({
379
+ provider: "openaiCompatible",
380
+ providerOptions,
381
+ schema: openaiCompatibleLanguageModelChatOptions
382
+ }) ?? {}, await parseProviderOptions({
383
+ provider: this.providerOptionsName,
384
+ providerOptions,
385
+ schema: openaiCompatibleLanguageModelChatOptions
386
+ }) ?? {}, await parseProviderOptions({
387
+ provider: toCamelCase(this.providerOptionsName),
388
+ providerOptions,
389
+ schema: openaiCompatibleLanguageModelChatOptions
390
+ }) ?? {});
391
+ const strictJsonSchema = compatibleOptions?.strictJsonSchema ?? true;
392
+ if (topK != null) warnings.push({
393
+ type: "unsupported",
394
+ feature: "topK"
395
+ });
396
+ if (responseFormat?.type === "json" && responseFormat.schema != null && !this.supportsStructuredOutputs) warnings.push({
397
+ type: "unsupported",
398
+ feature: "responseFormat",
399
+ details: "JSON response format schema is only supported with structuredOutputs"
400
+ });
401
+ const { tools: openaiTools, toolChoice: openaiToolChoice, toolWarnings } = prepareTools({
402
+ tools,
403
+ toolChoice
404
+ });
405
+ const metadataKey = resolveProviderOptionsKey(this.providerOptionsName, providerOptions);
406
+ return {
407
+ metadataKey,
408
+ args: {
409
+ model: this.modelId,
410
+ user: compatibleOptions.user,
411
+ max_tokens: maxOutputTokens,
412
+ temperature,
413
+ top_p: topP,
414
+ frequency_penalty: frequencyPenalty,
415
+ presence_penalty: presencePenalty,
416
+ response_format: responseFormat?.type === "json" ? this.supportsStructuredOutputs === true && responseFormat.schema != null ? {
417
+ type: "json_schema",
418
+ json_schema: {
419
+ schema: responseFormat.schema,
420
+ strict: strictJsonSchema,
421
+ name: responseFormat.name ?? "response",
422
+ description: responseFormat.description
423
+ }
424
+ } : { type: "json_object" } : void 0,
425
+ stop: stopSequences,
426
+ seed,
427
+ ...Object.fromEntries(Object.entries({
428
+ ...providerOptions?.[this.providerOptionsName],
429
+ ...providerOptions?.[toCamelCase(this.providerOptionsName)]
430
+ }).filter(([key]) => !Object.keys(openaiCompatibleLanguageModelChatOptions.shape).includes(key))),
431
+ reasoning_effort: compatibleOptions.reasoningEffort ?? (isCustomReasoning(reasoning) ? reasoning : void 0),
432
+ verbosity: compatibleOptions.textVerbosity,
433
+ messages: convertToOpenAICompatibleChatMessages(prompt, { providerOptionsKey: metadataKey }),
434
+ tools: openaiTools,
435
+ tool_choice: openaiToolChoice
436
+ },
437
+ warnings: [...warnings, ...toolWarnings]
438
+ };
439
+ }
440
+ async doGenerate(options) {
441
+ const { args, warnings, metadataKey } = await this.getArgs({ ...options });
442
+ const transformedBody = this.transformRequestBody(args);
443
+ const body = JSON.stringify(transformedBody);
444
+ const { responseHeaders, value: responseBody, rawValue: rawResponse } = await postJsonToApi({
445
+ url: this.config.url({
446
+ path: "/chat/completions",
447
+ modelId: this.modelId
448
+ }),
449
+ headers: combineHeaders(this.config.headers?.(), options.headers),
450
+ body: transformedBody,
451
+ failedResponseHandler: this.failedResponseHandler,
452
+ successfulResponseHandler: createJsonResponseHandler(OpenAICompatibleChatResponseSchema),
453
+ abortSignal: options.abortSignal,
454
+ fetch: this.config.fetch
455
+ });
456
+ const choice = responseBody.choices[0];
457
+ if (choice == null) throw new InvalidResponseDataError({
458
+ data: rawResponse,
459
+ message: "Response did not contain any choices."
460
+ });
461
+ const content = [];
462
+ content.push(...convertOpenAICompatibleContent(choice.message.content));
463
+ const reasoning = choice.message.reasoning_content ?? choice.message.reasoning;
464
+ if (reasoning != null && reasoning.length > 0) content.push({
465
+ type: "reasoning",
466
+ text: reasoning
467
+ });
468
+ if (choice.message.tool_calls != null) for (const toolCall of choice.message.tool_calls) {
469
+ const thoughtSignature = toolCall.extra_content?.google?.thought_signature;
470
+ content.push({
471
+ type: "tool-call",
472
+ toolCallId: toolCall.id || generateId(),
473
+ toolName: toolCall.function.name,
474
+ input: toolCall.function.arguments,
475
+ ...thoughtSignature ? { providerMetadata: { [metadataKey]: { thoughtSignature } } } : {}
476
+ });
477
+ }
478
+ const providerMetadata = {
479
+ [metadataKey]: {},
480
+ ...await this.config.metadataExtractor?.extractMetadata?.({ parsedBody: rawResponse })
481
+ };
482
+ const completionTokenDetails = responseBody.usage?.completion_tokens_details;
483
+ if (completionTokenDetails?.accepted_prediction_tokens != null) providerMetadata[metadataKey].acceptedPredictionTokens = completionTokenDetails?.accepted_prediction_tokens;
484
+ if (completionTokenDetails?.rejected_prediction_tokens != null) providerMetadata[metadataKey].rejectedPredictionTokens = completionTokenDetails?.rejected_prediction_tokens;
485
+ return {
486
+ content,
487
+ finishReason: {
488
+ unified: mapOpenAICompatibleFinishReason$1(choice.finish_reason),
489
+ raw: choice.finish_reason ?? void 0
490
+ },
491
+ usage: this.convertUsage(responseBody.usage),
492
+ providerMetadata,
493
+ request: { body },
494
+ response: {
495
+ ...getResponseMetadata$1(responseBody),
496
+ headers: responseHeaders,
497
+ body: rawResponse
498
+ },
499
+ warnings
500
+ };
501
+ }
502
+ async doStream(options) {
503
+ const { args, warnings, metadataKey } = await this.getArgs({ ...options });
504
+ const body = this.transformRequestBody({
505
+ ...args,
506
+ stream: true,
507
+ stream_options: this.config.includeUsage ? { include_usage: true } : void 0
508
+ });
509
+ const metadataExtractor = this.config.metadataExtractor?.createStreamExtractor();
510
+ const { responseHeaders, value: response } = await postJsonToApi({
511
+ url: this.config.url({
512
+ path: "/chat/completions",
513
+ modelId: this.modelId
514
+ }),
515
+ headers: combineHeaders(this.config.headers?.(), options.headers),
516
+ body,
517
+ failedResponseHandler: this.failedResponseHandler,
518
+ successfulResponseHandler: createEventSourceResponseHandler(this.chunkSchema),
519
+ abortSignal: options.abortSignal,
520
+ fetch: this.config.fetch
521
+ });
522
+ const providerOptionsName = metadataKey;
523
+ let toolCallTracker;
524
+ const pendingToolCalls = /* @__PURE__ */ new Map();
525
+ const forwardedToolCallIndices = /* @__PURE__ */ new Set();
526
+ const processToolCallDelta = (toolCallDelta) => {
527
+ const index = toolCallDelta.index;
528
+ if (index == null || forwardedToolCallIndices.has(index)) {
529
+ toolCallTracker.processDelta(toolCallDelta);
530
+ return;
531
+ }
532
+ let pending = pendingToolCalls.get(index);
533
+ if (pending == null) {
534
+ pending = {
535
+ id: toolCallDelta.id ?? null,
536
+ bufferedArguments: "",
537
+ extraContent: toolCallDelta.extra_content ?? null
538
+ };
539
+ pendingToolCalls.set(index, pending);
540
+ } else {
541
+ if (pending.id == null && toolCallDelta.id != null) pending.id = toolCallDelta.id;
542
+ if (pending.extraContent == null && toolCallDelta.extra_content != null) pending.extraContent = toolCallDelta.extra_content;
543
+ }
544
+ const argumentsDelta = toolCallDelta.function?.arguments;
545
+ if (argumentsDelta != null) pending.bufferedArguments += argumentsDelta;
546
+ const name = toolCallDelta.function?.name;
547
+ if (name != null) {
548
+ const forwardDelta = {
549
+ index,
550
+ id: pending.id,
551
+ function: {
552
+ name,
553
+ arguments: pending.bufferedArguments
554
+ },
555
+ extra_content: pending.extraContent ?? void 0
556
+ };
557
+ toolCallTracker.processDelta(forwardDelta);
558
+ pendingToolCalls.delete(index);
559
+ forwardedToolCallIndices.add(index);
560
+ }
561
+ };
562
+ let finishReason;
563
+ let usage = void 0;
564
+ let metadataExtracted = false;
565
+ let isActiveReasoning = false;
566
+ let isActiveText = false;
567
+ const convertUsage = (usage) => this.convertUsage(usage);
568
+ return {
569
+ stream: response.pipeThrough(new TransformStream({
570
+ start(controller) {
571
+ toolCallTracker = new StreamingToolCallTracker(controller, {
572
+ generateId,
573
+ extractMetadata: (delta) => {
574
+ const thoughtSignature = delta.extra_content?.google?.thought_signature;
575
+ return thoughtSignature ? { [providerOptionsName]: { thoughtSignature } } : void 0;
576
+ },
577
+ buildToolCallProviderMetadata: (metadata) => metadata
578
+ });
579
+ controller.enqueue({
580
+ type: "stream-start",
581
+ warnings
582
+ });
583
+ },
584
+ transform(chunk, controller) {
585
+ if (options.includeRawChunks) controller.enqueue({
586
+ type: "raw",
587
+ rawValue: chunk.rawValue
588
+ });
589
+ if (!chunk.success) {
590
+ finishReason = {
591
+ unified: "error",
592
+ raw: void 0
593
+ };
594
+ controller.enqueue({
595
+ type: "error",
596
+ error: chunk.error
597
+ });
598
+ return;
599
+ }
600
+ metadataExtractor?.processChunk(chunk.rawValue);
601
+ if ("error" in chunk.value) {
602
+ finishReason = {
603
+ unified: "error",
604
+ raw: void 0
605
+ };
606
+ controller.enqueue({
607
+ type: "error",
608
+ error: chunk.value.error
609
+ });
610
+ return;
611
+ }
612
+ const value = chunk.value;
613
+ if (!metadataExtracted) {
614
+ const metadata = getResponseMetadata$1(value);
615
+ if (Object.values(metadata).some(Boolean)) {
616
+ metadataExtracted = true;
617
+ controller.enqueue({
618
+ type: "response-metadata",
619
+ ...metadata
620
+ });
621
+ }
622
+ }
623
+ if (value.usage != null) usage = value.usage;
624
+ const choice = value.choices[0];
625
+ if (choice?.finish_reason != null) finishReason = {
626
+ unified: mapOpenAICompatibleFinishReason$1(choice.finish_reason),
627
+ raw: choice.finish_reason ?? void 0
628
+ };
629
+ if (choice?.delta == null) return;
630
+ const delta = choice.delta;
631
+ const enqueueReasoningDelta = (reasoningDelta) => {
632
+ if (isActiveText) {
633
+ controller.enqueue({
634
+ type: "text-end",
635
+ id: "txt-0"
636
+ });
637
+ isActiveText = false;
638
+ }
639
+ if (!isActiveReasoning) {
640
+ controller.enqueue({
641
+ type: "reasoning-start",
642
+ id: "reasoning-0"
643
+ });
644
+ isActiveReasoning = true;
645
+ }
646
+ controller.enqueue({
647
+ type: "reasoning-delta",
648
+ id: "reasoning-0",
649
+ delta: reasoningDelta
650
+ });
651
+ };
652
+ const enqueueTextDelta = (textDelta) => {
653
+ if (isActiveReasoning) {
654
+ controller.enqueue({
655
+ type: "reasoning-end",
656
+ id: "reasoning-0"
657
+ });
658
+ isActiveReasoning = false;
659
+ }
660
+ if (!isActiveText) {
661
+ controller.enqueue({
662
+ type: "text-start",
663
+ id: "txt-0"
664
+ });
665
+ isActiveText = true;
666
+ }
667
+ controller.enqueue({
668
+ type: "text-delta",
669
+ id: "txt-0",
670
+ delta: textDelta
671
+ });
672
+ };
673
+ const reasoningContent = delta.reasoning_content ?? delta.reasoning;
674
+ if (reasoningContent) enqueueReasoningDelta(reasoningContent);
675
+ for (const contentPart of convertOpenAICompatibleContent(delta.content)) if (contentPart.type === "reasoning") enqueueReasoningDelta(contentPart.text);
676
+ else enqueueTextDelta(contentPart.text);
677
+ if (delta.tool_calls != null && delta.tool_calls.length > 0) {
678
+ if (isActiveReasoning) {
679
+ controller.enqueue({
680
+ type: "reasoning-end",
681
+ id: "reasoning-0"
682
+ });
683
+ isActiveReasoning = false;
684
+ }
685
+ for (const toolCallDelta of delta.tool_calls) processToolCallDelta(toolCallDelta);
686
+ }
687
+ },
688
+ flush(controller) {
689
+ if (isActiveReasoning) controller.enqueue({
690
+ type: "reasoning-end",
691
+ id: "reasoning-0"
692
+ });
693
+ if (isActiveText) controller.enqueue({
694
+ type: "text-end",
695
+ id: "txt-0"
696
+ });
697
+ for (const [index, pending] of pendingToolCalls) toolCallTracker.processDelta({
698
+ index,
699
+ id: pending.id,
700
+ function: { arguments: pending.bufferedArguments }
701
+ });
702
+ pendingToolCalls.clear();
703
+ toolCallTracker.flush();
704
+ if (finishReason == null) {
705
+ finishReason = {
706
+ unified: "error",
707
+ raw: void 0
708
+ };
709
+ controller.enqueue({
710
+ type: "error",
711
+ error: new InvalidResponseDataError({
712
+ data: void 0,
713
+ message: "Response stream ended without a finish reason."
714
+ })
715
+ });
716
+ }
717
+ const providerMetadata = {
718
+ [providerOptionsName]: {},
719
+ ...metadataExtractor?.buildMetadata()
720
+ };
721
+ if (usage?.completion_tokens_details?.accepted_prediction_tokens != null) providerMetadata[providerOptionsName].acceptedPredictionTokens = usage?.completion_tokens_details?.accepted_prediction_tokens;
722
+ if (usage?.completion_tokens_details?.rejected_prediction_tokens != null) providerMetadata[providerOptionsName].rejectedPredictionTokens = usage?.completion_tokens_details?.rejected_prediction_tokens;
723
+ controller.enqueue({
724
+ type: "finish",
725
+ finishReason,
726
+ usage: convertUsage(usage),
727
+ providerMetadata
728
+ });
729
+ }
730
+ })),
731
+ request: { body },
732
+ response: { headers: responseHeaders }
733
+ };
734
+ }
938
735
  };
939
- var openaiCompatibleTokenUsageSchema = z3.looseObject({
940
- prompt_tokens: z3.number().nullish(),
941
- completion_tokens: z3.number().nullish(),
942
- total_tokens: z3.number().nullish(),
943
- prompt_tokens_details: z3.looseObject({
944
- cached_tokens: z3.number().nullish()
945
- }).nullish(),
946
- completion_tokens_details: z3.looseObject({
947
- reasoning_tokens: z3.number().nullish(),
948
- accepted_prediction_tokens: z3.number().nullish(),
949
- rejected_prediction_tokens: z3.number().nullish()
950
- }).nullish()
736
+ const openaiCompatibleTokenUsageSchema = z.looseObject({
737
+ prompt_tokens: z.number().nullish(),
738
+ completion_tokens: z.number().nullish(),
739
+ total_tokens: z.number().nullish(),
740
+ prompt_tokens_details: z.looseObject({ cached_tokens: z.number().nullish() }).nullish(),
741
+ completion_tokens_details: z.looseObject({
742
+ reasoning_tokens: z.number().nullish(),
743
+ accepted_prediction_tokens: z.number().nullish(),
744
+ rejected_prediction_tokens: z.number().nullish()
745
+ }).nullish()
951
746
  }).nullish();
952
- var openAICompatibleContentSchema = z3.union([
953
- z3.string(),
954
- z3.array(
955
- z3.looseObject({
956
- type: z3.string()
957
- })
958
- )
959
- ]).nullish();
747
+ const openAICompatibleContentSchema = z.union([z.string(), z.array(z.looseObject({ type: z.string() }))]).nullish();
960
748
  function convertOpenAICompatibleContent(content) {
961
- if (content == null) {
962
- return [];
963
- }
964
- if (typeof content === "string") {
965
- return content.length > 0 ? [{ type: "text", text: content }] : [];
966
- }
967
- const result = [];
968
- for (const part of content) {
969
- if (part.type === "text" && typeof part.text === "string") {
970
- if (part.text.length > 0) {
971
- result.push({ type: "text", text: part.text });
972
- }
973
- } else if (part.type === "thinking" && Array.isArray(part.thinking)) {
974
- const reasoningText = part.thinking.filter(
975
- (chunk) => chunk != null && typeof chunk === "object" && "type" in chunk && chunk.type === "text" && "text" in chunk && typeof chunk.text === "string"
976
- ).map((chunk) => chunk.text).join("");
977
- if (reasoningText.length > 0) {
978
- result.push({ type: "reasoning", text: reasoningText });
979
- }
980
- }
981
- }
982
- return result;
749
+ if (content == null) return [];
750
+ if (typeof content === "string") return content.length > 0 ? [{
751
+ type: "text",
752
+ text: content
753
+ }] : [];
754
+ const result = [];
755
+ for (const part of content) if (part.type === "text" && typeof part.text === "string") {
756
+ if (part.text.length > 0) result.push({
757
+ type: "text",
758
+ text: part.text
759
+ });
760
+ } else if (part.type === "thinking" && Array.isArray(part.thinking)) {
761
+ const reasoningText = part.thinking.filter((chunk) => chunk != null && typeof chunk === "object" && "type" in chunk && chunk.type === "text" && "text" in chunk && typeof chunk.text === "string").map((chunk) => chunk.text).join("");
762
+ if (reasoningText.length > 0) result.push({
763
+ type: "reasoning",
764
+ text: reasoningText
765
+ });
766
+ }
767
+ return result;
983
768
  }
984
- var OpenAICompatibleChatResponseSchema = z3.looseObject({
985
- id: z3.string().nullish(),
986
- created: z3.number().nullish(),
987
- model: z3.string().nullish(),
988
- choices: z3.array(
989
- z3.object({
990
- message: z3.object({
991
- role: z3.literal("assistant").nullish(),
992
- content: openAICompatibleContentSchema,
993
- reasoning_content: z3.string().nullish(),
994
- reasoning: z3.string().nullish(),
995
- tool_calls: z3.array(
996
- z3.object({
997
- id: z3.string().nullish(),
998
- function: z3.object({
999
- name: z3.string(),
1000
- arguments: z3.string()
1001
- }),
1002
- // Support for Google Gemini thought signatures via OpenAI compatibility
1003
- extra_content: z3.object({
1004
- google: z3.object({
1005
- thought_signature: z3.string().nullish()
1006
- }).nullish()
1007
- }).nullish()
1008
- })
1009
- ).nullish()
1010
- }),
1011
- finish_reason: z3.string().nullish()
1012
- })
1013
- ),
1014
- usage: openaiCompatibleTokenUsageSchema
769
+ const OpenAICompatibleChatResponseSchema = z.looseObject({
770
+ id: z.string().nullish(),
771
+ created: z.number().nullish(),
772
+ model: z.string().nullish(),
773
+ choices: z.array(z.object({
774
+ message: z.object({
775
+ role: z.literal("assistant").nullish(),
776
+ content: openAICompatibleContentSchema,
777
+ reasoning_content: z.string().nullish(),
778
+ reasoning: z.string().nullish(),
779
+ tool_calls: z.array(z.object({
780
+ id: z.string().nullish(),
781
+ function: z.object({
782
+ name: z.string(),
783
+ arguments: z.string()
784
+ }),
785
+ extra_content: z.object({ google: z.object({ thought_signature: z.string().nullish() }).nullish() }).nullish()
786
+ })).nullish()
787
+ }),
788
+ finish_reason: z.string().nullish()
789
+ })),
790
+ usage: openaiCompatibleTokenUsageSchema
1015
791
  });
1016
- var chunkBaseSchema = z3.looseObject({
1017
- id: z3.string().nullish(),
1018
- created: z3.number().nullish(),
1019
- model: z3.string().nullish(),
1020
- choices: z3.array(
1021
- z3.object({
1022
- delta: z3.object({
1023
- role: z3.enum(["assistant", ""]).nullish(),
1024
- content: openAICompatibleContentSchema,
1025
- // Most openai-compatible models set `reasoning_content`, but some
1026
- // providers serving `gpt-oss` set `reasoning`. See #7866
1027
- reasoning_content: z3.string().nullish(),
1028
- reasoning: z3.string().nullish(),
1029
- tool_calls: z3.array(
1030
- z3.object({
1031
- index: z3.number().nullish(),
1032
- //google does not send index
1033
- id: z3.string().nullish(),
1034
- function: z3.object({
1035
- name: z3.string().nullish(),
1036
- arguments: z3.string().nullish()
1037
- }),
1038
- // Support for Google Gemini thought signatures via OpenAI compatibility
1039
- extra_content: z3.object({
1040
- google: z3.object({
1041
- thought_signature: z3.string().nullish()
1042
- }).nullish()
1043
- }).nullish()
1044
- })
1045
- ).nullish()
1046
- }).nullish(),
1047
- finish_reason: z3.string().nullish()
1048
- })
1049
- ),
1050
- usage: openaiCompatibleTokenUsageSchema
792
+ const chunkBaseSchema = z.looseObject({
793
+ id: z.string().nullish(),
794
+ created: z.number().nullish(),
795
+ model: z.string().nullish(),
796
+ choices: z.array(z.object({
797
+ delta: z.object({
798
+ role: z.enum(["assistant", ""]).nullish(),
799
+ content: openAICompatibleContentSchema,
800
+ reasoning_content: z.string().nullish(),
801
+ reasoning: z.string().nullish(),
802
+ tool_calls: z.array(z.object({
803
+ index: z.number().nullish(),
804
+ id: z.string().nullish(),
805
+ function: z.object({
806
+ name: z.string().nullish(),
807
+ arguments: z.string().nullish()
808
+ }),
809
+ extra_content: z.object({ google: z.object({ thought_signature: z.string().nullish() }).nullish() }).nullish()
810
+ })).nullish()
811
+ }).nullish(),
812
+ finish_reason: z.string().nullish()
813
+ })),
814
+ usage: openaiCompatibleTokenUsageSchema
1051
815
  });
1052
- var createOpenAICompatibleChatChunkSchema = (errorSchema) => z3.union([chunkBaseSchema, errorSchema]);
1053
-
1054
- // src/completion/openai-compatible-completion-language-model.ts
1055
- import {
1056
- combineHeaders as combineHeaders2,
1057
- createEventSourceResponseHandler as createEventSourceResponseHandler2,
1058
- createJsonErrorResponseHandler as createJsonErrorResponseHandler2,
1059
- createJsonResponseHandler as createJsonResponseHandler2,
1060
- parseProviderOptions as parseProviderOptions2,
1061
- postJsonToApi as postJsonToApi2,
1062
- serializeModelOptions as serializeModelOptions2,
1063
- WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2,
1064
- WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2
1065
- } from "@ai-sdk/provider-utils";
1066
- import { z as z5 } from "zod/v4";
1067
-
1068
- // src/completion/convert-openai-compatible-completion-usage.ts
1069
- import { createNullLanguageModelUsage as createNullLanguageModelUsage2 } from "@ai-sdk/provider-utils";
816
+ const createOpenAICompatibleChatChunkSchema = (errorSchema) => z.union([chunkBaseSchema, errorSchema]);
817
+ //#endregion
818
+ //#region src/completion/convert-openai-compatible-completion-usage.ts
1070
819
  function convertOpenAICompatibleCompletionUsage(usage) {
1071
- if (usage == null) {
1072
- return createNullLanguageModelUsage2();
1073
- }
1074
- const promptTokens = usage.prompt_tokens ?? 0;
1075
- const completionTokens = usage.completion_tokens ?? 0;
1076
- return {
1077
- inputTokens: {
1078
- total: promptTokens,
1079
- noCache: promptTokens,
1080
- cacheRead: void 0,
1081
- cacheWrite: void 0
1082
- },
1083
- outputTokens: {
1084
- total: completionTokens,
1085
- text: completionTokens,
1086
- reasoning: void 0
1087
- },
1088
- raw: usage
1089
- };
820
+ if (usage == null) return createNullLanguageModelUsage();
821
+ const promptTokens = usage.prompt_tokens ?? 0;
822
+ const completionTokens = usage.completion_tokens ?? 0;
823
+ return {
824
+ inputTokens: {
825
+ total: promptTokens,
826
+ noCache: promptTokens,
827
+ cacheRead: void 0,
828
+ cacheWrite: void 0
829
+ },
830
+ outputTokens: {
831
+ total: completionTokens,
832
+ text: completionTokens,
833
+ reasoning: void 0
834
+ },
835
+ raw: usage
836
+ };
1090
837
  }
1091
-
1092
- // src/completion/convert-to-openai-compatible-completion-prompt.ts
1093
- import {
1094
- InvalidPromptError,
1095
- UnsupportedFunctionalityError as UnsupportedFunctionalityError3
1096
- } from "@ai-sdk/provider";
1097
- function convertToOpenAICompatibleCompletionPrompt({
1098
- prompt,
1099
- user = "user",
1100
- assistant = "assistant"
1101
- }) {
1102
- let text = "";
1103
- if (prompt[0].role === "system") {
1104
- text += `${prompt[0].content}
1105
-
1106
- `;
1107
- prompt = prompt.slice(1);
1108
- }
1109
- for (const { role, content } of prompt) {
1110
- switch (role) {
1111
- case "system": {
1112
- throw new InvalidPromptError({
1113
- message: "Unexpected system message in prompt: ${content}",
1114
- prompt
1115
- });
1116
- }
1117
- case "user": {
1118
- const userMessage = content.map((part) => {
1119
- switch (part.type) {
1120
- case "text": {
1121
- return part.text;
1122
- }
1123
- }
1124
- }).filter(Boolean).join("");
1125
- text += `${user}:
1126
- ${userMessage}
1127
-
1128
- `;
1129
- break;
1130
- }
1131
- case "assistant": {
1132
- const assistantMessage = content.map((part) => {
1133
- switch (part.type) {
1134
- case "text": {
1135
- return part.text;
1136
- }
1137
- case "tool-call": {
1138
- throw new UnsupportedFunctionalityError3({
1139
- functionality: "tool-call messages"
1140
- });
1141
- }
1142
- }
1143
- }).join("");
1144
- text += `${assistant}:
1145
- ${assistantMessage}
1146
-
1147
- `;
1148
- break;
1149
- }
1150
- case "tool": {
1151
- throw new UnsupportedFunctionalityError3({
1152
- functionality: "tool messages"
1153
- });
1154
- }
1155
- default: {
1156
- const _exhaustiveCheck = role;
1157
- throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
1158
- }
1159
- }
1160
- }
1161
- text += `${assistant}:
1162
- `;
1163
- return {
1164
- prompt: text,
1165
- stopSequences: [`
1166
- ${user}:`]
1167
- };
838
+ //#endregion
839
+ //#region src/completion/convert-to-openai-compatible-completion-prompt.ts
840
+ function convertToOpenAICompatibleCompletionPrompt({ prompt, user = "user", assistant = "assistant" }) {
841
+ let text = "";
842
+ if (prompt[0].role === "system") {
843
+ text += `${prompt[0].content}\n\n`;
844
+ prompt = prompt.slice(1);
845
+ }
846
+ for (const { role, content } of prompt) switch (role) {
847
+ case "system": throw new InvalidPromptError({
848
+ message: "Unexpected system message in prompt: ${content}",
849
+ prompt
850
+ });
851
+ case "user": {
852
+ const userMessage = content.map((part) => {
853
+ switch (part.type) {
854
+ case "text": return part.text;
855
+ }
856
+ }).filter(Boolean).join("");
857
+ text += `${user}:\n${userMessage}\n\n`;
858
+ break;
859
+ }
860
+ case "assistant": {
861
+ const assistantMessage = content.map((part) => {
862
+ switch (part.type) {
863
+ case "text": return part.text;
864
+ case "tool-call": throw new UnsupportedFunctionalityError({ functionality: "tool-call messages" });
865
+ }
866
+ }).join("");
867
+ text += `${assistant}:\n${assistantMessage}\n\n`;
868
+ break;
869
+ }
870
+ case "tool": throw new UnsupportedFunctionalityError({ functionality: "tool messages" });
871
+ default: throw new Error(`Unsupported role: ${role}`);
872
+ }
873
+ text += `${assistant}:\n`;
874
+ return {
875
+ prompt: text,
876
+ stopSequences: [`\n${user}:`]
877
+ };
1168
878
  }
1169
-
1170
- // src/completion/get-response-metadata.ts
1171
- import { createLanguageModelResponseMetadata as createLanguageModelResponseMetadata2 } from "@ai-sdk/provider-utils";
1172
-
1173
- // src/completion/map-openai-compatible-finish-reason.ts
1174
- function mapOpenAICompatibleFinishReason2(finishReason) {
1175
- switch (finishReason) {
1176
- case "stop":
1177
- return "stop";
1178
- case "length":
1179
- return "length";
1180
- case "content_filter":
1181
- return "content-filter";
1182
- case "function_call":
1183
- case "tool_calls":
1184
- return "tool-calls";
1185
- default:
1186
- return "other";
1187
- }
879
+ //#endregion
880
+ //#region src/completion/map-openai-compatible-finish-reason.ts
881
+ function mapOpenAICompatibleFinishReason(finishReason) {
882
+ switch (finishReason) {
883
+ case "stop": return "stop";
884
+ case "length": return "length";
885
+ case "content_filter": return "content-filter";
886
+ case "function_call":
887
+ case "tool_calls": return "tool-calls";
888
+ default: return "other";
889
+ }
1188
890
  }
1189
-
1190
- // src/completion/openai-compatible-completion-language-model-options.ts
1191
- import { z as z4 } from "zod/v4";
1192
- var openaiCompatibleLanguageModelCompletionOptions = z4.object({
1193
- /**
1194
- * Echo back the prompt in addition to the completion.
1195
- */
1196
- echo: z4.boolean().optional(),
1197
- /**
1198
- * Modify the likelihood of specified tokens appearing in the completion.
1199
- *
1200
- * Accepts a JSON object that maps tokens (specified by their token ID in
1201
- * the GPT tokenizer) to an associated bias value from -100 to 100.
1202
- */
1203
- logitBias: z4.record(z4.string(), z4.number()).optional(),
1204
- /**
1205
- * The suffix that comes after a completion of inserted text.
1206
- */
1207
- suffix: z4.string().optional(),
1208
- /**
1209
- * A unique identifier representing your end-user, which can help providers to
1210
- * monitor and detect abuse.
1211
- */
1212
- user: z4.string().optional()
891
+ //#endregion
892
+ //#region src/completion/openai-compatible-completion-language-model-options.ts
893
+ const openaiCompatibleLanguageModelCompletionOptions = z.object({
894
+ /**
895
+ * Echo back the prompt in addition to the completion.
896
+ */
897
+ echo: z.boolean().optional(),
898
+ /**
899
+ * Modify the likelihood of specified tokens appearing in the completion.
900
+ *
901
+ * Accepts a JSON object that maps tokens (specified by their token ID in
902
+ * the GPT tokenizer) to an associated bias value from -100 to 100.
903
+ */
904
+ logitBias: z.record(z.string(), z.number()).optional(),
905
+ /**
906
+ * The suffix that comes after a completion of inserted text.
907
+ */
908
+ suffix: z.string().optional(),
909
+ /**
910
+ * A unique identifier representing your end-user, which can help providers to
911
+ * monitor and detect abuse.
912
+ */
913
+ user: z.string().optional()
1213
914
  });
1214
-
1215
- // src/completion/openai-compatible-completion-language-model.ts
1216
- var OpenAICompatibleCompletionLanguageModel = class _OpenAICompatibleCompletionLanguageModel {
1217
- constructor(modelId, config) {
1218
- this.specificationVersion = "v4";
1219
- this.modelId = modelId;
1220
- this.config = config;
1221
- const errorStructure = config.errorStructure ?? defaultOpenAICompatibleErrorStructure;
1222
- this.chunkSchema = createOpenAICompatibleCompletionChunkSchema(
1223
- errorStructure.errorSchema
1224
- );
1225
- this.failedResponseHandler = createJsonErrorResponseHandler2(errorStructure);
1226
- }
1227
- // type inferred via constructor
1228
- static [WORKFLOW_SERIALIZE2](model) {
1229
- return serializeModelOptions2({
1230
- modelId: model.modelId,
1231
- config: model.config
1232
- });
1233
- }
1234
- static [WORKFLOW_DESERIALIZE2](options) {
1235
- return new _OpenAICompatibleCompletionLanguageModel(
1236
- options.modelId,
1237
- options.config
1238
- );
1239
- }
1240
- get provider() {
1241
- return this.config.provider;
1242
- }
1243
- get providerOptionsName() {
1244
- return this.config.provider.split(".")[0].trim();
1245
- }
1246
- get supportedUrls() {
1247
- return this.config.supportedUrls?.() ?? {};
1248
- }
1249
- async getArgs({
1250
- prompt,
1251
- maxOutputTokens,
1252
- temperature,
1253
- topP,
1254
- topK,
1255
- frequencyPenalty,
1256
- presencePenalty,
1257
- stopSequences: userStopSequences,
1258
- responseFormat,
1259
- seed,
1260
- providerOptions,
1261
- tools,
1262
- toolChoice
1263
- }) {
1264
- const warnings = [];
1265
- warnIfDeprecatedProviderOptionsKey({
1266
- rawName: this.providerOptionsName,
1267
- providerOptions,
1268
- warnings
1269
- });
1270
- const completionOptions = Object.assign(
1271
- await parseProviderOptions2({
1272
- provider: this.providerOptionsName,
1273
- providerOptions,
1274
- schema: openaiCompatibleLanguageModelCompletionOptions
1275
- }) ?? {},
1276
- await parseProviderOptions2({
1277
- provider: toCamelCase(this.providerOptionsName),
1278
- providerOptions,
1279
- schema: openaiCompatibleLanguageModelCompletionOptions
1280
- }) ?? {}
1281
- );
1282
- if (topK != null) {
1283
- warnings.push({ type: "unsupported", feature: "topK" });
1284
- }
1285
- if (tools?.length) {
1286
- warnings.push({ type: "unsupported", feature: "tools" });
1287
- }
1288
- if (toolChoice != null) {
1289
- warnings.push({ type: "unsupported", feature: "toolChoice" });
1290
- }
1291
- if (responseFormat != null && responseFormat.type !== "text") {
1292
- warnings.push({
1293
- type: "unsupported",
1294
- feature: "responseFormat",
1295
- details: "JSON response format is not supported."
1296
- });
1297
- }
1298
- const { prompt: completionPrompt, stopSequences } = convertToOpenAICompatibleCompletionPrompt({ prompt });
1299
- const stop = [...stopSequences ?? [], ...userStopSequences ?? []];
1300
- return {
1301
- args: {
1302
- // model id:
1303
- model: this.modelId,
1304
- // model specific settings:
1305
- echo: completionOptions.echo,
1306
- logit_bias: completionOptions.logitBias,
1307
- suffix: completionOptions.suffix,
1308
- user: completionOptions.user,
1309
- // standardized settings:
1310
- max_tokens: maxOutputTokens,
1311
- temperature,
1312
- top_p: topP,
1313
- frequency_penalty: frequencyPenalty,
1314
- presence_penalty: presencePenalty,
1315
- seed,
1316
- ...providerOptions?.[this.providerOptionsName],
1317
- ...providerOptions?.[toCamelCase(this.providerOptionsName)],
1318
- // prompt:
1319
- prompt: completionPrompt,
1320
- // stop sequences:
1321
- stop: stop.length > 0 ? stop : void 0
1322
- },
1323
- warnings
1324
- };
1325
- }
1326
- async doGenerate(options) {
1327
- const { args, warnings } = await this.getArgs(options);
1328
- const {
1329
- responseHeaders,
1330
- value: response,
1331
- rawValue: rawResponse
1332
- } = await postJsonToApi2({
1333
- url: this.config.url({
1334
- path: "/completions",
1335
- modelId: this.modelId
1336
- }),
1337
- headers: combineHeaders2(this.config.headers?.(), options.headers),
1338
- body: args,
1339
- failedResponseHandler: this.failedResponseHandler,
1340
- successfulResponseHandler: createJsonResponseHandler2(
1341
- openaiCompatibleCompletionResponseSchema
1342
- ),
1343
- abortSignal: options.abortSignal,
1344
- fetch: this.config.fetch
1345
- });
1346
- const choice = response.choices[0];
1347
- const content = [];
1348
- if (choice.text != null && choice.text.length > 0) {
1349
- content.push({ type: "text", text: choice.text });
1350
- }
1351
- return {
1352
- content,
1353
- usage: convertOpenAICompatibleCompletionUsage(response.usage),
1354
- finishReason: {
1355
- unified: mapOpenAICompatibleFinishReason2(choice.finish_reason),
1356
- raw: choice.finish_reason
1357
- },
1358
- request: { body: args },
1359
- response: {
1360
- ...createLanguageModelResponseMetadata2(response),
1361
- headers: responseHeaders,
1362
- body: rawResponse
1363
- },
1364
- warnings
1365
- };
1366
- }
1367
- async doStream(options) {
1368
- const { args, warnings } = await this.getArgs(options);
1369
- const body = {
1370
- ...args,
1371
- stream: true,
1372
- // only include stream_options when in strict compatibility mode:
1373
- stream_options: this.config.includeUsage ? { include_usage: true } : void 0
1374
- };
1375
- const { responseHeaders, value: response } = await postJsonToApi2({
1376
- url: this.config.url({
1377
- path: "/completions",
1378
- modelId: this.modelId
1379
- }),
1380
- headers: combineHeaders2(this.config.headers?.(), options.headers),
1381
- body,
1382
- failedResponseHandler: this.failedResponseHandler,
1383
- successfulResponseHandler: createEventSourceResponseHandler2(
1384
- this.chunkSchema
1385
- ),
1386
- abortSignal: options.abortSignal,
1387
- fetch: this.config.fetch
1388
- });
1389
- let finishReason = {
1390
- unified: "other",
1391
- raw: void 0
1392
- };
1393
- let usage = void 0;
1394
- let isFirstChunk = true;
1395
- return {
1396
- stream: response.pipeThrough(
1397
- new TransformStream({
1398
- start(controller) {
1399
- controller.enqueue({ type: "stream-start", warnings });
1400
- },
1401
- transform(chunk, controller) {
1402
- if (options.includeRawChunks) {
1403
- controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
1404
- }
1405
- if (!chunk.success) {
1406
- finishReason = { unified: "error", raw: void 0 };
1407
- controller.enqueue({ type: "error", error: chunk.error });
1408
- return;
1409
- }
1410
- const value = chunk.value;
1411
- if ("error" in value) {
1412
- finishReason = { unified: "error", raw: void 0 };
1413
- controller.enqueue({ type: "error", error: value.error });
1414
- return;
1415
- }
1416
- if (isFirstChunk) {
1417
- isFirstChunk = false;
1418
- controller.enqueue({
1419
- type: "response-metadata",
1420
- ...createLanguageModelResponseMetadata2(value)
1421
- });
1422
- controller.enqueue({
1423
- type: "text-start",
1424
- id: "0"
1425
- });
1426
- }
1427
- if (value.usage != null) {
1428
- usage = value.usage;
1429
- }
1430
- const choice = value.choices[0];
1431
- if (choice?.finish_reason != null) {
1432
- finishReason = {
1433
- unified: mapOpenAICompatibleFinishReason2(choice.finish_reason),
1434
- raw: choice.finish_reason ?? void 0
1435
- };
1436
- }
1437
- if (choice?.text != null) {
1438
- controller.enqueue({
1439
- type: "text-delta",
1440
- id: "0",
1441
- delta: choice.text
1442
- });
1443
- }
1444
- },
1445
- flush(controller) {
1446
- if (!isFirstChunk) {
1447
- controller.enqueue({ type: "text-end", id: "0" });
1448
- }
1449
- controller.enqueue({
1450
- type: "finish",
1451
- finishReason,
1452
- usage: convertOpenAICompatibleCompletionUsage(usage)
1453
- });
1454
- }
1455
- })
1456
- ),
1457
- request: { body },
1458
- response: { headers: responseHeaders }
1459
- };
1460
- }
915
+ //#endregion
916
+ //#region src/completion/openai-compatible-completion-language-model.ts
917
+ var OpenAICompatibleCompletionLanguageModel = class OpenAICompatibleCompletionLanguageModel {
918
+ static [WORKFLOW_SERIALIZE](model) {
919
+ return serializeModelOptions({
920
+ modelId: model.modelId,
921
+ config: model.config
922
+ });
923
+ }
924
+ static [WORKFLOW_DESERIALIZE](options) {
925
+ return new OpenAICompatibleCompletionLanguageModel(options.modelId, options.config);
926
+ }
927
+ constructor(modelId, config) {
928
+ this.specificationVersion = "v4";
929
+ this.modelId = modelId;
930
+ this.config = config;
931
+ const errorStructure = config.errorStructure ?? defaultOpenAICompatibleErrorStructure;
932
+ this.chunkSchema = createOpenAICompatibleCompletionChunkSchema(errorStructure.errorSchema);
933
+ this.failedResponseHandler = createJsonErrorResponseHandler(errorStructure);
934
+ }
935
+ get provider() {
936
+ return this.config.provider;
937
+ }
938
+ get providerOptionsName() {
939
+ return this.config.provider.split(".")[0].trim();
940
+ }
941
+ get supportedUrls() {
942
+ return this.config.supportedUrls?.() ?? {};
943
+ }
944
+ async getArgs({ prompt, maxOutputTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, stopSequences: userStopSequences, responseFormat, seed, providerOptions, tools, toolChoice }) {
945
+ const warnings = [];
946
+ warnIfDeprecatedProviderOptionsKey({
947
+ rawName: this.providerOptionsName,
948
+ providerOptions,
949
+ warnings
950
+ });
951
+ const completionOptions = Object.assign(await parseProviderOptions({
952
+ provider: this.providerOptionsName,
953
+ providerOptions,
954
+ schema: openaiCompatibleLanguageModelCompletionOptions
955
+ }) ?? {}, await parseProviderOptions({
956
+ provider: toCamelCase(this.providerOptionsName),
957
+ providerOptions,
958
+ schema: openaiCompatibleLanguageModelCompletionOptions
959
+ }) ?? {});
960
+ if (topK != null) warnings.push({
961
+ type: "unsupported",
962
+ feature: "topK"
963
+ });
964
+ if (tools?.length) warnings.push({
965
+ type: "unsupported",
966
+ feature: "tools"
967
+ });
968
+ if (toolChoice != null) warnings.push({
969
+ type: "unsupported",
970
+ feature: "toolChoice"
971
+ });
972
+ if (responseFormat != null && responseFormat.type !== "text") warnings.push({
973
+ type: "unsupported",
974
+ feature: "responseFormat",
975
+ details: "JSON response format is not supported."
976
+ });
977
+ const { prompt: completionPrompt, stopSequences } = convertToOpenAICompatibleCompletionPrompt({ prompt });
978
+ const stop = [...stopSequences ?? [], ...userStopSequences ?? []];
979
+ return {
980
+ args: {
981
+ model: this.modelId,
982
+ echo: completionOptions.echo,
983
+ logit_bias: completionOptions.logitBias,
984
+ suffix: completionOptions.suffix,
985
+ user: completionOptions.user,
986
+ max_tokens: maxOutputTokens,
987
+ temperature,
988
+ top_p: topP,
989
+ frequency_penalty: frequencyPenalty,
990
+ presence_penalty: presencePenalty,
991
+ seed,
992
+ ...providerOptions?.[this.providerOptionsName],
993
+ ...providerOptions?.[toCamelCase(this.providerOptionsName)],
994
+ prompt: completionPrompt,
995
+ stop: stop.length > 0 ? stop : void 0
996
+ },
997
+ warnings
998
+ };
999
+ }
1000
+ async doGenerate(options) {
1001
+ const { args, warnings } = await this.getArgs(options);
1002
+ const { responseHeaders, value: response, rawValue: rawResponse } = await postJsonToApi({
1003
+ url: this.config.url({
1004
+ path: "/completions",
1005
+ modelId: this.modelId
1006
+ }),
1007
+ headers: combineHeaders(this.config.headers?.(), options.headers),
1008
+ body: args,
1009
+ failedResponseHandler: this.failedResponseHandler,
1010
+ successfulResponseHandler: createJsonResponseHandler(openaiCompatibleCompletionResponseSchema),
1011
+ abortSignal: options.abortSignal,
1012
+ fetch: this.config.fetch
1013
+ });
1014
+ const choice = response.choices[0];
1015
+ const content = [];
1016
+ if (choice.text != null && choice.text.length > 0) content.push({
1017
+ type: "text",
1018
+ text: choice.text
1019
+ });
1020
+ return {
1021
+ content,
1022
+ usage: convertOpenAICompatibleCompletionUsage(response.usage),
1023
+ finishReason: {
1024
+ unified: mapOpenAICompatibleFinishReason(choice.finish_reason),
1025
+ raw: choice.finish_reason
1026
+ },
1027
+ request: { body: args },
1028
+ response: {
1029
+ ...getResponseMetadata(response),
1030
+ headers: responseHeaders,
1031
+ body: rawResponse
1032
+ },
1033
+ warnings
1034
+ };
1035
+ }
1036
+ async doStream(options) {
1037
+ const { args, warnings } = await this.getArgs(options);
1038
+ const body = {
1039
+ ...args,
1040
+ stream: true,
1041
+ stream_options: this.config.includeUsage ? { include_usage: true } : void 0
1042
+ };
1043
+ const { responseHeaders, value: response } = await postJsonToApi({
1044
+ url: this.config.url({
1045
+ path: "/completions",
1046
+ modelId: this.modelId
1047
+ }),
1048
+ headers: combineHeaders(this.config.headers?.(), options.headers),
1049
+ body,
1050
+ failedResponseHandler: this.failedResponseHandler,
1051
+ successfulResponseHandler: createEventSourceResponseHandler(this.chunkSchema),
1052
+ abortSignal: options.abortSignal,
1053
+ fetch: this.config.fetch
1054
+ });
1055
+ let finishReason = {
1056
+ unified: "other",
1057
+ raw: void 0
1058
+ };
1059
+ let usage = void 0;
1060
+ let isFirstChunk = true;
1061
+ return {
1062
+ stream: response.pipeThrough(new TransformStream({
1063
+ start(controller) {
1064
+ controller.enqueue({
1065
+ type: "stream-start",
1066
+ warnings
1067
+ });
1068
+ },
1069
+ transform(chunk, controller) {
1070
+ if (options.includeRawChunks) controller.enqueue({
1071
+ type: "raw",
1072
+ rawValue: chunk.rawValue
1073
+ });
1074
+ if (!chunk.success) {
1075
+ finishReason = {
1076
+ unified: "error",
1077
+ raw: void 0
1078
+ };
1079
+ controller.enqueue({
1080
+ type: "error",
1081
+ error: chunk.error
1082
+ });
1083
+ return;
1084
+ }
1085
+ const value = chunk.value;
1086
+ if ("error" in value) {
1087
+ finishReason = {
1088
+ unified: "error",
1089
+ raw: void 0
1090
+ };
1091
+ controller.enqueue({
1092
+ type: "error",
1093
+ error: value.error
1094
+ });
1095
+ return;
1096
+ }
1097
+ if (isFirstChunk) {
1098
+ isFirstChunk = false;
1099
+ controller.enqueue({
1100
+ type: "response-metadata",
1101
+ ...getResponseMetadata(value)
1102
+ });
1103
+ controller.enqueue({
1104
+ type: "text-start",
1105
+ id: "0"
1106
+ });
1107
+ }
1108
+ if (value.usage != null) usage = value.usage;
1109
+ const choice = value.choices[0];
1110
+ if (choice?.finish_reason != null) finishReason = {
1111
+ unified: mapOpenAICompatibleFinishReason(choice.finish_reason),
1112
+ raw: choice.finish_reason ?? void 0
1113
+ };
1114
+ if (choice?.text != null) controller.enqueue({
1115
+ type: "text-delta",
1116
+ id: "0",
1117
+ delta: choice.text
1118
+ });
1119
+ },
1120
+ flush(controller) {
1121
+ if (!isFirstChunk) controller.enqueue({
1122
+ type: "text-end",
1123
+ id: "0"
1124
+ });
1125
+ controller.enqueue({
1126
+ type: "finish",
1127
+ finishReason,
1128
+ usage: convertOpenAICompatibleCompletionUsage(usage)
1129
+ });
1130
+ }
1131
+ })),
1132
+ request: { body },
1133
+ response: { headers: responseHeaders }
1134
+ };
1135
+ }
1461
1136
  };
1462
- var usageSchema = z5.looseObject({
1463
- prompt_tokens: z5.number(),
1464
- completion_tokens: z5.number(),
1465
- total_tokens: z5.number()
1137
+ const usageSchema = z.looseObject({
1138
+ prompt_tokens: z.number(),
1139
+ completion_tokens: z.number(),
1140
+ total_tokens: z.number()
1466
1141
  });
1467
- var openaiCompatibleCompletionResponseSchema = z5.object({
1468
- id: z5.string().nullish(),
1469
- created: z5.number().nullish(),
1470
- model: z5.string().nullish(),
1471
- choices: z5.array(
1472
- z5.object({
1473
- text: z5.string(),
1474
- finish_reason: z5.string()
1475
- })
1476
- ),
1477
- usage: usageSchema.nullish()
1142
+ const openaiCompatibleCompletionResponseSchema = z.object({
1143
+ id: z.string().nullish(),
1144
+ created: z.number().nullish(),
1145
+ model: z.string().nullish(),
1146
+ choices: z.array(z.object({
1147
+ text: z.string(),
1148
+ finish_reason: z.string()
1149
+ })),
1150
+ usage: usageSchema.nullish()
1478
1151
  });
1479
- var createOpenAICompatibleCompletionChunkSchema = (errorSchema) => z5.union([
1480
- z5.object({
1481
- id: z5.string().nullish(),
1482
- created: z5.number().nullish(),
1483
- model: z5.string().nullish(),
1484
- choices: z5.array(
1485
- z5.object({
1486
- text: z5.string(),
1487
- finish_reason: z5.string().nullish(),
1488
- index: z5.number()
1489
- })
1490
- ),
1491
- usage: usageSchema.nullish()
1492
- }),
1493
- errorSchema
1494
- ]);
1495
-
1496
- // src/embedding/openai-compatible-embedding-model.ts
1497
- import {
1498
- TooManyEmbeddingValuesForCallError
1499
- } from "@ai-sdk/provider";
1500
- import {
1501
- combineHeaders as combineHeaders3,
1502
- createJsonErrorResponseHandler as createJsonErrorResponseHandler3,
1503
- createJsonResponseHandler as createJsonResponseHandler3,
1504
- parseProviderOptions as parseProviderOptions3,
1505
- postJsonToApi as postJsonToApi3,
1506
- serializeModelOptions as serializeModelOptions3,
1507
- WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE3,
1508
- WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE3
1509
- } from "@ai-sdk/provider-utils";
1510
- import { z as z7 } from "zod/v4";
1511
-
1512
- // src/embedding/openai-compatible-embedding-model-options.ts
1513
- import { z as z6 } from "zod/v4";
1514
- var openaiCompatibleEmbeddingModelOptions = z6.object({
1515
- /**
1516
- * The number of dimensions the resulting output embeddings should have.
1517
- * Only supported in text-embedding-3 and later models.
1518
- */
1519
- dimensions: z6.number().optional(),
1520
- /**
1521
- * A unique identifier representing your end-user, which can help providers to
1522
- * monitor and detect abuse.
1523
- */
1524
- user: z6.string().optional()
1152
+ const createOpenAICompatibleCompletionChunkSchema = (errorSchema) => z.union([z.object({
1153
+ id: z.string().nullish(),
1154
+ created: z.number().nullish(),
1155
+ model: z.string().nullish(),
1156
+ choices: z.array(z.object({
1157
+ text: z.string(),
1158
+ finish_reason: z.string().nullish(),
1159
+ index: z.number()
1160
+ })),
1161
+ usage: usageSchema.nullish()
1162
+ }), errorSchema]);
1163
+ //#endregion
1164
+ //#region src/embedding/openai-compatible-embedding-model-options.ts
1165
+ const openaiCompatibleEmbeddingModelOptions = z.object({
1166
+ /**
1167
+ * The number of dimensions the resulting output embeddings should have.
1168
+ * Only supported in text-embedding-3 and later models.
1169
+ */
1170
+ dimensions: z.number().optional(),
1171
+ /**
1172
+ * A unique identifier representing your end-user, which can help providers to
1173
+ * monitor and detect abuse.
1174
+ */
1175
+ user: z.string().optional()
1525
1176
  });
1526
-
1527
- // src/embedding/openai-compatible-embedding-model.ts
1528
- var OpenAICompatibleEmbeddingModel = class _OpenAICompatibleEmbeddingModel {
1529
- constructor(modelId, config) {
1530
- this.specificationVersion = "v4";
1531
- this.modelId = modelId;
1532
- this.config = config;
1533
- }
1534
- get provider() {
1535
- return this.config.provider;
1536
- }
1537
- get maxEmbeddingsPerCall() {
1538
- return this.config.maxEmbeddingsPerCall ?? 2048;
1539
- }
1540
- get supportsParallelCalls() {
1541
- return this.config.supportsParallelCalls ?? true;
1542
- }
1543
- static [WORKFLOW_SERIALIZE3](model) {
1544
- return serializeModelOptions3({
1545
- modelId: model.modelId,
1546
- config: model.config
1547
- });
1548
- }
1549
- static [WORKFLOW_DESERIALIZE3](options) {
1550
- return new _OpenAICompatibleEmbeddingModel(options.modelId, options.config);
1551
- }
1552
- get providerOptionsName() {
1553
- return this.config.provider.split(".")[0].trim();
1554
- }
1555
- async doEmbed({
1556
- values,
1557
- headers,
1558
- abortSignal,
1559
- providerOptions
1560
- }) {
1561
- const warnings = [];
1562
- const deprecatedOptions = await parseProviderOptions3({
1563
- provider: "openai-compatible",
1564
- providerOptions,
1565
- schema: openaiCompatibleEmbeddingModelOptions
1566
- });
1567
- if (deprecatedOptions != null) {
1568
- warnings.push({
1569
- type: "deprecated",
1570
- setting: "providerOptions key 'openai-compatible'",
1571
- message: "Use 'openaiCompatible' instead."
1572
- });
1573
- }
1574
- warnIfDeprecatedProviderOptionsKey({
1575
- rawName: this.providerOptionsName,
1576
- providerOptions,
1577
- warnings
1578
- });
1579
- const compatibleOptions = Object.assign(
1580
- deprecatedOptions ?? {},
1581
- await parseProviderOptions3({
1582
- provider: "openaiCompatible",
1583
- providerOptions,
1584
- schema: openaiCompatibleEmbeddingModelOptions
1585
- }) ?? {},
1586
- await parseProviderOptions3({
1587
- provider: this.providerOptionsName,
1588
- providerOptions,
1589
- schema: openaiCompatibleEmbeddingModelOptions
1590
- }) ?? {}
1591
- );
1592
- if (values.length > this.maxEmbeddingsPerCall) {
1593
- throw new TooManyEmbeddingValuesForCallError({
1594
- provider: this.provider,
1595
- modelId: this.modelId,
1596
- maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
1597
- values
1598
- });
1599
- }
1600
- const {
1601
- responseHeaders,
1602
- value: response,
1603
- rawValue
1604
- } = await postJsonToApi3({
1605
- url: this.config.url({
1606
- path: "/embeddings",
1607
- modelId: this.modelId
1608
- }),
1609
- headers: combineHeaders3(this.config.headers?.(), headers),
1610
- body: {
1611
- model: this.modelId,
1612
- input: values,
1613
- encoding_format: "float",
1614
- dimensions: compatibleOptions.dimensions,
1615
- user: compatibleOptions.user
1616
- },
1617
- failedResponseHandler: createJsonErrorResponseHandler3(
1618
- this.config.errorStructure ?? defaultOpenAICompatibleErrorStructure
1619
- ),
1620
- successfulResponseHandler: createJsonResponseHandler3(
1621
- openaiTextEmbeddingResponseSchema
1622
- ),
1623
- abortSignal,
1624
- fetch: this.config.fetch
1625
- });
1626
- return {
1627
- warnings,
1628
- embeddings: response.data.map((item) => item.embedding),
1629
- usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0,
1630
- providerMetadata: response.providerMetadata,
1631
- response: { headers: responseHeaders, body: rawValue }
1632
- };
1633
- }
1177
+ //#endregion
1178
+ //#region src/embedding/openai-compatible-embedding-model.ts
1179
+ var OpenAICompatibleEmbeddingModel = class OpenAICompatibleEmbeddingModel {
1180
+ get provider() {
1181
+ return this.config.provider;
1182
+ }
1183
+ get maxEmbeddingsPerCall() {
1184
+ return this.config.maxEmbeddingsPerCall ?? 2048;
1185
+ }
1186
+ get supportsParallelCalls() {
1187
+ return this.config.supportsParallelCalls ?? true;
1188
+ }
1189
+ static [WORKFLOW_SERIALIZE](model) {
1190
+ return serializeModelOptions({
1191
+ modelId: model.modelId,
1192
+ config: model.config
1193
+ });
1194
+ }
1195
+ static [WORKFLOW_DESERIALIZE](options) {
1196
+ return new OpenAICompatibleEmbeddingModel(options.modelId, options.config);
1197
+ }
1198
+ constructor(modelId, config) {
1199
+ this.specificationVersion = "v4";
1200
+ this.modelId = modelId;
1201
+ this.config = config;
1202
+ }
1203
+ get providerOptionsName() {
1204
+ return this.config.provider.split(".")[0].trim();
1205
+ }
1206
+ async doEmbed({ values, headers, abortSignal, providerOptions }) {
1207
+ const warnings = [];
1208
+ const deprecatedOptions = await parseProviderOptions({
1209
+ provider: "openai-compatible",
1210
+ providerOptions,
1211
+ schema: openaiCompatibleEmbeddingModelOptions
1212
+ });
1213
+ if (deprecatedOptions != null) warnings.push({
1214
+ type: "deprecated",
1215
+ setting: "providerOptions key 'openai-compatible'",
1216
+ message: "Use 'openaiCompatible' instead."
1217
+ });
1218
+ warnIfDeprecatedProviderOptionsKey({
1219
+ rawName: this.providerOptionsName,
1220
+ providerOptions,
1221
+ warnings
1222
+ });
1223
+ const compatibleOptions = Object.assign(deprecatedOptions ?? {}, await parseProviderOptions({
1224
+ provider: "openaiCompatible",
1225
+ providerOptions,
1226
+ schema: openaiCompatibleEmbeddingModelOptions
1227
+ }) ?? {}, await parseProviderOptions({
1228
+ provider: this.providerOptionsName,
1229
+ providerOptions,
1230
+ schema: openaiCompatibleEmbeddingModelOptions
1231
+ }) ?? {});
1232
+ if (values.length > this.maxEmbeddingsPerCall) throw new TooManyEmbeddingValuesForCallError({
1233
+ provider: this.provider,
1234
+ modelId: this.modelId,
1235
+ maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
1236
+ values
1237
+ });
1238
+ const { responseHeaders, value: response, rawValue } = await postJsonToApi({
1239
+ url: this.config.url({
1240
+ path: "/embeddings",
1241
+ modelId: this.modelId
1242
+ }),
1243
+ headers: combineHeaders(this.config.headers?.(), headers),
1244
+ body: {
1245
+ model: this.modelId,
1246
+ input: values,
1247
+ encoding_format: "float",
1248
+ dimensions: compatibleOptions.dimensions,
1249
+ user: compatibleOptions.user
1250
+ },
1251
+ failedResponseHandler: createJsonErrorResponseHandler(this.config.errorStructure ?? defaultOpenAICompatibleErrorStructure),
1252
+ successfulResponseHandler: createJsonResponseHandler(openaiTextEmbeddingResponseSchema),
1253
+ abortSignal,
1254
+ fetch: this.config.fetch
1255
+ });
1256
+ return {
1257
+ warnings,
1258
+ embeddings: response.data.map((item) => item.embedding),
1259
+ usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0,
1260
+ providerMetadata: response.providerMetadata,
1261
+ response: {
1262
+ headers: responseHeaders,
1263
+ body: rawValue
1264
+ }
1265
+ };
1266
+ }
1634
1267
  };
1635
- var openaiTextEmbeddingResponseSchema = z7.object({
1636
- data: z7.array(z7.object({ embedding: z7.array(z7.number()) })),
1637
- usage: z7.object({ prompt_tokens: z7.number() }).nullish(),
1638
- providerMetadata: z7.record(z7.string(), z7.record(z7.string(), z7.any())).optional()
1268
+ const openaiTextEmbeddingResponseSchema = z.object({
1269
+ data: z.array(z.object({ embedding: z.array(z.number()) })),
1270
+ usage: z.object({ prompt_tokens: z.number() }).nullish(),
1271
+ providerMetadata: z.record(z.string(), z.record(z.string(), z.any())).optional()
1639
1272
  });
1640
-
1641
- // src/image/openai-compatible-image-model.ts
1642
- import {
1643
- combineHeaders as combineHeaders4,
1644
- convertBase64ToUint8Array as convertBase64ToUint8Array2,
1645
- convertToFormData,
1646
- createJsonErrorResponseHandler as createJsonErrorResponseHandler4,
1647
- createJsonResponseHandler as createJsonResponseHandler4,
1648
- downloadBlob,
1649
- postFormDataToApi,
1650
- postJsonToApi as postJsonToApi4,
1651
- serializeModelOptions as serializeModelOptions4,
1652
- WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE4,
1653
- WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE4
1654
- } from "@ai-sdk/provider-utils";
1655
- import { z as z8 } from "zod/v4";
1656
- var OpenAICompatibleImageModel = class _OpenAICompatibleImageModel {
1657
- constructor(modelId, config) {
1658
- this.modelId = modelId;
1659
- this.config = config;
1660
- this.specificationVersion = "v4";
1661
- this.maxImagesPerCall = 10;
1662
- this.supportsFileInputs = void 0;
1663
- this.supportsMaskInputs = void 0;
1664
- }
1665
- get provider() {
1666
- return this.config.provider;
1667
- }
1668
- /**
1669
- * The provider options key used to extract provider-specific options.
1670
- */
1671
- get providerOptionsKey() {
1672
- return this.config.provider.split(".")[0].trim();
1673
- }
1674
- static [WORKFLOW_SERIALIZE4](model) {
1675
- return serializeModelOptions4({
1676
- modelId: model.modelId,
1677
- config: model.config
1678
- });
1679
- }
1680
- static [WORKFLOW_DESERIALIZE4](options) {
1681
- return new _OpenAICompatibleImageModel(options.modelId, options.config);
1682
- }
1683
- getArgs(providerOptions, warnings) {
1684
- warnIfDeprecatedProviderOptionsKey({
1685
- rawName: this.providerOptionsKey,
1686
- providerOptions,
1687
- warnings
1688
- });
1689
- return {
1690
- ...providerOptions[this.providerOptionsKey],
1691
- ...providerOptions[toCamelCase(this.providerOptionsKey)]
1692
- };
1693
- }
1694
- async doGenerate({
1695
- prompt,
1696
- n,
1697
- size,
1698
- aspectRatio,
1699
- seed,
1700
- providerOptions,
1701
- headers,
1702
- abortSignal,
1703
- files,
1704
- mask
1705
- }) {
1706
- const warnings = [];
1707
- if (aspectRatio != null) {
1708
- warnings.push({
1709
- type: "unsupported",
1710
- feature: "aspectRatio",
1711
- details: "This model does not support aspect ratio. Use `size` instead."
1712
- });
1713
- }
1714
- if (seed != null) {
1715
- warnings.push({ type: "unsupported", feature: "seed" });
1716
- }
1717
- const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
1718
- const args = this.getArgs(providerOptions, warnings);
1719
- if (files != null && files.length > 0) {
1720
- const { value: response2, responseHeaders: responseHeaders2 } = await postFormDataToApi({
1721
- url: this.config.url({
1722
- path: "/images/edits",
1723
- modelId: this.modelId
1724
- }),
1725
- headers: combineHeaders4(this.config.headers?.(), headers),
1726
- formData: convertToFormData({
1727
- model: this.modelId,
1728
- prompt,
1729
- image: await Promise.all(files.map((file) => fileToBlob(file))),
1730
- mask: mask != null ? await fileToBlob(mask) : void 0,
1731
- n,
1732
- size,
1733
- ...args
1734
- }),
1735
- failedResponseHandler: createJsonErrorResponseHandler4(
1736
- this.config.errorStructure ?? defaultOpenAICompatibleErrorStructure
1737
- ),
1738
- successfulResponseHandler: createJsonResponseHandler4(
1739
- openaiCompatibleImageResponseSchema
1740
- ),
1741
- abortSignal,
1742
- fetch: this.config.fetch
1743
- });
1744
- return {
1745
- images: response2.data.map((item) => item.b64_json),
1746
- warnings,
1747
- usage: mapImageUsage(response2.usage),
1748
- response: {
1749
- timestamp: currentDate,
1750
- modelId: this.modelId,
1751
- headers: responseHeaders2
1752
- }
1753
- };
1754
- }
1755
- const { value: response, responseHeaders } = await postJsonToApi4({
1756
- url: this.config.url({
1757
- path: "/images/generations",
1758
- modelId: this.modelId
1759
- }),
1760
- headers: combineHeaders4(this.config.headers?.(), headers),
1761
- body: {
1762
- model: this.modelId,
1763
- prompt,
1764
- n,
1765
- size,
1766
- ...args
1767
- },
1768
- failedResponseHandler: createJsonErrorResponseHandler4(
1769
- this.config.errorStructure ?? defaultOpenAICompatibleErrorStructure
1770
- ),
1771
- successfulResponseHandler: createJsonResponseHandler4(
1772
- openaiCompatibleImageResponseSchema
1773
- ),
1774
- abortSignal,
1775
- fetch: this.config.fetch
1776
- });
1777
- return {
1778
- images: response.data.map((item) => item.b64_json),
1779
- warnings,
1780
- usage: mapImageUsage(response.usage),
1781
- response: {
1782
- timestamp: currentDate,
1783
- modelId: this.modelId,
1784
- headers: responseHeaders
1785
- }
1786
- };
1787
- }
1273
+ //#endregion
1274
+ //#region src/image/openai-compatible-image-model.ts
1275
+ var OpenAICompatibleImageModel = class OpenAICompatibleImageModel {
1276
+ get provider() {
1277
+ return this.config.provider;
1278
+ }
1279
+ /**
1280
+ * The provider options key used to extract provider-specific options.
1281
+ */
1282
+ get providerOptionsKey() {
1283
+ return this.config.provider.split(".")[0].trim();
1284
+ }
1285
+ static [WORKFLOW_SERIALIZE](model) {
1286
+ return serializeModelOptions({
1287
+ modelId: model.modelId,
1288
+ config: model.config
1289
+ });
1290
+ }
1291
+ static [WORKFLOW_DESERIALIZE](options) {
1292
+ return new OpenAICompatibleImageModel(options.modelId, options.config);
1293
+ }
1294
+ constructor(modelId, config) {
1295
+ this.modelId = modelId;
1296
+ this.config = config;
1297
+ this.specificationVersion = "v4";
1298
+ this.maxImagesPerCall = 10;
1299
+ this.supportsFileInputs = void 0;
1300
+ this.supportsMaskInputs = void 0;
1301
+ }
1302
+ getArgs(providerOptions, warnings) {
1303
+ warnIfDeprecatedProviderOptionsKey({
1304
+ rawName: this.providerOptionsKey,
1305
+ providerOptions,
1306
+ warnings
1307
+ });
1308
+ return {
1309
+ ...providerOptions[this.providerOptionsKey],
1310
+ ...providerOptions[toCamelCase(this.providerOptionsKey)]
1311
+ };
1312
+ }
1313
+ async doGenerate({ prompt, n, size, aspectRatio, seed, providerOptions, headers, abortSignal, files, mask }) {
1314
+ const warnings = [];
1315
+ if (aspectRatio != null) warnings.push({
1316
+ type: "unsupported",
1317
+ feature: "aspectRatio",
1318
+ details: "This model does not support aspect ratio. Use `size` instead."
1319
+ });
1320
+ if (seed != null) warnings.push({
1321
+ type: "unsupported",
1322
+ feature: "seed"
1323
+ });
1324
+ const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
1325
+ const args = this.getArgs(providerOptions, warnings);
1326
+ if (files != null && files.length > 0) {
1327
+ const { value: response, responseHeaders } = await postFormDataToApi({
1328
+ url: this.config.url({
1329
+ path: "/images/edits",
1330
+ modelId: this.modelId
1331
+ }),
1332
+ headers: combineHeaders(this.config.headers?.(), headers),
1333
+ formData: convertToFormData({
1334
+ model: this.modelId,
1335
+ prompt,
1336
+ image: await Promise.all(files.map((file) => fileToBlob(file))),
1337
+ mask: mask != null ? await fileToBlob(mask) : void 0,
1338
+ n,
1339
+ size,
1340
+ ...args
1341
+ }),
1342
+ failedResponseHandler: createJsonErrorResponseHandler(this.config.errorStructure ?? defaultOpenAICompatibleErrorStructure),
1343
+ successfulResponseHandler: createJsonResponseHandler(openaiCompatibleImageResponseSchema),
1344
+ abortSignal,
1345
+ fetch: this.config.fetch
1346
+ });
1347
+ return {
1348
+ images: response.data.map((item) => item.b64_json),
1349
+ warnings,
1350
+ usage: mapImageUsage(response.usage),
1351
+ response: {
1352
+ timestamp: currentDate,
1353
+ modelId: this.modelId,
1354
+ headers: responseHeaders
1355
+ }
1356
+ };
1357
+ }
1358
+ const { value: response, responseHeaders } = await postJsonToApi({
1359
+ url: this.config.url({
1360
+ path: "/images/generations",
1361
+ modelId: this.modelId
1362
+ }),
1363
+ headers: combineHeaders(this.config.headers?.(), headers),
1364
+ body: {
1365
+ model: this.modelId,
1366
+ prompt,
1367
+ n,
1368
+ size,
1369
+ ...args
1370
+ },
1371
+ failedResponseHandler: createJsonErrorResponseHandler(this.config.errorStructure ?? defaultOpenAICompatibleErrorStructure),
1372
+ successfulResponseHandler: createJsonResponseHandler(openaiCompatibleImageResponseSchema),
1373
+ abortSignal,
1374
+ fetch: this.config.fetch
1375
+ });
1376
+ return {
1377
+ images: response.data.map((item) => item.b64_json),
1378
+ warnings,
1379
+ usage: mapImageUsage(response.usage),
1380
+ response: {
1381
+ timestamp: currentDate,
1382
+ modelId: this.modelId,
1383
+ headers: responseHeaders
1384
+ }
1385
+ };
1386
+ }
1788
1387
  };
1789
1388
  function mapImageUsage(usage) {
1790
- return usage == null ? void 0 : {
1791
- inputTokens: usage.input_tokens ?? void 0,
1792
- outputTokens: usage.output_tokens ?? void 0,
1793
- totalTokens: usage.total_tokens ?? void 0
1794
- };
1389
+ return usage == null ? void 0 : {
1390
+ inputTokens: usage.input_tokens ?? void 0,
1391
+ outputTokens: usage.output_tokens ?? void 0,
1392
+ totalTokens: usage.total_tokens ?? void 0
1393
+ };
1795
1394
  }
1796
- var openaiCompatibleImageResponseSchema = z8.object({
1797
- data: z8.array(z8.object({ b64_json: z8.string() })),
1798
- usage: z8.object({
1799
- input_tokens: z8.number().nullish(),
1800
- output_tokens: z8.number().nullish(),
1801
- total_tokens: z8.number().nullish()
1802
- }).nullish()
1395
+ const openaiCompatibleImageResponseSchema = z.object({
1396
+ data: z.array(z.object({ b64_json: z.string() })),
1397
+ usage: z.object({
1398
+ input_tokens: z.number().nullish(),
1399
+ output_tokens: z.number().nullish(),
1400
+ total_tokens: z.number().nullish()
1401
+ }).nullish()
1803
1402
  });
1804
1403
  async function fileToBlob(file) {
1805
- if (file.type === "url") {
1806
- return downloadBlob(file.url);
1807
- }
1808
- const data = file.data instanceof Uint8Array ? file.data : convertBase64ToUint8Array2(file.data);
1809
- return new Blob([data], { type: file.mediaType });
1404
+ if (file.type === "url") return downloadBlob(file.url);
1405
+ const data = file.data instanceof Uint8Array ? file.data : convertBase64ToUint8Array(file.data);
1406
+ return new Blob([data], { type: file.mediaType });
1810
1407
  }
1811
-
1812
- // src/openai-compatible-provider.ts
1813
- import {
1814
- withoutTrailingSlash,
1815
- withUserAgentSuffix
1816
- } from "@ai-sdk/provider-utils";
1817
-
1818
- // src/version.ts
1819
- var VERSION = true ? "3.0.58" : "0.0.0-test";
1820
-
1821
- // src/openai-compatible-provider.ts
1408
+ //#endregion
1409
+ //#region src/version.ts
1410
+ const VERSION = "3.0.60";
1411
+ //#endregion
1412
+ //#region src/openai-compatible-provider.ts
1413
+ /**
1414
+ * Create an OpenAICompatible provider instance.
1415
+ */
1822
1416
  function createOpenAICompatible(options) {
1823
- const baseURL = withoutTrailingSlash(options.baseURL);
1824
- const providerName = options.name;
1825
- const headers = {
1826
- ...options.apiKey && { Authorization: `Bearer ${options.apiKey}` },
1827
- ...options.headers
1828
- };
1829
- const getHeaders = () => withUserAgentSuffix(headers, `ai-sdk/openai-compatible/${VERSION}`);
1830
- const getCommonModelConfig = (modelType) => ({
1831
- provider: `${providerName}.${modelType}`,
1832
- url: ({ path }) => {
1833
- const url = new URL(`${baseURL}${path}`);
1834
- if (options.queryParams) {
1835
- url.search = new URLSearchParams(options.queryParams).toString();
1836
- }
1837
- return url.toString();
1838
- },
1839
- headers: getHeaders,
1840
- fetch: options.fetch
1841
- });
1842
- const createLanguageModel = (modelId) => createChatModel(modelId);
1843
- const createChatModel = (modelId) => new OpenAICompatibleChatLanguageModel(modelId, {
1844
- ...getCommonModelConfig("chat"),
1845
- includeUsage: options.includeUsage,
1846
- supportsStructuredOutputs: options.supportsStructuredOutputs,
1847
- supportedUrls: options.supportedUrls,
1848
- transformRequestBody: options.transformRequestBody,
1849
- metadataExtractor: options.metadataExtractor,
1850
- convertUsage: options.convertUsage
1851
- });
1852
- const createCompletionModel = (modelId) => new OpenAICompatibleCompletionLanguageModel(modelId, {
1853
- ...getCommonModelConfig("completion"),
1854
- includeUsage: options.includeUsage
1855
- });
1856
- const createEmbeddingModel = (modelId) => new OpenAICompatibleEmbeddingModel(modelId, {
1857
- ...getCommonModelConfig("embedding")
1858
- });
1859
- const createImageModel = (modelId) => new OpenAICompatibleImageModel(modelId, getCommonModelConfig("image"));
1860
- const provider = (modelId) => createLanguageModel(modelId);
1861
- provider.specificationVersion = "v4";
1862
- provider.languageModel = createLanguageModel;
1863
- provider.chatModel = createChatModel;
1864
- provider.completionModel = createCompletionModel;
1865
- provider.embeddingModel = createEmbeddingModel;
1866
- provider.textEmbeddingModel = createEmbeddingModel;
1867
- provider.imageModel = createImageModel;
1868
- return provider;
1417
+ const baseURL = withoutTrailingSlash(options.baseURL);
1418
+ const providerName = options.name;
1419
+ const headers = {
1420
+ ...options.apiKey && { Authorization: `Bearer ${options.apiKey}` },
1421
+ ...options.headers
1422
+ };
1423
+ const getHeaders = () => withUserAgentSuffix(headers, `ai-sdk-openai-compatible/${VERSION}`);
1424
+ const getCommonModelConfig = (modelType) => ({
1425
+ provider: `${providerName}.${modelType}`,
1426
+ url: ({ path }) => {
1427
+ const url = new URL(`${baseURL}${path}`);
1428
+ if (options.queryParams) url.search = new URLSearchParams(options.queryParams).toString();
1429
+ return url.toString();
1430
+ },
1431
+ headers: getHeaders,
1432
+ fetch: options.fetch
1433
+ });
1434
+ const createLanguageModel = (modelId) => createChatModel(modelId);
1435
+ const createChatModel = (modelId) => new OpenAICompatibleChatLanguageModel(modelId, {
1436
+ ...getCommonModelConfig("chat"),
1437
+ includeUsage: options.includeUsage,
1438
+ supportsStructuredOutputs: options.supportsStructuredOutputs,
1439
+ supportedUrls: options.supportedUrls,
1440
+ transformRequestBody: options.transformRequestBody,
1441
+ metadataExtractor: options.metadataExtractor,
1442
+ convertUsage: options.convertUsage
1443
+ });
1444
+ const createCompletionModel = (modelId) => new OpenAICompatibleCompletionLanguageModel(modelId, {
1445
+ ...getCommonModelConfig("completion"),
1446
+ includeUsage: options.includeUsage
1447
+ });
1448
+ const createEmbeddingModel = (modelId) => new OpenAICompatibleEmbeddingModel(modelId, { ...getCommonModelConfig("embedding") });
1449
+ const createImageModel = (modelId) => new OpenAICompatibleImageModel(modelId, getCommonModelConfig("image"));
1450
+ const provider = (modelId) => createLanguageModel(modelId);
1451
+ provider.specificationVersion = "v4";
1452
+ provider.languageModel = createLanguageModel;
1453
+ provider.chatModel = createChatModel;
1454
+ provider.completionModel = createCompletionModel;
1455
+ provider.embeddingModel = createEmbeddingModel;
1456
+ provider.textEmbeddingModel = createEmbeddingModel;
1457
+ provider.imageModel = createImageModel;
1458
+ return provider;
1869
1459
  }
1870
- export {
1871
- OpenAICompatibleChatLanguageModel,
1872
- OpenAICompatibleCompletionLanguageModel,
1873
- OpenAICompatibleEmbeddingModel,
1874
- OpenAICompatibleImageModel,
1875
- VERSION,
1876
- createOpenAICompatible
1877
- };
1460
+ //#endregion
1461
+ export { OpenAICompatibleChatLanguageModel, OpenAICompatibleCompletionLanguageModel, OpenAICompatibleEmbeddingModel, OpenAICompatibleImageModel, VERSION, createOpenAICompatible };
1462
+
1878
1463
  //# sourceMappingURL=index.js.map