From 78295cb42297852bd1d40af508f8268da091688f Mon Sep 17 00:00:00 2001 From: ethanvillalovoz Date: Sun, 2 Nov 2025 21:06:52 -0800 Subject: [PATCH 1/2] fix: add wait_until_completed helper for GPT-5 polling issue (#2725) --- src/openai/resources/responses/responses.py | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/openai/resources/responses/responses.py b/src/openai/resources/responses/responses.py index 439cf8d3ad..9df4d31e0d 100644 --- a/src/openai/resources/responses/responses.py +++ b/src/openai/resources/responses/responses.py @@ -1491,6 +1491,38 @@ def cancel( class AsyncResponses(AsyncAPIResource): + async def wait_until_completed( + self, + response_id: str, + *, + poll_interval: float = 1.0, + timeout: float = 60.0, + include: list = None, + **kwargs + ) -> "Response": + """ + Polls retrieve() until the response status is 'completed' or timeout is reached. + Args: + response_id: The response ID to poll. + poll_interval: Seconds between polls (default 1.0). + timeout: Max seconds to wait (default 60.0). + include: Optional fields to include in retrieve(). + **kwargs: Passed to retrieve(). + Returns: + The completed Response object. + Raises: + TimeoutError: If the response does not complete in time. + """ + import asyncio + import time + start = time.monotonic() + while True: + resp = await self.retrieve(response_id, include=include, **kwargs) + if hasattr(resp, "status") and resp.status == "completed": + return resp + if time.monotonic() - start > timeout: + raise TimeoutError(f"Response {response_id} did not complete within {timeout} seconds.") + await asyncio.sleep(poll_interval) @cached_property def input_items(self) -> AsyncInputItems: return AsyncInputItems(self._client) From bb9d7cfe685c14c94c050a3239747277675c4feb Mon Sep 17 00:00:00 2001 From: ethanvillalovoz Date: Sun, 2 Nov 2025 23:30:48 -0800 Subject: [PATCH 2/2] fix(responses): improve type annotations in AsyncResponses.wait_until_completed - Use Optional[List[ResponseIncludable]] for include - Pass omit when include is None to satisfy type checker - Explicitly cast resp to Response to silence Pyright errors - Ensure static type safety and pass all lints --- src/openai/resources/responses/responses.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/openai/resources/responses/responses.py b/src/openai/resources/responses/responses.py index 9df4d31e0d..f17335ff51 100644 --- a/src/openai/resources/responses/responses.py +++ b/src/openai/resources/responses/responses.py @@ -1497,9 +1497,9 @@ async def wait_until_completed( *, poll_interval: float = 1.0, timeout: float = 60.0, - include: list = None, - **kwargs - ) -> "Response": + include: Optional[List[ResponseIncludable]] = None, + **kwargs: Any, + ) -> Response: """ Polls retrieve() until the response status is 'completed' or timeout is reached. Args: @@ -1513,16 +1513,20 @@ async def wait_until_completed( Raises: TimeoutError: If the response does not complete in time. """ - import asyncio import time - start = time.monotonic() + import asyncio + + start: float = time.monotonic() while True: - resp = await self.retrieve(response_id, include=include, **kwargs) - if hasattr(resp, "status") and resp.status == "completed": + resp = cast( + Response, await self.retrieve(response_id, include=include if include is not None else omit, **kwargs) + ) + if hasattr(resp, "status") and getattr(resp, "status", None) == "completed": return resp if time.monotonic() - start > timeout: raise TimeoutError(f"Response {response_id} did not complete within {timeout} seconds.") await asyncio.sleep(poll_interval) + @cached_property def input_items(self) -> AsyncInputItems: return AsyncInputItems(self._client)