@ai-sdk/openai 3.0.109 → 3.0.111
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 +14 -0
- package/dist/index.d.mts +40 -21
- package/dist/index.d.ts +40 -21
- package/dist/index.js +84 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +84 -22
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +30 -10
- package/dist/internal/index.d.ts +30 -10
- package/dist/internal/index.js +81 -20
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +81 -20
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-openai.mdx +94 -13
- package/package.json +1 -1
- package/src/image/openai-image-model-options.ts +11 -2
- package/src/index.ts +2 -0
- package/src/openai-config.ts +5 -0
- package/src/openai-language-model-capabilities.ts +2 -0
- package/src/openai-tools.ts +2 -1
- package/src/responses/convert-to-openai-responses-input.ts +20 -0
- package/src/responses/openai-responses-api.ts +14 -1
- package/src/responses/openai-responses-language-model.ts +23 -4
- package/src/responses/openai-responses-prepare-tools.ts +48 -1
- package/src/responses/openai-responses-provider-metadata.ts +10 -0
- package/src/tool/custom.ts +7 -0
- package/src/tool/image-generation.ts +10 -5
package/docs/03-openai.mdx
CHANGED
|
@@ -548,6 +548,55 @@ metadata on tool-call parts. The SDK uses `providerMetadata.openai.namespace` or
|
|
|
548
548
|
`providerOptions.openai.namespace` to round-trip the namespace back to OpenAI on
|
|
549
549
|
subsequent requests.
|
|
550
550
|
|
|
551
|
+
#### Async Tool Calling
|
|
552
|
+
|
|
553
|
+
GPT-6 Astra and later Responses models support
|
|
554
|
+
[async tool calling](https://developers.openai.com/api/docs/guides/async-tool-calling).
|
|
555
|
+
An async tool lets the model continue generating independent output after issuing
|
|
556
|
+
the call instead of waiting for its result. Your application still executes the
|
|
557
|
+
tool and sends its result in a later request using the original tool call ID.
|
|
558
|
+
|
|
559
|
+
Enable async calling on a function tool with `providerOptions.openai.async`:
|
|
560
|
+
|
|
561
|
+
```ts
|
|
562
|
+
import { openai, type OpenAIToolOptions } from '@ai-sdk/openai';
|
|
563
|
+
import { generateText, tool } from 'ai';
|
|
564
|
+
import { z } from 'zod';
|
|
565
|
+
|
|
566
|
+
const result = await generateText({
|
|
567
|
+
model: openai.responses('gpt-6-astra'),
|
|
568
|
+
tools: {
|
|
569
|
+
getWeather: tool({
|
|
570
|
+
description: 'Get the weather for a city.',
|
|
571
|
+
inputSchema: z.object({ city: z.string() }),
|
|
572
|
+
outputSchema: z.object({
|
|
573
|
+
city: z.string(),
|
|
574
|
+
temperatureC: z.number(),
|
|
575
|
+
}),
|
|
576
|
+
providerOptions: {
|
|
577
|
+
openai: { async: true } satisfies OpenAIToolOptions,
|
|
578
|
+
},
|
|
579
|
+
}),
|
|
580
|
+
},
|
|
581
|
+
prompt:
|
|
582
|
+
'Start the weather lookup for Paris, then list three general packing essentials without waiting.',
|
|
583
|
+
});
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
The generated tool call exposes the provider marker as
|
|
587
|
+
`providerMetadata.openai.async`. Use `providerMetadata.openai.responseId` as the
|
|
588
|
+
next request's `previousResponseId`, and submit the result in a tool message with
|
|
589
|
+
the original `toolCallId`.
|
|
590
|
+
|
|
591
|
+
With `streamText`, OpenAI can continue streaming text after the completed
|
|
592
|
+
`tool-call` part. Use the tool's `onInputAvailable` callback to start work as soon
|
|
593
|
+
as that part arrives. If `execute` returns the same already-running promise, tool
|
|
594
|
+
execution overlaps the rest of the model stream. Omit `execute` when the job
|
|
595
|
+
should outlive the current generation and submit its result in a later request.
|
|
596
|
+
|
|
597
|
+
Async calling applies to directly called function and custom tools. It does not
|
|
598
|
+
apply to hosted tools.
|
|
599
|
+
|
|
551
600
|
#### Web Search Tool
|
|
552
601
|
|
|
553
602
|
The OpenAI responses API supports web search through the `openai.tools.webSearch` tool.
|
|
@@ -736,6 +785,16 @@ for await (const part of result.fullStream) {
|
|
|
736
785
|
setting `store: false`.
|
|
737
786
|
</Note>
|
|
738
787
|
|
|
788
|
+
To use `xhigh` or `max` quality, select `gpt-image-2.5-flare` or
|
|
789
|
+
`gpt-image-2.5-sunburst` as the image generation tool's model:
|
|
790
|
+
|
|
791
|
+
```ts
|
|
792
|
+
openai.tools.imageGeneration({
|
|
793
|
+
model: 'gpt-image-2.5-flare',
|
|
794
|
+
quality: 'xhigh',
|
|
795
|
+
});
|
|
796
|
+
```
|
|
797
|
+
|
|
739
798
|
For complete details on model availability, image quality controls, supported sizes, and tool-specific parameters,
|
|
740
799
|
refer to the OpenAI documentation:
|
|
741
800
|
|
|
@@ -2560,7 +2619,7 @@ Transform an existing image using text prompts:
|
|
|
2560
2619
|
const imageBuffer = readFileSync('./input-image.png');
|
|
2561
2620
|
|
|
2562
2621
|
const { images } = await generateImage({
|
|
2563
|
-
model: openai.image('gpt-image-2'),
|
|
2622
|
+
model: openai.image('gpt-image-2.5-sunburst'),
|
|
2564
2623
|
prompt: {
|
|
2565
2624
|
text: 'Turn the cat into a dog but retain the style of the original image',
|
|
2566
2625
|
images: [imageBuffer],
|
|
@@ -2577,7 +2636,7 @@ const image = readFileSync('./input-image.png');
|
|
|
2577
2636
|
const mask = readFileSync('./mask.png'); // Transparent areas = edit regions
|
|
2578
2637
|
|
|
2579
2638
|
const { images } = await generateImage({
|
|
2580
|
-
model: openai.image('gpt-image-2'),
|
|
2639
|
+
model: openai.image('gpt-image-2.5-sunburst'),
|
|
2581
2640
|
prompt: {
|
|
2582
2641
|
text: 'A sunlit indoor lounge area with a pool containing a flamingo',
|
|
2583
2642
|
images: [image],
|
|
@@ -2622,7 +2681,7 @@ const owl = readFileSync('./owl.png');
|
|
|
2622
2681
|
const bear = readFileSync('./bear.png');
|
|
2623
2682
|
|
|
2624
2683
|
const { images } = await generateImage({
|
|
2625
|
-
model: openai.image('gpt-image-2'),
|
|
2684
|
+
model: openai.image('gpt-image-2.5-sunburst'),
|
|
2626
2685
|
prompt: {
|
|
2627
2686
|
text: 'Combine these animals into a group photo, retaining the original style',
|
|
2628
2687
|
images: [cat, dog, owl, bear],
|
|
@@ -2638,14 +2697,23 @@ const { images } = await generateImage({
|
|
|
2638
2697
|
|
|
2639
2698
|
### Model Capabilities
|
|
2640
2699
|
|
|
2641
|
-
| Model
|
|
2642
|
-
|
|
|
2643
|
-
| `gpt-image-2`
|
|
2644
|
-
| `gpt-image-
|
|
2645
|
-
| `gpt-image-
|
|
2646
|
-
| `gpt-image-1`
|
|
2647
|
-
| `
|
|
2648
|
-
| `
|
|
2700
|
+
| Model | Sizes |
|
|
2701
|
+
| ------------------------ | -------------------------------------- |
|
|
2702
|
+
| `gpt-image-2.5-flare` | Standard presets and custom dimensions |
|
|
2703
|
+
| `gpt-image-2.5-sunburst` | Standard presets and custom dimensions |
|
|
2704
|
+
| `gpt-image-2` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2705
|
+
| `gpt-image-1.5` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2706
|
+
| `gpt-image-1-mini` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2707
|
+
| `gpt-image-1` | 1024x1024, 1536x1024, 1024x1536 |
|
|
2708
|
+
| `dall-e-3` | 1024x1024, 1792x1024, 1024x1792 |
|
|
2709
|
+
| `dall-e-2` | 256x256, 512x512, 1024x1024 |
|
|
2710
|
+
|
|
2711
|
+
Use `gpt-image-2.5-flare` for fast, general-purpose image generation and
|
|
2712
|
+
`gpt-image-2.5-sunburst` when editing precision and instruction following are
|
|
2713
|
+
the priority. Both models accept custom `WIDTHxHEIGHT` sizes whose dimensions
|
|
2714
|
+
are multiples of 16, with aspect ratios from 1:3 through 3:1, no edge longer
|
|
2715
|
+
than 3840 pixels, and a total area from 655,360 through 8,294,400 pixels.
|
|
2716
|
+
Resolutions above 2560x1440 are experimental.
|
|
2649
2717
|
|
|
2650
2718
|
You can pass optional `providerOptions` to the image model. These are prone to change by OpenAI and are model dependent. For example, the `gpt-image-*` models support the `quality` option:
|
|
2651
2719
|
|
|
@@ -2657,7 +2725,7 @@ import {
|
|
|
2657
2725
|
import { generateImage } from 'ai';
|
|
2658
2726
|
|
|
2659
2727
|
const { image, providerMetadata } = await generateImage({
|
|
2660
|
-
model: openai.image('gpt-image-2'),
|
|
2728
|
+
model: openai.image('gpt-image-2.5-flare'),
|
|
2661
2729
|
prompt: 'A salamander at sunrise in a forest pond in the Seychelles.',
|
|
2662
2730
|
providerOptions: {
|
|
2663
2731
|
openai: { quality: 'high' } satisfies OpenAIImageModelGenerationOptions,
|
|
@@ -2665,6 +2733,19 @@ const { image, providerMetadata } = await generateImage({
|
|
|
2665
2733
|
});
|
|
2666
2734
|
```
|
|
2667
2735
|
|
|
2736
|
+
The `gpt-image-2.5-flare` and `gpt-image-2.5-sunburst` models also support
|
|
2737
|
+
`quality: 'xhigh'` and `quality: 'max'` for both image generation and editing:
|
|
2738
|
+
|
|
2739
|
+
```ts
|
|
2740
|
+
const { image } = await generateImage({
|
|
2741
|
+
model: openai.image('gpt-image-2.5-sunburst'),
|
|
2742
|
+
prompt: 'A salamander at sunrise in a forest pond in the Seychelles.',
|
|
2743
|
+
providerOptions: {
|
|
2744
|
+
openai: { quality: 'max' } satisfies OpenAIImageModelGenerationOptions,
|
|
2745
|
+
},
|
|
2746
|
+
});
|
|
2747
|
+
```
|
|
2748
|
+
|
|
2668
2749
|
For more on `generateImage()` see [Image Generation](/docs/ai-sdk-core/image-generation).
|
|
2669
2750
|
|
|
2670
2751
|
OpenAI's image models return additional metadata in the response that can be
|
|
@@ -2678,7 +2759,7 @@ is available:
|
|
|
2678
2759
|
- `revisedPrompt` _string_ - The revised prompt that was actually used to generate the image (OpenAI may modify your prompt for safety or clarity)
|
|
2679
2760
|
- `created` _number_ - The Unix timestamp (in seconds) of when the image was created
|
|
2680
2761
|
- `size` _string_ - The size of the generated image. One of `1024x1024`, `1024x1536`, or `1536x1024`
|
|
2681
|
-
- `quality` _string_ - The quality of the generated image. One of `low`, `medium`, or `
|
|
2762
|
+
- `quality` _string_ - The quality of the generated image. One of `low`, `medium`, `high`, `xhigh`, or `max`
|
|
2682
2763
|
- `background` _string_ - The background parameter used for the image generation. Either `transparent` or `opaque`
|
|
2683
2764
|
- `outputFormat` _string_ - The output format of the generated image. One of `png`, `webp`, or `jpeg`
|
|
2684
2765
|
|
package/package.json
CHANGED
|
@@ -12,6 +12,10 @@ export type OpenAIImageModelId =
|
|
|
12
12
|
| 'gpt-image-1-mini'
|
|
13
13
|
| 'gpt-image-1.5'
|
|
14
14
|
| 'gpt-image-2'
|
|
15
|
+
| 'gpt-image-2.5-flare'
|
|
16
|
+
| 'gpt-image-2.5-flare-2026-09-08'
|
|
17
|
+
| 'gpt-image-2.5-sunburst'
|
|
18
|
+
| 'gpt-image-2.5-sunburst-2026-09-08'
|
|
15
19
|
| 'chatgpt-image-latest'
|
|
16
20
|
| (string & {});
|
|
17
21
|
|
|
@@ -23,6 +27,10 @@ export const modelMaxImagesPerCall: Record<OpenAIImageModelId, number> = {
|
|
|
23
27
|
'gpt-image-1-mini': 10,
|
|
24
28
|
'gpt-image-1.5': 10,
|
|
25
29
|
'gpt-image-2': 10,
|
|
30
|
+
'gpt-image-2.5-flare': 10,
|
|
31
|
+
'gpt-image-2.5-flare-2026-09-08': 10,
|
|
32
|
+
'gpt-image-2.5-sunburst': 10,
|
|
33
|
+
'gpt-image-2.5-sunburst-2026-09-08': 10,
|
|
26
34
|
'chatgpt-image-latest': 10,
|
|
27
35
|
};
|
|
28
36
|
|
|
@@ -45,10 +53,11 @@ const baseImageModelOptionsObject = z.object({
|
|
|
45
53
|
/**
|
|
46
54
|
* Quality of the generated image(s).
|
|
47
55
|
*
|
|
48
|
-
* Valid values: `standard`, `hd`, `low`, `medium`, `high`, `auto`.
|
|
56
|
+
* Valid values: `standard`, `hd`, `low`, `medium`, `high`, `xhigh`, `max`, `auto`.
|
|
57
|
+
* `xhigh` and `max` are supported by GPT Image 2.5 models.
|
|
49
58
|
*/
|
|
50
59
|
quality: z
|
|
51
|
-
.enum(['standard', 'hd', 'low', 'medium', 'high', 'auto'])
|
|
60
|
+
.enum(['standard', 'hd', 'low', 'medium', 'high', 'xhigh', 'max', 'auto'])
|
|
52
61
|
.optional(),
|
|
53
62
|
|
|
54
63
|
/**
|
package/src/index.ts
CHANGED
|
@@ -19,9 +19,11 @@ export type { OpenAILanguageModelCompletionOptions } from './completion/openai-c
|
|
|
19
19
|
export type { OpenAIEmbeddingModelOptions } from './embedding/openai-embedding-options';
|
|
20
20
|
export type { OpenAISpeechModelOptions } from './speech/openai-speech-options';
|
|
21
21
|
export type { OpenAITranscriptionModelOptions } from './transcription/openai-transcription-options';
|
|
22
|
+
export type { OpenAIToolOptions } from './responses/openai-responses-prepare-tools';
|
|
22
23
|
export type {
|
|
23
24
|
OpenaiResponsesProviderMetadata,
|
|
24
25
|
OpenaiResponsesReasoningProviderMetadata,
|
|
26
|
+
OpenaiResponsesToolCallProviderMetadata,
|
|
25
27
|
OpenaiResponsesTextProviderMetadata,
|
|
26
28
|
OpenaiResponsesSourceDocumentProviderMetadata,
|
|
27
29
|
} from './responses/openai-responses-provider-metadata';
|
package/src/openai-config.ts
CHANGED
|
@@ -6,6 +6,11 @@ export type OpenAIConfig = {
|
|
|
6
6
|
headers: () => Record<string, string | undefined>;
|
|
7
7
|
fetch?: FetchFunction;
|
|
8
8
|
generateId?: () => string;
|
|
9
|
+
/**
|
|
10
|
+
* Whether Responses API message input items must include an explicit
|
|
11
|
+
* `type: 'message'` discriminator.
|
|
12
|
+
*/
|
|
13
|
+
explicitMessageItemType?: boolean;
|
|
9
14
|
/**
|
|
10
15
|
* File ID prefixes used to identify file IDs in Responses API.
|
|
11
16
|
* When undefined, all file data is treated as base64 content.
|
|
@@ -4,6 +4,7 @@ export type OpenAILanguageModelCapabilities = {
|
|
|
4
4
|
supportsFlexProcessing: boolean;
|
|
5
5
|
supportsPriorityProcessing: boolean;
|
|
6
6
|
supportsConfigurationUpdate: boolean;
|
|
7
|
+
supportsAsyncToolCalling: boolean;
|
|
7
8
|
supportedReasoningEfforts: readonly string[] | undefined;
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -55,6 +56,7 @@ export function getOpenAILanguageModelCapabilities(
|
|
|
55
56
|
supportsFlexProcessing,
|
|
56
57
|
supportsPriorityProcessing,
|
|
57
58
|
supportsConfigurationUpdate: isGpt6OrLaterModel,
|
|
59
|
+
supportsAsyncToolCalling: isGpt6OrLaterModel,
|
|
58
60
|
supportedReasoningEfforts: isGpt6OrLaterModel
|
|
59
61
|
? ['low', 'medium', 'high', 'xhigh', 'max']
|
|
60
62
|
: undefined,
|
package/src/openai-tools.ts
CHANGED
|
@@ -27,6 +27,7 @@ export const openaiTools = {
|
|
|
27
27
|
*
|
|
28
28
|
* @param name - The name of the custom tool.
|
|
29
29
|
* @param description - An optional description of the tool.
|
|
30
|
+
* @param async - Whether the model can continue without waiting for the tool result.
|
|
30
31
|
* @param format - The output format constraint (grammar type, syntax, and definition).
|
|
31
32
|
*/
|
|
32
33
|
customTool,
|
|
@@ -65,7 +66,7 @@ export const openaiTools = {
|
|
|
65
66
|
* @param outputCompression - Compression level for the output image (0-100).
|
|
66
67
|
* @param outputFormat - The output format of the generated image. One of 'png', 'jpeg', or 'webp'.
|
|
67
68
|
* @param partialImages - Number of partial images to generate in streaming mode (0-3).
|
|
68
|
-
* @param quality - The quality of the generated image. One of 'auto', 'low', 'medium', or '
|
|
69
|
+
* @param quality - The quality of the generated image. One of 'auto', 'low', 'medium', 'high', 'xhigh', or 'max'. 'xhigh' and 'max' require a GPT Image 2.5 model.
|
|
69
70
|
* @param size - The size of the generated image. One of 'auto', '1024x1024', '1024x1536', or '1536x1024'.
|
|
70
71
|
*/
|
|
71
72
|
imageGeneration,
|
|
@@ -296,6 +296,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
296
296
|
toolNameMapping,
|
|
297
297
|
systemMessageMode,
|
|
298
298
|
providerOptionsName,
|
|
299
|
+
explicitMessageItemType = false,
|
|
299
300
|
fileIdPrefixes,
|
|
300
301
|
passThroughUnsupportedFiles = false,
|
|
301
302
|
store,
|
|
@@ -311,6 +312,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
311
312
|
toolNameMapping: ToolNameMapping;
|
|
312
313
|
systemMessageMode: 'system' | 'developer' | 'remove';
|
|
313
314
|
providerOptionsName: string;
|
|
315
|
+
explicitMessageItemType?: boolean;
|
|
314
316
|
fileIdPrefixes?: readonly string[];
|
|
315
317
|
passThroughUnsupportedFiles?: boolean;
|
|
316
318
|
store: boolean;
|
|
@@ -348,6 +350,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
348
350
|
providerOptionsName,
|
|
349
351
|
);
|
|
350
352
|
input.push({
|
|
353
|
+
...(explicitMessageItemType && { type: 'message' as const }),
|
|
351
354
|
role: 'system',
|
|
352
355
|
content:
|
|
353
356
|
promptCacheBreakpoint == null
|
|
@@ -368,6 +371,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
368
371
|
providerOptionsName,
|
|
369
372
|
);
|
|
370
373
|
input.push({
|
|
374
|
+
...(explicitMessageItemType && { type: 'message' as const }),
|
|
371
375
|
role: 'developer',
|
|
372
376
|
content:
|
|
373
377
|
promptCacheBreakpoint == null
|
|
@@ -401,6 +405,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
401
405
|
|
|
402
406
|
case 'user': {
|
|
403
407
|
input.push({
|
|
408
|
+
...(explicitMessageItemType && { type: 'message' as const }),
|
|
404
409
|
role: 'user',
|
|
405
410
|
content: content.map((part, index) => {
|
|
406
411
|
switch (part.type) {
|
|
@@ -514,6 +519,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
514
519
|
}
|
|
515
520
|
|
|
516
521
|
input.push({
|
|
522
|
+
...(explicitMessageItemType && { type: 'message' as const }),
|
|
517
523
|
role: 'assistant',
|
|
518
524
|
content: [{ type: 'output_text', text: part.text }],
|
|
519
525
|
id,
|
|
@@ -589,6 +595,18 @@ export async function convertToOpenAIResponsesInput({
|
|
|
589
595
|
| string
|
|
590
596
|
| undefined;
|
|
591
597
|
|
|
598
|
+
const isAsync = (part.providerOptions?.[providerOptionsName]
|
|
599
|
+
?.async ??
|
|
600
|
+
(
|
|
601
|
+
part as {
|
|
602
|
+
providerMetadata?: {
|
|
603
|
+
[providerOptionsName]?: { async?: boolean };
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
).providerMetadata?.[providerOptionsName]?.async) as
|
|
607
|
+
| boolean
|
|
608
|
+
| undefined;
|
|
609
|
+
|
|
592
610
|
if (hasConversation && id != null) {
|
|
593
611
|
break;
|
|
594
612
|
}
|
|
@@ -739,6 +757,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
739
757
|
typeof part.input === 'string'
|
|
740
758
|
? part.input
|
|
741
759
|
: JSON.stringify(part.input),
|
|
760
|
+
...(isAsync != null && { async: isAsync }),
|
|
742
761
|
id,
|
|
743
762
|
});
|
|
744
763
|
break;
|
|
@@ -749,6 +768,7 @@ export async function convertToOpenAIResponsesInput({
|
|
|
749
768
|
call_id: part.toolCallId,
|
|
750
769
|
name: resolvedToolName,
|
|
751
770
|
arguments: serializeToolCallArguments(part.input),
|
|
771
|
+
...(isAsync != null && { async: isAsync }),
|
|
752
772
|
...(namespace != null && { namespace }),
|
|
753
773
|
});
|
|
754
774
|
break;
|
|
@@ -121,6 +121,7 @@ export type OpenAIResponsesApplyPatchOperationDiffDoneChunk = {
|
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
export type OpenAIResponsesSystemMessage = {
|
|
124
|
+
type?: 'message';
|
|
124
125
|
role: 'system' | 'developer';
|
|
125
126
|
content:
|
|
126
127
|
| string
|
|
@@ -132,6 +133,7 @@ export type OpenAIResponsesSystemMessage = {
|
|
|
132
133
|
};
|
|
133
134
|
|
|
134
135
|
export type OpenAIResponsesUserMessage = {
|
|
136
|
+
type?: 'message';
|
|
135
137
|
role: 'user';
|
|
136
138
|
content: Array<
|
|
137
139
|
| {
|
|
@@ -169,6 +171,7 @@ export type OpenAIResponsesUserMessage = {
|
|
|
169
171
|
};
|
|
170
172
|
|
|
171
173
|
export type OpenAIResponsesAssistantMessage = {
|
|
174
|
+
type?: 'message';
|
|
172
175
|
role: 'assistant';
|
|
173
176
|
content: Array<{ type: 'output_text'; text: string }>;
|
|
174
177
|
id?: string;
|
|
@@ -180,6 +183,7 @@ export type OpenAIResponsesFunctionCall = {
|
|
|
180
183
|
call_id: string;
|
|
181
184
|
name: string;
|
|
182
185
|
arguments: string;
|
|
186
|
+
async?: boolean;
|
|
183
187
|
id?: string;
|
|
184
188
|
namespace?: string;
|
|
185
189
|
};
|
|
@@ -220,6 +224,7 @@ export type OpenAIResponsesCustomToolCall = {
|
|
|
220
224
|
call_id: string;
|
|
221
225
|
name: string;
|
|
222
226
|
input: string;
|
|
227
|
+
async?: boolean;
|
|
223
228
|
};
|
|
224
229
|
|
|
225
230
|
export type OpenAIResponsesCustomToolCallOutput = {
|
|
@@ -373,6 +378,7 @@ export type OpenAIResponsesFunctionTool = {
|
|
|
373
378
|
name: string;
|
|
374
379
|
description: string | undefined;
|
|
375
380
|
parameters: JSONSchema7;
|
|
381
|
+
async?: boolean;
|
|
376
382
|
strict?: boolean;
|
|
377
383
|
defer_loading?: boolean;
|
|
378
384
|
};
|
|
@@ -467,7 +473,7 @@ export type OpenAIResponsesTool =
|
|
|
467
473
|
output_compression: number | undefined;
|
|
468
474
|
output_format: 'png' | 'jpeg' | 'webp' | undefined;
|
|
469
475
|
partial_images: number | undefined;
|
|
470
|
-
quality: 'auto' | 'low' | 'medium' | 'high' | undefined;
|
|
476
|
+
quality: 'auto' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | undefined;
|
|
471
477
|
size: 'auto' | '1024x1024' | '1024x1536' | '1536x1024' | undefined;
|
|
472
478
|
}
|
|
473
479
|
|
|
@@ -501,6 +507,7 @@ export type OpenAIResponsesTool =
|
|
|
501
507
|
type: 'custom';
|
|
502
508
|
name: string;
|
|
503
509
|
description?: string;
|
|
510
|
+
async?: boolean;
|
|
504
511
|
format?:
|
|
505
512
|
| {
|
|
506
513
|
type: 'grammar';
|
|
@@ -772,6 +779,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
772
779
|
call_id: z.string(),
|
|
773
780
|
name: z.string(),
|
|
774
781
|
arguments: z.string(),
|
|
782
|
+
async: z.boolean().nullish(),
|
|
775
783
|
namespace: z.string().nullish(),
|
|
776
784
|
}),
|
|
777
785
|
z.object({
|
|
@@ -850,6 +858,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
850
858
|
call_id: z.string(),
|
|
851
859
|
name: z.string(),
|
|
852
860
|
input: z.string(),
|
|
861
|
+
async: z.boolean().nullish(),
|
|
853
862
|
}),
|
|
854
863
|
z.object({
|
|
855
864
|
type: z.literal('shell_call'),
|
|
@@ -917,6 +926,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
917
926
|
call_id: z.string(),
|
|
918
927
|
name: z.string(),
|
|
919
928
|
arguments: z.string(),
|
|
929
|
+
async: z.boolean().nullish(),
|
|
920
930
|
status: z.literal('completed'),
|
|
921
931
|
namespace: z.string().nullish(),
|
|
922
932
|
}),
|
|
@@ -926,6 +936,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
926
936
|
call_id: z.string(),
|
|
927
937
|
name: z.string(),
|
|
928
938
|
input: z.string(),
|
|
939
|
+
async: z.boolean().nullish(),
|
|
929
940
|
status: z.literal('completed'),
|
|
930
941
|
}),
|
|
931
942
|
z.object({
|
|
@@ -1410,6 +1421,7 @@ export const openaiResponsesResponseSchema = lazySchema(() =>
|
|
|
1410
1421
|
name: z.string(),
|
|
1411
1422
|
arguments: z.string(),
|
|
1412
1423
|
id: z.string(),
|
|
1424
|
+
async: z.boolean().nullish(),
|
|
1413
1425
|
namespace: z.string().nullish(),
|
|
1414
1426
|
}),
|
|
1415
1427
|
z.object({
|
|
@@ -1418,6 +1430,7 @@ export const openaiResponsesResponseSchema = lazySchema(() =>
|
|
|
1418
1430
|
name: z.string(),
|
|
1419
1431
|
input: z.string(),
|
|
1420
1432
|
id: z.string(),
|
|
1433
|
+
async: z.boolean().nullish(),
|
|
1421
1434
|
}),
|
|
1422
1435
|
z.object({
|
|
1423
1436
|
type: z.literal('computer_call'),
|
|
@@ -80,6 +80,7 @@ import type {
|
|
|
80
80
|
ResponsesReasoningProviderMetadata,
|
|
81
81
|
ResponsesSourceDocumentProviderMetadata,
|
|
82
82
|
ResponsesTextProviderMetadata,
|
|
83
|
+
ResponsesToolCallProviderMetadata,
|
|
83
84
|
} from './openai-responses-provider-metadata';
|
|
84
85
|
|
|
85
86
|
/**
|
|
@@ -242,6 +243,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
242
243
|
allowedTools: openaiOptions?.allowedTools ?? undefined,
|
|
243
244
|
toolNameMapping,
|
|
244
245
|
customProviderToolNames,
|
|
246
|
+
supportsAsyncToolCalling: modelCapabilities.supportsAsyncToolCalling,
|
|
245
247
|
});
|
|
246
248
|
|
|
247
249
|
const { input, warnings: inputWarnings } =
|
|
@@ -254,6 +256,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
254
256
|
? 'developer'
|
|
255
257
|
: modelCapabilities.systemMessageMode),
|
|
256
258
|
providerOptionsName,
|
|
259
|
+
explicitMessageItemType: this.config.explicitMessageItemType,
|
|
257
260
|
fileIdPrefixes: this.config.fileIdPrefixes,
|
|
258
261
|
passThroughUnsupportedFiles:
|
|
259
262
|
openaiOptions?.passThroughUnsupportedFiles ?? false,
|
|
@@ -910,8 +913,9 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
910
913
|
providerMetadata: {
|
|
911
914
|
[providerOptionsName]: {
|
|
912
915
|
itemId: part.id,
|
|
916
|
+
...(part.async != null && { async: part.async }),
|
|
913
917
|
...(part.namespace != null && { namespace: part.namespace }),
|
|
914
|
-
},
|
|
918
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
915
919
|
},
|
|
916
920
|
});
|
|
917
921
|
break;
|
|
@@ -929,7 +933,8 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
929
933
|
providerMetadata: {
|
|
930
934
|
[providerOptionsName]: {
|
|
931
935
|
itemId: part.id,
|
|
932
|
-
|
|
936
|
+
...(part.async != null && { async: part.async }),
|
|
937
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
933
938
|
},
|
|
934
939
|
});
|
|
935
940
|
break;
|
|
@@ -1242,6 +1247,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1242
1247
|
toolSearchExecution?: 'server' | 'client';
|
|
1243
1248
|
suppressInputStreaming?: boolean;
|
|
1244
1249
|
bufferedInputDeltas?: string[];
|
|
1250
|
+
async?: boolean | null;
|
|
1245
1251
|
}
|
|
1246
1252
|
| undefined
|
|
1247
1253
|
> = {};
|
|
@@ -1321,6 +1327,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1321
1327
|
toolCallId: value.item.call_id,
|
|
1322
1328
|
suppressInputStreaming,
|
|
1323
1329
|
bufferedInputDeltas: suppressInputStreaming ? [] : undefined,
|
|
1330
|
+
async: value.item.async,
|
|
1324
1331
|
};
|
|
1325
1332
|
|
|
1326
1333
|
if (!suppressInputStreaming) {
|
|
@@ -1337,6 +1344,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1337
1344
|
ongoingToolCalls[value.output_index] = {
|
|
1338
1345
|
toolName,
|
|
1339
1346
|
toolCallId: value.item.call_id,
|
|
1347
|
+
async: value.item.async,
|
|
1340
1348
|
};
|
|
1341
1349
|
|
|
1342
1350
|
controller.enqueue({
|
|
@@ -1620,10 +1628,15 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1620
1628
|
providerMetadata: {
|
|
1621
1629
|
[providerOptionsName]: {
|
|
1622
1630
|
itemId: item.id,
|
|
1631
|
+
...(item.async != null
|
|
1632
|
+
? { async: item.async }
|
|
1633
|
+
: ongoingToolCall?.async != null
|
|
1634
|
+
? { async: ongoingToolCall.async }
|
|
1635
|
+
: {}),
|
|
1623
1636
|
...(item.namespace != null && {
|
|
1624
1637
|
namespace: item.namespace,
|
|
1625
1638
|
}),
|
|
1626
|
-
},
|
|
1639
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
1627
1640
|
},
|
|
1628
1641
|
});
|
|
1629
1642
|
};
|
|
@@ -1667,6 +1680,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1667
1680
|
}
|
|
1668
1681
|
});
|
|
1669
1682
|
} else if (value.item.type === 'custom_tool_call') {
|
|
1683
|
+
const ongoingToolCall = ongoingToolCalls[value.output_index];
|
|
1670
1684
|
ongoingToolCalls[value.output_index] = undefined;
|
|
1671
1685
|
hasFunctionCall = true;
|
|
1672
1686
|
const toolName = toolNameMapping.toCustomToolName(
|
|
@@ -1686,7 +1700,12 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
|
|
|
1686
1700
|
providerMetadata: {
|
|
1687
1701
|
[providerOptionsName]: {
|
|
1688
1702
|
itemId: value.item.id,
|
|
1689
|
-
|
|
1703
|
+
...(value.item.async != null
|
|
1704
|
+
? { async: value.item.async }
|
|
1705
|
+
: ongoingToolCall?.async != null
|
|
1706
|
+
? { async: ongoingToolCall.async }
|
|
1707
|
+
: {}),
|
|
1708
|
+
} satisfies ResponsesToolCallProviderMetadata,
|
|
1690
1709
|
},
|
|
1691
1710
|
});
|
|
1692
1711
|
} else if (value.item.type === 'web_search_call') {
|
|
@@ -24,7 +24,12 @@ type AllowedToolResolution =
|
|
|
24
24
|
| { supported: true; entry: OpenAIResponsesAllowedTool }
|
|
25
25
|
| { supported: false; reason: string };
|
|
26
26
|
|
|
27
|
-
type OpenAIToolOptions = {
|
|
27
|
+
export type OpenAIToolOptions = {
|
|
28
|
+
/**
|
|
29
|
+
* Whether the model can continue generating after calling this tool without
|
|
30
|
+
* waiting for its result.
|
|
31
|
+
*/
|
|
32
|
+
async?: boolean;
|
|
28
33
|
deferLoading?: boolean;
|
|
29
34
|
namespace?: {
|
|
30
35
|
name: string;
|
|
@@ -38,6 +43,7 @@ export async function prepareResponsesTools({
|
|
|
38
43
|
allowedTools,
|
|
39
44
|
toolNameMapping,
|
|
40
45
|
customProviderToolNames,
|
|
46
|
+
supportsAsyncToolCalling = true,
|
|
41
47
|
}: {
|
|
42
48
|
tools: LanguageModelV3CallOptions['tools'];
|
|
43
49
|
toolChoice: LanguageModelV3CallOptions['toolChoice'] | undefined;
|
|
@@ -47,6 +53,7 @@ export async function prepareResponsesTools({
|
|
|
47
53
|
};
|
|
48
54
|
toolNameMapping?: ToolNameMapping;
|
|
49
55
|
customProviderToolNames?: Set<string>;
|
|
56
|
+
supportsAsyncToolCalling?: boolean;
|
|
50
57
|
}): Promise<{
|
|
51
58
|
tools?: Array<OpenAIResponsesTool>;
|
|
52
59
|
toolChoice?:
|
|
@@ -124,6 +131,12 @@ export async function prepareResponsesTools({
|
|
|
124
131
|
const openaiFunctionTool = prepareFunctionTool({
|
|
125
132
|
tool,
|
|
126
133
|
options: openaiOptions,
|
|
134
|
+
async: resolveAsyncToolOption({
|
|
135
|
+
value: openaiOptions?.async,
|
|
136
|
+
supportsAsyncToolCalling,
|
|
137
|
+
toolName: tool.name,
|
|
138
|
+
toolWarnings,
|
|
139
|
+
}),
|
|
127
140
|
});
|
|
128
141
|
const namespace = openaiOptions?.namespace;
|
|
129
142
|
|
|
@@ -355,6 +368,14 @@ export async function prepareResponsesTools({
|
|
|
355
368
|
type: 'custom',
|
|
356
369
|
name: args.name,
|
|
357
370
|
description: args.description,
|
|
371
|
+
...(resolveAsyncToolOption({
|
|
372
|
+
value: args.async,
|
|
373
|
+
supportsAsyncToolCalling,
|
|
374
|
+
toolName: args.name,
|
|
375
|
+
toolWarnings,
|
|
376
|
+
}) != null
|
|
377
|
+
? { async: args.async }
|
|
378
|
+
: {}),
|
|
358
379
|
format: args.format,
|
|
359
380
|
});
|
|
360
381
|
resolvedCustomProviderToolNames.add(args.name);
|
|
@@ -573,9 +594,11 @@ function toAllowedToolResolution(
|
|
|
573
594
|
function prepareFunctionTool({
|
|
574
595
|
tool,
|
|
575
596
|
options,
|
|
597
|
+
async,
|
|
576
598
|
}: {
|
|
577
599
|
tool: LanguageModelV3FunctionTool;
|
|
578
600
|
options: OpenAIToolOptions | undefined;
|
|
601
|
+
async: boolean | undefined;
|
|
579
602
|
}): OpenAIResponsesFunctionTool {
|
|
580
603
|
const deferLoading = options?.deferLoading;
|
|
581
604
|
|
|
@@ -584,11 +607,35 @@ function prepareFunctionTool({
|
|
|
584
607
|
name: tool.name,
|
|
585
608
|
description: tool.description,
|
|
586
609
|
parameters: tool.inputSchema,
|
|
610
|
+
...(async != null ? { async } : {}),
|
|
587
611
|
...(tool.strict != null ? { strict: tool.strict } : {}),
|
|
588
612
|
...(deferLoading != null ? { defer_loading: deferLoading } : {}),
|
|
589
613
|
};
|
|
590
614
|
}
|
|
591
615
|
|
|
616
|
+
function resolveAsyncToolOption({
|
|
617
|
+
value,
|
|
618
|
+
supportsAsyncToolCalling,
|
|
619
|
+
toolName,
|
|
620
|
+
toolWarnings,
|
|
621
|
+
}: {
|
|
622
|
+
value: boolean | undefined;
|
|
623
|
+
supportsAsyncToolCalling: boolean;
|
|
624
|
+
toolName: string;
|
|
625
|
+
toolWarnings: SharedV3Warning[];
|
|
626
|
+
}): boolean | undefined {
|
|
627
|
+
if (value !== true || supportsAsyncToolCalling) {
|
|
628
|
+
return value;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
toolWarnings.push({
|
|
632
|
+
type: 'unsupported',
|
|
633
|
+
feature: `async tool calling for "${toolName}"`,
|
|
634
|
+
details: 'Async tool calling is only supported by GPT-6 and later models.',
|
|
635
|
+
});
|
|
636
|
+
return undefined;
|
|
637
|
+
}
|
|
638
|
+
|
|
592
639
|
function mapShellEnvironment(environment: {
|
|
593
640
|
type?: string;
|
|
594
641
|
[key: string]: unknown;
|