@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,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
LanguageModelV4Prompt,
|
|
3
|
-
SharedV4ProviderMetadata,
|
|
4
2
|
UnsupportedFunctionalityError,
|
|
3
|
+
type LanguageModelV4Prompt,
|
|
4
|
+
type SharedV4ProviderMetadata,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
|
-
import { OpenAICompatibleChatPrompt } from './openai-compatible-api-types';
|
|
6
|
+
import type { OpenAICompatibleChatPrompt } from './openai-compatible-api-types';
|
|
7
7
|
import {
|
|
8
8
|
convertBase64ToUint8Array,
|
|
9
9
|
convertToBase64,
|
|
10
|
+
getTopLevelMediaType,
|
|
11
|
+
resolveFullMediaType,
|
|
10
12
|
} from '@ai-sdk/provider-utils';
|
|
11
13
|
|
|
12
14
|
function getOpenAIMetadata(message: {
|
|
@@ -58,86 +60,105 @@ export function convertToOpenAICompatibleChatMessages(
|
|
|
58
60
|
return { type: 'text', text: part.text, ...partMetadata };
|
|
59
61
|
}
|
|
60
62
|
case 'file': {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
part.mediaType === 'image/*'
|
|
64
|
-
? 'image/jpeg'
|
|
65
|
-
: part.mediaType;
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
type: 'image_url',
|
|
69
|
-
image_url: {
|
|
70
|
-
url:
|
|
71
|
-
part.data instanceof URL
|
|
72
|
-
? part.data.toString()
|
|
73
|
-
: `data:${mediaType};base64,${convertToBase64(part.data)}`,
|
|
74
|
-
},
|
|
75
|
-
...partMetadata,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (part.mediaType.startsWith('audio/')) {
|
|
80
|
-
if (part.data instanceof URL) {
|
|
63
|
+
switch (part.data.type) {
|
|
64
|
+
case 'reference': {
|
|
81
65
|
throw new UnsupportedFunctionalityError({
|
|
82
|
-
functionality: '
|
|
66
|
+
functionality: 'file parts with provider references',
|
|
83
67
|
});
|
|
84
68
|
}
|
|
85
|
-
|
|
86
|
-
const format = getAudioFormat(part.mediaType);
|
|
87
|
-
if (format === null) {
|
|
69
|
+
case 'text': {
|
|
88
70
|
throw new UnsupportedFunctionalityError({
|
|
89
|
-
functionality:
|
|
71
|
+
functionality: 'text file parts',
|
|
90
72
|
});
|
|
91
73
|
}
|
|
74
|
+
case 'url':
|
|
75
|
+
case 'data': {
|
|
76
|
+
const topLevel = getTopLevelMediaType(part.mediaType);
|
|
92
77
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
78
|
+
if (topLevel === 'image') {
|
|
79
|
+
return {
|
|
80
|
+
type: 'image_url',
|
|
81
|
+
image_url: {
|
|
82
|
+
url:
|
|
83
|
+
part.data.type === 'url'
|
|
84
|
+
? part.data.url.toString()
|
|
85
|
+
: `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`,
|
|
86
|
+
},
|
|
87
|
+
...partMetadata,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
102
90
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
91
|
+
if (topLevel === 'audio') {
|
|
92
|
+
if (part.data.type === 'url') {
|
|
93
|
+
throw new UnsupportedFunctionalityError({
|
|
94
|
+
functionality: 'audio file parts with URLs',
|
|
95
|
+
});
|
|
96
|
+
}
|
|
109
97
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
};
|
|
118
|
-
}
|
|
98
|
+
const fullMediaType = resolveFullMediaType({ part });
|
|
99
|
+
const format = getAudioFormat(fullMediaType);
|
|
100
|
+
if (format === null) {
|
|
101
|
+
throw new UnsupportedFunctionalityError({
|
|
102
|
+
functionality: `audio media type ${fullMediaType}`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
119
105
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
106
|
+
return {
|
|
107
|
+
type: 'input_audio',
|
|
108
|
+
input_audio: {
|
|
109
|
+
data: convertToBase64(part.data.data),
|
|
110
|
+
format,
|
|
111
|
+
},
|
|
112
|
+
...partMetadata,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
129
115
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
116
|
+
if (topLevel === 'application') {
|
|
117
|
+
if (part.data.type === 'url') {
|
|
118
|
+
throw new UnsupportedFunctionalityError({
|
|
119
|
+
functionality: 'PDF file parts with URLs',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const fullMediaType = resolveFullMediaType({ part });
|
|
124
|
+
if (fullMediaType !== 'application/pdf') {
|
|
125
|
+
throw new UnsupportedFunctionalityError({
|
|
126
|
+
functionality: `file part media type ${fullMediaType}`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
type: 'file',
|
|
132
|
+
file: {
|
|
133
|
+
filename: part.filename ?? 'document.pdf',
|
|
134
|
+
file_data: `data:application/pdf;base64,${convertToBase64(part.data.data)}`,
|
|
135
|
+
},
|
|
136
|
+
...partMetadata,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (topLevel === 'text') {
|
|
141
|
+
const textContent =
|
|
142
|
+
part.data.type === 'url'
|
|
143
|
+
? part.data.url.toString()
|
|
144
|
+
: typeof part.data.data === 'string'
|
|
145
|
+
? new TextDecoder().decode(
|
|
146
|
+
convertBase64ToUint8Array(part.data.data),
|
|
147
|
+
)
|
|
148
|
+
: new TextDecoder().decode(part.data.data);
|
|
136
149
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
return {
|
|
151
|
+
type: 'text',
|
|
152
|
+
text: textContent,
|
|
153
|
+
...partMetadata,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
throw new UnsupportedFunctionalityError({
|
|
158
|
+
functionality: `file part media type ${part.mediaType}`,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
141
162
|
}
|
|
142
163
|
}
|
|
143
164
|
}),
|
|
@@ -202,7 +223,7 @@ export function convertToOpenAICompatibleChatMessages(
|
|
|
202
223
|
|
|
203
224
|
messages.push({
|
|
204
225
|
role: 'assistant',
|
|
205
|
-
content: text,
|
|
226
|
+
content: toolCalls.length > 0 ? text || null : text,
|
|
206
227
|
...(reasoning.length > 0 ? { reasoning_content: reasoning } : {}),
|
|
207
228
|
tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
208
229
|
...metadata,
|
|
@@ -226,7 +247,7 @@ export function convertToOpenAICompatibleChatMessages(
|
|
|
226
247
|
contentValue = output.value;
|
|
227
248
|
break;
|
|
228
249
|
case 'execution-denied':
|
|
229
|
-
contentValue = output.reason ?? 'Tool execution denied.';
|
|
250
|
+
contentValue = output.reason ?? 'Tool call execution denied.';
|
|
230
251
|
break;
|
|
231
252
|
case 'content':
|
|
232
253
|
case 'json':
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { JSONValue } from '@ai-sdk/provider';
|
|
1
|
+
import type { JSONValue } from '@ai-sdk/provider';
|
|
2
2
|
|
|
3
3
|
export type OpenAICompatibleChatPrompt = Array<OpenAICompatibleMessage>;
|
|
4
4
|
|
|
@@ -20,8 +20,7 @@ export interface OpenAICompatibleSystemMessage extends JsonRecord {
|
|
|
20
20
|
content: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export interface OpenAICompatibleUserMessage
|
|
24
|
-
extends JsonRecord<OpenAICompatibleContentPart> {
|
|
23
|
+
export interface OpenAICompatibleUserMessage extends JsonRecord<OpenAICompatibleContentPart> {
|
|
25
24
|
role: 'user';
|
|
26
25
|
content: string | Array<OpenAICompatibleContentPart>;
|
|
27
26
|
}
|
|
@@ -54,8 +53,7 @@ export interface OpenAICompatibleContentPartFile extends JsonRecord {
|
|
|
54
53
|
file: { filename: string; file_data: string };
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
export interface OpenAICompatibleAssistantMessage
|
|
58
|
-
extends JsonRecord<OpenAICompatibleMessageToolCall> {
|
|
56
|
+
export interface OpenAICompatibleAssistantMessage extends JsonRecord<OpenAICompatibleMessageToolCall> {
|
|
59
57
|
role: 'assistant';
|
|
60
58
|
content?: string | null;
|
|
61
59
|
reasoning_content?: string;
|