@ai-sdk/openai 3.0.68 → 3.0.69
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 +6 -0
- package/dist/index.js +40 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -9
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +39 -8
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +39 -8
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-openai.mdx +78 -0
- package/package.json +3 -3
- package/src/responses/openai-responses-api.ts +13 -5
- package/src/responses/openai-responses-prepare-tools.ts +64 -11
package/docs/03-openai.mdx
CHANGED
|
@@ -434,6 +434,38 @@ The `textVerbosity` parameter scales output length without changing the underlyi
|
|
|
434
434
|
- `'medium'`: Balanced detail (default)
|
|
435
435
|
- `'high'`: Verbose responses with comprehensive detail
|
|
436
436
|
|
|
437
|
+
#### Namespaced Function Calls
|
|
438
|
+
|
|
439
|
+
OpenAI supports grouping related function tools into
|
|
440
|
+
[namespaces](https://developers.openai.com/api/docs/guides/function-calling#defining-namespaces).
|
|
441
|
+
When the Responses API returns a `function_call` with a `namespace`, the OpenAI provider
|
|
442
|
+
exposes this value on the generated `tool-call` part as
|
|
443
|
+
`providerMetadata.openai.namespace`.
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
for (const part of result.content) {
|
|
447
|
+
if (part.type === 'tool-call') {
|
|
448
|
+
console.log(part.providerMetadata?.openai?.namespace);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
When using `streamText`, the namespace is available on the `tool-input-end` event and on
|
|
454
|
+
the final `tool-call` event:
|
|
455
|
+
|
|
456
|
+
```ts
|
|
457
|
+
for await (const part of result.stream) {
|
|
458
|
+
if (part.type === 'tool-input-end' || part.type === 'tool-call') {
|
|
459
|
+
console.log(part.providerMetadata?.openai?.namespace);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
If you persist or reconstruct messages for later turns, preserve the OpenAI provider
|
|
465
|
+
metadata on tool-call parts. The SDK uses `providerMetadata.openai.namespace` or
|
|
466
|
+
`providerOptions.openai.namespace` to round-trip the namespace back to OpenAI on
|
|
467
|
+
subsequent requests.
|
|
468
|
+
|
|
437
469
|
#### Web Search Tool
|
|
438
470
|
|
|
439
471
|
The OpenAI responses API supports web search through the `openai.tools.webSearch` tool.
|
|
@@ -1024,6 +1056,52 @@ In hosted mode, the model internally searches the deferred tools, loads the rele
|
|
|
1024
1056
|
proceeds to call them — all within a single response. The `tool_search_call` and
|
|
1025
1057
|
`tool_search_output` items appear in the response with `execution: 'server'` and `call_id: null`.
|
|
1026
1058
|
|
|
1059
|
+
##### Namespaces
|
|
1060
|
+
|
|
1061
|
+
Use `providerOptions.openai.namespace` to group related function tools for OpenAI.
|
|
1062
|
+
The SDK keeps each tool executable as a normal AI SDK tool, but serializes grouped
|
|
1063
|
+
tools as OpenAI `namespace` entries in the request:
|
|
1064
|
+
|
|
1065
|
+
```ts
|
|
1066
|
+
const crmNamespace = {
|
|
1067
|
+
name: 'crm',
|
|
1068
|
+
description: 'CRM tools for customer lookup and order management.',
|
|
1069
|
+
};
|
|
1070
|
+
|
|
1071
|
+
const result = await generateText({
|
|
1072
|
+
model: openai.responses('gpt-5.4'),
|
|
1073
|
+
prompt: 'List open orders for customer cust_123.',
|
|
1074
|
+
tools: {
|
|
1075
|
+
toolSearch: openai.tools.toolSearch(),
|
|
1076
|
+
|
|
1077
|
+
get_customer_profile: tool({
|
|
1078
|
+
description: 'Fetch a customer profile by customer ID.',
|
|
1079
|
+
inputSchema: z.object({ customer_id: z.string() }),
|
|
1080
|
+
execute: async ({ customer_id }) => ({ customer_id }),
|
|
1081
|
+
providerOptions: {
|
|
1082
|
+
openai: { namespace: crmNamespace },
|
|
1083
|
+
},
|
|
1084
|
+
}),
|
|
1085
|
+
|
|
1086
|
+
list_open_orders: tool({
|
|
1087
|
+
description: 'List open orders for a customer ID.',
|
|
1088
|
+
inputSchema: z.object({ customer_id: z.string() }),
|
|
1089
|
+
execute: async ({ customer_id }) => ({ customer_id, orders: [] }),
|
|
1090
|
+
providerOptions: {
|
|
1091
|
+
openai: {
|
|
1092
|
+
namespace: crmNamespace,
|
|
1093
|
+
deferLoading: true,
|
|
1094
|
+
},
|
|
1095
|
+
},
|
|
1096
|
+
}),
|
|
1097
|
+
},
|
|
1098
|
+
});
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
Tools in the same namespace must use the same namespace `name` and `description`.
|
|
1102
|
+
For best results with tool search, keep namespace descriptions concise and put
|
|
1103
|
+
detailed usage guidance on the individual function tools.
|
|
1104
|
+
|
|
1027
1105
|
##### Client-Executed Tool Search
|
|
1028
1106
|
|
|
1029
1107
|
Use client-executed tool search when tool discovery depends on runtime state — for example,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/openai",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.69",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"tsup": "^8",
|
|
45
45
|
"typescript": "5.8.3",
|
|
46
46
|
"zod": "3.25.76",
|
|
47
|
-
"@ai-
|
|
48
|
-
"@
|
|
47
|
+
"@vercel/ai-tsconfig": "0.0.0",
|
|
48
|
+
"@ai-sdk/test-server": "1.0.5"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"zod": "^3.25.76 || ^4.1.8"
|
|
@@ -279,14 +279,22 @@ export type OpenAIResponsesFileSearchToolCompoundFilter = {
|
|
|
279
279
|
>;
|
|
280
280
|
};
|
|
281
281
|
|
|
282
|
+
export type OpenAIResponsesFunctionTool = {
|
|
283
|
+
type: 'function';
|
|
284
|
+
name: string;
|
|
285
|
+
description: string | undefined;
|
|
286
|
+
parameters: JSONSchema7;
|
|
287
|
+
strict?: boolean;
|
|
288
|
+
defer_loading?: boolean;
|
|
289
|
+
};
|
|
290
|
+
|
|
282
291
|
export type OpenAIResponsesTool =
|
|
292
|
+
| OpenAIResponsesFunctionTool
|
|
283
293
|
| {
|
|
284
|
-
type: '
|
|
294
|
+
type: 'namespace';
|
|
285
295
|
name: string;
|
|
286
|
-
description: string
|
|
287
|
-
|
|
288
|
-
strict?: boolean;
|
|
289
|
-
defer_loading?: boolean;
|
|
296
|
+
description: string;
|
|
297
|
+
tools: Array<OpenAIResponsesFunctionTool>;
|
|
290
298
|
}
|
|
291
299
|
| {
|
|
292
300
|
type: 'apply_patch';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
UnsupportedFunctionalityError,
|
|
3
3
|
type LanguageModelV3CallOptions,
|
|
4
|
+
type LanguageModelV3FunctionTool,
|
|
4
5
|
type SharedV3Warning,
|
|
5
6
|
} from '@ai-sdk/provider';
|
|
6
7
|
import { validateTypes, type ToolNameMapping } from '@ai-sdk/provider-utils';
|
|
@@ -13,7 +14,18 @@ import { shellArgsSchema } from '../tool/shell';
|
|
|
13
14
|
import { toolSearchArgsSchema } from '../tool/tool-search';
|
|
14
15
|
import { webSearchArgsSchema } from '../tool/web-search';
|
|
15
16
|
import { webSearchPreviewArgsSchema } from '../tool/web-search-preview';
|
|
16
|
-
import type {
|
|
17
|
+
import type {
|
|
18
|
+
OpenAIResponsesFunctionTool,
|
|
19
|
+
OpenAIResponsesTool,
|
|
20
|
+
} from './openai-responses-api';
|
|
21
|
+
|
|
22
|
+
type OpenAIToolOptions = {
|
|
23
|
+
deferLoading?: boolean;
|
|
24
|
+
namespace?: {
|
|
25
|
+
name: string;
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
17
29
|
|
|
18
30
|
export async function prepareResponsesTools({
|
|
19
31
|
tools,
|
|
@@ -62,6 +74,10 @@ export async function prepareResponsesTools({
|
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
const openaiTools: Array<OpenAIResponsesTool> = [];
|
|
77
|
+
const namespaceTools = new Map<
|
|
78
|
+
string,
|
|
79
|
+
Extract<OpenAIResponsesTool, { type: 'namespace' }>
|
|
80
|
+
>();
|
|
65
81
|
const resolvedCustomProviderToolNames =
|
|
66
82
|
customProviderToolNames ?? new Set<string>();
|
|
67
83
|
|
|
@@ -69,18 +85,36 @@ export async function prepareResponsesTools({
|
|
|
69
85
|
switch (tool.type) {
|
|
70
86
|
case 'function': {
|
|
71
87
|
const openaiOptions = tool.providerOptions?.openai as
|
|
72
|
-
|
|
|
88
|
+
| OpenAIToolOptions
|
|
73
89
|
| undefined;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
type: 'function',
|
|
78
|
-
name: tool.name,
|
|
79
|
-
description: tool.description,
|
|
80
|
-
parameters: tool.inputSchema,
|
|
81
|
-
...(tool.strict != null ? { strict: tool.strict } : {}),
|
|
82
|
-
...(deferLoading != null ? { defer_loading: deferLoading } : {}),
|
|
90
|
+
const openaiFunctionTool = prepareFunctionTool({
|
|
91
|
+
tool,
|
|
92
|
+
options: openaiOptions,
|
|
83
93
|
});
|
|
94
|
+
const namespace = openaiOptions?.namespace;
|
|
95
|
+
|
|
96
|
+
if (namespace == null) {
|
|
97
|
+
openaiTools.push(openaiFunctionTool);
|
|
98
|
+
} else {
|
|
99
|
+
let namespaceTool = namespaceTools.get(namespace.name);
|
|
100
|
+
|
|
101
|
+
if (namespaceTool == null) {
|
|
102
|
+
namespaceTool = {
|
|
103
|
+
type: 'namespace',
|
|
104
|
+
name: namespace.name,
|
|
105
|
+
description: namespace.description,
|
|
106
|
+
tools: [],
|
|
107
|
+
};
|
|
108
|
+
namespaceTools.set(namespace.name, namespaceTool);
|
|
109
|
+
openaiTools.push(namespaceTool);
|
|
110
|
+
} else if (namespaceTool.description !== namespace.description) {
|
|
111
|
+
throw new UnsupportedFunctionalityError({
|
|
112
|
+
functionality: `conflicting descriptions for OpenAI tool namespace "${namespace.name}"`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
namespaceTool.tools.push(openaiFunctionTool);
|
|
117
|
+
}
|
|
84
118
|
break;
|
|
85
119
|
}
|
|
86
120
|
case 'provider': {
|
|
@@ -352,6 +386,25 @@ export async function prepareResponsesTools({
|
|
|
352
386
|
}
|
|
353
387
|
}
|
|
354
388
|
|
|
389
|
+
function prepareFunctionTool({
|
|
390
|
+
tool,
|
|
391
|
+
options,
|
|
392
|
+
}: {
|
|
393
|
+
tool: LanguageModelV3FunctionTool;
|
|
394
|
+
options: OpenAIToolOptions | undefined;
|
|
395
|
+
}): OpenAIResponsesFunctionTool {
|
|
396
|
+
const deferLoading = options?.deferLoading;
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
type: 'function',
|
|
400
|
+
name: tool.name,
|
|
401
|
+
description: tool.description,
|
|
402
|
+
parameters: tool.inputSchema,
|
|
403
|
+
...(tool.strict != null ? { strict: tool.strict } : {}),
|
|
404
|
+
...(deferLoading != null ? { defer_loading: deferLoading } : {}),
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
355
408
|
function mapShellEnvironment(environment: {
|
|
356
409
|
type?: string;
|
|
357
410
|
[key: string]: unknown;
|