From bbda5b0ccd941b7229263b5fb5d386d99116d43d Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Mon, 6 Jul 2026 14:57:36 +0400 Subject: [PATCH] Support streaming compaction output --- .../Responses/Streaming/OutputItem.php | 7 +++++-- tests/Fixtures/Responses.php | 5 +++++ .../ResponseOutputItemCompactionDone.txt | 1 + .../Responses/CreateStreamedResponse.php | 17 +++++++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 tests/Fixtures/Streams/ResponseOutputItemCompactionDone.txt diff --git a/src/Responses/Responses/Streaming/OutputItem.php b/src/Responses/Responses/Streaming/OutputItem.php index 1223c0e3b..68e037452 100644 --- a/src/Responses/Responses/Streaming/OutputItem.php +++ b/src/Responses/Responses/Streaming/OutputItem.php @@ -10,6 +10,7 @@ use OpenAI\Responses\Concerns\HasMetaInformation; use OpenAI\Responses\Meta\MetaInformation; use OpenAI\Responses\Responses\Output\OutputCodeInterpreterToolCall; +use OpenAI\Responses\Responses\Output\OutputCompaction; use OpenAI\Responses\Responses\Output\OutputComputerToolCall; use OpenAI\Responses\Responses\Output\OutputFileSearchToolCall; use OpenAI\Responses\Responses\Output\OutputFunctionToolCall; @@ -34,8 +35,9 @@ * @phpstan-import-type OutputMcpApprovalRequestType from OutputMcpApprovalRequest * @phpstan-import-type OutputMcpCallType from OutputMcpCall * @phpstan-import-type OutputCodeInterpreterToolCallType from OutputCodeInterpreterToolCall + * @phpstan-import-type OutputCompactionType from OutputCompaction * - * @phpstan-type OutputItemType array{type: string, output_index: int, sequence_number: int, item: OutputCodeInterpreterToolCallType|OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType} + * @phpstan-type OutputItemType array{type: string, output_index: int, sequence_number: int, item: OutputCodeInterpreterToolCallType|OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType|OutputCompactionType} * * @implements ResponseContract */ @@ -53,7 +55,7 @@ private function __construct( public readonly string $type, public readonly int $outputIndex, public readonly int $sequenceNumber, - public readonly OutputMessage|OutputCodeInterpreterToolCall|OutputFileSearchToolCall|OutputFunctionToolCall|OutputWebSearchToolCall|OutputComputerToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall $item, + public readonly OutputMessage|OutputCodeInterpreterToolCall|OutputFileSearchToolCall|OutputFunctionToolCall|OutputWebSearchToolCall|OutputComputerToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall|OutputCompaction $item, private readonly MetaInformation $meta, ) {} @@ -74,6 +76,7 @@ public static function from(array $attributes, MetaInformation $meta): self 'mcp_approval_request' => OutputMcpApprovalRequest::from($attributes['item']), 'mcp_call' => OutputMcpCall::from($attributes['item']), 'code_interpreter_call' => OutputCodeInterpreterToolCall::from($attributes['item']), + 'compaction' => OutputCompaction::from($attributes['item']), }; return new self( diff --git a/tests/Fixtures/Responses.php b/tests/Fixtures/Responses.php index 36fd6a2a2..4da44a0f7 100644 --- a/tests/Fixtures/Responses.php +++ b/tests/Fixtures/Responses.php @@ -1042,3 +1042,8 @@ function responseRateLimitsUpdatedEvent() { return fopen(__DIR__.'/Streams/ResponseRateLimitsUpdated.txt', 'r'); } + +function responseOutputItemCompactionDoneEvent() +{ + return fopen(__DIR__.'/Streams/ResponseOutputItemCompactionDone.txt', 'r'); +} diff --git a/tests/Fixtures/Streams/ResponseOutputItemCompactionDone.txt b/tests/Fixtures/Streams/ResponseOutputItemCompactionDone.txt new file mode 100644 index 000000000..c8d409118 --- /dev/null +++ b/tests/Fixtures/Streams/ResponseOutputItemCompactionDone.txt @@ -0,0 +1 @@ +data: {"type":"response.output_item.done","output_index":0,"sequence_number":11,"item":{"id":"cmp_67ccf18f64008190a39b619f4c8455ef087bb177ab789d5c","encrypted_content":"encrypted_string_value","type":"compaction","created_by":"user_123"}} diff --git a/tests/Responses/Responses/CreateStreamedResponse.php b/tests/Responses/Responses/CreateStreamedResponse.php index e303d37f7..907243fbd 100644 --- a/tests/Responses/Responses/CreateStreamedResponse.php +++ b/tests/Responses/Responses/CreateStreamedResponse.php @@ -2,6 +2,8 @@ use OpenAI\Responses\Responses\CreateResponse; use OpenAI\Responses\Responses\CreateStreamedResponse; +use OpenAI\Responses\Responses\Output\OutputCompaction; +use OpenAI\Responses\Responses\Streaming\OutputItem; use OpenAI\Responses\Responses\Streaming\RateLimits; use OpenAI\Responses\Responses\Streaming\ReasoningTextDelta; use OpenAI\Responses\Responses\Streaming\ReasoningTextDone; @@ -68,3 +70,18 @@ 'type' => 'response.rate_limits.updated', ]); }); + +test('output item done event with compaction item', function () { + $response = CreateStreamedResponse::fake(responseOutputItemCompactionDoneEvent()); + + expect($response->getIterator()->current()) + ->toBeInstanceOf(CreateStreamedResponse::class) + ->event->toBe('response.output_item.done') + ->response->toBeInstanceOf(OutputItem::class) + ->response->outputIndex->toBe(0) + ->response->sequenceNumber->toBe(11) + ->response->item->toBeInstanceOf(OutputCompaction::class) + ->response->item->id->toBe('cmp_67ccf18f64008190a39b619f4c8455ef087bb177ab789d5c') + ->response->item->encryptedContent->toBe('encrypted_string_value') + ->response->item->createdBy->toBe('user_123'); +});