@ai-sdk/openai 3.0.36 → 3.0.38

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.
@@ -3,10 +3,11 @@ import {
3
3
  SharedV3Warning,
4
4
  UnsupportedFunctionalityError,
5
5
  } from '@ai-sdk/provider';
6
- import { validateTypes } from '@ai-sdk/provider-utils';
6
+ import { ToolNameMapping, validateTypes } from '@ai-sdk/provider-utils';
7
7
  import { codeInterpreterArgsSchema } from '../tool/code-interpreter';
8
8
  import { fileSearchArgsSchema } from '../tool/file-search';
9
9
  import { imageGenerationArgsSchema } from '../tool/image-generation';
10
+ import { customArgsSchema } from '../tool/custom';
10
11
  import { mcpArgsSchema } from '../tool/mcp';
11
12
  import { shellArgsSchema } from '../tool/shell';
12
13
  import { webSearchArgsSchema } from '../tool/web-search';
@@ -16,9 +17,13 @@ import { OpenAIResponsesTool } from './openai-responses-api';
16
17
  export async function prepareResponsesTools({
17
18
  tools,
18
19
  toolChoice,
20
+ toolNameMapping,
21
+ customProviderToolNames,
19
22
  }: {
20
23
  tools: LanguageModelV3CallOptions['tools'];
21
24
  toolChoice: LanguageModelV3CallOptions['toolChoice'] | undefined;
25
+ toolNameMapping?: ToolNameMapping;
26
+ customProviderToolNames?: Set<string>;
22
27
  }): Promise<{
23
28
  tools?: Array<OpenAIResponsesTool>;
24
29
  toolChoice?:
@@ -29,6 +34,7 @@ export async function prepareResponsesTools({
29
34
  | { type: 'web_search_preview' }
30
35
  | { type: 'web_search' }
31
36
  | { type: 'function'; name: string }
37
+ | { type: 'custom'; name: string }
32
38
  | { type: 'code_interpreter' }
33
39
  | { type: 'mcp' }
34
40
  | { type: 'image_generation' }
@@ -45,6 +51,8 @@ export async function prepareResponsesTools({
45
51
  }
46
52
 
47
53
  const openaiTools: Array<OpenAIResponsesTool> = [];
54
+ const resolvedCustomProviderToolNames =
55
+ customProviderToolNames ?? new Set<string>();
48
56
 
49
57
  for (const tool of tools) {
50
58
  switch (tool.type) {
@@ -225,6 +233,21 @@ export async function prepareResponsesTools({
225
233
 
226
234
  break;
227
235
  }
236
+ case 'openai.custom': {
237
+ const args = await validateTypes({
238
+ value: tool.args,
239
+ schema: customArgsSchema,
240
+ });
241
+
242
+ openaiTools.push({
243
+ type: 'custom',
244
+ name: args.name,
245
+ description: args.description,
246
+ format: args.format,
247
+ });
248
+ resolvedCustomProviderToolNames.add(args.name);
249
+ break;
250
+ }
228
251
  }
229
252
  break;
230
253
  }
@@ -248,21 +271,28 @@ export async function prepareResponsesTools({
248
271
  case 'none':
249
272
  case 'required':
250
273
  return { tools: openaiTools, toolChoice: type, toolWarnings };
251
- case 'tool':
274
+ case 'tool': {
275
+ const resolvedToolName =
276
+ toolNameMapping?.toProviderToolName(toolChoice.toolName) ??
277
+ toolChoice.toolName;
278
+
252
279
  return {
253
280
  tools: openaiTools,
254
281
  toolChoice:
255
- toolChoice.toolName === 'code_interpreter' ||
256
- toolChoice.toolName === 'file_search' ||
257
- toolChoice.toolName === 'image_generation' ||
258
- toolChoice.toolName === 'web_search_preview' ||
259
- toolChoice.toolName === 'web_search' ||
260
- toolChoice.toolName === 'mcp' ||
261
- toolChoice.toolName === 'apply_patch'
262
- ? { type: toolChoice.toolName }
263
- : { type: 'function', name: toolChoice.toolName },
282
+ resolvedToolName === 'code_interpreter' ||
283
+ resolvedToolName === 'file_search' ||
284
+ resolvedToolName === 'image_generation' ||
285
+ resolvedToolName === 'web_search_preview' ||
286
+ resolvedToolName === 'web_search' ||
287
+ resolvedToolName === 'mcp' ||
288
+ resolvedToolName === 'apply_patch'
289
+ ? { type: resolvedToolName }
290
+ : resolvedCustomProviderToolNames.has(resolvedToolName)
291
+ ? { type: 'custom', name: resolvedToolName }
292
+ : { type: 'function', name: resolvedToolName },
264
293
  toolWarnings,
265
294
  };
295
+ }
266
296
  default: {
267
297
  const _exhaustiveCheck: never = type;
268
298
  throw new UnsupportedFunctionalityError({
@@ -0,0 +1,64 @@
1
+ import {
2
+ createProviderToolFactory,
3
+ lazySchema,
4
+ zodSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod/v4';
7
+
8
+ export const customArgsSchema = lazySchema(() =>
9
+ zodSchema(
10
+ z.object({
11
+ name: z.string(),
12
+ description: z.string().optional(),
13
+ format: z
14
+ .union([
15
+ z.object({
16
+ type: z.literal('grammar'),
17
+ syntax: z.enum(['regex', 'lark']),
18
+ definition: z.string(),
19
+ }),
20
+ z.object({
21
+ type: z.literal('text'),
22
+ }),
23
+ ])
24
+ .optional(),
25
+ }),
26
+ ),
27
+ );
28
+
29
+ const customInputSchema = lazySchema(() => zodSchema(z.string()));
30
+
31
+ export const customToolFactory = createProviderToolFactory<
32
+ string,
33
+ {
34
+ /**
35
+ * The name of the custom tool, used to identify it in the API.
36
+ */
37
+ name: string;
38
+
39
+ /**
40
+ * An optional description of what the tool does.
41
+ */
42
+ description?: string;
43
+
44
+ /**
45
+ * The output format specification for the tool.
46
+ * Omit for unconstrained text output.
47
+ */
48
+ format?:
49
+ | {
50
+ type: 'grammar';
51
+ syntax: 'regex' | 'lark';
52
+ definition: string;
53
+ }
54
+ | {
55
+ type: 'text';
56
+ };
57
+ }
58
+ >({
59
+ id: 'openai.custom',
60
+ inputSchema: customInputSchema,
61
+ });
62
+
63
+ export const customTool = (args: Parameters<typeof customToolFactory>[0]) =>
64
+ customToolFactory(args);