From 118b09c2d811df635e4b288d1ecbad2f34eee74c Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Sun, 19 Apr 2026 07:59:32 -0400 Subject: [PATCH 1/2] fix(OpenAI): add no-op rate limit stream class --- .../Responses/CreateStreamedResponse.php | 4 +- .../Responses/Streaming/RateLimits.php | 52 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/Responses/Responses/Streaming/RateLimits.php diff --git a/src/Responses/Responses/CreateStreamedResponse.php b/src/Responses/Responses/CreateStreamedResponse.php index 370faca7..834b5d41 100644 --- a/src/Responses/Responses/CreateStreamedResponse.php +++ b/src/Responses/Responses/CreateStreamedResponse.php @@ -26,6 +26,7 @@ use OpenAI\Responses\Responses\Streaming\OutputTextAnnotationAdded; use OpenAI\Responses\Responses\Streaming\OutputTextDelta; use OpenAI\Responses\Responses\Streaming\OutputTextDone; +use OpenAI\Responses\Responses\Streaming\RateLimits; use OpenAI\Responses\Responses\Streaming\ReasoningSummaryPart; use OpenAI\Responses\Responses\Streaming\ReasoningSummaryTextDelta; use OpenAI\Responses\Responses\Streaming\ReasoningSummaryTextDone; @@ -53,7 +54,7 @@ final class CreateStreamedResponse implements ResponseContract private function __construct( public readonly string $event, - public readonly Response|OutputItem|ContentPart|OutputTextDelta|OutputTextAnnotationAdded|OutputTextDone|RefusalDelta|RefusalDone|FunctionCallArgumentsDelta|FunctionCallArgumentsDone|FileSearchCall|WebSearchCall|CodeInterpreterCall|CodeInterpreterCodeDelta|CodeInterpreterCodeDone|ReasoningSummaryPart|ReasoningSummaryTextDelta|ReasoningSummaryTextDone|ReasoningTextDelta|ReasoningTextDone|McpListTools|McpListToolsInProgress|McpCall|McpCallArgumentsDelta|McpCallArgumentsDone|ImageGenerationPart|ImageGenerationPartialImage|Error $response, + public readonly Response|OutputItem|ContentPart|OutputTextDelta|OutputTextAnnotationAdded|OutputTextDone|RefusalDelta|RefusalDone|FunctionCallArgumentsDelta|FunctionCallArgumentsDone|FileSearchCall|WebSearchCall|CodeInterpreterCall|CodeInterpreterCodeDelta|CodeInterpreterCodeDone|ReasoningSummaryPart|ReasoningSummaryTextDelta|ReasoningSummaryTextDone|ReasoningTextDelta|ReasoningTextDone|McpListTools|McpListToolsInProgress|McpCall|McpCallArgumentsDelta|McpCallArgumentsDone|ImageGenerationPart|ImageGenerationPartialImage|RateLimits|Error $response, ) {} /** @@ -115,6 +116,7 @@ public static function from(array $attributes): self 'response.image_generation_call.generating', 'response.image_generation_call.in_progress' => ImageGenerationPart::from($attributes, $meta), // @phpstan-ignore-line 'response.image_generation_call.partial_image' => ImageGenerationPartialImage::from($attributes, $meta), // @phpstan-ignore-line + 'response.rate_limits.updated' => RateLimits::from($attributes, $meta), // @phpstan-ignore-line 'error' => Error::from($attributes, $meta), // @phpstan-ignore-line default => throw new UnknownEventException('Unknown Responses streaming event: '.$event), }; diff --git a/src/Responses/Responses/Streaming/RateLimits.php b/src/Responses/Responses/Streaming/RateLimits.php new file mode 100644 index 00000000..b1cd858c --- /dev/null +++ b/src/Responses/Responses/Streaming/RateLimits.php @@ -0,0 +1,52 @@ + + */ +final class RateLimits implements ResponseContract, ResponseHasMetaInformationContract +{ + /** + * @use ArrayAccessible + */ + use ArrayAccessible; + + use Fakeable; + use HasMetaInformation; + + private function __construct( + private readonly MetaInformation $meta, + ) {} + + /** + * @param RateLimitsType $attributes + */ + public static function from(array $attributes, MetaInformation $meta): self + { + return new self( + meta: $meta, + ); + } + + /** + * {@inheritDoc} + */ + public function toArray(): array + { + return [ + 'type' => 'response.rate_limits.updated', + ]; + } +} From af25501d65fde01b4bb1fefe813d1dc0bbcd5c18 Mon Sep 17 00:00:00 2001 From: Connor Tumbleson Date: Sun, 19 Apr 2026 08:43:12 -0400 Subject: [PATCH 2/2] test(OpenAI): add no-op rate limit stream class --- tests/Fixtures/Responses.php | 5 +++++ .../Fixtures/Streams/ResponseRateLimitsUpdated.txt | 1 + .../Responses/Responses/CreateStreamedResponse.php | 13 +++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 tests/Fixtures/Streams/ResponseRateLimitsUpdated.txt diff --git a/tests/Fixtures/Responses.php b/tests/Fixtures/Responses.php index cdafd18c..b0eda37a 100644 --- a/tests/Fixtures/Responses.php +++ b/tests/Fixtures/Responses.php @@ -944,3 +944,8 @@ function responseReasoningTextDoneEvent() { return fopen(__DIR__.'/Streams/ResponseReasoningTextDone.txt', 'r'); } + +function responseRateLimitsUpdatedEvent() +{ + return fopen(__DIR__.'/Streams/ResponseRateLimitsUpdated.txt', 'r'); +} diff --git a/tests/Fixtures/Streams/ResponseRateLimitsUpdated.txt b/tests/Fixtures/Streams/ResponseRateLimitsUpdated.txt new file mode 100644 index 00000000..18161e0e --- /dev/null +++ b/tests/Fixtures/Streams/ResponseRateLimitsUpdated.txt @@ -0,0 +1 @@ +data: {"type":"response.rate_limits.updated"} diff --git a/tests/Responses/Responses/CreateStreamedResponse.php b/tests/Responses/Responses/CreateStreamedResponse.php index 5c56a74b..e303d37f 100644 --- a/tests/Responses/Responses/CreateStreamedResponse.php +++ b/tests/Responses/Responses/CreateStreamedResponse.php @@ -2,6 +2,7 @@ use OpenAI\Responses\Responses\CreateResponse; use OpenAI\Responses\Responses\CreateStreamedResponse; +use OpenAI\Responses\Responses\Streaming\RateLimits; use OpenAI\Responses\Responses\Streaming\ReasoningTextDelta; use OpenAI\Responses\Responses\Streaming\ReasoningTextDone; use OpenAI\Responses\Responses\Streaming\Response; @@ -55,3 +56,15 @@ ->response->contentIndex->toBe(0) ->response->sequenceNumber->toBe(10); }); + +test('rate limits updated event', function () { + $response = CreateStreamedResponse::fake(responseRateLimitsUpdatedEvent()); + + expect($response->getIterator()->current()) + ->toBeInstanceOf(CreateStreamedResponse::class) + ->event->toBe('response.rate_limits.updated') + ->response->toBeInstanceOf(RateLimits::class) + ->response->toArray()->toBe([ + 'type' => 'response.rate_limits.updated', + ]); +});