@ai-sdk/openai-compatible 3.0.59 → 3.0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/index.d.ts +342 -330
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1419 -1834
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +176 -168
- package/dist/internal/index.d.ts.map +1 -0
- package/dist/internal/index.js +254 -346
- package/dist/internal/index.js.map +1 -1
- package/docs/index.mdx +1 -1
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -1,1878 +1,1463 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
return rawName;
|
|
14
|
+
const camelName = toCamelCase(rawName);
|
|
15
|
+
if (camelName !== rawName && providerOptions?.[camelName] != null) return camelName;
|
|
16
|
+
return rawName;
|
|
31
17
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
64
|
+
return message?.providerOptions?.openaiCompatible ?? {};
|
|
103
65
|
}
|
|
104
66
|
function getAudioFormat(mediaType) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
-
|
|
342
|
-
function mapOpenAICompatibleFinishReason(finishReason) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
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
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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
|
-
|
|
444
|
-
var OpenAICompatibleChatLanguageModel = class
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
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
|
-
|
|
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
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
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
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
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
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
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
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
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
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
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
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
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
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
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
|
-
|
|
1216
|
-
var OpenAICompatibleCompletionLanguageModel = class
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
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
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1137
|
+
const usageSchema = z.looseObject({
|
|
1138
|
+
prompt_tokens: z.number(),
|
|
1139
|
+
completion_tokens: z.number(),
|
|
1140
|
+
total_tokens: z.number()
|
|
1466
1141
|
});
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
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
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
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
|
-
|
|
1528
|
-
var OpenAICompatibleEmbeddingModel = class
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
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
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
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
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
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
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
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
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
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
|
-
|
|
1806
|
-
|
|
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
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
var VERSION = true ? "3.0.59" : "0.0.0-test";
|
|
1820
|
-
|
|
1821
|
-
// src/openai-compatible-provider.ts
|
|
1408
|
+
//#endregion
|
|
1409
|
+
//#region src/version.ts
|
|
1410
|
+
const VERSION = "3.0.61";
|
|
1411
|
+
//#endregion
|
|
1412
|
+
//#region src/openai-compatible-provider.ts
|
|
1413
|
+
/**
|
|
1414
|
+
* Create an OpenAICompatible provider instance.
|
|
1415
|
+
*/
|
|
1822
1416
|
function createOpenAICompatible(options) {
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
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
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
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
|