@ai-sdk/openai-compatible 3.0.0-beta.2 → 3.0.0-beta.21
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 +153 -8
- package/README.md +2 -0
- package/dist/index.d.mts +27 -27
- package/dist/index.d.ts +27 -27
- package/dist/index.js +110 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +110 -37
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +10 -10
- package/dist/internal/index.d.ts +10 -10
- package/dist/internal/index.js +8 -3
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +7 -1
- package/dist/internal/index.mjs.map +1 -1
- package/package.json +3 -5
- package/src/chat/convert-openai-compatible-chat-usage.ts +2 -2
- package/src/chat/convert-to-openai-compatible-chat-messages.ts +11 -4
- package/src/chat/map-openai-compatible-finish-reason.ts +2 -2
- package/src/chat/openai-compatible-api-types.ts +2 -4
- package/src/chat/openai-compatible-chat-language-model.ts +69 -36
- package/src/chat/openai-compatible-metadata-extractor.ts +3 -3
- package/src/chat/openai-compatible-prepare-tools.ts +6 -6
- package/src/completion/convert-openai-compatible-completion-usage.ts +2 -2
- package/src/completion/convert-to-openai-compatible-completion-prompt.ts +2 -2
- package/src/completion/map-openai-compatible-finish-reason.ts +2 -2
- package/src/completion/openai-compatible-completion-language-model.ts +41 -25
- package/src/embedding/openai-compatible-embedding-model.ts +18 -9
- package/src/image/openai-compatible-image-model.ts +22 -17
- package/src/openai-compatible-provider.ts +13 -13
- package/src/utils/to-camel-case.ts +43 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APICallError,
|
|
3
3
|
InvalidResponseDataError,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
LanguageModelV4,
|
|
5
|
+
LanguageModelV4CallOptions,
|
|
6
|
+
LanguageModelV4Content,
|
|
7
|
+
LanguageModelV4FinishReason,
|
|
8
|
+
LanguageModelV4GenerateResult,
|
|
9
|
+
LanguageModelV4StreamPart,
|
|
10
|
+
LanguageModelV4StreamResult,
|
|
11
|
+
SharedV4ProviderMetadata,
|
|
12
|
+
SharedV4Warning,
|
|
13
13
|
} from '@ai-sdk/provider';
|
|
14
14
|
import {
|
|
15
15
|
combineHeaders,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
createJsonResponseHandler,
|
|
19
19
|
FetchFunction,
|
|
20
20
|
generateId,
|
|
21
|
+
isCustomReasoning,
|
|
21
22
|
isParsableJson,
|
|
22
23
|
parseProviderOptions,
|
|
23
24
|
ParseResult,
|
|
@@ -25,6 +26,11 @@ import {
|
|
|
25
26
|
ResponseHandler,
|
|
26
27
|
} from '@ai-sdk/provider-utils';
|
|
27
28
|
import { z } from 'zod/v4';
|
|
29
|
+
import {
|
|
30
|
+
resolveProviderOptionsKey,
|
|
31
|
+
toCamelCase,
|
|
32
|
+
warnIfDeprecatedProviderOptionsKey,
|
|
33
|
+
} from '../utils/to-camel-case';
|
|
28
34
|
import {
|
|
29
35
|
defaultOpenAICompatibleErrorStructure,
|
|
30
36
|
ProviderErrorStructure,
|
|
@@ -57,7 +63,7 @@ export type OpenAICompatibleChatConfig = {
|
|
|
57
63
|
/**
|
|
58
64
|
* The supported URLs for the model.
|
|
59
65
|
*/
|
|
60
|
-
supportedUrls?: () =>
|
|
66
|
+
supportedUrls?: () => LanguageModelV4['supportedUrls'];
|
|
61
67
|
|
|
62
68
|
/**
|
|
63
69
|
* Optional function to transform the request body before sending it to the API.
|
|
@@ -67,8 +73,8 @@ export type OpenAICompatibleChatConfig = {
|
|
|
67
73
|
transformRequestBody?: (args: Record<string, any>) => Record<string, any>;
|
|
68
74
|
};
|
|
69
75
|
|
|
70
|
-
export class OpenAICompatibleChatLanguageModel implements
|
|
71
|
-
readonly specificationVersion = '
|
|
76
|
+
export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
77
|
+
readonly specificationVersion = 'v4';
|
|
72
78
|
|
|
73
79
|
readonly supportsStructuredOutputs: boolean;
|
|
74
80
|
|
|
@@ -119,14 +125,15 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
119
125
|
topK,
|
|
120
126
|
frequencyPenalty,
|
|
121
127
|
presencePenalty,
|
|
128
|
+
reasoning,
|
|
122
129
|
providerOptions,
|
|
123
130
|
stopSequences,
|
|
124
131
|
responseFormat,
|
|
125
132
|
seed,
|
|
126
133
|
toolChoice,
|
|
127
134
|
tools,
|
|
128
|
-
}:
|
|
129
|
-
const warnings:
|
|
135
|
+
}: LanguageModelV4CallOptions) {
|
|
136
|
+
const warnings: SharedV4Warning[] = [];
|
|
130
137
|
|
|
131
138
|
// Parse provider options - check for deprecated 'openai-compatible' key
|
|
132
139
|
const deprecatedOptions = await parseProviderOptions({
|
|
@@ -137,11 +144,19 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
137
144
|
|
|
138
145
|
if (deprecatedOptions != null) {
|
|
139
146
|
warnings.push({
|
|
140
|
-
type: '
|
|
141
|
-
|
|
147
|
+
type: 'deprecated',
|
|
148
|
+
setting: "providerOptions key 'openai-compatible'",
|
|
149
|
+
message: "Use 'openaiCompatible' instead.",
|
|
142
150
|
});
|
|
143
151
|
}
|
|
144
152
|
|
|
153
|
+
// Warn when the raw (non-camelCase) provider name is used
|
|
154
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
155
|
+
rawName: this.providerOptionsName,
|
|
156
|
+
providerOptions,
|
|
157
|
+
warnings,
|
|
158
|
+
});
|
|
159
|
+
|
|
145
160
|
const compatibleOptions = Object.assign(
|
|
146
161
|
deprecatedOptions ?? {},
|
|
147
162
|
(await parseProviderOptions({
|
|
@@ -154,6 +169,11 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
154
169
|
providerOptions,
|
|
155
170
|
schema: openaiCompatibleLanguageModelChatOptions,
|
|
156
171
|
})) ?? {},
|
|
172
|
+
(await parseProviderOptions({
|
|
173
|
+
provider: toCamelCase(this.providerOptionsName),
|
|
174
|
+
providerOptions,
|
|
175
|
+
schema: openaiCompatibleLanguageModelChatOptions,
|
|
176
|
+
})) ?? {},
|
|
157
177
|
);
|
|
158
178
|
|
|
159
179
|
const strictJsonSchema = compatibleOptions?.strictJsonSchema ?? true;
|
|
@@ -184,7 +204,13 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
184
204
|
toolChoice,
|
|
185
205
|
});
|
|
186
206
|
|
|
207
|
+
const metadataKey = resolveProviderOptionsKey(
|
|
208
|
+
this.providerOptionsName,
|
|
209
|
+
providerOptions,
|
|
210
|
+
);
|
|
211
|
+
|
|
187
212
|
return {
|
|
213
|
+
metadataKey,
|
|
188
214
|
args: {
|
|
189
215
|
// model id:
|
|
190
216
|
model: this.modelId,
|
|
@@ -217,9 +243,10 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
217
243
|
stop: stopSequences,
|
|
218
244
|
seed,
|
|
219
245
|
...Object.fromEntries(
|
|
220
|
-
Object.entries(
|
|
221
|
-
providerOptions?.[this.providerOptionsName]
|
|
222
|
-
|
|
246
|
+
Object.entries({
|
|
247
|
+
...providerOptions?.[this.providerOptionsName],
|
|
248
|
+
...providerOptions?.[toCamelCase(this.providerOptionsName)],
|
|
249
|
+
}).filter(
|
|
223
250
|
([key]) =>
|
|
224
251
|
!Object.keys(
|
|
225
252
|
openaiCompatibleLanguageModelChatOptions.shape,
|
|
@@ -227,7 +254,11 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
227
254
|
),
|
|
228
255
|
),
|
|
229
256
|
|
|
230
|
-
reasoning_effort:
|
|
257
|
+
reasoning_effort:
|
|
258
|
+
compatibleOptions.reasoningEffort ??
|
|
259
|
+
(isCustomReasoning(reasoning) && reasoning !== 'none'
|
|
260
|
+
? reasoning
|
|
261
|
+
: undefined),
|
|
231
262
|
verbosity: compatibleOptions.textVerbosity,
|
|
232
263
|
|
|
233
264
|
// messages:
|
|
@@ -242,9 +273,9 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
242
273
|
}
|
|
243
274
|
|
|
244
275
|
async doGenerate(
|
|
245
|
-
options:
|
|
246
|
-
): Promise<
|
|
247
|
-
const { args, warnings } = await this.getArgs({ ...options });
|
|
276
|
+
options: LanguageModelV4CallOptions,
|
|
277
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
278
|
+
const { args, warnings, metadataKey } = await this.getArgs({ ...options });
|
|
248
279
|
|
|
249
280
|
const transformedBody = this.transformRequestBody(args);
|
|
250
281
|
const body = JSON.stringify(transformedBody);
|
|
@@ -269,7 +300,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
269
300
|
});
|
|
270
301
|
|
|
271
302
|
const choice = responseBody.choices[0];
|
|
272
|
-
const content: Array<
|
|
303
|
+
const content: Array<LanguageModelV4Content> = [];
|
|
273
304
|
|
|
274
305
|
// text content:
|
|
275
306
|
const text = choice.message.content;
|
|
@@ -300,7 +331,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
300
331
|
...(thoughtSignature
|
|
301
332
|
? {
|
|
302
333
|
providerMetadata: {
|
|
303
|
-
[
|
|
334
|
+
[metadataKey]: { thoughtSignature },
|
|
304
335
|
},
|
|
305
336
|
}
|
|
306
337
|
: {}),
|
|
@@ -309,8 +340,8 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
309
340
|
}
|
|
310
341
|
|
|
311
342
|
// provider metadata:
|
|
312
|
-
const providerMetadata:
|
|
313
|
-
[
|
|
343
|
+
const providerMetadata: SharedV4ProviderMetadata = {
|
|
344
|
+
[metadataKey]: {},
|
|
314
345
|
...(await this.config.metadataExtractor?.extractMetadata?.({
|
|
315
346
|
parsedBody: rawResponse,
|
|
316
347
|
})),
|
|
@@ -318,11 +349,11 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
318
349
|
const completionTokenDetails =
|
|
319
350
|
responseBody.usage?.completion_tokens_details;
|
|
320
351
|
if (completionTokenDetails?.accepted_prediction_tokens != null) {
|
|
321
|
-
providerMetadata[
|
|
352
|
+
providerMetadata[metadataKey].acceptedPredictionTokens =
|
|
322
353
|
completionTokenDetails?.accepted_prediction_tokens;
|
|
323
354
|
}
|
|
324
355
|
if (completionTokenDetails?.rejected_prediction_tokens != null) {
|
|
325
|
-
providerMetadata[
|
|
356
|
+
providerMetadata[metadataKey].rejectedPredictionTokens =
|
|
326
357
|
completionTokenDetails?.rejected_prediction_tokens;
|
|
327
358
|
}
|
|
328
359
|
|
|
@@ -345,9 +376,11 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
345
376
|
}
|
|
346
377
|
|
|
347
378
|
async doStream(
|
|
348
|
-
options:
|
|
349
|
-
): Promise<
|
|
350
|
-
const { args, warnings } = await this.getArgs({
|
|
379
|
+
options: LanguageModelV4CallOptions,
|
|
380
|
+
): Promise<LanguageModelV4StreamResult> {
|
|
381
|
+
const { args, warnings, metadataKey } = await this.getArgs({
|
|
382
|
+
...options,
|
|
383
|
+
});
|
|
351
384
|
|
|
352
385
|
const body = this.transformRequestBody({
|
|
353
386
|
...args,
|
|
@@ -388,14 +421,14 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
388
421
|
thoughtSignature?: string;
|
|
389
422
|
}> = [];
|
|
390
423
|
|
|
391
|
-
let finishReason:
|
|
424
|
+
let finishReason: LanguageModelV4FinishReason = {
|
|
392
425
|
unified: 'other',
|
|
393
426
|
raw: undefined,
|
|
394
427
|
};
|
|
395
428
|
let usage: z.infer<typeof openaiCompatibleTokenUsageSchema> | undefined =
|
|
396
429
|
undefined;
|
|
397
430
|
let isFirstChunk = true;
|
|
398
|
-
const providerOptionsName =
|
|
431
|
+
const providerOptionsName = metadataKey;
|
|
399
432
|
let isActiveReasoning = false;
|
|
400
433
|
let isActiveText = false;
|
|
401
434
|
|
|
@@ -403,7 +436,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
403
436
|
stream: response.pipeThrough(
|
|
404
437
|
new TransformStream<
|
|
405
438
|
ParseResult<z.infer<typeof this.chunkSchema>>,
|
|
406
|
-
|
|
439
|
+
LanguageModelV4StreamPart
|
|
407
440
|
>({
|
|
408
441
|
start(controller) {
|
|
409
442
|
controller.enqueue({ type: 'stream-start', warnings });
|
|
@@ -684,7 +717,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV3 {
|
|
|
684
717
|
});
|
|
685
718
|
}
|
|
686
719
|
|
|
687
|
-
const providerMetadata:
|
|
720
|
+
const providerMetadata: SharedV4ProviderMetadata = {
|
|
688
721
|
[providerOptionsName]: {},
|
|
689
722
|
...metadataExtractor?.buildMetadata(),
|
|
690
723
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SharedV4ProviderMetadata } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Extracts provider-specific metadata from API responses.
|
|
@@ -18,7 +18,7 @@ export type MetadataExtractor = {
|
|
|
18
18
|
parsedBody,
|
|
19
19
|
}: {
|
|
20
20
|
parsedBody: unknown;
|
|
21
|
-
}) => Promise<
|
|
21
|
+
}) => Promise<SharedV4ProviderMetadata | undefined>;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Creates an extractor for handling streaming responses. The returned object provides
|
|
@@ -43,6 +43,6 @@ export type MetadataExtractor = {
|
|
|
43
43
|
* @returns Provider-specific metadata or undefined if no metadata is available.
|
|
44
44
|
* The metadata should be under a key indicating the provider id.
|
|
45
45
|
*/
|
|
46
|
-
buildMetadata():
|
|
46
|
+
buildMetadata(): SharedV4ProviderMetadata | undefined;
|
|
47
47
|
};
|
|
48
48
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
LanguageModelV4CallOptions,
|
|
3
|
+
SharedV4Warning,
|
|
4
4
|
UnsupportedFunctionalityError,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
|
|
@@ -8,8 +8,8 @@ export function prepareTools({
|
|
|
8
8
|
tools,
|
|
9
9
|
toolChoice,
|
|
10
10
|
}: {
|
|
11
|
-
tools:
|
|
12
|
-
toolChoice?:
|
|
11
|
+
tools: LanguageModelV4CallOptions['tools'];
|
|
12
|
+
toolChoice?: LanguageModelV4CallOptions['toolChoice'];
|
|
13
13
|
}): {
|
|
14
14
|
tools:
|
|
15
15
|
| undefined
|
|
@@ -28,12 +28,12 @@ export function prepareTools({
|
|
|
28
28
|
| 'none'
|
|
29
29
|
| 'required'
|
|
30
30
|
| undefined;
|
|
31
|
-
toolWarnings:
|
|
31
|
+
toolWarnings: SharedV4Warning[];
|
|
32
32
|
} {
|
|
33
33
|
// when the tools array is empty, change it to undefined to prevent errors:
|
|
34
34
|
tools = tools?.length ? tools : undefined;
|
|
35
35
|
|
|
36
|
-
const toolWarnings:
|
|
36
|
+
const toolWarnings: SharedV4Warning[] = [];
|
|
37
37
|
|
|
38
38
|
if (tools == null) {
|
|
39
39
|
return { tools: undefined, toolChoice: undefined, toolWarnings };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LanguageModelV4Usage } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
export function convertOpenAICompatibleCompletionUsage(
|
|
4
4
|
usage:
|
|
@@ -8,7 +8,7 @@ export function convertOpenAICompatibleCompletionUsage(
|
|
|
8
8
|
}
|
|
9
9
|
| undefined
|
|
10
10
|
| null,
|
|
11
|
-
):
|
|
11
|
+
): LanguageModelV4Usage {
|
|
12
12
|
if (usage == null) {
|
|
13
13
|
return {
|
|
14
14
|
inputTokens: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
InvalidPromptError,
|
|
3
|
-
|
|
3
|
+
LanguageModelV4Prompt,
|
|
4
4
|
UnsupportedFunctionalityError,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ export function convertToOpenAICompatibleCompletionPrompt({
|
|
|
9
9
|
user = 'user',
|
|
10
10
|
assistant = 'assistant',
|
|
11
11
|
}: {
|
|
12
|
-
prompt:
|
|
12
|
+
prompt: LanguageModelV4Prompt;
|
|
13
13
|
user?: string;
|
|
14
14
|
assistant?: string;
|
|
15
15
|
}): {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LanguageModelV4FinishReason } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
export function mapOpenAICompatibleFinishReason(
|
|
4
4
|
finishReason: string | null | undefined,
|
|
5
|
-
):
|
|
5
|
+
): LanguageModelV4FinishReason['unified'] {
|
|
6
6
|
switch (finishReason) {
|
|
7
7
|
case 'stop':
|
|
8
8
|
return 'stop';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APICallError,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
LanguageModelV4,
|
|
4
|
+
LanguageModelV4CallOptions,
|
|
5
|
+
LanguageModelV4Content,
|
|
6
|
+
LanguageModelV4FinishReason,
|
|
7
|
+
LanguageModelV4GenerateResult,
|
|
8
|
+
LanguageModelV4StreamPart,
|
|
9
|
+
LanguageModelV4StreamResult,
|
|
10
|
+
SharedV4Warning,
|
|
11
11
|
} from '@ai-sdk/provider';
|
|
12
12
|
import {
|
|
13
13
|
combineHeaders,
|
|
@@ -21,6 +21,10 @@ import {
|
|
|
21
21
|
ResponseHandler,
|
|
22
22
|
} from '@ai-sdk/provider-utils';
|
|
23
23
|
import { z } from 'zod/v4';
|
|
24
|
+
import {
|
|
25
|
+
toCamelCase,
|
|
26
|
+
warnIfDeprecatedProviderOptionsKey,
|
|
27
|
+
} from '../utils/to-camel-case';
|
|
24
28
|
import {
|
|
25
29
|
defaultOpenAICompatibleErrorStructure,
|
|
26
30
|
ProviderErrorStructure,
|
|
@@ -45,13 +49,11 @@ type OpenAICompatibleCompletionConfig = {
|
|
|
45
49
|
/**
|
|
46
50
|
* The supported URLs for the model.
|
|
47
51
|
*/
|
|
48
|
-
supportedUrls?: () =>
|
|
52
|
+
supportedUrls?: () => LanguageModelV4['supportedUrls'];
|
|
49
53
|
};
|
|
50
54
|
|
|
51
|
-
export class OpenAICompatibleCompletionLanguageModel
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
readonly specificationVersion = 'v3';
|
|
55
|
+
export class OpenAICompatibleCompletionLanguageModel implements LanguageModelV4 {
|
|
56
|
+
readonly specificationVersion = 'v4';
|
|
55
57
|
|
|
56
58
|
readonly modelId: OpenAICompatibleCompletionModelId;
|
|
57
59
|
private readonly config: OpenAICompatibleCompletionConfig;
|
|
@@ -100,16 +102,29 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
100
102
|
providerOptions,
|
|
101
103
|
tools,
|
|
102
104
|
toolChoice,
|
|
103
|
-
}:
|
|
104
|
-
const warnings:
|
|
105
|
+
}: LanguageModelV4CallOptions) {
|
|
106
|
+
const warnings: SharedV4Warning[] = [];
|
|
107
|
+
|
|
108
|
+
// Warn when the raw (non-camelCase) provider name is used
|
|
109
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
110
|
+
rawName: this.providerOptionsName,
|
|
111
|
+
providerOptions,
|
|
112
|
+
warnings,
|
|
113
|
+
});
|
|
105
114
|
|
|
106
|
-
// Parse provider options
|
|
107
|
-
const completionOptions =
|
|
115
|
+
// Parse provider options (support both raw and camelCase keys)
|
|
116
|
+
const completionOptions = Object.assign(
|
|
108
117
|
(await parseProviderOptions({
|
|
109
118
|
provider: this.providerOptionsName,
|
|
110
119
|
providerOptions,
|
|
111
120
|
schema: openaiCompatibleLanguageModelCompletionOptions,
|
|
112
|
-
})) ?? {}
|
|
121
|
+
})) ?? {},
|
|
122
|
+
(await parseProviderOptions({
|
|
123
|
+
provider: toCamelCase(this.providerOptionsName),
|
|
124
|
+
providerOptions,
|
|
125
|
+
schema: openaiCompatibleLanguageModelCompletionOptions,
|
|
126
|
+
})) ?? {},
|
|
127
|
+
);
|
|
113
128
|
|
|
114
129
|
if (topK != null) {
|
|
115
130
|
warnings.push({ type: 'unsupported', feature: 'topK' });
|
|
@@ -155,6 +170,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
155
170
|
presence_penalty: presencePenalty,
|
|
156
171
|
seed,
|
|
157
172
|
...providerOptions?.[this.providerOptionsName],
|
|
173
|
+
...providerOptions?.[toCamelCase(this.providerOptionsName)],
|
|
158
174
|
|
|
159
175
|
// prompt:
|
|
160
176
|
prompt: completionPrompt,
|
|
@@ -167,8 +183,8 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
167
183
|
}
|
|
168
184
|
|
|
169
185
|
async doGenerate(
|
|
170
|
-
options:
|
|
171
|
-
): Promise<
|
|
186
|
+
options: LanguageModelV4CallOptions,
|
|
187
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
172
188
|
const { args, warnings } = await this.getArgs(options);
|
|
173
189
|
|
|
174
190
|
const {
|
|
@@ -191,7 +207,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
191
207
|
});
|
|
192
208
|
|
|
193
209
|
const choice = response.choices[0];
|
|
194
|
-
const content: Array<
|
|
210
|
+
const content: Array<LanguageModelV4Content> = [];
|
|
195
211
|
|
|
196
212
|
// text content:
|
|
197
213
|
if (choice.text != null && choice.text.length > 0) {
|
|
@@ -216,8 +232,8 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
216
232
|
}
|
|
217
233
|
|
|
218
234
|
async doStream(
|
|
219
|
-
options:
|
|
220
|
-
): Promise<
|
|
235
|
+
options: LanguageModelV4CallOptions,
|
|
236
|
+
): Promise<LanguageModelV4StreamResult> {
|
|
221
237
|
const { args, warnings } = await this.getArgs(options);
|
|
222
238
|
|
|
223
239
|
const body = {
|
|
@@ -245,7 +261,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
245
261
|
fetch: this.config.fetch,
|
|
246
262
|
});
|
|
247
263
|
|
|
248
|
-
let finishReason:
|
|
264
|
+
let finishReason: LanguageModelV4FinishReason = {
|
|
249
265
|
unified: 'other',
|
|
250
266
|
raw: undefined,
|
|
251
267
|
};
|
|
@@ -262,7 +278,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
262
278
|
stream: response.pipeThrough(
|
|
263
279
|
new TransformStream<
|
|
264
280
|
ParseResult<z.infer<typeof this.chunkSchema>>,
|
|
265
|
-
|
|
281
|
+
LanguageModelV4StreamPart
|
|
266
282
|
>({
|
|
267
283
|
start(controller) {
|
|
268
284
|
controller.enqueue({ type: 'stream-start', warnings });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
EmbeddingModelV4,
|
|
3
|
+
SharedV4Warning,
|
|
4
4
|
TooManyEmbeddingValuesForCallError,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import {
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
defaultOpenAICompatibleErrorStructure,
|
|
21
21
|
ProviderErrorStructure,
|
|
22
22
|
} from '../openai-compatible-error';
|
|
23
|
+
import { warnIfDeprecatedProviderOptionsKey } from '../utils/to-camel-case';
|
|
23
24
|
|
|
24
25
|
type OpenAICompatibleEmbeddingConfig = {
|
|
25
26
|
/**
|
|
@@ -39,8 +40,8 @@ type OpenAICompatibleEmbeddingConfig = {
|
|
|
39
40
|
errorStructure?: ProviderErrorStructure<any>;
|
|
40
41
|
};
|
|
41
42
|
|
|
42
|
-
export class OpenAICompatibleEmbeddingModel implements
|
|
43
|
-
readonly specificationVersion = '
|
|
43
|
+
export class OpenAICompatibleEmbeddingModel implements EmbeddingModelV4 {
|
|
44
|
+
readonly specificationVersion = 'v4';
|
|
44
45
|
readonly modelId: OpenAICompatibleEmbeddingModelId;
|
|
45
46
|
|
|
46
47
|
private readonly config: OpenAICompatibleEmbeddingConfig;
|
|
@@ -74,10 +75,10 @@ export class OpenAICompatibleEmbeddingModel implements EmbeddingModelV3 {
|
|
|
74
75
|
headers,
|
|
75
76
|
abortSignal,
|
|
76
77
|
providerOptions,
|
|
77
|
-
}: Parameters<
|
|
78
|
-
Awaited<ReturnType<
|
|
78
|
+
}: Parameters<EmbeddingModelV4['doEmbed']>[0]): Promise<
|
|
79
|
+
Awaited<ReturnType<EmbeddingModelV4['doEmbed']>>
|
|
79
80
|
> {
|
|
80
|
-
const warnings:
|
|
81
|
+
const warnings: SharedV4Warning[] = [];
|
|
81
82
|
|
|
82
83
|
// Parse provider options - check for deprecated 'openai-compatible' key
|
|
83
84
|
const deprecatedOptions = await parseProviderOptions({
|
|
@@ -88,11 +89,19 @@ export class OpenAICompatibleEmbeddingModel implements EmbeddingModelV3 {
|
|
|
88
89
|
|
|
89
90
|
if (deprecatedOptions != null) {
|
|
90
91
|
warnings.push({
|
|
91
|
-
type: '
|
|
92
|
-
|
|
92
|
+
type: 'deprecated',
|
|
93
|
+
setting: "providerOptions key 'openai-compatible'",
|
|
94
|
+
message: "Use 'openaiCompatible' instead.",
|
|
93
95
|
});
|
|
94
96
|
}
|
|
95
97
|
|
|
98
|
+
// Warn when the raw (non-camelCase) provider name is used
|
|
99
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
100
|
+
rawName: this.providerOptionsName,
|
|
101
|
+
providerOptions,
|
|
102
|
+
warnings,
|
|
103
|
+
});
|
|
104
|
+
|
|
96
105
|
const compatibleOptions = Object.assign(
|
|
97
106
|
deprecatedOptions ?? {},
|
|
98
107
|
(await parseProviderOptions({
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
ImageModelV4,
|
|
3
|
+
ImageModelV4File,
|
|
4
|
+
SharedV4ProviderOptions,
|
|
5
|
+
SharedV4Warning,
|
|
6
6
|
} from '@ai-sdk/provider';
|
|
7
|
+
import {
|
|
8
|
+
toCamelCase,
|
|
9
|
+
warnIfDeprecatedProviderOptionsKey,
|
|
10
|
+
} from '../utils/to-camel-case';
|
|
7
11
|
import {
|
|
8
12
|
combineHeaders,
|
|
9
13
|
convertBase64ToUint8Array,
|
|
@@ -33,8 +37,8 @@ export type OpenAICompatibleImageModelConfig = {
|
|
|
33
37
|
};
|
|
34
38
|
};
|
|
35
39
|
|
|
36
|
-
export class OpenAICompatibleImageModel implements
|
|
37
|
-
readonly specificationVersion = '
|
|
40
|
+
export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
41
|
+
readonly specificationVersion = 'v4';
|
|
38
42
|
readonly maxImagesPerCall = 10;
|
|
39
43
|
|
|
40
44
|
get provider(): string {
|
|
@@ -53,10 +57,15 @@ export class OpenAICompatibleImageModel implements ImageModelV3 {
|
|
|
53
57
|
private readonly config: OpenAICompatibleImageModelConfig,
|
|
54
58
|
) {}
|
|
55
59
|
|
|
56
|
-
// TODO: deprecate non-camelCase keys and remove in future major version
|
|
57
60
|
private getArgs(
|
|
58
|
-
providerOptions:
|
|
61
|
+
providerOptions: SharedV4ProviderOptions,
|
|
62
|
+
warnings: SharedV4Warning[],
|
|
59
63
|
): Record<string, unknown> {
|
|
64
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
65
|
+
rawName: this.providerOptionsKey,
|
|
66
|
+
providerOptions,
|
|
67
|
+
warnings,
|
|
68
|
+
});
|
|
60
69
|
return {
|
|
61
70
|
...providerOptions[this.providerOptionsKey],
|
|
62
71
|
...providerOptions[toCamelCase(this.providerOptionsKey)],
|
|
@@ -74,10 +83,10 @@ export class OpenAICompatibleImageModel implements ImageModelV3 {
|
|
|
74
83
|
abortSignal,
|
|
75
84
|
files,
|
|
76
85
|
mask,
|
|
77
|
-
}: Parameters<
|
|
78
|
-
Awaited<ReturnType<
|
|
86
|
+
}: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
|
|
87
|
+
Awaited<ReturnType<ImageModelV4['doGenerate']>>
|
|
79
88
|
> {
|
|
80
|
-
const warnings: Array<
|
|
89
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
81
90
|
|
|
82
91
|
if (aspectRatio != null) {
|
|
83
92
|
warnings.push({
|
|
@@ -94,7 +103,7 @@ export class OpenAICompatibleImageModel implements ImageModelV3 {
|
|
|
94
103
|
|
|
95
104
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
96
105
|
|
|
97
|
-
const args = this.getArgs(providerOptions);
|
|
106
|
+
const args = this.getArgs(providerOptions, warnings);
|
|
98
107
|
|
|
99
108
|
// Image editing mode - use form data and /images/edits endpoint
|
|
100
109
|
if (files != null && files.length > 0) {
|
|
@@ -187,7 +196,7 @@ type OpenAICompatibleFormDataInput = {
|
|
|
187
196
|
[key: string]: unknown;
|
|
188
197
|
};
|
|
189
198
|
|
|
190
|
-
async function fileToBlob(file:
|
|
199
|
+
async function fileToBlob(file: ImageModelV4File): Promise<Blob> {
|
|
191
200
|
if (file.type === 'url') {
|
|
192
201
|
return downloadBlob(file.url);
|
|
193
202
|
}
|
|
@@ -199,7 +208,3 @@ async function fileToBlob(file: ImageModelV3File): Promise<Blob> {
|
|
|
199
208
|
|
|
200
209
|
return new Blob([data as BlobPart], { type: file.mediaType });
|
|
201
210
|
}
|
|
202
|
-
|
|
203
|
-
function toCamelCase(str: string): string {
|
|
204
|
-
return str.replace(/[_-]([a-z])/g, g => g[1].toUpperCase());
|
|
205
|
-
}
|