mirror of
https://github.com/openai/codex.git
synced 2026-10-24 18:18:41 +00:00
Start Python SDK turn subscriptions at their attachment point (#44400)
## What changed Make turn event delivery depend on when each consumer attaches: - Handles returned by `thread.turn(...)` receive events from when the request is sent, including events received before the response arrives. - Other handles and explicit low-level registrations receive only events from when they join. Remove replay of completed items, token usage, and terminal events; use `thread.read(include_turns=True)` for earlier history. - Retain unread events for active subscribers and pending starts, release unused turn state, and close the returned subscription when an async start is cancelled. Preserve the existing low-level subscription when repeated `turn_start(...)` calls return the same turn. ## Testing Update coverage for late joins, request-time buffering, completion or transport failure before a start returns, async cancellation cleanup, and repeated low-level starts. Adjust external-message integration tests to allow handles to collect different items while receiving the same final response. GitOrigin-RevId: 3b7f1268df1193dee88385006ae9510101086c24
This commit is contained in:
@@ -654,6 +654,15 @@ class CodexClient:
|
||||
params: V2TurnStartParams | JsonObject | None = None,
|
||||
) -> TurnStartResponse:
|
||||
"""Start a turn and register its notification queue as early as possible."""
|
||||
return self._start_turn(thread_id, input_items, params, for_handle=False)[0]
|
||||
|
||||
def _start_turn(
|
||||
self,
|
||||
thread_id: str,
|
||||
input_items: list[JsonObject] | JsonObject | str,
|
||||
params: V2TurnStartParams | JsonObject | None,
|
||||
for_handle: bool,
|
||||
) -> tuple[TurnStartResponse, _TurnSubscription | None]:
|
||||
with self._thread_start_lock(thread_id):
|
||||
if self._router.has_goal(thread_id):
|
||||
raise InvalidRequestError(
|
||||
@@ -665,10 +674,12 @@ class CodexClient:
|
||||
"threadId": thread_id,
|
||||
"input": self._normalize_input_items(input_items),
|
||||
}
|
||||
with self._router.pending_turn(thread_id):
|
||||
with self._router.pending_turn(thread_id) as cursors:
|
||||
started = self.request("turn/start", payload, response_model=TurnStartResponse)
|
||||
self._router.prepare_turn(started.turn.id, thread_id)
|
||||
return started
|
||||
subscription = self._router.prepare_turn(
|
||||
started.turn.id, thread_id, cursors, for_handle=for_handle
|
||||
)
|
||||
return started, subscription
|
||||
|
||||
@contextmanager
|
||||
def _thread_start_lock(self, thread_id: str) -> Iterator[None]:
|
||||
|
||||
Reference in New Issue
Block a user