@ai-sdk/openai-compatible 3.0.0-beta.3 → 3.0.0-beta.30
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 +227 -8
- package/README.md +2 -0
- package/dist/index.d.ts +39 -6
- package/dist/index.js +419 -378
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.js +27 -45
- package/dist/internal/index.js.map +1 -1
- package/package.json +9 -12
- package/src/chat/convert-to-openai-compatible-chat-messages.ts +7 -0
- package/src/chat/openai-compatible-api-types.ts +2 -4
- package/src/chat/openai-compatible-chat-language-model.ts +86 -182
- package/src/completion/openai-compatible-completion-language-model.ts +45 -9
- package/src/embedding/openai-compatible-embedding-model.ts +30 -4
- package/src/image/openai-compatible-image-model.ts +31 -9
- package/src/utils/to-camel-case.ts +43 -0
- package/dist/index.d.mts +0 -290
- package/dist/index.mjs +0 -1742
- package/dist/index.mjs.map +0 -1
- package/dist/internal/index.d.mts +0 -193
- package/dist/internal/index.mjs +0 -340
- package/dist/internal/index.mjs.map +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APICallError,
|
|
3
|
-
InvalidResponseDataError,
|
|
4
3
|
LanguageModelV4,
|
|
5
4
|
LanguageModelV4CallOptions,
|
|
6
5
|
LanguageModelV4Content,
|
|
@@ -18,13 +17,22 @@ import {
|
|
|
18
17
|
createJsonResponseHandler,
|
|
19
18
|
FetchFunction,
|
|
20
19
|
generateId,
|
|
21
|
-
|
|
20
|
+
isCustomReasoning,
|
|
22
21
|
parseProviderOptions,
|
|
23
22
|
ParseResult,
|
|
24
23
|
postJsonToApi,
|
|
25
24
|
ResponseHandler,
|
|
25
|
+
serializeModelOptions,
|
|
26
|
+
StreamingToolCallTracker,
|
|
27
|
+
WORKFLOW_SERIALIZE,
|
|
28
|
+
WORKFLOW_DESERIALIZE,
|
|
26
29
|
} from '@ai-sdk/provider-utils';
|
|
27
30
|
import { z } from 'zod/v4';
|
|
31
|
+
import {
|
|
32
|
+
resolveProviderOptionsKey,
|
|
33
|
+
toCamelCase,
|
|
34
|
+
warnIfDeprecatedProviderOptionsKey,
|
|
35
|
+
} from '../utils/to-camel-case';
|
|
28
36
|
import {
|
|
29
37
|
defaultOpenAICompatibleErrorStructure,
|
|
30
38
|
ProviderErrorStructure,
|
|
@@ -42,7 +50,7 @@ import { prepareTools } from './openai-compatible-prepare-tools';
|
|
|
42
50
|
|
|
43
51
|
export type OpenAICompatibleChatConfig = {
|
|
44
52
|
provider: string;
|
|
45
|
-
headers
|
|
53
|
+
headers?: () => Record<string, string | undefined>;
|
|
46
54
|
url: (options: { modelId: string; path: string }) => string;
|
|
47
55
|
fetch?: FetchFunction;
|
|
48
56
|
includeUsage?: boolean;
|
|
@@ -73,10 +81,27 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
73
81
|
readonly supportsStructuredOutputs: boolean;
|
|
74
82
|
|
|
75
83
|
readonly modelId: OpenAICompatibleChatModelId;
|
|
76
|
-
|
|
84
|
+
protected readonly config: OpenAICompatibleChatConfig;
|
|
77
85
|
private readonly failedResponseHandler: ResponseHandler<APICallError>;
|
|
78
86
|
private readonly chunkSchema; // type inferred via constructor
|
|
79
87
|
|
|
88
|
+
static [WORKFLOW_SERIALIZE](model: OpenAICompatibleChatLanguageModel) {
|
|
89
|
+
return serializeModelOptions({
|
|
90
|
+
modelId: model.modelId,
|
|
91
|
+
config: model.config,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
96
|
+
modelId: string;
|
|
97
|
+
config: OpenAICompatibleChatConfig;
|
|
98
|
+
}) {
|
|
99
|
+
return new OpenAICompatibleChatLanguageModel(
|
|
100
|
+
options.modelId,
|
|
101
|
+
options.config,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
80
105
|
constructor(
|
|
81
106
|
modelId: OpenAICompatibleChatModelId,
|
|
82
107
|
config: OpenAICompatibleChatConfig,
|
|
@@ -119,6 +144,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
119
144
|
topK,
|
|
120
145
|
frequencyPenalty,
|
|
121
146
|
presencePenalty,
|
|
147
|
+
reasoning,
|
|
122
148
|
providerOptions,
|
|
123
149
|
stopSequences,
|
|
124
150
|
responseFormat,
|
|
@@ -137,11 +163,19 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
137
163
|
|
|
138
164
|
if (deprecatedOptions != null) {
|
|
139
165
|
warnings.push({
|
|
140
|
-
type: '
|
|
141
|
-
|
|
166
|
+
type: 'deprecated',
|
|
167
|
+
setting: "providerOptions key 'openai-compatible'",
|
|
168
|
+
message: "Use 'openaiCompatible' instead.",
|
|
142
169
|
});
|
|
143
170
|
}
|
|
144
171
|
|
|
172
|
+
// Warn when the raw (non-camelCase) provider name is used
|
|
173
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
174
|
+
rawName: this.providerOptionsName,
|
|
175
|
+
providerOptions,
|
|
176
|
+
warnings,
|
|
177
|
+
});
|
|
178
|
+
|
|
145
179
|
const compatibleOptions = Object.assign(
|
|
146
180
|
deprecatedOptions ?? {},
|
|
147
181
|
(await parseProviderOptions({
|
|
@@ -154,6 +188,11 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
154
188
|
providerOptions,
|
|
155
189
|
schema: openaiCompatibleLanguageModelChatOptions,
|
|
156
190
|
})) ?? {},
|
|
191
|
+
(await parseProviderOptions({
|
|
192
|
+
provider: toCamelCase(this.providerOptionsName),
|
|
193
|
+
providerOptions,
|
|
194
|
+
schema: openaiCompatibleLanguageModelChatOptions,
|
|
195
|
+
})) ?? {},
|
|
157
196
|
);
|
|
158
197
|
|
|
159
198
|
const strictJsonSchema = compatibleOptions?.strictJsonSchema ?? true;
|
|
@@ -184,7 +223,13 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
184
223
|
toolChoice,
|
|
185
224
|
});
|
|
186
225
|
|
|
226
|
+
const metadataKey = resolveProviderOptionsKey(
|
|
227
|
+
this.providerOptionsName,
|
|
228
|
+
providerOptions,
|
|
229
|
+
);
|
|
230
|
+
|
|
187
231
|
return {
|
|
232
|
+
metadataKey,
|
|
188
233
|
args: {
|
|
189
234
|
// model id:
|
|
190
235
|
model: this.modelId,
|
|
@@ -217,9 +262,10 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
217
262
|
stop: stopSequences,
|
|
218
263
|
seed,
|
|
219
264
|
...Object.fromEntries(
|
|
220
|
-
Object.entries(
|
|
221
|
-
providerOptions?.[this.providerOptionsName]
|
|
222
|
-
|
|
265
|
+
Object.entries({
|
|
266
|
+
...providerOptions?.[this.providerOptionsName],
|
|
267
|
+
...providerOptions?.[toCamelCase(this.providerOptionsName)],
|
|
268
|
+
}).filter(
|
|
223
269
|
([key]) =>
|
|
224
270
|
!Object.keys(
|
|
225
271
|
openaiCompatibleLanguageModelChatOptions.shape,
|
|
@@ -227,7 +273,11 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
227
273
|
),
|
|
228
274
|
),
|
|
229
275
|
|
|
230
|
-
reasoning_effort:
|
|
276
|
+
reasoning_effort:
|
|
277
|
+
compatibleOptions.reasoningEffort ??
|
|
278
|
+
(isCustomReasoning(reasoning) && reasoning !== 'none'
|
|
279
|
+
? reasoning
|
|
280
|
+
: undefined),
|
|
231
281
|
verbosity: compatibleOptions.textVerbosity,
|
|
232
282
|
|
|
233
283
|
// messages:
|
|
@@ -244,7 +294,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
244
294
|
async doGenerate(
|
|
245
295
|
options: LanguageModelV4CallOptions,
|
|
246
296
|
): Promise<LanguageModelV4GenerateResult> {
|
|
247
|
-
const { args, warnings } = await this.getArgs({ ...options });
|
|
297
|
+
const { args, warnings, metadataKey } = await this.getArgs({ ...options });
|
|
248
298
|
|
|
249
299
|
const transformedBody = this.transformRequestBody(args);
|
|
250
300
|
const body = JSON.stringify(transformedBody);
|
|
@@ -258,7 +308,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
258
308
|
path: '/chat/completions',
|
|
259
309
|
modelId: this.modelId,
|
|
260
310
|
}),
|
|
261
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
311
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
262
312
|
body: transformedBody,
|
|
263
313
|
failedResponseHandler: this.failedResponseHandler,
|
|
264
314
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -300,7 +350,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
300
350
|
...(thoughtSignature
|
|
301
351
|
? {
|
|
302
352
|
providerMetadata: {
|
|
303
|
-
[
|
|
353
|
+
[metadataKey]: { thoughtSignature },
|
|
304
354
|
},
|
|
305
355
|
}
|
|
306
356
|
: {}),
|
|
@@ -310,7 +360,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
310
360
|
|
|
311
361
|
// provider metadata:
|
|
312
362
|
const providerMetadata: SharedV4ProviderMetadata = {
|
|
313
|
-
[
|
|
363
|
+
[metadataKey]: {},
|
|
314
364
|
...(await this.config.metadataExtractor?.extractMetadata?.({
|
|
315
365
|
parsedBody: rawResponse,
|
|
316
366
|
})),
|
|
@@ -318,11 +368,11 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
318
368
|
const completionTokenDetails =
|
|
319
369
|
responseBody.usage?.completion_tokens_details;
|
|
320
370
|
if (completionTokenDetails?.accepted_prediction_tokens != null) {
|
|
321
|
-
providerMetadata[
|
|
371
|
+
providerMetadata[metadataKey].acceptedPredictionTokens =
|
|
322
372
|
completionTokenDetails?.accepted_prediction_tokens;
|
|
323
373
|
}
|
|
324
374
|
if (completionTokenDetails?.rejected_prediction_tokens != null) {
|
|
325
|
-
providerMetadata[
|
|
375
|
+
providerMetadata[metadataKey].rejectedPredictionTokens =
|
|
326
376
|
completionTokenDetails?.rejected_prediction_tokens;
|
|
327
377
|
}
|
|
328
378
|
|
|
@@ -347,7 +397,9 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
347
397
|
async doStream(
|
|
348
398
|
options: LanguageModelV4CallOptions,
|
|
349
399
|
): Promise<LanguageModelV4StreamResult> {
|
|
350
|
-
const { args, warnings } = await this.getArgs({
|
|
400
|
+
const { args, warnings, metadataKey } = await this.getArgs({
|
|
401
|
+
...options,
|
|
402
|
+
});
|
|
351
403
|
|
|
352
404
|
const body = this.transformRequestBody({
|
|
353
405
|
...args,
|
|
@@ -367,7 +419,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
367
419
|
path: '/chat/completions',
|
|
368
420
|
modelId: this.modelId,
|
|
369
421
|
}),
|
|
370
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
422
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
371
423
|
body,
|
|
372
424
|
failedResponseHandler: this.failedResponseHandler,
|
|
373
425
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -377,16 +429,17 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
377
429
|
fetch: this.config.fetch,
|
|
378
430
|
});
|
|
379
431
|
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
432
|
+
const providerOptionsName = metadataKey;
|
|
433
|
+
const toolCallTracker = new StreamingToolCallTracker({
|
|
434
|
+
generateId,
|
|
435
|
+
extractMetadata: delta => {
|
|
436
|
+
const sig = (delta as any).extra_content?.google?.thought_signature;
|
|
437
|
+
return sig
|
|
438
|
+
? { [providerOptionsName]: { thoughtSignature: sig } }
|
|
439
|
+
: undefined;
|
|
440
|
+
},
|
|
441
|
+
buildToolCallProviderMetadata: metadata => metadata,
|
|
442
|
+
});
|
|
390
443
|
|
|
391
444
|
let finishReason: LanguageModelV4FinishReason = {
|
|
392
445
|
unified: 'other',
|
|
@@ -395,7 +448,6 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
395
448
|
let usage: z.infer<typeof openaiCompatibleTokenUsageSchema> | undefined =
|
|
396
449
|
undefined;
|
|
397
450
|
let isFirstChunk = true;
|
|
398
|
-
const providerOptionsName = this.providerOptionsName;
|
|
399
451
|
let isActiveReasoning = false;
|
|
400
452
|
let isActiveText = false;
|
|
401
453
|
|
|
@@ -517,134 +569,10 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
517
569
|
}
|
|
518
570
|
|
|
519
571
|
for (const toolCallDelta of delta.tool_calls) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
throw new InvalidResponseDataError({
|
|
525
|
-
data: toolCallDelta,
|
|
526
|
-
message: `Expected 'id' to be a string.`,
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
if (toolCallDelta.function?.name == null) {
|
|
531
|
-
throw new InvalidResponseDataError({
|
|
532
|
-
data: toolCallDelta,
|
|
533
|
-
message: `Expected 'function.name' to be a string.`,
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
controller.enqueue({
|
|
538
|
-
type: 'tool-input-start',
|
|
539
|
-
id: toolCallDelta.id,
|
|
540
|
-
toolName: toolCallDelta.function.name,
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
toolCalls[index] = {
|
|
544
|
-
id: toolCallDelta.id,
|
|
545
|
-
type: 'function',
|
|
546
|
-
function: {
|
|
547
|
-
name: toolCallDelta.function.name,
|
|
548
|
-
arguments: toolCallDelta.function.arguments ?? '',
|
|
549
|
-
},
|
|
550
|
-
hasFinished: false,
|
|
551
|
-
thoughtSignature:
|
|
552
|
-
toolCallDelta.extra_content?.google?.thought_signature ??
|
|
553
|
-
undefined,
|
|
554
|
-
};
|
|
555
|
-
|
|
556
|
-
const toolCall = toolCalls[index];
|
|
557
|
-
|
|
558
|
-
if (
|
|
559
|
-
toolCall.function?.name != null &&
|
|
560
|
-
toolCall.function?.arguments != null
|
|
561
|
-
) {
|
|
562
|
-
// send delta if the argument text has already started:
|
|
563
|
-
if (toolCall.function.arguments.length > 0) {
|
|
564
|
-
controller.enqueue({
|
|
565
|
-
type: 'tool-input-delta',
|
|
566
|
-
id: toolCall.id,
|
|
567
|
-
delta: toolCall.function.arguments,
|
|
568
|
-
});
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
// check if tool call is complete
|
|
572
|
-
// (some providers send the full tool call in one chunk):
|
|
573
|
-
if (isParsableJson(toolCall.function.arguments)) {
|
|
574
|
-
controller.enqueue({
|
|
575
|
-
type: 'tool-input-end',
|
|
576
|
-
id: toolCall.id,
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
controller.enqueue({
|
|
580
|
-
type: 'tool-call',
|
|
581
|
-
toolCallId: toolCall.id ?? generateId(),
|
|
582
|
-
toolName: toolCall.function.name,
|
|
583
|
-
input: toolCall.function.arguments,
|
|
584
|
-
...(toolCall.thoughtSignature
|
|
585
|
-
? {
|
|
586
|
-
providerMetadata: {
|
|
587
|
-
[providerOptionsName]: {
|
|
588
|
-
thoughtSignature: toolCall.thoughtSignature,
|
|
589
|
-
},
|
|
590
|
-
},
|
|
591
|
-
}
|
|
592
|
-
: {}),
|
|
593
|
-
});
|
|
594
|
-
toolCall.hasFinished = true;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
continue;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// existing tool call, merge if not finished
|
|
602
|
-
const toolCall = toolCalls[index];
|
|
603
|
-
|
|
604
|
-
if (toolCall.hasFinished) {
|
|
605
|
-
continue;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
if (toolCallDelta.function?.arguments != null) {
|
|
609
|
-
toolCall.function!.arguments +=
|
|
610
|
-
toolCallDelta.function?.arguments ?? '';
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// send delta
|
|
614
|
-
controller.enqueue({
|
|
615
|
-
type: 'tool-input-delta',
|
|
616
|
-
id: toolCall.id,
|
|
617
|
-
delta: toolCallDelta.function.arguments ?? '',
|
|
618
|
-
});
|
|
619
|
-
|
|
620
|
-
// check if tool call is complete
|
|
621
|
-
if (
|
|
622
|
-
toolCall.function?.name != null &&
|
|
623
|
-
toolCall.function?.arguments != null &&
|
|
624
|
-
isParsableJson(toolCall.function.arguments)
|
|
625
|
-
) {
|
|
626
|
-
controller.enqueue({
|
|
627
|
-
type: 'tool-input-end',
|
|
628
|
-
id: toolCall.id,
|
|
629
|
-
});
|
|
630
|
-
|
|
631
|
-
controller.enqueue({
|
|
632
|
-
type: 'tool-call',
|
|
633
|
-
toolCallId: toolCall.id ?? generateId(),
|
|
634
|
-
toolName: toolCall.function.name,
|
|
635
|
-
input: toolCall.function.arguments,
|
|
636
|
-
...(toolCall.thoughtSignature
|
|
637
|
-
? {
|
|
638
|
-
providerMetadata: {
|
|
639
|
-
[providerOptionsName]: {
|
|
640
|
-
thoughtSignature: toolCall.thoughtSignature,
|
|
641
|
-
},
|
|
642
|
-
},
|
|
643
|
-
}
|
|
644
|
-
: {}),
|
|
645
|
-
});
|
|
646
|
-
toolCall.hasFinished = true;
|
|
647
|
-
}
|
|
572
|
+
toolCallTracker.processDelta(
|
|
573
|
+
toolCallDelta,
|
|
574
|
+
controller.enqueue.bind(controller),
|
|
575
|
+
);
|
|
648
576
|
}
|
|
649
577
|
}
|
|
650
578
|
},
|
|
@@ -658,31 +586,7 @@ export class OpenAICompatibleChatLanguageModel implements LanguageModelV4 {
|
|
|
658
586
|
controller.enqueue({ type: 'text-end', id: 'txt-0' });
|
|
659
587
|
}
|
|
660
588
|
|
|
661
|
-
|
|
662
|
-
for (const toolCall of toolCalls.filter(
|
|
663
|
-
toolCall => !toolCall.hasFinished,
|
|
664
|
-
)) {
|
|
665
|
-
controller.enqueue({
|
|
666
|
-
type: 'tool-input-end',
|
|
667
|
-
id: toolCall.id,
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
controller.enqueue({
|
|
671
|
-
type: 'tool-call',
|
|
672
|
-
toolCallId: toolCall.id ?? generateId(),
|
|
673
|
-
toolName: toolCall.function.name,
|
|
674
|
-
input: toolCall.function.arguments,
|
|
675
|
-
...(toolCall.thoughtSignature
|
|
676
|
-
? {
|
|
677
|
-
providerMetadata: {
|
|
678
|
-
[providerOptionsName]: {
|
|
679
|
-
thoughtSignature: toolCall.thoughtSignature,
|
|
680
|
-
},
|
|
681
|
-
},
|
|
682
|
-
}
|
|
683
|
-
: {}),
|
|
684
|
-
});
|
|
685
|
-
}
|
|
589
|
+
toolCallTracker.flush(controller.enqueue.bind(controller));
|
|
686
590
|
|
|
687
591
|
const providerMetadata: SharedV4ProviderMetadata = {
|
|
688
592
|
[providerOptionsName]: {},
|
|
@@ -19,8 +19,15 @@ import {
|
|
|
19
19
|
ParseResult,
|
|
20
20
|
postJsonToApi,
|
|
21
21
|
ResponseHandler,
|
|
22
|
+
serializeModelOptions,
|
|
23
|
+
WORKFLOW_SERIALIZE,
|
|
24
|
+
WORKFLOW_DESERIALIZE,
|
|
22
25
|
} from '@ai-sdk/provider-utils';
|
|
23
26
|
import { z } from 'zod/v4';
|
|
27
|
+
import {
|
|
28
|
+
toCamelCase,
|
|
29
|
+
warnIfDeprecatedProviderOptionsKey,
|
|
30
|
+
} from '../utils/to-camel-case';
|
|
24
31
|
import {
|
|
25
32
|
defaultOpenAICompatibleErrorStructure,
|
|
26
33
|
ProviderErrorStructure,
|
|
@@ -37,7 +44,7 @@ import {
|
|
|
37
44
|
type OpenAICompatibleCompletionConfig = {
|
|
38
45
|
provider: string;
|
|
39
46
|
includeUsage?: boolean;
|
|
40
|
-
headers
|
|
47
|
+
headers?: () => Record<string, string | undefined>;
|
|
41
48
|
url: (options: { modelId: string; path: string }) => string;
|
|
42
49
|
fetch?: FetchFunction;
|
|
43
50
|
errorStructure?: ProviderErrorStructure<any>;
|
|
@@ -48,9 +55,7 @@ type OpenAICompatibleCompletionConfig = {
|
|
|
48
55
|
supportedUrls?: () => LanguageModelV4['supportedUrls'];
|
|
49
56
|
};
|
|
50
57
|
|
|
51
|
-
export class OpenAICompatibleCompletionLanguageModel
|
|
52
|
-
implements LanguageModelV4
|
|
53
|
-
{
|
|
58
|
+
export class OpenAICompatibleCompletionLanguageModel implements LanguageModelV4 {
|
|
54
59
|
readonly specificationVersion = 'v4';
|
|
55
60
|
|
|
56
61
|
readonly modelId: OpenAICompatibleCompletionModelId;
|
|
@@ -58,6 +63,23 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
58
63
|
private readonly failedResponseHandler: ResponseHandler<APICallError>;
|
|
59
64
|
private readonly chunkSchema; // type inferred via constructor
|
|
60
65
|
|
|
66
|
+
static [WORKFLOW_SERIALIZE](model: OpenAICompatibleCompletionLanguageModel) {
|
|
67
|
+
return serializeModelOptions({
|
|
68
|
+
modelId: model.modelId,
|
|
69
|
+
config: model.config,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
74
|
+
modelId: string;
|
|
75
|
+
config: OpenAICompatibleCompletionConfig;
|
|
76
|
+
}) {
|
|
77
|
+
return new OpenAICompatibleCompletionLanguageModel(
|
|
78
|
+
options.modelId,
|
|
79
|
+
options.config,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
61
83
|
constructor(
|
|
62
84
|
modelId: OpenAICompatibleCompletionModelId,
|
|
63
85
|
config: OpenAICompatibleCompletionConfig,
|
|
@@ -103,13 +125,26 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
103
125
|
}: LanguageModelV4CallOptions) {
|
|
104
126
|
const warnings: SharedV4Warning[] = [];
|
|
105
127
|
|
|
106
|
-
//
|
|
107
|
-
|
|
128
|
+
// Warn when the raw (non-camelCase) provider name is used
|
|
129
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
130
|
+
rawName: this.providerOptionsName,
|
|
131
|
+
providerOptions,
|
|
132
|
+
warnings,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Parse provider options (support both raw and camelCase keys)
|
|
136
|
+
const completionOptions = Object.assign(
|
|
108
137
|
(await parseProviderOptions({
|
|
109
138
|
provider: this.providerOptionsName,
|
|
110
139
|
providerOptions,
|
|
111
140
|
schema: openaiCompatibleLanguageModelCompletionOptions,
|
|
112
|
-
})) ?? {}
|
|
141
|
+
})) ?? {},
|
|
142
|
+
(await parseProviderOptions({
|
|
143
|
+
provider: toCamelCase(this.providerOptionsName),
|
|
144
|
+
providerOptions,
|
|
145
|
+
schema: openaiCompatibleLanguageModelCompletionOptions,
|
|
146
|
+
})) ?? {},
|
|
147
|
+
);
|
|
113
148
|
|
|
114
149
|
if (topK != null) {
|
|
115
150
|
warnings.push({ type: 'unsupported', feature: 'topK' });
|
|
@@ -155,6 +190,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
155
190
|
presence_penalty: presencePenalty,
|
|
156
191
|
seed,
|
|
157
192
|
...providerOptions?.[this.providerOptionsName],
|
|
193
|
+
...providerOptions?.[toCamelCase(this.providerOptionsName)],
|
|
158
194
|
|
|
159
195
|
// prompt:
|
|
160
196
|
prompt: completionPrompt,
|
|
@@ -180,7 +216,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
180
216
|
path: '/completions',
|
|
181
217
|
modelId: this.modelId,
|
|
182
218
|
}),
|
|
183
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
219
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
184
220
|
body: args,
|
|
185
221
|
failedResponseHandler: this.failedResponseHandler,
|
|
186
222
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -235,7 +271,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
235
271
|
path: '/completions',
|
|
236
272
|
modelId: this.modelId,
|
|
237
273
|
}),
|
|
238
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
274
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
239
275
|
body,
|
|
240
276
|
failedResponseHandler: this.failedResponseHandler,
|
|
241
277
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
FetchFunction,
|
|
11
11
|
parseProviderOptions,
|
|
12
12
|
postJsonToApi,
|
|
13
|
+
serializeModelOptions,
|
|
14
|
+
WORKFLOW_SERIALIZE,
|
|
15
|
+
WORKFLOW_DESERIALIZE,
|
|
13
16
|
} from '@ai-sdk/provider-utils';
|
|
14
17
|
import { z } from 'zod/v4';
|
|
15
18
|
import {
|
|
@@ -20,6 +23,7 @@ import {
|
|
|
20
23
|
defaultOpenAICompatibleErrorStructure,
|
|
21
24
|
ProviderErrorStructure,
|
|
22
25
|
} from '../openai-compatible-error';
|
|
26
|
+
import { warnIfDeprecatedProviderOptionsKey } from '../utils/to-camel-case';
|
|
23
27
|
|
|
24
28
|
type OpenAICompatibleEmbeddingConfig = {
|
|
25
29
|
/**
|
|
@@ -34,7 +38,7 @@ type OpenAICompatibleEmbeddingConfig = {
|
|
|
34
38
|
|
|
35
39
|
provider: string;
|
|
36
40
|
url: (options: { modelId: string; path: string }) => string;
|
|
37
|
-
headers
|
|
41
|
+
headers?: () => Record<string, string | undefined>;
|
|
38
42
|
fetch?: FetchFunction;
|
|
39
43
|
errorStructure?: ProviderErrorStructure<any>;
|
|
40
44
|
};
|
|
@@ -57,6 +61,20 @@ export class OpenAICompatibleEmbeddingModel implements EmbeddingModelV4 {
|
|
|
57
61
|
return this.config.supportsParallelCalls ?? true;
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
static [WORKFLOW_SERIALIZE](model: OpenAICompatibleEmbeddingModel) {
|
|
65
|
+
return serializeModelOptions({
|
|
66
|
+
modelId: model.modelId,
|
|
67
|
+
config: model.config,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
72
|
+
modelId: string;
|
|
73
|
+
config: OpenAICompatibleEmbeddingConfig;
|
|
74
|
+
}) {
|
|
75
|
+
return new OpenAICompatibleEmbeddingModel(options.modelId, options.config);
|
|
76
|
+
}
|
|
77
|
+
|
|
60
78
|
constructor(
|
|
61
79
|
modelId: OpenAICompatibleEmbeddingModelId,
|
|
62
80
|
config: OpenAICompatibleEmbeddingConfig,
|
|
@@ -88,11 +106,19 @@ export class OpenAICompatibleEmbeddingModel implements EmbeddingModelV4 {
|
|
|
88
106
|
|
|
89
107
|
if (deprecatedOptions != null) {
|
|
90
108
|
warnings.push({
|
|
91
|
-
type: '
|
|
92
|
-
|
|
109
|
+
type: 'deprecated',
|
|
110
|
+
setting: "providerOptions key 'openai-compatible'",
|
|
111
|
+
message: "Use 'openaiCompatible' instead.",
|
|
93
112
|
});
|
|
94
113
|
}
|
|
95
114
|
|
|
115
|
+
// Warn when the raw (non-camelCase) provider name is used
|
|
116
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
117
|
+
rawName: this.providerOptionsName,
|
|
118
|
+
providerOptions,
|
|
119
|
+
warnings,
|
|
120
|
+
});
|
|
121
|
+
|
|
96
122
|
const compatibleOptions = Object.assign(
|
|
97
123
|
deprecatedOptions ?? {},
|
|
98
124
|
(await parseProviderOptions({
|
|
@@ -125,7 +151,7 @@ export class OpenAICompatibleEmbeddingModel implements EmbeddingModelV4 {
|
|
|
125
151
|
path: '/embeddings',
|
|
126
152
|
modelId: this.modelId,
|
|
127
153
|
}),
|
|
128
|
-
headers: combineHeaders(this.config.headers(), headers),
|
|
154
|
+
headers: combineHeaders(this.config.headers?.(), headers),
|
|
129
155
|
body: {
|
|
130
156
|
model: this.modelId,
|
|
131
157
|
input: values,
|