@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
package/docs/03-openai.mdx
CHANGED
|
@@ -757,6 +757,13 @@ for (const toolResult of result.toolResults) {
|
|
|
757
757
|
}
|
|
758
758
|
```
|
|
759
759
|
|
|
760
|
+
`result.sources` and source stream events expose the URLs returned in
|
|
761
|
+
`web_search_call.action.sources`. These may include uncited URLs. Inline
|
|
762
|
+
references are available separately on `text.citations` and `text-end.citations`,
|
|
763
|
+
including titles and provider-supplied text ranges. Raw annotations remain in
|
|
764
|
+
text provider metadata. Citation-only responses and `web_search_preview`
|
|
765
|
+
responses without retrieval data retain citation-derived sources.
|
|
766
|
+
|
|
760
767
|
The web search tool supports the following configuration options:
|
|
761
768
|
|
|
762
769
|
- **externalWebAccess** _boolean_ - Whether to use external web access for fetching live content. Defaults to `true`.
|
|
@@ -1853,6 +1860,10 @@ for (const part of result.content) {
|
|
|
1853
1860
|
// url_citation is returned from web_search and provides:
|
|
1854
1861
|
// properties: type, url, title, start_index and end_index
|
|
1855
1862
|
break;
|
|
1863
|
+
case 'file_search':
|
|
1864
|
+
// Retrieved file-search result; provides fileId.
|
|
1865
|
+
// The filename is available as part.filename.
|
|
1866
|
+
break;
|
|
1856
1867
|
case 'file_citation':
|
|
1857
1868
|
// file_citation is returned from file_search and provides:
|
|
1858
1869
|
// properties: type, file_id, filename and index
|
|
@@ -1931,12 +1942,20 @@ for (const part of result.content) {
|
|
|
1931
1942
|
}
|
|
1932
1943
|
```
|
|
1933
1944
|
|
|
1945
|
+
When file-search results are included in the API response, each retrieved file
|
|
1946
|
+
is exposed once as a document source, even if it has multiple matching passages
|
|
1947
|
+
or is not cited. Inline file citations are available on `text.citations` and
|
|
1948
|
+
`text-end.citations`. If the response omits file-search results, file citations
|
|
1949
|
+
also remain document sources for compatibility. Generated file paths remain
|
|
1950
|
+
source parts and are not treated as citations.
|
|
1951
|
+
|
|
1934
1952
|
#### Typed providerMetadata in Source Document Parts
|
|
1935
1953
|
|
|
1936
1954
|
For source document parts, when `part.type === 'source'` and `sourceType === 'document'`, the `providerMetadata` is provided as `OpenaiResponsesSourceDocumentProviderMetadata`.
|
|
1937
1955
|
|
|
1938
1956
|
This metadata is also a discriminated union with a required `type` field. Supported types include:
|
|
1939
1957
|
|
|
1958
|
+
- `file_search` (retrieved file; includes `fileId`)
|
|
1940
1959
|
- `file_citation`
|
|
1941
1960
|
- `container_file_citation`
|
|
1942
1961
|
- `file_path`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/openai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.92",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ai-sdk/provider": "4.0.
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
38
|
+
"@ai-sdk/provider": "4.0.27",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.59"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.4",
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
parseProviderOptions,
|
|
16
16
|
resolveFullMediaType,
|
|
17
17
|
resolveProviderReference,
|
|
18
|
+
safeValidateTypes,
|
|
18
19
|
validateTypes,
|
|
19
20
|
type ToolNameMapping,
|
|
20
21
|
} from '@ai-sdk/provider-utils';
|
|
@@ -37,6 +38,7 @@ import type {
|
|
|
37
38
|
OpenAIResponsesInput,
|
|
38
39
|
OpenAIResponsesReasoning,
|
|
39
40
|
OpenAIResponsesToolCaller,
|
|
41
|
+
OpenAIResponsesWebSearchCall,
|
|
40
42
|
} from './openai-responses-api';
|
|
41
43
|
import {
|
|
42
44
|
toolSearchInputSchema,
|
|
@@ -46,6 +48,7 @@ import {
|
|
|
46
48
|
programmaticToolCallingInputSchema,
|
|
47
49
|
programmaticToolCallingOutputSchema,
|
|
48
50
|
} from '../tool/programmatic-tool-calling';
|
|
51
|
+
import { webSearchOutputSchema } from '../tool/web-search';
|
|
49
52
|
import {
|
|
50
53
|
getParallelToolCallMetadata,
|
|
51
54
|
type ParallelToolCallMetadata,
|
|
@@ -68,6 +71,65 @@ function mapToolCaller(
|
|
|
68
71
|
: caller;
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
async function convertWebSearchToolResultOutput({
|
|
75
|
+
output,
|
|
76
|
+
id,
|
|
77
|
+
}: {
|
|
78
|
+
output: LanguageModelV4ToolResultOutput;
|
|
79
|
+
id: string;
|
|
80
|
+
}): Promise<OpenAIResponsesWebSearchCall | undefined> {
|
|
81
|
+
if (output.type !== 'json') {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const validation = await safeValidateTypes({
|
|
86
|
+
value: output.value,
|
|
87
|
+
schema: webSearchOutputSchema,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (!validation.success || validation.value.action == null) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const { action, sources } = validation.value;
|
|
95
|
+
|
|
96
|
+
switch (action.type) {
|
|
97
|
+
case 'search':
|
|
98
|
+
return {
|
|
99
|
+
type: 'web_search_call',
|
|
100
|
+
id,
|
|
101
|
+
status: 'completed',
|
|
102
|
+
action: {
|
|
103
|
+
type: 'search',
|
|
104
|
+
...(action.query != null && { query: action.query }),
|
|
105
|
+
...(action.queries != null && { queries: action.queries }),
|
|
106
|
+
...(sources != null && { sources }),
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
case 'openPage':
|
|
110
|
+
return {
|
|
111
|
+
type: 'web_search_call',
|
|
112
|
+
id,
|
|
113
|
+
status: 'completed',
|
|
114
|
+
action: {
|
|
115
|
+
type: 'open_page',
|
|
116
|
+
url: action.url,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
case 'findInPage':
|
|
120
|
+
return {
|
|
121
|
+
type: 'web_search_call',
|
|
122
|
+
id,
|
|
123
|
+
status: 'completed',
|
|
124
|
+
action: {
|
|
125
|
+
type: 'find_in_page',
|
|
126
|
+
url: action.url,
|
|
127
|
+
pattern: action.pattern,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
71
133
|
async function convertFunctionToolResultOutput({
|
|
72
134
|
output,
|
|
73
135
|
toolName,
|
|
@@ -1039,6 +1101,33 @@ export async function convertToOpenAIResponsesInput({
|
|
|
1039
1101
|
part.toolName,
|
|
1040
1102
|
);
|
|
1041
1103
|
|
|
1104
|
+
if (
|
|
1105
|
+
resolvedResultToolName === 'web_search' ||
|
|
1106
|
+
resolvedResultToolName === 'web_search_preview'
|
|
1107
|
+
) {
|
|
1108
|
+
const itemId =
|
|
1109
|
+
(
|
|
1110
|
+
part.providerOptions?.[providerOptionsName] as
|
|
1111
|
+
| { itemId?: string }
|
|
1112
|
+
| undefined
|
|
1113
|
+
)?.itemId ?? part.toolCallId;
|
|
1114
|
+
|
|
1115
|
+
if (store) {
|
|
1116
|
+
input.push({ type: 'item_reference', id: itemId });
|
|
1117
|
+
break;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
const webSearchCall = await convertWebSearchToolResultOutput({
|
|
1121
|
+
output: part.output,
|
|
1122
|
+
id: itemId,
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
if (webSearchCall != null) {
|
|
1126
|
+
input.push(webSearchCall);
|
|
1127
|
+
break;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1042
1131
|
if (part.toolName === toolSearchToolName) {
|
|
1043
1132
|
const itemId = (part.providerOptions?.[providerOptionsName]
|
|
1044
1133
|
?.itemId ??
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
LanguageModelV4Citation,
|
|
3
|
+
LanguageModelV4Source,
|
|
4
|
+
} from '@ai-sdk/provider';
|
|
5
|
+
import type { ResponsesTextProviderMetadata } from './openai-responses-provider-metadata';
|
|
6
|
+
|
|
7
|
+
type Annotation = NonNullable<
|
|
8
|
+
ResponsesTextProviderMetadata['annotations']
|
|
9
|
+
>[number];
|
|
10
|
+
|
|
11
|
+
export function mapOpenAIResponsesAnnotationSource(
|
|
12
|
+
annotation: Annotation,
|
|
13
|
+
providerOptionsName: string,
|
|
14
|
+
id: string,
|
|
15
|
+
): LanguageModelV4Source {
|
|
16
|
+
if (annotation.type === 'url_citation') {
|
|
17
|
+
return {
|
|
18
|
+
type: 'source',
|
|
19
|
+
sourceType: 'url',
|
|
20
|
+
id,
|
|
21
|
+
url: annotation.url,
|
|
22
|
+
title: annotation.title,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const filename =
|
|
27
|
+
annotation.type === 'file_path' ? annotation.file_id : annotation.filename;
|
|
28
|
+
return {
|
|
29
|
+
type: 'source',
|
|
30
|
+
sourceType: 'document',
|
|
31
|
+
id,
|
|
32
|
+
mediaType:
|
|
33
|
+
annotation.type === 'file_path'
|
|
34
|
+
? 'application/octet-stream'
|
|
35
|
+
: 'text/plain',
|
|
36
|
+
title: filename,
|
|
37
|
+
filename,
|
|
38
|
+
providerMetadata: {
|
|
39
|
+
[providerOptionsName]: {
|
|
40
|
+
type: annotation.type,
|
|
41
|
+
fileId: annotation.file_id,
|
|
42
|
+
...(annotation.type === 'container_file_citation'
|
|
43
|
+
? { containerId: annotation.container_id }
|
|
44
|
+
: { index: annotation.index }),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function mapOpenAIResponsesCitations(
|
|
51
|
+
annotations: Array<Annotation>,
|
|
52
|
+
providerOptionsName: string,
|
|
53
|
+
): Array<LanguageModelV4Citation> {
|
|
54
|
+
return annotations.flatMap(annotation =>
|
|
55
|
+
annotation.type === 'file_path'
|
|
56
|
+
? []
|
|
57
|
+
: [
|
|
58
|
+
{
|
|
59
|
+
source: mapOpenAIResponsesAnnotationSource(
|
|
60
|
+
annotation,
|
|
61
|
+
providerOptionsName,
|
|
62
|
+
annotation.type === 'url_citation'
|
|
63
|
+
? annotation.url
|
|
64
|
+
: annotation.file_id,
|
|
65
|
+
),
|
|
66
|
+
...('start_index' in annotation
|
|
67
|
+
? {
|
|
68
|
+
startIndex: annotation.start_index,
|
|
69
|
+
endIndex: annotation.end_index,
|
|
70
|
+
}
|
|
71
|
+
: {}),
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
);
|
|
75
|
+
}
|
|
@@ -177,6 +177,7 @@ export type OpenAIResponsesInputItem =
|
|
|
177
177
|
| OpenAIResponsesApplyPatchCallOutput
|
|
178
178
|
| OpenAIResponsesToolSearchCall
|
|
179
179
|
| OpenAIResponsesToolSearchOutput
|
|
180
|
+
| OpenAIResponsesWebSearchCall
|
|
180
181
|
| OpenAIResponsesReasoning
|
|
181
182
|
| OpenAIResponsesItemReference
|
|
182
183
|
| OpenAIResponsesCompactionItem
|
|
@@ -342,6 +343,13 @@ export type OpenAIResponsesProgramOutput = {
|
|
|
342
343
|
status: 'completed' | 'incomplete';
|
|
343
344
|
};
|
|
344
345
|
|
|
346
|
+
export type OpenAIResponsesWebSearchCall = {
|
|
347
|
+
type: 'web_search_call';
|
|
348
|
+
id: string;
|
|
349
|
+
status: 'completed';
|
|
350
|
+
action: OpenAIResponsesWebSearchAction;
|
|
351
|
+
};
|
|
352
|
+
|
|
345
353
|
export type OpenAIResponsesCustomToolCall = {
|
|
346
354
|
type: 'custom_tool_call';
|
|
347
355
|
id?: string;
|