@ai-sdk/openai 4.0.47 → 4.0.50
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 +27 -0
- package/dist/index.d.ts +29 -12
- package/dist/index.js +384 -278
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +45 -26
- package/dist/internal/index.js +280 -170
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +31 -11
- package/package.json +2 -2
- package/src/chat/convert-to-openai-chat-messages.ts +5 -1
- package/src/chat/openai-chat-language-model.ts +9 -2
- package/src/completion/openai-completion-language-model.ts +9 -2
- package/src/embedding/openai-embedding-model.ts +2 -0
- package/src/openai-responses-batch.ts +90 -102
- package/src/openai-stream-error.ts +68 -15
- package/src/responses/convert-to-openai-responses-input.ts +5 -3
- package/src/responses/openai-responses-api.ts +114 -40
- package/src/responses/openai-responses-language-model.ts +35 -21
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JSONObject, JSONSchema7, JSONValue } from '@ai-sdk/provider';
|
|
2
2
|
import {
|
|
3
|
+
isRecord,
|
|
3
4
|
lazySchema,
|
|
4
5
|
zodSchema,
|
|
5
6
|
type InferSchema,
|
|
@@ -108,6 +109,20 @@ const openaiResponsesProgramOutputSchema = z.object({
|
|
|
108
109
|
status: z.enum(['completed', 'incomplete']),
|
|
109
110
|
});
|
|
110
111
|
|
|
112
|
+
const openaiResponsesLocalShellCallSchema = z.object({
|
|
113
|
+
type: z.literal('local_shell_call'),
|
|
114
|
+
id: z.string(),
|
|
115
|
+
call_id: z.string(),
|
|
116
|
+
action: z.object({
|
|
117
|
+
type: z.literal('exec'),
|
|
118
|
+
command: z.array(z.string()),
|
|
119
|
+
timeout_ms: z.number().optional(),
|
|
120
|
+
user: z.string().optional(),
|
|
121
|
+
working_directory: z.string().optional(),
|
|
122
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
125
|
+
|
|
111
126
|
export type OpenAIResponsesInput = Array<OpenAIResponsesInputItem>;
|
|
112
127
|
|
|
113
128
|
export type OpenAIResponsesInputItem =
|
|
@@ -326,19 +341,9 @@ export type OpenAIResponsesComputerCallOutput = {
|
|
|
326
341
|
}>;
|
|
327
342
|
};
|
|
328
343
|
|
|
329
|
-
export type OpenAIResponsesLocalShellCall =
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
call_id: string;
|
|
333
|
-
action: {
|
|
334
|
-
type: 'exec';
|
|
335
|
-
command: string[];
|
|
336
|
-
timeout_ms?: number;
|
|
337
|
-
user?: string;
|
|
338
|
-
working_directory?: string;
|
|
339
|
-
env?: Record<string, string>;
|
|
340
|
-
};
|
|
341
|
-
};
|
|
344
|
+
export type OpenAIResponsesLocalShellCall = InferSchema<
|
|
345
|
+
typeof openaiResponsesLocalShellCallSchema
|
|
346
|
+
>;
|
|
342
347
|
|
|
343
348
|
export type OpenAIResponsesLocalShellCallOutput = {
|
|
344
349
|
type: 'local_shell_call_output';
|
|
@@ -709,7 +714,8 @@ const openaiResponsesNestedErrorChunkSchema = z.object({
|
|
|
709
714
|
});
|
|
710
715
|
|
|
711
716
|
// Current OpenAI OpenAPI docs define ResponseErrorEvent with top-level
|
|
712
|
-
// code/message/param fields
|
|
717
|
+
// code/message/param fields:
|
|
718
|
+
// https://developers.openai.com/api/reference/resources/responses/streaming-events
|
|
713
719
|
const openaiResponsesErrorChunkSchema = z.object({
|
|
714
720
|
type: z.literal('error'),
|
|
715
721
|
sequence_number: z.number(),
|
|
@@ -718,6 +724,86 @@ const openaiResponsesErrorChunkSchema = z.object({
|
|
|
718
724
|
param: z.string().nullish(),
|
|
719
725
|
});
|
|
720
726
|
|
|
727
|
+
/**
|
|
728
|
+
* Chunk types explicitly modeled by openaiResponsesChunkSchema. Keep this set
|
|
729
|
+
* in sync with the union below. OpenAI's complete event catalog:
|
|
730
|
+
* https://developers.openai.com/api/reference/resources/responses/streaming-events
|
|
731
|
+
*/
|
|
732
|
+
const openaiResponsesModeledChunkTypes = new Set([
|
|
733
|
+
'error',
|
|
734
|
+
'response.apply_patch_call_operation_diff.delta',
|
|
735
|
+
'response.apply_patch_call_operation_diff.done',
|
|
736
|
+
'response.code_interpreter_call_code.delta',
|
|
737
|
+
'response.code_interpreter_call_code.done',
|
|
738
|
+
'response.completed',
|
|
739
|
+
'response.created',
|
|
740
|
+
'response.custom_tool_call_input.delta',
|
|
741
|
+
'response.failed',
|
|
742
|
+
'response.function_call_arguments.delta',
|
|
743
|
+
'response.function_call_arguments.done',
|
|
744
|
+
'response.image_generation_call.partial_image',
|
|
745
|
+
'response.in_progress',
|
|
746
|
+
'response.incomplete',
|
|
747
|
+
'response.output_item.added',
|
|
748
|
+
'response.output_item.done',
|
|
749
|
+
'response.output_text.annotation.added',
|
|
750
|
+
'response.output_text.delta',
|
|
751
|
+
'response.reasoning_summary_part.added',
|
|
752
|
+
'response.reasoning_summary_part.done',
|
|
753
|
+
'response.reasoning_summary_text.delta',
|
|
754
|
+
]);
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Output item types explicitly modeled by both output item event schemas below.
|
|
758
|
+
* OpenAI's complete ResponseOutputItem schema:
|
|
759
|
+
* https://developers.openai.com/api/reference/resources/responses#(resource)%20responses%20%3E%20(model)%20response_output_item%20%3E%20(schema)
|
|
760
|
+
*/
|
|
761
|
+
const openaiResponsesModeledOutputItemTypes = new Set([
|
|
762
|
+
'apply_patch_call',
|
|
763
|
+
'code_interpreter_call',
|
|
764
|
+
'compaction',
|
|
765
|
+
'computer_call',
|
|
766
|
+
'custom_tool_call',
|
|
767
|
+
'file_search_call',
|
|
768
|
+
'function_call',
|
|
769
|
+
'image_generation_call',
|
|
770
|
+
'local_shell_call',
|
|
771
|
+
'mcp_approval_request',
|
|
772
|
+
'mcp_call',
|
|
773
|
+
'mcp_list_tools',
|
|
774
|
+
'message',
|
|
775
|
+
'program',
|
|
776
|
+
'program_output',
|
|
777
|
+
'reasoning',
|
|
778
|
+
'shell_call',
|
|
779
|
+
'shell_call_output',
|
|
780
|
+
'tool_search_call',
|
|
781
|
+
'tool_search_output',
|
|
782
|
+
'web_search_call',
|
|
783
|
+
]);
|
|
784
|
+
|
|
785
|
+
function isModeledOpenAIResponsesChunk(value: Record<string, unknown>) {
|
|
786
|
+
if (
|
|
787
|
+
typeof value.type !== 'string' ||
|
|
788
|
+
!openaiResponsesModeledChunkTypes.has(value.type)
|
|
789
|
+
) {
|
|
790
|
+
return false;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
if (
|
|
794
|
+
value.type !== 'response.output_item.added' &&
|
|
795
|
+
value.type !== 'response.output_item.done'
|
|
796
|
+
) {
|
|
797
|
+
return true;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
if (!isRecord(value.item) || typeof value.item.type !== 'string') {
|
|
801
|
+
return true;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
return openaiResponsesModeledOutputItemTypes.has(value.item.type);
|
|
805
|
+
}
|
|
806
|
+
|
|
721
807
|
export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
722
808
|
zodSchema(
|
|
723
809
|
z.union([
|
|
@@ -863,6 +949,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
863
949
|
type: z.literal('file_search_call'),
|
|
864
950
|
id: z.string(),
|
|
865
951
|
}),
|
|
952
|
+
openaiResponsesLocalShellCallSchema,
|
|
866
953
|
z.object({
|
|
867
954
|
type: z.literal('image_generation_call'),
|
|
868
955
|
id: z.string(),
|
|
@@ -1079,19 +1166,7 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
1079
1166
|
)
|
|
1080
1167
|
.nullish(),
|
|
1081
1168
|
}),
|
|
1082
|
-
|
|
1083
|
-
type: z.literal('local_shell_call'),
|
|
1084
|
-
id: z.string(),
|
|
1085
|
-
call_id: z.string(),
|
|
1086
|
-
action: z.object({
|
|
1087
|
-
type: z.literal('exec'),
|
|
1088
|
-
command: z.array(z.string()),
|
|
1089
|
-
timeout_ms: z.number().optional(),
|
|
1090
|
-
user: z.string().optional(),
|
|
1091
|
-
working_directory: z.string().optional(),
|
|
1092
|
-
env: z.record(z.string(), z.string()).optional(),
|
|
1093
|
-
}),
|
|
1094
|
-
}),
|
|
1169
|
+
openaiResponsesLocalShellCallSchema,
|
|
1095
1170
|
openaiResponsesComputerCallSchema,
|
|
1096
1171
|
z.object({
|
|
1097
1172
|
type: z.literal('mcp_call'),
|
|
@@ -1227,6 +1302,14 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
1227
1302
|
output_index: z.number(),
|
|
1228
1303
|
delta: z.string(),
|
|
1229
1304
|
}),
|
|
1305
|
+
z.object({
|
|
1306
|
+
// `name` is documented as required but omitted from live API events:
|
|
1307
|
+
// https://github.com/openai/openai-openapi/issues/545
|
|
1308
|
+
type: z.literal('response.function_call_arguments.done'),
|
|
1309
|
+
item_id: z.string(),
|
|
1310
|
+
output_index: z.number(),
|
|
1311
|
+
arguments: z.string(),
|
|
1312
|
+
}),
|
|
1230
1313
|
z.object({
|
|
1231
1314
|
type: z.literal('response.custom_tool_call_input.delta'),
|
|
1232
1315
|
item_id: z.string(),
|
|
@@ -1319,6 +1402,9 @@ export const openaiResponsesChunkSchema = lazySchema(() =>
|
|
|
1319
1402
|
z
|
|
1320
1403
|
.object({ type: z.string() })
|
|
1321
1404
|
.loose()
|
|
1405
|
+
.refine(value => !isModeledOpenAIResponsesChunk(value), {
|
|
1406
|
+
message: 'Known response chunk failed schema validation',
|
|
1407
|
+
})
|
|
1322
1408
|
.transform(value => ({
|
|
1323
1409
|
type: 'unknown_chunk' as const,
|
|
1324
1410
|
message: value.type,
|
|
@@ -1490,19 +1576,7 @@ export const openaiResponsesResponseSchema = lazySchema(() =>
|
|
|
1490
1576
|
id: z.string(),
|
|
1491
1577
|
result: z.string(),
|
|
1492
1578
|
}),
|
|
1493
|
-
|
|
1494
|
-
type: z.literal('local_shell_call'),
|
|
1495
|
-
id: z.string(),
|
|
1496
|
-
call_id: z.string(),
|
|
1497
|
-
action: z.object({
|
|
1498
|
-
type: z.literal('exec'),
|
|
1499
|
-
command: z.array(z.string()),
|
|
1500
|
-
timeout_ms: z.number().optional(),
|
|
1501
|
-
user: z.string().optional(),
|
|
1502
|
-
working_directory: z.string().optional(),
|
|
1503
|
-
env: z.record(z.string(), z.string()).optional(),
|
|
1504
|
-
}),
|
|
1505
|
-
}),
|
|
1579
|
+
openaiResponsesLocalShellCallSchema,
|
|
1506
1580
|
z.object({
|
|
1507
1581
|
type: z.literal('function_call'),
|
|
1508
1582
|
call_id: z.string(),
|
|
@@ -33,7 +33,10 @@ import {
|
|
|
33
33
|
import type { OpenAIConfig } from '../openai-config';
|
|
34
34
|
import { openaiFailedResponseHandler } from '../openai-error';
|
|
35
35
|
import { getOpenAILanguageModelCapabilities } from '../openai-language-model-capabilities';
|
|
36
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
createOpenAIProviderStreamError,
|
|
38
|
+
throwIfOpenAIStreamErrorBeforeOutput,
|
|
39
|
+
} from '../openai-stream-error';
|
|
37
40
|
import type { applyPatchInputSchema } from '../tool/apply-patch';
|
|
38
41
|
import type {
|
|
39
42
|
codeInterpreterInputSchema,
|
|
@@ -364,6 +367,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
364
367
|
hasShellTool: hasOpenAITool('openai.shell'),
|
|
365
368
|
hasApplyPatchTool: hasOpenAITool('openai.apply_patch'),
|
|
366
369
|
hasComputerTool: hasOpenAITool('openai.computer'),
|
|
370
|
+
toolSearchToolName: getOpenAIToolName('openai.tool_search'),
|
|
367
371
|
customProviderToolNames:
|
|
368
372
|
customProviderToolNames.size > 0
|
|
369
373
|
? customProviderToolNames
|
|
@@ -393,10 +397,13 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
393
397
|
}
|
|
394
398
|
}
|
|
395
399
|
|
|
400
|
+
function getOpenAIToolName(id: string) {
|
|
401
|
+
return tools?.find(tool => tool.type === 'provider' && tool.id === id)
|
|
402
|
+
?.name;
|
|
403
|
+
}
|
|
404
|
+
|
|
396
405
|
function hasOpenAITool(id: string) {
|
|
397
|
-
return (
|
|
398
|
-
tools?.find(tool => tool.type === 'provider' && tool.id === id) != null
|
|
399
|
-
);
|
|
406
|
+
return getOpenAIToolName(id) != null;
|
|
400
407
|
}
|
|
401
408
|
|
|
402
409
|
// when logprobs are requested, automatically include them:
|
|
@@ -1473,6 +1480,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
1473
1480
|
})
|
|
1474
1481
|
: chunk.error;
|
|
1475
1482
|
|
|
1483
|
+
encounteredStreamError = true;
|
|
1476
1484
|
finishReason = { unified: 'error', raw: undefined };
|
|
1477
1485
|
controller.enqueue({ type: 'error', error });
|
|
1478
1486
|
return;
|
|
@@ -2561,13 +2569,15 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2561
2569
|
}
|
|
2562
2570
|
}
|
|
2563
2571
|
} else if (isResponseFinishedChunk(value)) {
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2572
|
+
if (!encounteredStreamError) {
|
|
2573
|
+
finishReason = {
|
|
2574
|
+
unified: mapOpenAIResponseFinishReason({
|
|
2575
|
+
finishReason: value.response.incomplete_details?.reason,
|
|
2576
|
+
hasFunctionCall,
|
|
2577
|
+
}),
|
|
2578
|
+
raw: value.response.incomplete_details?.reason ?? undefined,
|
|
2579
|
+
};
|
|
2580
|
+
}
|
|
2571
2581
|
usage = value.response.usage;
|
|
2572
2582
|
if (typeof value.response.service_tier === 'string') {
|
|
2573
2583
|
serviceTier = value.response.service_tier;
|
|
@@ -2594,17 +2604,18 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2594
2604
|
|
|
2595
2605
|
if (!encounteredStreamError && value.response.error != null) {
|
|
2596
2606
|
encounteredStreamError = true;
|
|
2607
|
+
const error = {
|
|
2608
|
+
type: 'response.failed',
|
|
2609
|
+
sequence_number: value.sequence_number,
|
|
2610
|
+
response: {
|
|
2611
|
+
error: value.response.error,
|
|
2612
|
+
incomplete_details: value.response.incomplete_details,
|
|
2613
|
+
service_tier: value.response.service_tier,
|
|
2614
|
+
},
|
|
2615
|
+
};
|
|
2597
2616
|
controller.enqueue({
|
|
2598
2617
|
type: 'error',
|
|
2599
|
-
error:
|
|
2600
|
-
type: 'response.failed',
|
|
2601
|
-
sequence_number: value.sequence_number,
|
|
2602
|
-
response: {
|
|
2603
|
-
error: value.response.error,
|
|
2604
|
-
incomplete_details: value.response.incomplete_details,
|
|
2605
|
-
service_tier: value.response.service_tier,
|
|
2606
|
-
},
|
|
2607
|
-
},
|
|
2618
|
+
error: createOpenAIProviderStreamError(error) ?? error,
|
|
2608
2619
|
});
|
|
2609
2620
|
}
|
|
2610
2621
|
} else if (isResponseAnnotationAddedChunk(value)) {
|
|
@@ -2678,7 +2689,10 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV4 {
|
|
|
2678
2689
|
} else if (isErrorChunk(value)) {
|
|
2679
2690
|
encounteredStreamError = true;
|
|
2680
2691
|
finishReason = { unified: 'error', raw: 'error' };
|
|
2681
|
-
controller.enqueue({
|
|
2692
|
+
controller.enqueue({
|
|
2693
|
+
type: 'error',
|
|
2694
|
+
error: createOpenAIProviderStreamError(value) ?? value,
|
|
2695
|
+
});
|
|
2682
2696
|
}
|
|
2683
2697
|
},
|
|
2684
2698
|
|