diff --git a/src/Actions/Responses/ItemObjects.php b/src/Actions/Responses/ItemObjects.php new file mode 100644 index 00000000..f31e5657 --- /dev/null +++ b/src/Actions/Responses/ItemObjects.php @@ -0,0 +1,68 @@ + + * @phpstan-type ResponseItemObjectReturnType array + */ +final class ItemObjects +{ + /** + * @param ResponseItemObjectTypes $outputItems + * @return ResponseItemObjectReturnType + */ + public static function parse(array $outputItems): array + { + return array_map( + fn (array $item): InputMessage|ComputerToolCallOutput|FunctionToolCallOutput|OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall => match ($item['type']) { + 'message' => $item['role'] === 'assistant' ? OutputMessage::from($item) : InputMessage::from($item), + 'file_search_call' => OutputFileSearchToolCall::from($item), + 'function_call' => OutputFunctionToolCall::from($item), + 'function_call_output' => FunctionToolCallOutput::from($item), + 'web_search_call' => OutputWebSearchToolCall::from($item), + 'computer_call' => OutputComputerToolCall::from($item), + 'computer_call_output' => ComputerToolCallOutput::from($item), + 'reasoning' => OutputReasoning::from($item), + 'mcp_list_tools' => OutputMcpListTools::from($item), + 'mcp_approval_request' => OutputMcpApprovalRequest::from($item), + 'mcp_call' => OutputMcpCall::from($item), + 'image_generation_call' => OutputImageGenerationToolCall::from($item), + 'code_interpreter_call' => OutputCodeInterpreterToolCall::from($item), + }, + $outputItems, + ); + } +} diff --git a/src/Actions/Responses/OutputObjects.php b/src/Actions/Responses/OutputObjects.php new file mode 100644 index 00000000..8d30cb87 --- /dev/null +++ b/src/Actions/Responses/OutputObjects.php @@ -0,0 +1,60 @@ + + * @phpstan-type ResponseOutputObjectReturnType array + */ +final class OutputObjects +{ + /** + * @param ResponseOutputObjectTypes $outputItems + * @return ResponseOutputObjectReturnType + */ + public static function parse(array $outputItems): array + { + return array_map( + fn (array $item): OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall => match ($item['type']) { + 'message' => OutputMessage::from($item), + 'file_search_call' => OutputFileSearchToolCall::from($item), + 'function_call' => OutputFunctionToolCall::from($item), + 'web_search_call' => OutputWebSearchToolCall::from($item), + 'computer_call' => OutputComputerToolCall::from($item), + 'reasoning' => OutputReasoning::from($item), + 'mcp_list_tools' => OutputMcpListTools::from($item), + 'mcp_approval_request' => OutputMcpApprovalRequest::from($item), + 'mcp_call' => OutputMcpCall::from($item), + 'image_generation_call' => OutputImageGenerationToolCall::from($item), + 'code_interpreter_call' => OutputCodeInterpreterToolCall::from($item), + }, + $outputItems, + ); + } +} diff --git a/src/Actions/Responses/OutputText.php b/src/Actions/Responses/OutputText.php new file mode 100644 index 00000000..e70fd889 --- /dev/null +++ b/src/Actions/Responses/OutputText.php @@ -0,0 +1,35 @@ +content as $content) { + if ($content instanceof OutputMessageContentOutputText) { + $texts[] = $content->text; + } + } + } + } + + return empty($texts) ? null : implode(' ', $texts); + } +} diff --git a/src/Actions/Responses/ToolChoiceObjects.php b/src/Actions/Responses/ToolChoiceObjects.php new file mode 100644 index 00000000..9dc52cf7 --- /dev/null +++ b/src/Actions/Responses/ToolChoiceObjects.php @@ -0,0 +1,32 @@ + HostedToolChoice::from($toolChoice), + 'function' => FunctionToolChoice::from($toolChoice), + } + : $toolChoice; + } +} diff --git a/src/Actions/Responses/ToolObjects.php b/src/Actions/Responses/ToolObjects.php new file mode 100644 index 00000000..774d04cc --- /dev/null +++ b/src/Actions/Responses/ToolObjects.php @@ -0,0 +1,48 @@ + + * @phpstan-type ResponseToolObjectReturnType array + */ +final class ToolObjects +{ + /** + * @param ResponseToolObjectTypes $toolItems + * @return ResponseToolObjectReturnType + */ + public static function parse(array $toolItems): array + { + return array_map( + fn (array $tool): ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool|RemoteMcpTool|CodeInterpreterTool => match ($tool['type']) { + 'file_search' => FileSearchTool::from($tool), + 'web_search', 'web_search_preview', 'web_search_preview_2025_03_11' => WebSearchTool::from($tool), + 'function' => FunctionTool::from($tool), + 'computer_use_preview' => ComputerUseTool::from($tool), + 'image_generation' => ImageGenerationTool::from($tool), + 'mcp' => RemoteMcpTool::from($tool), + 'code_interpreter' => CodeInterpreterTool::from($tool), + }, + $toolItems, + ); + } +} diff --git a/src/Responses/Responses/CreateResponse.php b/src/Responses/Responses/CreateResponse.php index 94eef4ac..239997a1 100644 --- a/src/Responses/Responses/CreateResponse.php +++ b/src/Responses/Responses/CreateResponse.php @@ -4,6 +4,10 @@ namespace OpenAI\Responses\Responses; +use OpenAI\Actions\Responses\OutputObjects; +use OpenAI\Actions\Responses\OutputText; +use OpenAI\Actions\Responses\ToolChoiceObjects; +use OpenAI\Actions\Responses\ToolObjects; use OpenAI\Contracts\ResponseContract; use OpenAI\Contracts\ResponseHasMetaInformationContract; use OpenAI\Responses\Concerns\ArrayAccessible; @@ -18,7 +22,6 @@ use OpenAI\Responses\Responses\Output\OutputMcpCall; use OpenAI\Responses\Responses\Output\OutputMcpListTools; use OpenAI\Responses\Responses\Output\OutputMessage; -use OpenAI\Responses\Responses\Output\OutputMessageContentOutputText; use OpenAI\Responses\Responses\Output\OutputReasoning; use OpenAI\Responses\Responses\Output\OutputWebSearchToolCall; use OpenAI\Responses\Responses\Tool\CodeInterpreterTool; @@ -34,37 +37,17 @@ /** * @phpstan-import-type ResponseFormatType from CreateResponseFormat - * @phpstan-import-type OutputComputerToolCallType from OutputComputerToolCall - * @phpstan-import-type OutputFileSearchToolCallType from OutputFileSearchToolCall - * @phpstan-import-type OutputFunctionToolCallType from OutputFunctionToolCall - * @phpstan-import-type OutputMessageType from OutputMessage - * @phpstan-import-type OutputReasoningType from OutputReasoning - * @phpstan-import-type OutputWebSearchToolCallType from OutputWebSearchToolCall - * @phpstan-import-type OutputMcpListToolsType from OutputMcpListTools - * @phpstan-import-type OutputMcpApprovalRequestType from OutputMcpApprovalRequest - * @phpstan-import-type OutputMcpCallType from OutputMcpCall - * @phpstan-import-type OutputImageGenerationToolCallType from OutputImageGenerationToolCall - * @phpstan-import-type OutputCodeInterpreterToolCallType from OutputCodeInterpreterToolCall - * @phpstan-import-type ComputerUseToolType from ComputerUseTool - * @phpstan-import-type FileSearchToolType from FileSearchTool - * @phpstan-import-type ImageGenerationToolType from ImageGenerationTool - * @phpstan-import-type RemoteMcpToolType from RemoteMcpTool - * @phpstan-import-type FunctionToolType from FunctionTool - * @phpstan-import-type WebSearchToolType from WebSearchTool - * @phpstan-import-type CodeInterpreterToolType from CodeInterpreterTool * @phpstan-import-type ErrorType from GenericResponseError * @phpstan-import-type IncompleteDetailsType from CreateResponseIncompleteDetails * @phpstan-import-type UsageType from CreateResponseUsage - * @phpstan-import-type FunctionToolChoiceType from FunctionToolChoice - * @phpstan-import-type HostedToolChoiceType from HostedToolChoice * @phpstan-import-type ReasoningType from CreateResponseReasoning * @phpstan-import-type ReferencePromptObjectType from ReferencePromptObject + * @phpstan-import-type ResponseOutputObjectTypes from OutputObjects + * @phpstan-import-type ResponseToolChoiceTypes from ToolChoiceObjects + * @phpstan-import-type ResponseToolObjectTypes from ToolObjects * * @phpstan-type InstructionsType array|string|null - * @phpstan-type ToolChoiceType 'none'|'auto'|'required'|FunctionToolChoiceType|HostedToolChoiceType - * @phpstan-type ToolsType array - * @phpstan-type OutputType array - * @phpstan-type CreateResponseType array{id: string, background?: bool|null, object: 'response', created_at: int, status: 'completed'|'failed'|'in_progress'|'incomplete', error: ErrorType|null, incomplete_details: IncompleteDetailsType|null, instructions: InstructionsType, max_output_tokens: int|null, max_tool_calls?: int|null, model: string, output: OutputType, output_text: string|null, parallel_tool_calls: bool, previous_response_id: string|null, prompt: ReferencePromptObjectType|null, prompt_cache_key?: string|null, reasoning: ReasoningType|null, safety_identifier?: string|null, service_tier?: string|null, store?: bool|null, temperature: float|null, text?: ResponseFormatType|null, tool_choice: ToolChoiceType, tools: ToolsType, top_logprobs?: int|null, top_p: float|null, truncation: 'auto'|'disabled'|null, usage: UsageType|null, user: string|null, verbosity: string|null, metadata: array|null} + * @phpstan-type CreateResponseType array{id: string, background?: bool|null, object: 'response', created_at: int, status: 'completed'|'failed'|'in_progress'|'incomplete', error: ErrorType|null, incomplete_details: IncompleteDetailsType|null, instructions: InstructionsType, max_output_tokens: int|null, max_tool_calls?: int|null, model: string, output: ResponseOutputObjectTypes, output_text: string|null, parallel_tool_calls: bool, previous_response_id: string|null, prompt: ReferencePromptObjectType|null, prompt_cache_key?: string|null, reasoning: ReasoningType|null, safety_identifier?: string|null, service_tier?: string|null, store?: bool|null, temperature: float|null, text?: ResponseFormatType|null, tool_choice: ResponseToolChoiceTypes, tools: ResponseToolObjectTypes, top_logprobs?: int|null, top_p: float|null, truncation: 'auto'|'disabled'|null, usage: UsageType|null, user: string|null, verbosity: string|null, metadata: array|null} * * @implements ResponseContract */ @@ -128,54 +111,9 @@ private function __construct( */ public static function from(array $attributes, MetaInformation $meta): self { - $output = array_map( - fn (array $output): OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall => match ($output['type']) { - 'message' => OutputMessage::from($output), - 'file_search_call' => OutputFileSearchToolCall::from($output), - 'function_call' => OutputFunctionToolCall::from($output), - 'web_search_call' => OutputWebSearchToolCall::from($output), - 'computer_call' => OutputComputerToolCall::from($output), - 'reasoning' => OutputReasoning::from($output), - 'mcp_list_tools' => OutputMcpListTools::from($output), - 'mcp_approval_request' => OutputMcpApprovalRequest::from($output), - 'mcp_call' => OutputMcpCall::from($output), - 'image_generation_call' => OutputImageGenerationToolCall::from($output), - 'code_interpreter_call' => OutputCodeInterpreterToolCall::from($output), - }, - $attributes['output'], - ); - - $toolChoice = is_array($attributes['tool_choice']) - ? match ($attributes['tool_choice']['type']) { - 'file_search', 'web_search', 'web_search_preview', 'computer_use_preview' => HostedToolChoice::from($attributes['tool_choice']), - 'function' => FunctionToolChoice::from($attributes['tool_choice']), - } - : $attributes['tool_choice']; - - $tools = array_map( - fn (array $tool): ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool|RemoteMcpTool|CodeInterpreterTool => match ($tool['type']) { - 'file_search' => FileSearchTool::from($tool), - 'web_search', 'web_search_preview', 'web_search_preview_2025_03_11' => WebSearchTool::from($tool), - 'function' => FunctionTool::from($tool), - 'computer_use_preview' => ComputerUseTool::from($tool), - 'image_generation' => ImageGenerationTool::from($tool), - 'mcp' => RemoteMcpTool::from($tool), - 'code_interpreter' => CodeInterpreterTool::from($tool), - }, - $attributes['tools'], - ); - - // Remake the sdk only property output_text. - $texts = []; - foreach ($output as $item) { - if ($item instanceof OutputMessage) { - foreach ($item->content as $content) { - if ($content instanceof OutputMessageContentOutputText) { - $texts[] = $content->text; - } - } - } - } + $output = OutputObjects::parse($attributes['output']); + $toolChoice = ToolChoiceObjects::parse($attributes['tool_choice']); + $tools = ToolObjects::parse($attributes['tools']); return new self( id: $attributes['id'], @@ -194,7 +132,7 @@ public static function from(array $attributes, MetaInformation $meta): self maxOutputTokens: $attributes['max_output_tokens'], model: $attributes['model'], output: $output, - outputText: empty($texts) ? null : implode(' ', $texts), + outputText: OutputText::parse($output), parallelToolCalls: $attributes['parallel_tool_calls'], previousResponseId: $attributes['previous_response_id'], prompt: isset($attributes['prompt']) diff --git a/src/Responses/Responses/ListInputItems.php b/src/Responses/Responses/ListInputItems.php index 018c2a98..adeaa860 100644 --- a/src/Responses/Responses/ListInputItems.php +++ b/src/Responses/Responses/ListInputItems.php @@ -4,6 +4,7 @@ namespace OpenAI\Responses\Responses; +use OpenAI\Actions\Responses\ItemObjects; use OpenAI\Contracts\ResponseContract; use OpenAI\Contracts\ResponseHasMetaInformationContract; use OpenAI\Responses\Concerns\ArrayAccessible; @@ -26,22 +27,9 @@ use OpenAI\Testing\Responses\Concerns\Fakeable; /** - * @phpstan-import-type InputMessageType from InputMessage - * @phpstan-import-type OutputMessageType from OutputMessage - * @phpstan-import-type OutputFileSearchToolCallType from OutputFileSearchToolCall - * @phpstan-import-type OutputComputerToolCallType from OutputComputerToolCall - * @phpstan-import-type ComputerToolCallOutputType from ComputerToolCallOutput - * @phpstan-import-type OutputWebSearchToolCallType from OutputWebSearchToolCall - * @phpstan-import-type OutputFunctionToolCallType from OutputFunctionToolCall - * @phpstan-import-type FunctionToolCallOutputType from FunctionToolCallOutput - * @phpstan-import-type OutputReasoningType from OutputReasoning - * @phpstan-import-type OutputMcpListToolsType from OutputMcpListTools - * @phpstan-import-type OutputMcpApprovalRequestType from OutputMcpApprovalRequest - * @phpstan-import-type OutputMcpCallType from OutputMcpCall - * @phpstan-import-type OutputImageGenerationToolCallType from OutputImageGenerationToolCall - * @phpstan-import-type OutputCodeInterpreterToolCallType from OutputCodeInterpreterToolCall + * @phpstan-import-type ResponseItemObjectTypes from ItemObjects * - * @phpstan-type ListInputItemsType array{data: array, first_id: string, has_more: bool, last_id: string, object: 'list'} + * @phpstan-type ListInputItemsType array{data: ResponseItemObjectTypes, first_id: string, has_more: bool, last_id: string, object: 'list'} * * @implements ResponseContract */ @@ -71,24 +59,7 @@ private function __construct( */ public static function from(array $attributes, MetaInformation $meta): self { - $data = array_map( - fn (array $item): InputMessage|OutputMessage|OutputFileSearchToolCall|OutputComputerToolCall|ComputerToolCallOutput|OutputWebSearchToolCall|OutputFunctionToolCall|FunctionToolCallOutput|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall => match ($item['type']) { - 'message' => $item['role'] === 'assistant' ? OutputMessage::from($item) : InputMessage::from($item), - 'file_search_call' => OutputFileSearchToolCall::from($item), - 'function_call' => OutputFunctionToolCall::from($item), - 'function_call_output' => FunctionToolCallOutput::from($item), - 'web_search_call' => OutputWebSearchToolCall::from($item), - 'computer_call' => OutputComputerToolCall::from($item), - 'computer_call_output' => ComputerToolCallOutput::from($item), - 'reasoning' => OutputReasoning::from($item), - 'mcp_list_tools' => OutputMcpListTools::from($item), - 'mcp_approval_request' => OutputMcpApprovalRequest::from($item), - 'mcp_call' => OutputMcpCall::from($item), - 'image_generation_call' => OutputImageGenerationToolCall::from($item), - 'code_interpreter_call' => OutputCodeInterpreterToolCall::from($item), - }, - $attributes['data'], - ); + $data = ItemObjects::parse($attributes['data']); return new self( object: $attributes['object'], diff --git a/src/Responses/Responses/RetrieveResponse.php b/src/Responses/Responses/RetrieveResponse.php index bdc117dd..01243565 100644 --- a/src/Responses/Responses/RetrieveResponse.php +++ b/src/Responses/Responses/RetrieveResponse.php @@ -4,6 +4,10 @@ namespace OpenAI\Responses\Responses; +use OpenAI\Actions\Responses\OutputObjects; +use OpenAI\Actions\Responses\OutputText; +use OpenAI\Actions\Responses\ToolChoiceObjects; +use OpenAI\Actions\Responses\ToolObjects; use OpenAI\Contracts\ResponseContract; use OpenAI\Contracts\ResponseHasMetaInformationContract; use OpenAI\Responses\Concerns\ArrayAccessible; @@ -18,7 +22,6 @@ use OpenAI\Responses\Responses\Output\OutputMcpCall; use OpenAI\Responses\Responses\Output\OutputMcpListTools; use OpenAI\Responses\Responses\Output\OutputMessage; -use OpenAI\Responses\Responses\Output\OutputMessageContentOutputText; use OpenAI\Responses\Responses\Output\OutputReasoning; use OpenAI\Responses\Responses\Output\OutputWebSearchToolCall; use OpenAI\Responses\Responses\Tool\CodeInterpreterTool; @@ -34,38 +37,17 @@ /** * @phpstan-import-type ResponseFormatType from CreateResponseFormat - * @phpstan-import-type OutputComputerToolCallType from OutputComputerToolCall - * @phpstan-import-type OutputFileSearchToolCallType from OutputFileSearchToolCall - * @phpstan-import-type OutputFunctionToolCallType from OutputFunctionToolCall - * @phpstan-import-type OutputMessageType from OutputMessage - * @phpstan-import-type OutputReasoningType from OutputReasoning - * @phpstan-import-type OutputWebSearchToolCallType from OutputWebSearchToolCall - * @phpstan-import-type OutputImageGenerationToolCallType from OutputImageGenerationToolCall - * @phpstan-import-type OutputMcpListToolsType from OutputMcpListTools - * @phpstan-import-type OutputMcpApprovalRequestType from OutputMcpApprovalRequest - * @phpstan-import-type OutputMcpCallType from OutputMcpCall - * @phpstan-import-type OutputImageGenerationToolCallType from OutputImageGenerationToolCall - * @phpstan-import-type OutputCodeInterpreterToolCallType from OutputCodeInterpreterToolCall - * @phpstan-import-type ComputerUseToolType from ComputerUseTool - * @phpstan-import-type FileSearchToolType from FileSearchTool - * @phpstan-import-type ImageGenerationToolType from ImageGenerationTool - * @phpstan-import-type RemoteMcpToolType from RemoteMcpTool - * @phpstan-import-type FunctionToolType from FunctionTool - * @phpstan-import-type WebSearchToolType from WebSearchTool - * @phpstan-import-type CodeInterpreterToolType from CodeInterpreterTool * @phpstan-import-type ErrorType from GenericResponseError * @phpstan-import-type IncompleteDetailsType from CreateResponseIncompleteDetails * @phpstan-import-type UsageType from CreateResponseUsage - * @phpstan-import-type FunctionToolChoiceType from FunctionToolChoice - * @phpstan-import-type HostedToolChoiceType from HostedToolChoice * @phpstan-import-type ReasoningType from CreateResponseReasoning * @phpstan-import-type ReferencePromptObjectType from ReferencePromptObject + * @phpstan-import-type ResponseOutputObjectTypes from OutputObjects + * @phpstan-import-type ResponseToolChoiceTypes from ToolChoiceObjects + * @phpstan-import-type ResponseToolObjectTypes from ToolObjects * * @phpstan-type InstructionsType array|string|null - * @phpstan-type ToolChoiceType 'none'|'auto'|'required'|FunctionToolChoiceType|HostedToolChoiceType - * @phpstan-type ToolsType array - * @phpstan-type OutputType array - * @phpstan-type RetrieveResponseType array{id: string, background?: bool|null, object: 'response', created_at: int, status: 'completed'|'failed'|'in_progress'|'incomplete', error: ErrorType|null, incomplete_details: IncompleteDetailsType|null, instructions: InstructionsType, max_output_tokens: int|null, max_tool_calls?: int|null, model: string, output: OutputType, output_text: string|null, parallel_tool_calls: bool, previous_response_id: string|null, prompt: ReferencePromptObjectType|null, prompt_cache_key?: string|null, reasoning: ReasoningType|null, safety_identifier?: string|null, service_tier?: string|null, store: bool, temperature: float|null, text: ResponseFormatType, tool_choice: ToolChoiceType, tools: ToolsType, top_logprobs?: int|null, top_p: float|null, truncation: 'auto'|'disabled'|null, usage: UsageType|null, user: string|null, verbosity: string|null, metadata: array|null} + * @phpstan-type RetrieveResponseType array{id: string, background?: bool|null, object: 'response', created_at: int, status: 'completed'|'failed'|'in_progress'|'incomplete', error: ErrorType|null, incomplete_details: IncompleteDetailsType|null, instructions: InstructionsType, max_output_tokens: int|null, max_tool_calls?: int|null, model: string, output: ResponseOutputObjectTypes, output_text: string|null, parallel_tool_calls: bool, previous_response_id: string|null, prompt: ReferencePromptObjectType|null, prompt_cache_key?: string|null, reasoning: ReasoningType|null, safety_identifier?: string|null, service_tier?: string|null, store: bool, temperature: float|null, text: ResponseFormatType, tool_choice: ResponseToolChoiceTypes, tools: ResponseToolObjectTypes, top_logprobs?: int|null, top_p: float|null, truncation: 'auto'|'disabled'|null, usage: UsageType|null, user: string|null, verbosity: string|null, metadata: array|null} * * @implements ResponseContract */ @@ -129,54 +111,9 @@ private function __construct( */ public static function from(array $attributes, MetaInformation $meta): self { - $output = array_map( - fn (array $output): OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCodeInterpreterToolCall => match ($output['type']) { - 'message' => OutputMessage::from($output), - 'file_search_call' => OutputFileSearchToolCall::from($output), - 'function_call' => OutputFunctionToolCall::from($output), - 'web_search_call' => OutputWebSearchToolCall::from($output), - 'computer_call' => OutputComputerToolCall::from($output), - 'reasoning' => OutputReasoning::from($output), - 'mcp_list_tools' => OutputMcpListTools::from($output), - 'mcp_approval_request' => OutputMcpApprovalRequest::from($output), - 'mcp_call' => OutputMcpCall::from($output), - 'image_generation_call' => OutputImageGenerationToolCall::from($output), - 'code_interpreter_call' => OutputCodeInterpreterToolCall::from($output), - }, - $attributes['output'], - ); - - $toolChoice = is_array($attributes['tool_choice']) - ? match ($attributes['tool_choice']['type']) { - 'file_search', 'web_search', 'web_search_preview', 'computer_use_preview' => HostedToolChoice::from($attributes['tool_choice']), - 'function' => FunctionToolChoice::from($attributes['tool_choice']), - } - : $attributes['tool_choice']; - - $tools = array_map( - fn (array $tool): ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool|RemoteMcpTool|CodeInterpreterTool => match ($tool['type']) { - 'file_search' => FileSearchTool::from($tool), - 'web_search', 'web_search_preview', 'web_search_preview_2025_03_11' => WebSearchTool::from($tool), - 'function' => FunctionTool::from($tool), - 'computer_use_preview' => ComputerUseTool::from($tool), - 'image_generation' => ImageGenerationTool::from($tool), - 'mcp' => RemoteMcpTool::from($tool), - 'code_interpreter' => CodeInterpreterTool::from($tool), - }, - $attributes['tools'], - ); - - // Remake the sdk only property output_text. - $texts = []; - foreach ($output as $item) { - if ($item instanceof OutputMessage) { - foreach ($item->content as $content) { - if ($content instanceof OutputMessageContentOutputText) { - $texts[] = $content->text; - } - } - } - } + $output = OutputObjects::parse($attributes['output']); + $toolChoice = ToolChoiceObjects::parse($attributes['tool_choice']); + $tools = ToolObjects::parse($attributes['tools']); return new self( id: $attributes['id'], @@ -195,7 +132,7 @@ public static function from(array $attributes, MetaInformation $meta): self maxOutputTokens: $attributes['max_output_tokens'], model: $attributes['model'], output: $output, - outputText: empty($texts) ? null : implode(' ', $texts), + outputText: OutputText::parse($output), parallelToolCalls: $attributes['parallel_tool_calls'], previousResponseId: $attributes['previous_response_id'], prompt: isset($attributes['prompt']) diff --git a/tests/Arch.php b/tests/Arch.php index b63c7a6d..c6836e4a 100644 --- a/tests/Arch.php +++ b/tests/Arch.php @@ -31,6 +31,7 @@ test('responses')->expect('OpenAI\Responses')->toOnlyUse([ 'Http\Discovery\Psr17Factory', + 'OpenAI\Actions', 'OpenAI\Enums', 'OpenAI\Exceptions\ErrorException', 'OpenAI\Exceptions\UnknownEventException',