Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .castiron.stats.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
schema_version: 1
generation_id: 7c85e3b8-1fd9-4422-9e62-0b845e4d0dd6
openapi_spec_hash: 4e1ab2560f0c0f65641ea0a2d769a0d5
openapi_transformed_spec_hash: 55e7b75c47c80e83f6e3c2970444e5ba
config_hash: dfe8a20c64cc5d852e69c441cbd28ae7
codegen_sha: 1a2564e113780db175aecce7b826099172da9171
codegen_hash: aee79621a90e3602ea790e7bc34cfc58368c4217f4d77921bc8960d65b4a8845
public_codegen_sha: 5d5101490afb27fea944f63bc21b52140409bf4a
generation_id: c48dfb66-88a5-4465-96d1-0585b9ab8215
openapi_spec_hash: 0ac5ea4ab2546a188a36a0d370367637
openapi_transformed_spec_hash: 6be6c39576ec27111cab26c251d2ab65
config_hash: d92ec885ac2a08b6a4c1ff90420f0327
codegen_sha: 9a9f8502cf7f372b0bc13c052819b78d02991ca5
codegen_hash: 82d1c3235b99cb90187912ae7dd653fba230efd59dbf3c947b6c522a1a801d85
public_codegen_sha: db47bcd202616d35b583b2433270b565be76233a
318 changes: 217 additions & 101 deletions api_reference/openapi.transformed.yml

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions src/openai/resources/beta/responses/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -4206,6 +4206,15 @@ async def recv_bytes(self) -> bytes:
"""
message = await self._connection.recv(decode=False)
log.debug("Received WebSocket message: %i bytes", len(message))
if self._reconnect_attempt:
# Account for raw application progress without changing frame delivery.
try:
event_data: object = json.loads(message)
except (ValueError, RecursionError):
return message
event_type = cast("dict[str, object]", event_data).get("type") if isinstance(event_data, dict) else None
if isinstance(event_type, str) and event_type and event_type != "error":
self._reconnect_attempt = 0
return message

async def send(self, event: BetaResponsesClientEvent | BetaResponsesClientEventParam) -> None:
Expand Down Expand Up @@ -4675,6 +4684,15 @@ def recv_bytes(self) -> bytes:
"""
message = self._connection.recv(decode=False)
log.debug("Received WebSocket message: %i bytes", len(message))
if self._reconnect_attempt:
# Account for raw application progress without changing frame delivery.
try:
event_data: object = json.loads(message)
except (ValueError, RecursionError):
return message
event_type = cast("dict[str, object]", event_data).get("type") if isinstance(event_data, dict) else None
if isinstance(event_type, str) and event_type and event_type != "error":
self._reconnect_attempt = 0
return message

def send(self, event: BetaResponsesClientEvent | BetaResponsesClientEventParam) -> None:
Expand Down
578 changes: 334 additions & 244 deletions src/openai/resources/images.py

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions src/openai/resources/realtime/realtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,15 @@ async def recv_bytes(self) -> bytes:
"""
message = await self._connection.recv(decode=False)
log.debug("Received WebSocket message: %i bytes", len(message))
if self._reconnect_attempt:
# Account for raw application progress without changing frame delivery.
try:
event_data: object = json.loads(message)
except (ValueError, RecursionError):
return message
event_type = cast("dict[str, object]", event_data).get("type") if isinstance(event_data, dict) else None
if isinstance(event_type, str) and event_type and event_type != "error":
self._reconnect_attempt = 0
return message

async def send(self, event: RealtimeClientEvent | RealtimeClientEventParam) -> None:
Expand Down Expand Up @@ -846,6 +855,15 @@ def recv_bytes(self) -> bytes:
"""
message = self._connection.recv(decode=False)
log.debug("Received WebSocket message: %i bytes", len(message))
if self._reconnect_attempt:
# Account for raw application progress without changing frame delivery.
try:
event_data: object = json.loads(message)
except (ValueError, RecursionError):
return message
event_type = cast("dict[str, object]", event_data).get("type") if isinstance(event_data, dict) else None
if isinstance(event_type, str) and event_type and event_type != "error":
self._reconnect_attempt = 0
return message

def send(self, event: RealtimeClientEvent | RealtimeClientEventParam) -> None:
Expand Down
18 changes: 18 additions & 0 deletions src/openai/resources/responses/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -4093,6 +4093,15 @@ async def recv_bytes(self) -> bytes:
"""
message = await self._connection.recv(decode=False)
log.debug("Received WebSocket message: %i bytes", len(message))
if self._reconnect_attempt:
# Account for raw application progress without changing frame delivery.
try:
event_data: object = json.loads(message)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve raw delivery without parsing the entire event

When recv_bytes() receives the first non-error event after a reconnect, this now materializes the complete JSON object solely to update retry accounting; callers using the raw API to process very large image, audio, or Responses events therefore incur an unexpected full parse and allocation before receiving the bytes, and .recv() parses that same event a second time. This pattern is duplicated across the synchronous and asynchronous Realtime, Responses, and Beta Responses connections and can cause severe latency or memory exhaustion for payloads that were previously passed through unchanged; track application progress without fully materializing the raw payload.

AGENTS.md reference: AGENTS.md:L114-L121

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The raw-read change preserves retry-budget accounting after a reconnect. The extra JSON decode runs while the retry budget is consumed; a healthy non-error event resets it. Raw bytes are preserved, but parsing/allocation overhead is real and typed recv() can parse the same event again. I'd accept that tradeoff here and handle optimization separately rather than undo the retry fix. I haven't benchmarked large-frame overhead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jbeckwith-oai could you take another look at the response above? Are you comfortable with retaining the retry fix here and addressing the parsing overhead separately, or is there something else you need before re-reviewing?

except (ValueError, RecursionError):
return message
event_type = cast("dict[str, object]", event_data).get("type") if isinstance(event_data, dict) else None
if isinstance(event_type, str) and event_type and event_type != "error":
self._reconnect_attempt = 0
return message

async def send(self, event: ResponsesClientEvent | ResponsesClientEventParam) -> None:
Expand Down Expand Up @@ -4562,6 +4571,15 @@ def recv_bytes(self) -> bytes:
"""
message = self._connection.recv(decode=False)
log.debug("Received WebSocket message: %i bytes", len(message))
if self._reconnect_attempt:
# Account for raw application progress without changing frame delivery.
try:
event_data: object = json.loads(message)
except (ValueError, RecursionError):
return message
event_type = cast("dict[str, object]", event_data).get("type") if isinstance(event_data, dict) else None
if isinstance(event_type, str) and event_type and event_type != "error":
self._reconnect_attempt = 0
return message

def send(self, event: ResponsesClientEvent | ResponsesClientEventParam) -> None:
Expand Down
9 changes: 9 additions & 0 deletions src/openai/types/beta/beta_response_input_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,15 @@ class ImageGenerationCall(BaseModel):
agent: Optional[ImageGenerationCallAgent] = None
"""The agent that produced this item."""

quality: Optional[Literal["low", "medium", "high", "xhigh", "max", "auto"]] = None
"""The quality of the image generated by the image generation tool call.

One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024"], None] = None
"""The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`."""


class LocalShellCallAction(BaseModel):
"""Execute a shell command on the server."""
Expand Down
9 changes: 9 additions & 0 deletions src/openai/types/beta/beta_response_input_item_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,15 @@ class ImageGenerationCall(TypedDict, total=False):
agent: Optional[ImageGenerationCallAgent]
"""The agent that produced this item."""

quality: Optional[Literal["low", "medium", "high", "xhigh", "max", "auto"]]
"""The quality of the image generated by the image generation tool call.

One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024"], None]
"""The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`."""


class LocalShellCallAction(TypedDict, total=False):
"""Execute a shell command on the server."""
Expand Down
9 changes: 9 additions & 0 deletions src/openai/types/beta/beta_response_input_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,15 @@ class ImageGenerationCall(TypedDict, total=False):
agent: Optional[ImageGenerationCallAgent]
"""The agent that produced this item."""

quality: Optional[Literal["low", "medium", "high", "xhigh", "max", "auto"]]
"""The quality of the image generated by the image generation tool call.

One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024"], None]
"""The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`."""


class LocalShellCallAction(TypedDict, total=False):
"""Execute a shell command on the server."""
Expand Down
9 changes: 9 additions & 0 deletions src/openai/types/beta/beta_response_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,15 @@ class ImageGenerationCall(BaseModel):
agent: Optional[ImageGenerationCallAgent] = None
"""The agent that produced this item."""

quality: Optional[Literal["low", "medium", "high", "xhigh", "max", "auto"]] = None
"""The quality of the image generated by the image generation tool call.

One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024"], None] = None
"""The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`."""


class LocalShellCallAction(BaseModel):
"""Execute a shell command on the server."""
Expand Down
9 changes: 9 additions & 0 deletions src/openai/types/beta/beta_response_output_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,15 @@ class ImageGenerationCall(BaseModel):
agent: Optional[ImageGenerationCallAgent] = None
"""The agent that produced this item."""

quality: Optional[Literal["low", "medium", "high", "xhigh", "max", "auto"]] = None
"""The quality of the image generated by the image generation tool call.

One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024"], None] = None
"""The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`."""


class LocalShellCallAction(BaseModel):
"""Execute a shell command on the server."""
Expand Down
54 changes: 34 additions & 20 deletions src/openai/types/beta/beta_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,17 @@ class ImageGeneration(BaseModel):
"""Whether to generate a new image or edit an existing image. Default: `auto`."""

background: Optional[Literal["transparent", "opaque", "auto"]] = None
"""
Allows to set transparency for the background of the generated image(s). Must be
one of `transparent`, `opaque`, or `auto` (default value). When `auto` is used,
the model will automatically determine the best background for the image.
"""Allows to set transparency for the background of the generated image(s).

Must be one of `transparent`, `opaque`, or `auto` (default value). When `auto`
is used, the model will automatically determine the best background for the
image.

Transparent backgrounds are available for supported GPT Image models. For
`gpt-image-2` and `gpt-image-2-2026-04-21`, this support is in preview. When
using `transparent`, set the output format to `png` or `webp`.
`gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08`
snapshots, support `opaque` and `transparent` backgrounds. Transparent
backgrounds are available for supported GPT Image models. For `gpt-image-2` and
`gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`,
set the output format to `png` or `webp`.
"""

input_fidelity: Optional[Literal["high", "low"]] = None
Expand All @@ -292,6 +295,10 @@ class ImageGeneration(BaseModel):
"gpt-image-1-mini",
"gpt-image-2",
"gpt-image-2-2026-04-21",
"gpt-image-2.5-sunburst",
"gpt-image-2.5-sunburst-2026-09-08",
"gpt-image-2.5-flare",
"gpt-image-2.5-flare-2026-09-08",
"gpt-image-1.5",
"chatgpt-image-latest",
],
Expand All @@ -300,7 +307,10 @@ class ImageGeneration(BaseModel):
"""The image generation model to use.

One of `gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`, `gpt-image-2`,
`gpt-image-2-2026-04-21`, or `chatgpt-image-latest`. Default: `gpt-image-1`.
`gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`,
`gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`,
`gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default:
`gpt-image-1`.
"""

moderation: Optional[Literal["auto", "low"]] = None
Expand All @@ -321,25 +331,29 @@ class ImageGeneration(BaseModel):
to 3.
"""

quality: Optional[Literal["low", "medium", "high", "auto"]] = None
quality: Optional[Literal["low", "medium", "high", "xhigh", "max", "auto"]] = None
"""The quality of the generated image.

One of `low`, `medium`, `high`, or `auto`. Default: `auto`.
The GPT image models support `low`, `medium`, and `high`.
`gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08`
snapshots, also support `xhigh` and `max`. Default: `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024", "auto"], None] = None
"""The size of the generated images.

For `gpt-image-2` and `gpt-image-2-2026-04-21`, arbitrary resolutions are
supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height
must both be divisible by 16 and the requested aspect ratio must be between 1:3
and 3:1. Resolutions above `2560x1440` are experimental, and the maximum
supported resolution is `3840x2160`. The requested size must also satisfy the
model's current pixel and edge limits. The standard sizes `1024x1024`,
`1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is
supported for models that allow automatic sizing. For `dall-e-2`, use one of
`256x256`, `512x512`, or `1024x1024`. For `dall-e-3`, use one of `1024x1024`,
`1792x1024`, or `1024x1792`.
For `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`,
`gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and
`gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as
`WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be
divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1.
Resolutions above `2560x1440` are experimental, and the maximum supported
resolution is `3840x2160`. The requested size must also satisfy the model's
current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and
`1024x1536` are supported by the GPT image models; `auto` is supported for
models that allow automatic sizing. For `dall-e-2`, use one of `256x256`,
`512x512`, or `1024x1024`. For `dall-e-3`, use one of `1024x1024`, `1792x1024`,
or `1024x1792`.
"""


Expand Down
54 changes: 34 additions & 20 deletions src/openai/types/beta/beta_tool_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,17 @@ class ImageGeneration(TypedDict, total=False):
"""Whether to generate a new image or edit an existing image. Default: `auto`."""

background: Literal["transparent", "opaque", "auto"]
"""
Allows to set transparency for the background of the generated image(s). Must be
one of `transparent`, `opaque`, or `auto` (default value). When `auto` is used,
the model will automatically determine the best background for the image.
"""Allows to set transparency for the background of the generated image(s).

Must be one of `transparent`, `opaque`, or `auto` (default value). When `auto`
is used, the model will automatically determine the best background for the
image.

Transparent backgrounds are available for supported GPT Image models. For
`gpt-image-2` and `gpt-image-2-2026-04-21`, this support is in preview. When
using `transparent`, set the output format to `png` or `webp`.
`gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08`
snapshots, support `opaque` and `transparent` backgrounds. Transparent
backgrounds are available for supported GPT Image models. For `gpt-image-2` and
`gpt-image-2-2026-04-21`, this support is in preview. When using `transparent`,
set the output format to `png` or `webp`.
"""

input_fidelity: Optional[Literal["high", "low"]]
Expand All @@ -291,14 +294,21 @@ class ImageGeneration(TypedDict, total=False):
"gpt-image-1-mini",
"gpt-image-2",
"gpt-image-2-2026-04-21",
"gpt-image-2.5-sunburst",
"gpt-image-2.5-sunburst-2026-09-08",
"gpt-image-2.5-flare",
"gpt-image-2.5-flare-2026-09-08",
"gpt-image-1.5",
"chatgpt-image-latest",
],
]
"""The image generation model to use.

One of `gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`, `gpt-image-2`,
`gpt-image-2-2026-04-21`, or `chatgpt-image-latest`. Default: `gpt-image-1`.
`gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`,
`gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`,
`gpt-image-2.5-flare-2026-09-08`, or `chatgpt-image-latest`. Default:
`gpt-image-1`.
"""

moderation: Literal["auto", "low"]
Expand All @@ -319,25 +329,29 @@ class ImageGeneration(TypedDict, total=False):
to 3.
"""

quality: Literal["low", "medium", "high", "auto"]
quality: Literal["low", "medium", "high", "xhigh", "max", "auto"]
"""The quality of the generated image.

One of `low`, `medium`, `high`, or `auto`. Default: `auto`.
The GPT image models support `low`, `medium`, and `high`.
`gpt-image-2.5-sunburst` and `gpt-image-2.5-flare`, including their `2026-09-08`
snapshots, also support `xhigh` and `max`. Default: `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024", "auto"]]
"""The size of the generated images.

For `gpt-image-2` and `gpt-image-2-2026-04-21`, arbitrary resolutions are
supported as `WIDTHxHEIGHT` strings, for example `1536x864`. Width and height
must both be divisible by 16 and the requested aspect ratio must be between 1:3
and 3:1. Resolutions above `2560x1440` are experimental, and the maximum
supported resolution is `3840x2160`. The requested size must also satisfy the
model's current pixel and edge limits. The standard sizes `1024x1024`,
`1536x1024`, and `1024x1536` are supported by the GPT image models; `auto` is
supported for models that allow automatic sizing. For `dall-e-2`, use one of
`256x256`, `512x512`, or `1024x1024`. For `dall-e-3`, use one of `1024x1024`,
`1792x1024`, or `1024x1792`.
For `gpt-image-2`, `gpt-image-2-2026-04-21`, `gpt-image-2.5-sunburst`,
`gpt-image-2.5-sunburst-2026-09-08`, `gpt-image-2.5-flare`, and
`gpt-image-2.5-flare-2026-09-08`, arbitrary resolutions are supported as
`WIDTHxHEIGHT` strings, for example `1536x864`. Width and height must both be
divisible by 16 and the requested aspect ratio must be between 1:3 and 3:1.
Resolutions above `2560x1440` are experimental, and the maximum supported
resolution is `3840x2160`. The requested size must also satisfy the model's
current pixel and edge limits. The standard sizes `1024x1024`, `1536x1024`, and
`1024x1536` are supported by the GPT image models; `auto` is supported for
models that allow automatic sizing. For `dall-e-2`, use one of `256x256`,
`512x512`, or `1024x1024`. For `dall-e-3`, use one of `1024x1024`, `1792x1024`,
or `1024x1792`.
"""


Expand Down
9 changes: 9 additions & 0 deletions src/openai/types/conversations/conversation_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ class ImageGenerationCall(BaseModel):
type: Literal["image_generation_call"]
"""The type of the image generation call. Always `image_generation_call`."""

quality: Optional[Literal["low", "medium", "high", "xhigh", "max", "auto"]] = None
"""The quality of the image generated by the image generation tool call.

One of `low`, `medium`, `high`, `xhigh`, `max`, or `auto`.
"""

size: Union[str, Literal["1024x1024", "1024x1536", "1536x1024"], None] = None
"""The image dimensions as a `WIDTHxHEIGHT` string, for example `1536x864`."""


class AdditionalTools(BaseModel):
id: str
Expand Down
Loading
Loading