Skip to content

Commit 5d4dc90

Browse files
authored
feat(OpenAI): add support for programmatic tool calling in Responses API (#790)
* Support streaming compaction output * Add programmatic tool calling support * Add fixtures for programmatic DTOs
1 parent de32ca4 commit 5d4dc90

49 files changed

Lines changed: 948 additions & 56 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Actions/Conversations/ItemObjects.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
use OpenAI\Responses\Responses\Output\OutputMcpApprovalRequest;
2121
use OpenAI\Responses\Responses\Output\OutputMcpCall;
2222
use OpenAI\Responses\Responses\Output\OutputMcpListTools;
23+
use OpenAI\Responses\Responses\Output\OutputProgram;
24+
use OpenAI\Responses\Responses\Output\OutputProgramOutput;
2325
use OpenAI\Responses\Responses\Output\OutputReasoning;
2426
use OpenAI\Responses\Responses\Output\OutputWebSearchToolCall;
2527

@@ -42,10 +44,12 @@
4244
* @phpstan-import-type OutputCodeInterpreterToolCallType from OutputCodeInterpreterToolCall
4345
* @phpstan-import-type OutputLocalShellCallType from OutputLocalShellCall
4446
* @phpstan-import-type OutputCustomToolCallType from OutputCustomToolCall
47+
* @phpstan-import-type OutputProgramType from OutputProgram
48+
* @phpstan-import-type OutputProgramOutputType from OutputProgramOutput
4549
*
46-
* @phpstan-type ItemObjectTypes MessageType|ComputerToolCallOutputType|FunctionToolCallOutputType|LocalShellCallOutputType|McpApprovalResponseType|CustomToolCallOutputType|OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType|OutputCodeInterpreterToolCallType|OutputLocalShellCallType|OutputCustomToolCallType
50+
* @phpstan-type ItemObjectTypes MessageType|ComputerToolCallOutputType|FunctionToolCallOutputType|LocalShellCallOutputType|McpApprovalResponseType|CustomToolCallOutputType|OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType|OutputCodeInterpreterToolCallType|OutputLocalShellCallType|OutputCustomToolCallType|OutputProgramType|OutputProgramOutputType
4751
* @phpstan-type ConversationItemObjectTypes array<int, ItemObjectTypes>
48-
* @phpstan-type ConversationItemObjectReturnType array<int, Message|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|CustomToolCallOutput>
52+
* @phpstan-type ConversationItemObjectReturnType array<int, Message|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|CustomToolCallOutput|OutputProgram|OutputProgramOutput>
4953
*/
5054
final class ItemObjects
5155
{
@@ -56,7 +60,7 @@ final class ItemObjects
5660
public static function parse(array $outputItems): array
5761
{
5862
return array_map(
59-
fn (array $item): Message|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|CustomToolCallOutput => match ($item['type']) {
63+
fn (array $item): Message|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|CustomToolCallOutput|OutputProgram|OutputProgramOutput => match ($item['type']) {
6064
'message' => Message::from($item),
6165
'file_search_call' => OutputFileSearchToolCall::from($item),
6266
'function_call' => OutputFunctionToolCall::from($item),
@@ -75,6 +79,8 @@ public static function parse(array $outputItems): array
7579
'local_shell_call_output' => LocalShellCallOutput::from($item),
7680
'custom_tool_call_output' => CustomToolCallOutput::from($item),
7781
'mcp_approval_response' => McpApprovalResponse::from($item),
82+
'program' => OutputProgram::from($item),
83+
'program_output' => OutputProgramOutput::from($item),
7884
},
7985
$outputItems,
8086
);

src/Actions/Responses/ItemObjects.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
use OpenAI\Responses\Responses\Output\OutputMcpCall;
2222
use OpenAI\Responses\Responses\Output\OutputMcpListTools;
2323
use OpenAI\Responses\Responses\Output\OutputMessage;
24+
use OpenAI\Responses\Responses\Output\OutputProgram;
25+
use OpenAI\Responses\Responses\Output\OutputProgramOutput;
2426
use OpenAI\Responses\Responses\Output\OutputReasoning;
2527
use OpenAI\Responses\Responses\Output\OutputWebSearchToolCall;
2628

@@ -44,9 +46,11 @@
4446
* @phpstan-import-type OutputCodeInterpreterToolCallType from OutputCodeInterpreterToolCall
4547
* @phpstan-import-type OutputLocalShellCallType from OutputLocalShellCall
4648
* @phpstan-import-type OutputCustomToolCallType from OutputCustomToolCall
49+
* @phpstan-import-type OutputProgramType from OutputProgram
50+
* @phpstan-import-type OutputProgramOutputType from OutputProgramOutput
4751
*
48-
* @phpstan-type ResponseItemObjectTypes array<int, InputMessageType|ComputerToolCallOutputType|FunctionToolCallOutputType|LocalShellCallOutputType|McpApprovalResponseType|CustomToolCallOutputType|OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType|OutputCodeInterpreterToolCallType|OutputLocalShellCallType|OutputCustomToolCallType>
49-
* @phpstan-type ResponseItemObjectReturnType array<int, InputMessage|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|CustomToolCallOutput|OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall>
52+
* @phpstan-type ResponseItemObjectTypes array<int, InputMessageType|ComputerToolCallOutputType|FunctionToolCallOutputType|LocalShellCallOutputType|McpApprovalResponseType|CustomToolCallOutputType|OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType|OutputCodeInterpreterToolCallType|OutputLocalShellCallType|OutputCustomToolCallType|OutputProgramType|OutputProgramOutputType>
53+
* @phpstan-type ResponseItemObjectReturnType array<int, InputMessage|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|CustomToolCallOutput|OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|OutputProgram|OutputProgramOutput>
5054
*/
5155
final class ItemObjects
5256
{
@@ -57,7 +61,7 @@ final class ItemObjects
5761
public static function parse(array $outputItems): array
5862
{
5963
return array_map(
60-
fn (array $item): InputMessage|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|CustomToolCallOutput|OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall => match ($item['type']) {
64+
fn (array $item): InputMessage|ComputerToolCallOutput|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|CustomToolCallOutput|OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|OutputProgram|OutputProgramOutput => match ($item['type']) {
6165
'message' => $item['role'] === 'assistant' ? OutputMessage::from($item) : InputMessage::from($item),
6266
'file_search_call' => OutputFileSearchToolCall::from($item),
6367
'function_call' => OutputFunctionToolCall::from($item),
@@ -76,6 +80,8 @@ public static function parse(array $outputItems): array
7680
'local_shell_call_output' => LocalShellCallOutput::from($item),
7781
'custom_tool_call_output' => CustomToolCallOutput::from($item),
7882
'mcp_approval_response' => McpApprovalResponse::from($item),
83+
'program' => OutputProgram::from($item),
84+
'program_output' => OutputProgramOutput::from($item),
7985
},
8086
$outputItems,
8187
);

src/Actions/Responses/OutputObjects.php

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use OpenAI\Responses\Responses\Output\OutputMcpCall;
1717
use OpenAI\Responses\Responses\Output\OutputMcpListTools;
1818
use OpenAI\Responses\Responses\Output\OutputMessage;
19+
use OpenAI\Responses\Responses\Output\OutputProgram;
20+
use OpenAI\Responses\Responses\Output\OutputProgramOutput;
1921
use OpenAI\Responses\Responses\Output\OutputReasoning;
2022
use OpenAI\Responses\Responses\Output\OutputToolSearchCall;
2123
use OpenAI\Responses\Responses\Output\OutputToolSearchOutput;
@@ -34,13 +36,15 @@
3436
* @phpstan-import-type OutputImageGenerationToolCallType from OutputImageGenerationToolCall
3537
* @phpstan-import-type OutputCodeInterpreterToolCallType from OutputCodeInterpreterToolCall
3638
* @phpstan-import-type OutputCompactionType from OutputCompaction
39+
* @phpstan-import-type OutputProgramType from OutputProgram
40+
* @phpstan-import-type OutputProgramOutputType from OutputProgramOutput
3741
* @phpstan-import-type OutputLocalShellCallType from OutputLocalShellCall
3842
* @phpstan-import-type OutputCustomToolCallType from OutputCustomToolCall
3943
* @phpstan-import-type OutputToolSearchCallType from OutputToolSearchCall
4044
* @phpstan-import-type OutputToolSearchOutputType from OutputToolSearchOutput
4145
*
42-
* @phpstan-type ResponseOutputObjectTypes array<int, OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType|OutputCodeInterpreterToolCallType|OutputLocalShellCallType|OutputCustomToolCallType|OutputToolSearchCallType|OutputToolSearchOutputType|OutputCompactionType>
43-
* @phpstan-type ResponseOutputObjectReturnType array<int, OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|OutputToolSearchCall|OutputToolSearchOutput|OutputCompaction>
46+
* @phpstan-type ResponseOutputObjectTypes array<int, OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputProgramType|OutputProgramOutputType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType|OutputCodeInterpreterToolCallType|OutputLocalShellCallType|OutputCustomToolCallType|OutputToolSearchCallType|OutputToolSearchOutputType|OutputCompactionType>
47+
* @phpstan-type ResponseOutputObjectReturnType array<int, OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputProgram|OutputProgramOutput|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|OutputToolSearchCall|OutputToolSearchOutput|OutputCompaction>
4448
*/
4549
final class OutputObjects
4650
{
@@ -51,10 +55,12 @@ final class OutputObjects
5155
public static function parse(array $outputItems): array
5256
{
5357
return array_map(
54-
fn (array $item): OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|OutputToolSearchCall|OutputToolSearchOutput|OutputCompaction => match ($item['type']) {
58+
fn (array $item): OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputProgram|OutputProgramOutput|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|OutputToolSearchCall|OutputToolSearchOutput|OutputCompaction => match ($item['type']) {
5559
'message' => OutputMessage::from($item),
5660
'file_search_call' => OutputFileSearchToolCall::from($item),
5761
'function_call' => OutputFunctionToolCall::from($item),
62+
'program' => OutputProgram::from($item),
63+
'program_output' => OutputProgramOutput::from($item),
5864
'web_search_call' => OutputWebSearchToolCall::from($item),
5965
'computer_call' => OutputComputerToolCall::from($item),
6066
'reasoning' => OutputReasoning::from($item),

src/Actions/Responses/ToolChoiceObjects.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static function parse(array|string $toolChoice): string|FunctionToolChoic
2424
{
2525
return is_array($toolChoice)
2626
? match ($toolChoice['type']) {
27-
'file_search', 'web_search', 'web_search_preview', 'computer_use_preview' => HostedToolChoice::from($toolChoice),
27+
'file_search', 'web_search', 'web_search_preview', 'computer_use_preview', 'programmatic_tool_calling' => HostedToolChoice::from($toolChoice),
2828
'function' => FunctionToolChoice::from($toolChoice),
2929
}
3030
: $toolChoice;

src/Actions/Responses/ToolObjects.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use OpenAI\Responses\Responses\Tool\FunctionTool;
1212
use OpenAI\Responses\Responses\Tool\ImageGenerationTool;
1313
use OpenAI\Responses\Responses\Tool\NamespaceTool;
14+
use OpenAI\Responses\Responses\Tool\ProgrammaticToolCallingTool;
1415
use OpenAI\Responses\Responses\Tool\RemoteMcpTool;
1516
use OpenAI\Responses\Responses\Tool\ToolSearchTool;
1617
use OpenAI\Responses\Responses\Tool\WebSearchTool;
@@ -23,12 +24,13 @@
2324
* @phpstan-import-type FunctionToolType from FunctionTool
2425
* @phpstan-import-type ImageGenerationToolType from ImageGenerationTool
2526
* @phpstan-import-type NamespaceToolType from NamespaceTool
27+
* @phpstan-import-type ProgrammaticToolCallingToolType from ProgrammaticToolCallingTool
2628
* @phpstan-import-type RemoteMcpToolType from RemoteMcpTool
2729
* @phpstan-import-type ToolSearchToolType from ToolSearchTool
2830
* @phpstan-import-type WebSearchToolType from WebSearchTool
2931
*
30-
* @phpstan-type ResponseToolObjectTypes array<int, CodeInterpreterToolType|ComputerUseToolType|CustomToolType|FileSearchToolType|FunctionToolType|ImageGenerationToolType|NamespaceToolType|RemoteMcpToolType|ToolSearchToolType|WebSearchToolType>
31-
* @phpstan-type ResponseToolObjectReturnType array<int, CodeInterpreterTool|ComputerUseTool|CustomTool|FileSearchTool|FunctionTool|ImageGenerationTool|NamespaceTool|RemoteMcpTool|ToolSearchTool|WebSearchTool>
32+
* @phpstan-type ResponseToolObjectTypes array<int, CodeInterpreterToolType|ComputerUseToolType|CustomToolType|FileSearchToolType|FunctionToolType|ImageGenerationToolType|NamespaceToolType|ProgrammaticToolCallingToolType|RemoteMcpToolType|ToolSearchToolType|WebSearchToolType>
33+
* @phpstan-type ResponseToolObjectReturnType array<int, CodeInterpreterTool|ComputerUseTool|CustomTool|FileSearchTool|FunctionTool|ImageGenerationTool|NamespaceTool|ProgrammaticToolCallingTool|RemoteMcpTool|ToolSearchTool|WebSearchTool>
3234
*/
3335
final class ToolObjects
3436
{
@@ -39,7 +41,7 @@ final class ToolObjects
3941
public static function parse(array $toolItems): array
4042
{
4143
return array_map(
42-
fn (array $tool): CodeInterpreterTool|ComputerUseTool|CustomTool|FileSearchTool|FunctionTool|ImageGenerationTool|NamespaceTool|RemoteMcpTool|ToolSearchTool|WebSearchTool => match ($tool['type']) {
44+
fn (array $tool): CodeInterpreterTool|ComputerUseTool|CustomTool|FileSearchTool|FunctionTool|ImageGenerationTool|NamespaceTool|ProgrammaticToolCallingTool|RemoteMcpTool|ToolSearchTool|WebSearchTool => match ($tool['type']) {
4345
'file_search' => FileSearchTool::from($tool),
4446
'web_search', 'web_search_preview', 'web_search_preview_2025_03_11' => WebSearchTool::from($tool),
4547
'function' => FunctionTool::from($tool),
@@ -50,6 +52,7 @@ public static function parse(array $toolItems): array
5052
'tool_search' => ToolSearchTool::from($tool),
5153
'namespace' => NamespaceTool::from($tool),
5254
'custom' => CustomTool::from($tool),
55+
'programmatic_tool_calling' => ProgrammaticToolCallingTool::from($tool),
5356
},
5457
$toolItems,
5558
);

src/Responses/Conversations/ConversationItem.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
use OpenAI\Responses\Responses\Output\OutputMcpApprovalRequest;
2424
use OpenAI\Responses\Responses\Output\OutputMcpCall;
2525
use OpenAI\Responses\Responses\Output\OutputMcpListTools;
26+
use OpenAI\Responses\Responses\Output\OutputProgram;
27+
use OpenAI\Responses\Responses\Output\OutputProgramOutput;
2628
use OpenAI\Responses\Responses\Output\OutputReasoning;
2729
use OpenAI\Responses\Responses\Output\OutputWebSearchToolCall;
2830
use OpenAI\Testing\Responses\Concerns\Fakeable;
@@ -44,7 +46,7 @@ final class ConversationItem implements ResponseContract
4446
use Fakeable;
4547

4648
private function __construct(
47-
public readonly Message|OutputFileSearchToolCall|OutputFunctionToolCall|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|CustomToolCallOutput|OutputWebSearchToolCall|OutputComputerToolCall|ComputerToolCallOutput|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall $item
49+
public readonly Message|OutputFileSearchToolCall|OutputFunctionToolCall|FunctionToolCallOutput|LocalShellCallOutput|McpApprovalResponse|CustomToolCallOutput|OutputWebSearchToolCall|OutputComputerToolCall|ComputerToolCallOutput|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall|OutputLocalShellCall|OutputCustomToolCall|OutputProgram|OutputProgramOutput $item
4850
) {}
4951

5052
/**

0 commit comments

Comments
 (0)