@ai-sdk/openai-compatible 3.0.0-beta.4 → 3.0.0-beta.57
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 +440 -8
- package/README.md +2 -0
- package/dist/index.d.ts +69 -8
- package/dist/index.js +548 -428
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +20 -2
- package/dist/internal/index.js +91 -91
- package/dist/internal/index.js.map +1 -1
- package/docs/index.mdx +1 -0
- package/package.json +16 -17
- package/src/chat/convert-openai-compatible-chat-usage.ts +1 -1
- package/src/chat/convert-to-openai-compatible-chat-messages.ts +94 -73
- package/src/chat/map-openai-compatible-finish-reason.ts +1 -1
- package/src/chat/openai-compatible-api-types.ts +3 -5
- package/src/chat/openai-compatible-chat-language-model.ts +205 -191
- package/src/chat/openai-compatible-metadata-extractor.ts +1 -1
- package/src/chat/openai-compatible-prepare-tools.ts +2 -3
- package/src/completion/convert-openai-compatible-completion-usage.ts +1 -1
- package/src/completion/convert-to-openai-compatible-completion-prompt.ts +1 -2
- package/src/completion/map-openai-compatible-finish-reason.ts +1 -1
- package/src/completion/openai-compatible-completion-language-model.ts +52 -17
- package/src/embedding/openai-compatible-embedding-model.ts +36 -10
- package/src/image/openai-compatible-image-model.ts +35 -13
- package/src/index.ts +3 -3
- package/src/openai-compatible-error.ts +1 -2
- package/src/openai-compatible-provider.ts +18 -5
- 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
- /package/src/chat/{openai-compatible-chat-options.ts → openai-compatible-chat-language-model-options.ts} +0 -0
- /package/src/completion/{openai-compatible-completion-options.ts → openai-compatible-completion-language-model-options.ts} +0 -0
- /package/src/embedding/{openai-compatible-embedding-options.ts → openai-compatible-embedding-model-options.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
APICallError,
|
|
3
3
|
LanguageModelV4,
|
|
4
4
|
LanguageModelV4CallOptions,
|
|
@@ -14,30 +14,36 @@ import {
|
|
|
14
14
|
createEventSourceResponseHandler,
|
|
15
15
|
createJsonErrorResponseHandler,
|
|
16
16
|
createJsonResponseHandler,
|
|
17
|
-
FetchFunction,
|
|
18
17
|
parseProviderOptions,
|
|
19
|
-
ParseResult,
|
|
20
18
|
postJsonToApi,
|
|
21
|
-
|
|
19
|
+
serializeModelOptions,
|
|
20
|
+
WORKFLOW_SERIALIZE,
|
|
21
|
+
WORKFLOW_DESERIALIZE,
|
|
22
|
+
type FetchFunction,
|
|
23
|
+
type ParseResult,
|
|
24
|
+
type ResponseHandler,
|
|
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
|
-
ProviderErrorStructure,
|
|
33
|
+
type ProviderErrorStructure,
|
|
27
34
|
} from '../openai-compatible-error';
|
|
28
35
|
import { convertOpenAICompatibleCompletionUsage } from './convert-openai-compatible-completion-usage';
|
|
29
36
|
import { convertToOpenAICompatibleCompletionPrompt } from './convert-to-openai-compatible-completion-prompt';
|
|
30
37
|
import { getResponseMetadata } from './get-response-metadata';
|
|
31
38
|
import { mapOpenAICompatibleFinishReason } from './map-openai-compatible-finish-reason';
|
|
32
39
|
import {
|
|
33
|
-
OpenAICompatibleCompletionModelId,
|
|
34
40
|
openaiCompatibleLanguageModelCompletionOptions,
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
type OpenAICompatibleCompletionModelId,
|
|
42
|
+
} from './openai-compatible-completion-language-model-options';
|
|
37
43
|
type OpenAICompatibleCompletionConfig = {
|
|
38
44
|
provider: string;
|
|
39
45
|
includeUsage?: boolean;
|
|
40
|
-
headers
|
|
46
|
+
headers?: () => Record<string, string | undefined>;
|
|
41
47
|
url: (options: { modelId: string; path: string }) => string;
|
|
42
48
|
fetch?: FetchFunction;
|
|
43
49
|
errorStructure?: ProviderErrorStructure<any>;
|
|
@@ -48,9 +54,7 @@ type OpenAICompatibleCompletionConfig = {
|
|
|
48
54
|
supportedUrls?: () => LanguageModelV4['supportedUrls'];
|
|
49
55
|
};
|
|
50
56
|
|
|
51
|
-
export class OpenAICompatibleCompletionLanguageModel
|
|
52
|
-
implements LanguageModelV4
|
|
53
|
-
{
|
|
57
|
+
export class OpenAICompatibleCompletionLanguageModel implements LanguageModelV4 {
|
|
54
58
|
readonly specificationVersion = 'v4';
|
|
55
59
|
|
|
56
60
|
readonly modelId: OpenAICompatibleCompletionModelId;
|
|
@@ -58,6 +62,23 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
58
62
|
private readonly failedResponseHandler: ResponseHandler<APICallError>;
|
|
59
63
|
private readonly chunkSchema; // type inferred via constructor
|
|
60
64
|
|
|
65
|
+
static [WORKFLOW_SERIALIZE](model: OpenAICompatibleCompletionLanguageModel) {
|
|
66
|
+
return serializeModelOptions({
|
|
67
|
+
modelId: model.modelId,
|
|
68
|
+
config: model.config,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
73
|
+
modelId: string;
|
|
74
|
+
config: OpenAICompatibleCompletionConfig;
|
|
75
|
+
}) {
|
|
76
|
+
return new OpenAICompatibleCompletionLanguageModel(
|
|
77
|
+
options.modelId,
|
|
78
|
+
options.config,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
61
82
|
constructor(
|
|
62
83
|
modelId: OpenAICompatibleCompletionModelId,
|
|
63
84
|
config: OpenAICompatibleCompletionConfig,
|
|
@@ -103,13 +124,26 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
103
124
|
}: LanguageModelV4CallOptions) {
|
|
104
125
|
const warnings: SharedV4Warning[] = [];
|
|
105
126
|
|
|
106
|
-
//
|
|
107
|
-
|
|
127
|
+
// Warn when the raw (non-camelCase) provider name is used
|
|
128
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
129
|
+
rawName: this.providerOptionsName,
|
|
130
|
+
providerOptions,
|
|
131
|
+
warnings,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Parse provider options (support both raw and camelCase keys)
|
|
135
|
+
const completionOptions = Object.assign(
|
|
108
136
|
(await parseProviderOptions({
|
|
109
137
|
provider: this.providerOptionsName,
|
|
110
138
|
providerOptions,
|
|
111
139
|
schema: openaiCompatibleLanguageModelCompletionOptions,
|
|
112
|
-
})) ?? {}
|
|
140
|
+
})) ?? {},
|
|
141
|
+
(await parseProviderOptions({
|
|
142
|
+
provider: toCamelCase(this.providerOptionsName),
|
|
143
|
+
providerOptions,
|
|
144
|
+
schema: openaiCompatibleLanguageModelCompletionOptions,
|
|
145
|
+
})) ?? {},
|
|
146
|
+
);
|
|
113
147
|
|
|
114
148
|
if (topK != null) {
|
|
115
149
|
warnings.push({ type: 'unsupported', feature: 'topK' });
|
|
@@ -155,6 +189,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
155
189
|
presence_penalty: presencePenalty,
|
|
156
190
|
seed,
|
|
157
191
|
...providerOptions?.[this.providerOptionsName],
|
|
192
|
+
...providerOptions?.[toCamelCase(this.providerOptionsName)],
|
|
158
193
|
|
|
159
194
|
// prompt:
|
|
160
195
|
prompt: completionPrompt,
|
|
@@ -180,7 +215,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
180
215
|
path: '/completions',
|
|
181
216
|
modelId: this.modelId,
|
|
182
217
|
}),
|
|
183
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
218
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
184
219
|
body: args,
|
|
185
220
|
failedResponseHandler: this.failedResponseHandler,
|
|
186
221
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -235,7 +270,7 @@ export class OpenAICompatibleCompletionLanguageModel
|
|
|
235
270
|
path: '/completions',
|
|
236
271
|
modelId: this.modelId,
|
|
237
272
|
}),
|
|
238
|
-
headers: combineHeaders(this.config.headers(), options.headers),
|
|
273
|
+
headers: combineHeaders(this.config.headers?.(), options.headers),
|
|
239
274
|
body,
|
|
240
275
|
failedResponseHandler: this.failedResponseHandler,
|
|
241
276
|
successfulResponseHandler: createEventSourceResponseHandler(
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
|
-
EmbeddingModelV4,
|
|
3
|
-
SharedV4Warning,
|
|
4
2
|
TooManyEmbeddingValuesForCallError,
|
|
3
|
+
type EmbeddingModelV4,
|
|
4
|
+
type SharedV4Warning,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import {
|
|
7
7
|
combineHeaders,
|
|
8
8
|
createJsonErrorResponseHandler,
|
|
9
9
|
createJsonResponseHandler,
|
|
10
|
-
FetchFunction,
|
|
11
10
|
parseProviderOptions,
|
|
12
11
|
postJsonToApi,
|
|
12
|
+
serializeModelOptions,
|
|
13
|
+
WORKFLOW_SERIALIZE,
|
|
14
|
+
WORKFLOW_DESERIALIZE,
|
|
15
|
+
type FetchFunction,
|
|
13
16
|
} from '@ai-sdk/provider-utils';
|
|
14
17
|
import { z } from 'zod/v4';
|
|
15
18
|
import {
|
|
16
|
-
OpenAICompatibleEmbeddingModelId,
|
|
17
19
|
openaiCompatibleEmbeddingModelOptions,
|
|
18
|
-
|
|
20
|
+
type OpenAICompatibleEmbeddingModelId,
|
|
21
|
+
} from './openai-compatible-embedding-model-options';
|
|
19
22
|
import {
|
|
20
23
|
defaultOpenAICompatibleErrorStructure,
|
|
21
|
-
ProviderErrorStructure,
|
|
24
|
+
type 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,
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
ImageModelV4,
|
|
3
3
|
ImageModelV4File,
|
|
4
4
|
SharedV4ProviderOptions,
|
|
5
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,
|
|
@@ -11,20 +15,23 @@ import {
|
|
|
11
15
|
createJsonErrorResponseHandler,
|
|
12
16
|
createJsonResponseHandler,
|
|
13
17
|
downloadBlob,
|
|
14
|
-
FetchFunction,
|
|
15
18
|
postFormDataToApi,
|
|
16
19
|
postJsonToApi,
|
|
20
|
+
serializeModelOptions,
|
|
21
|
+
WORKFLOW_SERIALIZE,
|
|
22
|
+
WORKFLOW_DESERIALIZE,
|
|
23
|
+
type FetchFunction,
|
|
17
24
|
} from '@ai-sdk/provider-utils';
|
|
18
25
|
import { z } from 'zod/v4';
|
|
19
26
|
import {
|
|
20
27
|
defaultOpenAICompatibleErrorStructure,
|
|
21
|
-
ProviderErrorStructure,
|
|
28
|
+
type ProviderErrorStructure,
|
|
22
29
|
} from '../openai-compatible-error';
|
|
23
|
-
import { OpenAICompatibleImageModelId } from './openai-compatible-image-settings';
|
|
30
|
+
import type { OpenAICompatibleImageModelId } from './openai-compatible-image-settings';
|
|
24
31
|
|
|
25
32
|
export type OpenAICompatibleImageModelConfig = {
|
|
26
33
|
provider: string;
|
|
27
|
-
headers
|
|
34
|
+
headers?: () => Record<string, string | undefined>;
|
|
28
35
|
url: (options: { modelId: string; path: string }) => string;
|
|
29
36
|
fetch?: FetchFunction;
|
|
30
37
|
errorStructure?: ProviderErrorStructure<any>;
|
|
@@ -48,15 +55,34 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
48
55
|
return this.config.provider.split('.')[0].trim();
|
|
49
56
|
}
|
|
50
57
|
|
|
58
|
+
static [WORKFLOW_SERIALIZE](model: OpenAICompatibleImageModel) {
|
|
59
|
+
return serializeModelOptions({
|
|
60
|
+
modelId: model.modelId,
|
|
61
|
+
config: model.config,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
66
|
+
modelId: string;
|
|
67
|
+
config: OpenAICompatibleImageModelConfig;
|
|
68
|
+
}) {
|
|
69
|
+
return new OpenAICompatibleImageModel(options.modelId, options.config);
|
|
70
|
+
}
|
|
71
|
+
|
|
51
72
|
constructor(
|
|
52
73
|
readonly modelId: OpenAICompatibleImageModelId,
|
|
53
74
|
private readonly config: OpenAICompatibleImageModelConfig,
|
|
54
75
|
) {}
|
|
55
76
|
|
|
56
|
-
// TODO: deprecate non-camelCase keys and remove in future major version
|
|
57
77
|
private getArgs(
|
|
58
78
|
providerOptions: SharedV4ProviderOptions,
|
|
79
|
+
warnings: SharedV4Warning[],
|
|
59
80
|
): Record<string, unknown> {
|
|
81
|
+
warnIfDeprecatedProviderOptionsKey({
|
|
82
|
+
rawName: this.providerOptionsKey,
|
|
83
|
+
providerOptions,
|
|
84
|
+
warnings,
|
|
85
|
+
});
|
|
60
86
|
return {
|
|
61
87
|
...providerOptions[this.providerOptionsKey],
|
|
62
88
|
...providerOptions[toCamelCase(this.providerOptionsKey)],
|
|
@@ -94,7 +120,7 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
94
120
|
|
|
95
121
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
96
122
|
|
|
97
|
-
const args = this.getArgs(providerOptions);
|
|
123
|
+
const args = this.getArgs(providerOptions, warnings);
|
|
98
124
|
|
|
99
125
|
// Image editing mode - use form data and /images/edits endpoint
|
|
100
126
|
if (files != null && files.length > 0) {
|
|
@@ -103,7 +129,7 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
103
129
|
path: '/images/edits',
|
|
104
130
|
modelId: this.modelId,
|
|
105
131
|
}),
|
|
106
|
-
headers: combineHeaders(this.config.headers(), headers),
|
|
132
|
+
headers: combineHeaders(this.config.headers?.(), headers),
|
|
107
133
|
formData: convertToFormData<OpenAICompatibleFormDataInput>({
|
|
108
134
|
model: this.modelId,
|
|
109
135
|
prompt,
|
|
@@ -140,7 +166,7 @@ export class OpenAICompatibleImageModel implements ImageModelV4 {
|
|
|
140
166
|
path: '/images/generations',
|
|
141
167
|
modelId: this.modelId,
|
|
142
168
|
}),
|
|
143
|
-
headers: combineHeaders(this.config.headers(), headers),
|
|
169
|
+
headers: combineHeaders(this.config.headers?.(), headers),
|
|
144
170
|
body: {
|
|
145
171
|
model: this.modelId,
|
|
146
172
|
prompt,
|
|
@@ -199,7 +225,3 @@ async function fileToBlob(file: ImageModelV4File): Promise<Blob> {
|
|
|
199
225
|
|
|
200
226
|
return new Blob([data as BlobPart], { type: file.mediaType });
|
|
201
227
|
}
|
|
202
|
-
|
|
203
|
-
function toCamelCase(str: string): string {
|
|
204
|
-
return str.replace(/[_-]([a-z])/g, g => g[1].toUpperCase());
|
|
205
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -4,21 +4,21 @@ export type {
|
|
|
4
4
|
OpenAICompatibleLanguageModelChatOptions,
|
|
5
5
|
/** @deprecated Use `OpenAICompatibleLanguageModelChatOptions` instead. */
|
|
6
6
|
OpenAICompatibleLanguageModelChatOptions as OpenAICompatibleProviderOptions,
|
|
7
|
-
} from './chat/openai-compatible-chat-options';
|
|
7
|
+
} from './chat/openai-compatible-chat-language-model-options';
|
|
8
8
|
export { OpenAICompatibleCompletionLanguageModel } from './completion/openai-compatible-completion-language-model';
|
|
9
9
|
export type {
|
|
10
10
|
OpenAICompatibleCompletionModelId,
|
|
11
11
|
OpenAICompatibleLanguageModelCompletionOptions,
|
|
12
12
|
/** @deprecated Use `OpenAICompatibleLanguageModelCompletionOptions` instead. */
|
|
13
13
|
OpenAICompatibleLanguageModelCompletionOptions as OpenAICompatibleCompletionProviderOptions,
|
|
14
|
-
} from './completion/openai-compatible-completion-options';
|
|
14
|
+
} from './completion/openai-compatible-completion-language-model-options';
|
|
15
15
|
export { OpenAICompatibleEmbeddingModel } from './embedding/openai-compatible-embedding-model';
|
|
16
16
|
export type {
|
|
17
17
|
OpenAICompatibleEmbeddingModelId,
|
|
18
18
|
OpenAICompatibleEmbeddingModelOptions,
|
|
19
19
|
/** @deprecated Use `OpenAICompatibleEmbeddingModelOptions` instead. */
|
|
20
20
|
OpenAICompatibleEmbeddingModelOptions as OpenAICompatibleEmbeddingProviderOptions,
|
|
21
|
-
} from './embedding/openai-compatible-embedding-options';
|
|
21
|
+
} from './embedding/openai-compatible-embedding-model-options';
|
|
22
22
|
export { OpenAICompatibleImageModel } from './image/openai-compatible-image-model';
|
|
23
23
|
export type {
|
|
24
24
|
OpenAICompatibleErrorData,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
EmbeddingModelV4,
|
|
3
3
|
ImageModelV4,
|
|
4
4
|
LanguageModelV4,
|
|
5
5
|
ProviderV4,
|
|
6
6
|
} from '@ai-sdk/provider';
|
|
7
7
|
import {
|
|
8
|
-
FetchFunction,
|
|
9
8
|
withoutTrailingSlash,
|
|
10
9
|
withUserAgentSuffix,
|
|
10
|
+
type FetchFunction,
|
|
11
11
|
} from '@ai-sdk/provider-utils';
|
|
12
12
|
import {
|
|
13
|
-
OpenAICompatibleChatConfig,
|
|
14
13
|
OpenAICompatibleChatLanguageModel,
|
|
14
|
+
type OpenAICompatibleChatConfig,
|
|
15
15
|
} from './chat/openai-compatible-chat-language-model';
|
|
16
|
-
import { MetadataExtractor } from './chat/openai-compatible-metadata-extractor';
|
|
16
|
+
import type { MetadataExtractor } from './chat/openai-compatible-metadata-extractor';
|
|
17
17
|
import { OpenAICompatibleCompletionLanguageModel } from './completion/openai-compatible-completion-language-model';
|
|
18
18
|
import { OpenAICompatibleEmbeddingModel } from './embedding/openai-compatible-embedding-model';
|
|
19
19
|
import { OpenAICompatibleImageModel } from './image/openai-compatible-image-model';
|
|
@@ -24,7 +24,7 @@ export interface OpenAICompatibleProvider<
|
|
|
24
24
|
COMPLETION_MODEL_IDS extends string = string,
|
|
25
25
|
EMBEDDING_MODEL_IDS extends string = string,
|
|
26
26
|
IMAGE_MODEL_IDS extends string = string,
|
|
27
|
-
> extends
|
|
27
|
+
> extends ProviderV4 {
|
|
28
28
|
(modelId: CHAT_MODEL_IDS): LanguageModelV4;
|
|
29
29
|
|
|
30
30
|
languageModel(
|
|
@@ -104,6 +104,17 @@ export interface OpenAICompatibleProviderSettings {
|
|
|
104
104
|
* or provider-specific metrics from both streaming and non-streaming responses.
|
|
105
105
|
*/
|
|
106
106
|
metadataExtractor?: MetadataExtractor;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The supported URLs for chat models.
|
|
110
|
+
*/
|
|
111
|
+
supportedUrls?: OpenAICompatibleChatConfig['supportedUrls'];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Optional usage converter for providers with token accounting semantics that
|
|
115
|
+
* differ from the default OpenAI-compatible shape.
|
|
116
|
+
*/
|
|
117
|
+
convertUsage?: OpenAICompatibleChatConfig['convertUsage'];
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
/**
|
|
@@ -161,8 +172,10 @@ export function createOpenAICompatible<
|
|
|
161
172
|
...getCommonModelConfig('chat'),
|
|
162
173
|
includeUsage: options.includeUsage,
|
|
163
174
|
supportsStructuredOutputs: options.supportsStructuredOutputs,
|
|
175
|
+
supportedUrls: options.supportedUrls,
|
|
164
176
|
transformRequestBody: options.transformRequestBody,
|
|
165
177
|
metadataExtractor: options.metadataExtractor,
|
|
178
|
+
convertUsage: options.convertUsage,
|
|
166
179
|
});
|
|
167
180
|
|
|
168
181
|
const createCompletionModel = (modelId: COMPLETION_MODEL_IDS) =>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { SharedV4Warning } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
export function toCamelCase(str: string): string {
|
|
4
|
+
return str.replace(/[_-]([a-z])/g, g => g[1].toUpperCase());
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
Resolves which key to use for providerMetadata based on what the caller
|
|
9
|
+
passed in providerOptions. Returns the camelCase variant when the caller
|
|
10
|
+
supplied it, otherwise falls back to the raw name.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveProviderOptionsKey(
|
|
13
|
+
rawName: string,
|
|
14
|
+
providerOptions: Record<string, unknown> | undefined,
|
|
15
|
+
): string {
|
|
16
|
+
const camelName = toCamelCase(rawName);
|
|
17
|
+
if (camelName !== rawName && providerOptions?.[camelName] != null) {
|
|
18
|
+
return camelName;
|
|
19
|
+
}
|
|
20
|
+
return rawName;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
Pushes a deprecation warning when the user supplies providerOptions under a non-camelCase key
|
|
25
|
+
*/
|
|
26
|
+
export function warnIfDeprecatedProviderOptionsKey({
|
|
27
|
+
rawName,
|
|
28
|
+
providerOptions,
|
|
29
|
+
warnings,
|
|
30
|
+
}: {
|
|
31
|
+
rawName: string;
|
|
32
|
+
providerOptions: Record<string, unknown> | undefined;
|
|
33
|
+
warnings: SharedV4Warning[];
|
|
34
|
+
}): void {
|
|
35
|
+
const camelName = toCamelCase(rawName);
|
|
36
|
+
if (camelName !== rawName && providerOptions?.[rawName] != null) {
|
|
37
|
+
warnings.push({
|
|
38
|
+
type: 'deprecated',
|
|
39
|
+
setting: `providerOptions key '${rawName}'`,
|
|
40
|
+
message: `Use '${camelName}' instead.`,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|