@ai-sdk/openai 4.0.91 → 4.0.92
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 +13 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +178 -96
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +10 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +231 -149
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +19 -0
- package/package.json +3 -3
- package/src/responses/convert-to-openai-responses-input.ts +89 -0
- package/src/responses/map-openai-responses-annotation.ts +75 -0
- package/src/responses/openai-responses-api.ts +8 -0
- package/src/responses/openai-responses-language-model.ts +167 -134
- package/src/responses/openai-responses-provider-metadata.ts +4 -0
|
@@ -71,6 +71,10 @@ import {
|
|
|
71
71
|
expandParallelToolCall,
|
|
72
72
|
isUndeclaredParallelToolCall,
|
|
73
73
|
} from './expand-parallel-tool-call';
|
|
74
|
+
import {
|
|
75
|
+
mapOpenAIResponsesAnnotationSource,
|
|
76
|
+
mapOpenAIResponsesCitations,
|
|
77
|
+
} from './map-openai-responses-annotation';
|
|
74
78
|
import { mapOpenAIResponseFinishReason } from './map-openai-responses-finish-reason';
|
|
75
79
|
import {
|
|
76
80
|
openaiResponsesChunkSchema,
|
|
@@ -95,7 +99,6 @@ import type {
|
|
|
95
99
|
ResponsesCompactionProviderMetadata,
|
|
96
100
|
ResponsesProviderMetadata,
|
|
97
101
|
ResponsesReasoningProviderMetadata,
|
|
98
|
-
ResponsesSourceDocumentProviderMetadata,
|
|
99
102
|
ResponsesTextProviderMetadata,
|
|
100
103
|
ResponsesToolCallProviderMetadata,
|
|
101
104
|
} from './openai-responses-provider-metadata';
|
|
@@ -905,6 +908,18 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
905
908
|
options.tools?.filter(
|
|
906
909
|
(tool): tool is LanguageModelV4FunctionTool => tool.type === 'function',
|
|
907
910
|
) ?? [];
|
|
911
|
+
const hasWebSearchActionSources = response.output.some(
|
|
912
|
+
part =>
|
|
913
|
+
part.type === 'web_search_call' &&
|
|
914
|
+
part.action?.type === 'search' &&
|
|
915
|
+
part.action.sources?.some(source => source.type === 'url'),
|
|
916
|
+
);
|
|
917
|
+
|
|
918
|
+
const hasFileSearchResults = response.output.some(
|
|
919
|
+
part =>
|
|
920
|
+
part.type === 'file_search_call' && (part.results?.length ?? 0) > 0,
|
|
921
|
+
);
|
|
922
|
+
const retrievedFileIds = new Set<string>();
|
|
908
923
|
|
|
909
924
|
// flag that checks if there have been client-side tool calls (not executed by openai)
|
|
910
925
|
let hasFunctionCall = false;
|
|
@@ -1084,78 +1099,35 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1084
1099
|
content.push({
|
|
1085
1100
|
type: 'text',
|
|
1086
1101
|
text: contentPart.text,
|
|
1102
|
+
...(contentPart.annotations.some(
|
|
1103
|
+
annotation => annotation.type !== 'file_path',
|
|
1104
|
+
) && {
|
|
1105
|
+
citations: mapOpenAIResponsesCitations(
|
|
1106
|
+
contentPart.annotations,
|
|
1107
|
+
providerOptionsName,
|
|
1108
|
+
),
|
|
1109
|
+
}),
|
|
1087
1110
|
providerMetadata: {
|
|
1088
1111
|
[providerOptionsName]: providerMetadata,
|
|
1089
1112
|
},
|
|
1090
1113
|
});
|
|
1091
1114
|
|
|
1092
1115
|
for (const annotation of contentPart.annotations) {
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
});
|
|
1101
|
-
} else if (annotation.type === 'file_citation') {
|
|
1102
|
-
content.push({
|
|
1103
|
-
type: 'source',
|
|
1104
|
-
sourceType: 'document',
|
|
1105
|
-
id: this.config.generateId?.() ?? generateId(),
|
|
1106
|
-
mediaType: 'text/plain',
|
|
1107
|
-
title: annotation.filename,
|
|
1108
|
-
filename: annotation.filename,
|
|
1109
|
-
providerMetadata: {
|
|
1110
|
-
[providerOptionsName]: {
|
|
1111
|
-
type: annotation.type,
|
|
1112
|
-
fileId: annotation.file_id,
|
|
1113
|
-
index: annotation.index,
|
|
1114
|
-
} satisfies Extract<
|
|
1115
|
-
ResponsesSourceDocumentProviderMetadata,
|
|
1116
|
-
{ type: 'file_citation' }
|
|
1117
|
-
>,
|
|
1118
|
-
},
|
|
1119
|
-
});
|
|
1120
|
-
} else if (annotation.type === 'container_file_citation') {
|
|
1121
|
-
content.push({
|
|
1122
|
-
type: 'source',
|
|
1123
|
-
sourceType: 'document',
|
|
1124
|
-
id: this.config.generateId?.() ?? generateId(),
|
|
1125
|
-
mediaType: 'text/plain',
|
|
1126
|
-
title: annotation.filename,
|
|
1127
|
-
filename: annotation.filename,
|
|
1128
|
-
providerMetadata: {
|
|
1129
|
-
[providerOptionsName]: {
|
|
1130
|
-
type: annotation.type,
|
|
1131
|
-
fileId: annotation.file_id,
|
|
1132
|
-
containerId: annotation.container_id,
|
|
1133
|
-
} satisfies Extract<
|
|
1134
|
-
ResponsesSourceDocumentProviderMetadata,
|
|
1135
|
-
{ type: 'container_file_citation' }
|
|
1136
|
-
>,
|
|
1137
|
-
},
|
|
1138
|
-
});
|
|
1139
|
-
} else if (annotation.type === 'file_path') {
|
|
1140
|
-
content.push({
|
|
1141
|
-
type: 'source',
|
|
1142
|
-
sourceType: 'document',
|
|
1143
|
-
id: this.config.generateId?.() ?? generateId(),
|
|
1144
|
-
mediaType: 'application/octet-stream',
|
|
1145
|
-
title: annotation.file_id,
|
|
1146
|
-
filename: annotation.file_id,
|
|
1147
|
-
providerMetadata: {
|
|
1148
|
-
[providerOptionsName]: {
|
|
1149
|
-
type: annotation.type,
|
|
1150
|
-
fileId: annotation.file_id,
|
|
1151
|
-
index: annotation.index,
|
|
1152
|
-
} satisfies Extract<
|
|
1153
|
-
ResponsesSourceDocumentProviderMetadata,
|
|
1154
|
-
{ type: 'file_path' }
|
|
1155
|
-
>,
|
|
1156
|
-
},
|
|
1157
|
-
});
|
|
1116
|
+
// Use citation-derived sources only when retrieval data is unavailable.
|
|
1117
|
+
if (
|
|
1118
|
+
(annotation.type === 'url_citation' &&
|
|
1119
|
+
hasWebSearchActionSources) ||
|
|
1120
|
+
(annotation.type === 'file_citation' && hasFileSearchResults)
|
|
1121
|
+
) {
|
|
1122
|
+
continue;
|
|
1158
1123
|
}
|
|
1124
|
+
content.push(
|
|
1125
|
+
mapOpenAIResponsesAnnotationSource(
|
|
1126
|
+
annotation,
|
|
1127
|
+
providerOptionsName,
|
|
1128
|
+
this.config.generateId?.() ?? generateId(),
|
|
1129
|
+
),
|
|
1130
|
+
);
|
|
1159
1131
|
}
|
|
1160
1132
|
}
|
|
1161
1133
|
|
|
@@ -1288,6 +1260,19 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1288
1260
|
: { result: mapWebSearchOutput(part.action) }),
|
|
1289
1261
|
});
|
|
1290
1262
|
|
|
1263
|
+
if (part.action?.type === 'search') {
|
|
1264
|
+
for (const source of part.action.sources ?? []) {
|
|
1265
|
+
if (source.type === 'url') {
|
|
1266
|
+
content.push({
|
|
1267
|
+
type: 'source',
|
|
1268
|
+
sourceType: 'url',
|
|
1269
|
+
id: this.config.generateId?.() ?? generateId(),
|
|
1270
|
+
url: source.url,
|
|
1271
|
+
});
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1291
1276
|
break;
|
|
1292
1277
|
}
|
|
1293
1278
|
|
|
@@ -1424,6 +1409,26 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1424
1409
|
})) ?? null,
|
|
1425
1410
|
} satisfies InferSchema<typeof fileSearchOutputSchema>,
|
|
1426
1411
|
});
|
|
1412
|
+
for (const result of part.results ?? []) {
|
|
1413
|
+
if (retrievedFileIds.has(result.file_id)) {
|
|
1414
|
+
continue;
|
|
1415
|
+
}
|
|
1416
|
+
retrievedFileIds.add(result.file_id);
|
|
1417
|
+
content.push({
|
|
1418
|
+
type: 'source',
|
|
1419
|
+
sourceType: 'document',
|
|
1420
|
+
id: this.config.generateId?.() ?? generateId(),
|
|
1421
|
+
mediaType: 'text/plain',
|
|
1422
|
+
title: result.filename,
|
|
1423
|
+
filename: result.filename,
|
|
1424
|
+
providerMetadata: {
|
|
1425
|
+
[providerOptionsName]: {
|
|
1426
|
+
type: 'file_search',
|
|
1427
|
+
fileId: result.file_id,
|
|
1428
|
+
},
|
|
1429
|
+
},
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1427
1432
|
break;
|
|
1428
1433
|
}
|
|
1429
1434
|
|
|
@@ -1617,12 +1622,16 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1617
1622
|
> = {};
|
|
1618
1623
|
|
|
1619
1624
|
// set annotations in 'text-end' part providerMetadata.
|
|
1620
|
-
|
|
1625
|
+
let ongoingAnnotations: Array<
|
|
1621
1626
|
Extract<
|
|
1622
1627
|
OpenAIResponsesChunk,
|
|
1623
1628
|
{ type: 'response.output_text.annotation.added' }
|
|
1624
1629
|
>['annotation']
|
|
1625
1630
|
> = [];
|
|
1631
|
+
let hasWebSearchActionSources = false;
|
|
1632
|
+
let hasFileSearchResults = false;
|
|
1633
|
+
const retrievedFileIds = new Set<string>();
|
|
1634
|
+
const fallbackAnnotations: typeof ongoingAnnotations = [];
|
|
1626
1635
|
|
|
1627
1636
|
// track the phase of the current message being streamed
|
|
1628
1637
|
let activeMessagePhase: 'commentary' | 'final_answer' | undefined;
|
|
@@ -1730,6 +1739,14 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1730
1739
|
id: value.item.call_id,
|
|
1731
1740
|
toolName,
|
|
1732
1741
|
});
|
|
1742
|
+
|
|
1743
|
+
// Custom tool input is a string, so stream its JSON encoding
|
|
1744
|
+
// consistently with the final tool call input.
|
|
1745
|
+
controller.enqueue({
|
|
1746
|
+
type: 'tool-input-delta',
|
|
1747
|
+
id: value.item.call_id,
|
|
1748
|
+
delta: '"',
|
|
1749
|
+
});
|
|
1733
1750
|
} else if (value.item.type === 'web_search_call') {
|
|
1734
1751
|
ongoingToolCalls[value.output_index] = {
|
|
1735
1752
|
toolName: toolNameMapping.toCustomToolName(
|
|
@@ -1894,7 +1911,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1894
1911
|
// shell_call_output is handled in output_item.done
|
|
1895
1912
|
} else if (value.item.type === 'message') {
|
|
1896
1913
|
activeOutputItemIds[value.output_index] = value.item.id;
|
|
1897
|
-
ongoingAnnotations
|
|
1914
|
+
ongoingAnnotations = [];
|
|
1898
1915
|
activeMessagePhase = value.item.phase ?? undefined;
|
|
1899
1916
|
controller.enqueue({
|
|
1900
1917
|
type: 'text-start',
|
|
@@ -1941,6 +1958,14 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1941
1958
|
controller.enqueue({
|
|
1942
1959
|
type: 'text-end',
|
|
1943
1960
|
id: itemId,
|
|
1961
|
+
...(ongoingAnnotations.some(
|
|
1962
|
+
annotation => annotation.type !== 'file_path',
|
|
1963
|
+
) && {
|
|
1964
|
+
citations: mapOpenAIResponsesCitations(
|
|
1965
|
+
ongoingAnnotations,
|
|
1966
|
+
providerOptionsName,
|
|
1967
|
+
),
|
|
1968
|
+
}),
|
|
1944
1969
|
providerMetadata: {
|
|
1945
1970
|
[providerOptionsName]: {
|
|
1946
1971
|
itemId,
|
|
@@ -2120,6 +2145,12 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2120
2145
|
value.item.name,
|
|
2121
2146
|
);
|
|
2122
2147
|
|
|
2148
|
+
controller.enqueue({
|
|
2149
|
+
type: 'tool-input-delta',
|
|
2150
|
+
id: value.item.call_id,
|
|
2151
|
+
delta: '"',
|
|
2152
|
+
});
|
|
2153
|
+
|
|
2123
2154
|
controller.enqueue({
|
|
2124
2155
|
type: 'tool-input-end',
|
|
2125
2156
|
id: value.item.call_id,
|
|
@@ -2155,6 +2186,20 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2155
2186
|
? { isError: true, result: { status: value.item.status } }
|
|
2156
2187
|
: { result: mapWebSearchOutput(value.item.action) }),
|
|
2157
2188
|
});
|
|
2189
|
+
|
|
2190
|
+
if (value.item.action?.type === 'search') {
|
|
2191
|
+
for (const source of value.item.action.sources ?? []) {
|
|
2192
|
+
if (source.type === 'url') {
|
|
2193
|
+
hasWebSearchActionSources = true;
|
|
2194
|
+
controller.enqueue({
|
|
2195
|
+
type: 'source',
|
|
2196
|
+
sourceType: 'url',
|
|
2197
|
+
id: self.config.generateId?.() ?? generateId(),
|
|
2198
|
+
url: source.url,
|
|
2199
|
+
});
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2158
2203
|
} else if (value.item.type === 'computer_call') {
|
|
2159
2204
|
ongoingToolCalls[value.output_index] = undefined;
|
|
2160
2205
|
|
|
@@ -2227,6 +2272,27 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2227
2272
|
})) ?? null,
|
|
2228
2273
|
} satisfies InferSchema<typeof fileSearchOutputSchema>,
|
|
2229
2274
|
});
|
|
2275
|
+
for (const result of value.item.results ?? []) {
|
|
2276
|
+
hasFileSearchResults = true;
|
|
2277
|
+
if (retrievedFileIds.has(result.file_id)) {
|
|
2278
|
+
continue;
|
|
2279
|
+
}
|
|
2280
|
+
retrievedFileIds.add(result.file_id);
|
|
2281
|
+
controller.enqueue({
|
|
2282
|
+
type: 'source',
|
|
2283
|
+
sourceType: 'document',
|
|
2284
|
+
id: self.config.generateId?.() ?? generateId(),
|
|
2285
|
+
mediaType: 'text/plain',
|
|
2286
|
+
title: result.filename,
|
|
2287
|
+
filename: result.filename,
|
|
2288
|
+
providerMetadata: {
|
|
2289
|
+
[providerOptionsName]: {
|
|
2290
|
+
type: 'file_search',
|
|
2291
|
+
fileId: result.file_id,
|
|
2292
|
+
},
|
|
2293
|
+
},
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2230
2296
|
} else if (value.item.type === 'code_interpreter_call') {
|
|
2231
2297
|
ongoingToolCalls[value.output_index] = undefined;
|
|
2232
2298
|
|
|
@@ -2582,7 +2648,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2582
2648
|
controller.enqueue({
|
|
2583
2649
|
type: 'tool-input-delta',
|
|
2584
2650
|
id: toolCall.toolCallId,
|
|
2585
|
-
delta: value.delta,
|
|
2651
|
+
delta: escapeJSONDelta(value.delta),
|
|
2586
2652
|
});
|
|
2587
2653
|
}
|
|
2588
2654
|
} else if (isResponseApplyPatchCallOperationDiffDeltaChunk(value)) {
|
|
@@ -2843,71 +2909,21 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2843
2909
|
}
|
|
2844
2910
|
} else if (isResponseAnnotationAddedChunk(value)) {
|
|
2845
2911
|
ongoingAnnotations.push(value.annotation);
|
|
2846
|
-
if (
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
filename: value.annotation.filename,
|
|
2862
|
-
providerMetadata: {
|
|
2863
|
-
[providerOptionsName]: {
|
|
2864
|
-
type: value.annotation.type,
|
|
2865
|
-
fileId: value.annotation.file_id,
|
|
2866
|
-
index: value.annotation.index,
|
|
2867
|
-
} satisfies Extract<
|
|
2868
|
-
ResponsesSourceDocumentProviderMetadata,
|
|
2869
|
-
{ type: 'file_citation' }
|
|
2870
|
-
>,
|
|
2871
|
-
},
|
|
2872
|
-
});
|
|
2873
|
-
} else if (value.annotation.type === 'container_file_citation') {
|
|
2874
|
-
controller.enqueue({
|
|
2875
|
-
type: 'source',
|
|
2876
|
-
sourceType: 'document',
|
|
2877
|
-
id: self.config.generateId?.() ?? generateId(),
|
|
2878
|
-
mediaType: 'text/plain',
|
|
2879
|
-
title: value.annotation.filename,
|
|
2880
|
-
filename: value.annotation.filename,
|
|
2881
|
-
providerMetadata: {
|
|
2882
|
-
[providerOptionsName]: {
|
|
2883
|
-
type: value.annotation.type,
|
|
2884
|
-
fileId: value.annotation.file_id,
|
|
2885
|
-
containerId: value.annotation.container_id,
|
|
2886
|
-
} satisfies Extract<
|
|
2887
|
-
ResponsesSourceDocumentProviderMetadata,
|
|
2888
|
-
{ type: 'container_file_citation' }
|
|
2889
|
-
>,
|
|
2890
|
-
},
|
|
2891
|
-
});
|
|
2892
|
-
} else if (value.annotation.type === 'file_path') {
|
|
2893
|
-
controller.enqueue({
|
|
2894
|
-
type: 'source',
|
|
2895
|
-
sourceType: 'document',
|
|
2896
|
-
id: self.config.generateId?.() ?? generateId(),
|
|
2897
|
-
mediaType: 'application/octet-stream',
|
|
2898
|
-
title: value.annotation.file_id,
|
|
2899
|
-
filename: value.annotation.file_id,
|
|
2900
|
-
providerMetadata: {
|
|
2901
|
-
[providerOptionsName]: {
|
|
2902
|
-
type: value.annotation.type,
|
|
2903
|
-
fileId: value.annotation.file_id,
|
|
2904
|
-
index: value.annotation.index,
|
|
2905
|
-
} satisfies Extract<
|
|
2906
|
-
ResponsesSourceDocumentProviderMetadata,
|
|
2907
|
-
{ type: 'file_path' }
|
|
2908
|
-
>,
|
|
2909
|
-
},
|
|
2910
|
-
});
|
|
2912
|
+
if (
|
|
2913
|
+
value.annotation.type === 'url_citation' ||
|
|
2914
|
+
value.annotation.type === 'file_citation'
|
|
2915
|
+
) {
|
|
2916
|
+
// Retrieval events may arrive after the annotation. Decide the
|
|
2917
|
+
// compatibility fallback once the complete source set is known.
|
|
2918
|
+
fallbackAnnotations.push(value.annotation);
|
|
2919
|
+
} else {
|
|
2920
|
+
controller.enqueue(
|
|
2921
|
+
mapOpenAIResponsesAnnotationSource(
|
|
2922
|
+
value.annotation,
|
|
2923
|
+
providerOptionsName,
|
|
2924
|
+
self.config.generateId?.() ?? generateId(),
|
|
2925
|
+
),
|
|
2926
|
+
);
|
|
2911
2927
|
}
|
|
2912
2928
|
} else if (isErrorChunk(value)) {
|
|
2913
2929
|
encounteredStreamError = true;
|
|
@@ -2920,6 +2936,23 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2920
2936
|
},
|
|
2921
2937
|
|
|
2922
2938
|
flush(controller) {
|
|
2939
|
+
for (const annotation of fallbackAnnotations) {
|
|
2940
|
+
if (
|
|
2941
|
+
(annotation.type === 'url_citation' &&
|
|
2942
|
+
hasWebSearchActionSources) ||
|
|
2943
|
+
(annotation.type === 'file_citation' && hasFileSearchResults)
|
|
2944
|
+
) {
|
|
2945
|
+
continue;
|
|
2946
|
+
}
|
|
2947
|
+
controller.enqueue(
|
|
2948
|
+
mapOpenAIResponsesAnnotationSource(
|
|
2949
|
+
annotation,
|
|
2950
|
+
providerOptionsName,
|
|
2951
|
+
self.config.generateId?.() ?? generateId(),
|
|
2952
|
+
),
|
|
2953
|
+
);
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2923
2956
|
for (const toolCall of Object.values(ongoingToolCalls)) {
|
|
2924
2957
|
if (!toolCall?.suppressInputStreaming) {
|
|
2925
2958
|
continue;
|