@ai-sdk/open-responses 0.0.0-6b196531-20260710185421
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 +606 -0
- package/LICENSE +13 -0
- package/README.md +57 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +729 -0
- package/dist/index.js.map +1 -0
- package/docs/06-open-responses.mdx +238 -0
- package/package.json +76 -0
- package/src/index.ts +11 -0
- package/src/open-responses-provider.ts +100 -0
- package/src/responses/convert-to-open-responses-input.ts +253 -0
- package/src/responses/map-open-responses-finish-reason.ts +21 -0
- package/src/responses/open-responses-api.ts +1238 -0
- package/src/responses/open-responses-config.ts +10 -0
- package/src/responses/open-responses-language-model-options.ts +22 -0
- package/src/responses/open-responses-language-model.ts +557 -0
- package/src/version.ts +6 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UnsupportedFunctionalityError,
|
|
3
|
+
type LanguageModelV4Prompt,
|
|
4
|
+
type SharedV4Warning,
|
|
5
|
+
} from '@ai-sdk/provider';
|
|
6
|
+
import {
|
|
7
|
+
convertToBase64,
|
|
8
|
+
getTopLevelMediaType,
|
|
9
|
+
resolveFullMediaType,
|
|
10
|
+
} from '@ai-sdk/provider-utils';
|
|
11
|
+
import type {
|
|
12
|
+
FunctionCallItemParam,
|
|
13
|
+
FunctionCallOutputItemParam,
|
|
14
|
+
InputFileContentParam,
|
|
15
|
+
InputImageContentParam,
|
|
16
|
+
InputTextContentParam,
|
|
17
|
+
OpenResponsesRequestBody,
|
|
18
|
+
OutputTextContentParam,
|
|
19
|
+
RefusalContentParam,
|
|
20
|
+
} from './open-responses-api';
|
|
21
|
+
|
|
22
|
+
export async function convertToOpenResponsesInput({
|
|
23
|
+
prompt,
|
|
24
|
+
}: {
|
|
25
|
+
prompt: LanguageModelV4Prompt;
|
|
26
|
+
}): Promise<{
|
|
27
|
+
input: OpenResponsesRequestBody['input'];
|
|
28
|
+
instructions: string | undefined;
|
|
29
|
+
warnings: Array<SharedV4Warning>;
|
|
30
|
+
}> {
|
|
31
|
+
const input: OpenResponsesRequestBody['input'] = [];
|
|
32
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
33
|
+
const systemMessages: string[] = [];
|
|
34
|
+
|
|
35
|
+
for (const { role, content } of prompt) {
|
|
36
|
+
switch (role) {
|
|
37
|
+
case 'system': {
|
|
38
|
+
systemMessages.push(content);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
case 'user': {
|
|
43
|
+
const userContent: Array<
|
|
44
|
+
InputTextContentParam | InputImageContentParam | InputFileContentParam
|
|
45
|
+
> = [];
|
|
46
|
+
|
|
47
|
+
for (const part of content) {
|
|
48
|
+
switch (part.type) {
|
|
49
|
+
case 'text': {
|
|
50
|
+
userContent.push({ type: 'input_text', text: part.text });
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case 'file': {
|
|
54
|
+
switch (part.data.type) {
|
|
55
|
+
case 'reference': {
|
|
56
|
+
throw new UnsupportedFunctionalityError({
|
|
57
|
+
functionality: 'file parts with provider references',
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
case 'text': {
|
|
61
|
+
throw new UnsupportedFunctionalityError({
|
|
62
|
+
functionality: 'text file parts',
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
case 'url':
|
|
66
|
+
case 'data': {
|
|
67
|
+
const topLevel = getTopLevelMediaType(part.mediaType);
|
|
68
|
+
|
|
69
|
+
if (topLevel === 'image') {
|
|
70
|
+
userContent.push({
|
|
71
|
+
type: 'input_image',
|
|
72
|
+
...(part.data.type === 'url'
|
|
73
|
+
? { image_url: part.data.url.toString() }
|
|
74
|
+
: {
|
|
75
|
+
image_url: `data:${resolveFullMediaType({ part })};base64,${convertToBase64(part.data.data)}`,
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
} else if (part.data.type === 'url') {
|
|
79
|
+
userContent.push({
|
|
80
|
+
type: 'input_file',
|
|
81
|
+
file_url: part.data.url.toString(),
|
|
82
|
+
});
|
|
83
|
+
} else {
|
|
84
|
+
const fullMediaType = resolveFullMediaType({ part });
|
|
85
|
+
userContent.push({
|
|
86
|
+
type: 'input_file',
|
|
87
|
+
filename: part.filename ?? 'data',
|
|
88
|
+
file_data: `data:${fullMediaType};base64,${convertToBase64(part.data.data)}`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
input.push({ type: 'message', role: 'user', content: userContent });
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
case 'assistant': {
|
|
105
|
+
const assistantContent: Array<
|
|
106
|
+
OutputTextContentParam | RefusalContentParam
|
|
107
|
+
> = [];
|
|
108
|
+
const toolCalls: Array<FunctionCallItemParam> = [];
|
|
109
|
+
|
|
110
|
+
for (const part of content) {
|
|
111
|
+
switch (part.type) {
|
|
112
|
+
case 'text': {
|
|
113
|
+
assistantContent.push({ type: 'output_text', text: part.text });
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'tool-call': {
|
|
117
|
+
const argumentsValue =
|
|
118
|
+
typeof part.input === 'string'
|
|
119
|
+
? part.input
|
|
120
|
+
: JSON.stringify(part.input);
|
|
121
|
+
toolCalls.push({
|
|
122
|
+
type: 'function_call',
|
|
123
|
+
call_id: part.toolCallId,
|
|
124
|
+
name: part.toolName,
|
|
125
|
+
arguments: argumentsValue,
|
|
126
|
+
});
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Push assistant message with text content if any
|
|
133
|
+
if (assistantContent.length > 0) {
|
|
134
|
+
input.push({
|
|
135
|
+
type: 'message',
|
|
136
|
+
role: 'assistant',
|
|
137
|
+
content: assistantContent,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Push function calls as separate items
|
|
142
|
+
for (const toolCall of toolCalls) {
|
|
143
|
+
input.push(toolCall);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
case 'tool': {
|
|
150
|
+
for (const part of content) {
|
|
151
|
+
if (part.type === 'tool-result') {
|
|
152
|
+
const output = part.output;
|
|
153
|
+
let contentValue: FunctionCallOutputItemParam['output'];
|
|
154
|
+
|
|
155
|
+
switch (output.type) {
|
|
156
|
+
case 'text':
|
|
157
|
+
case 'error-text':
|
|
158
|
+
contentValue = output.value;
|
|
159
|
+
break;
|
|
160
|
+
case 'execution-denied':
|
|
161
|
+
contentValue = output.reason ?? 'Tool call execution denied.';
|
|
162
|
+
break;
|
|
163
|
+
case 'json':
|
|
164
|
+
case 'error-json':
|
|
165
|
+
contentValue = JSON.stringify(output.value);
|
|
166
|
+
break;
|
|
167
|
+
case 'content': {
|
|
168
|
+
const contentParts: Array<
|
|
169
|
+
| InputTextContentParam
|
|
170
|
+
| InputImageContentParam
|
|
171
|
+
| InputFileContentParam
|
|
172
|
+
> = [];
|
|
173
|
+
for (const item of output.value) {
|
|
174
|
+
switch (item.type) {
|
|
175
|
+
case 'text': {
|
|
176
|
+
contentParts.push({
|
|
177
|
+
type: 'input_text',
|
|
178
|
+
text: item.text,
|
|
179
|
+
});
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case 'file': {
|
|
183
|
+
const topLevel = getTopLevelMediaType(item.mediaType);
|
|
184
|
+
|
|
185
|
+
if (item.data.type === 'data') {
|
|
186
|
+
const fullMediaType = resolveFullMediaType({
|
|
187
|
+
part: item,
|
|
188
|
+
});
|
|
189
|
+
if (topLevel === 'image') {
|
|
190
|
+
contentParts.push({
|
|
191
|
+
type: 'input_image',
|
|
192
|
+
image_url: `data:${fullMediaType};base64,${convertToBase64(item.data.data)}`,
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
contentParts.push({
|
|
196
|
+
type: 'input_file',
|
|
197
|
+
filename: item.filename ?? 'data',
|
|
198
|
+
file_data: `data:${fullMediaType};base64,${convertToBase64(item.data.data)}`,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
} else if (item.data.type === 'url') {
|
|
202
|
+
if (topLevel === 'image') {
|
|
203
|
+
contentParts.push({
|
|
204
|
+
type: 'input_image',
|
|
205
|
+
image_url: item.data.url.toString(),
|
|
206
|
+
});
|
|
207
|
+
} else {
|
|
208
|
+
contentParts.push({
|
|
209
|
+
type: 'input_file',
|
|
210
|
+
file_url: item.data.url.toString(),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
warnings.push({
|
|
215
|
+
type: 'other',
|
|
216
|
+
message: `unsupported tool content part type: ${item.type} with data type: ${item.data.type}`,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
default: {
|
|
222
|
+
warnings.push({
|
|
223
|
+
type: 'other',
|
|
224
|
+
message: `unsupported tool content part type: ${(item as { type: string }).type}`,
|
|
225
|
+
});
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
contentValue = contentParts;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
input.push({
|
|
236
|
+
type: 'function_call_output',
|
|
237
|
+
call_id: part.toolCallId,
|
|
238
|
+
output: contentValue,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
input,
|
|
249
|
+
instructions:
|
|
250
|
+
systemMessages.length > 0 ? systemMessages.join('\n') : undefined,
|
|
251
|
+
warnings,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LanguageModelV4FinishReason } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
export function mapOpenResponsesFinishReason({
|
|
4
|
+
finishReason,
|
|
5
|
+
hasToolCalls,
|
|
6
|
+
}: {
|
|
7
|
+
finishReason: string | null | undefined;
|
|
8
|
+
hasToolCalls: boolean;
|
|
9
|
+
}): LanguageModelV4FinishReason['unified'] {
|
|
10
|
+
switch (finishReason) {
|
|
11
|
+
case undefined:
|
|
12
|
+
case null:
|
|
13
|
+
return hasToolCalls ? 'tool-calls' : 'stop';
|
|
14
|
+
case 'max_output_tokens':
|
|
15
|
+
return 'length';
|
|
16
|
+
case 'content_filter':
|
|
17
|
+
return 'content-filter';
|
|
18
|
+
default:
|
|
19
|
+
return hasToolCalls ? 'tool-calls' : 'other';
|
|
20
|
+
}
|
|
21
|
+
}
|