From bfd3680c8d3b715bb3175b82cd0fa1c1fb53162f Mon Sep 17 00:00:00 2001 From: Haokai Ding Date: Wed, 23 Sep 2026 21:28:59 +0000 Subject: [PATCH 1/5] fix: preserve single files for fallback extraction paths (#3875) - [x] I understand that this repository is auto-generated and my pull request may not be merged. ## Changes being requested Fixes #3874. When the Skills `files` parameter is a single file, the array extraction path consumes it before the fallback single-file path can run. This produces an empty JSON request instead of uploading the file. Keep non-list values available when a path still expects an array. Direct file extraction and list uploads retain their existing behavior. Add bytes/tuple extraction regressions and synchronous/asynchronous public-client tests that construct a real in-memory zip and inspect its multipart field, filename and content through MockTransport. ## Additional context & links - [Skills create accepts a single zip or multiple files](https://developers.openai.com/api/reference/python/resources/skills/methods/create). - Before the fix: 4 failed, 33 passed. After: 37 passed with `PYTHONPATH=src .venv/bin/python -m pytest -o addopts='' tests/test_extract_files.py tests/test_files.py -q`. Tests run serially and make no live API requests. - Ruff lint and format checks pass on all three changed files; `git diff --check` passes. - Python 3.13.15, httpx2 2.12.0, Pydantic 2.13.5 on macOS ARM64. The full SDK suite, Pyright and mypy were not run locally. - The custom-code policy, budget and generated ownership metadata are unchanged. Budget validation remains with the trusted upstream CI; SDK CODEOWNER review is required for this file-handling change. Co-authored-by: Marcus Wood --- src/openai/_utils/_utils.py | 2 +- tests/test_extract_files.py | 10 ++++++++++ tests/test_files.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/openai/_utils/_utils.py b/src/openai/_utils/_utils.py index 02046a352c..95641eb158 100644 --- a/src/openai/_utils/_utils.py +++ b/src/openai/_utils/_utils.py @@ -114,7 +114,7 @@ def _extract_items( try: # Remove the field if there are no more dict keys in the path, # only "" traversal markers or end. - if all(p == "" for p in path[index:]): + if all(p == "" for p in path[index:]) and (index == len(path) or is_list(obj[key])): item = obj.pop(key) else: item = obj[key] diff --git a/tests/test_extract_files.py b/tests/test_extract_files.py index 54490e133f..6116c42c18 100644 --- a/tests/test_extract_files.py +++ b/tests/test_extract_files.py @@ -41,6 +41,16 @@ def test_top_level_file_array() -> None: assert query == {"title": "hello"} +@pytest.mark.parametrize("file", [b"zip contents", ("skill.zip", b"zip contents")]) +def test_single_file_fallback_after_array_path(file: FileTypes) -> None: + query = {"files": file, "title": "hello"} + assert extract_files(query, paths=[["files", ""]]) == [] + assert query == {"files": file, "title": "hello"} + + assert extract_files(query, paths=[["files", ""], ["files"]]) == [("files", file)] + assert query == {"title": "hello"} + + @pytest.mark.parametrize( "query,paths,expected", [ diff --git a/tests/test_files.py b/tests/test_files.py index a94ddce0ef..51ca9f0acc 100644 --- a/tests/test_files.py +++ b/tests/test_files.py @@ -1,14 +1,49 @@ +import io +import zipfile from pathlib import Path import anyio +import httpx2 import pytest +from openai import OpenAI, AsyncOpenAI +from tests.respx2 import MockRouter from openai._files import to_httpx_files, deepcopy_with_paths, async_to_httpx_files from openai._utils import extract_files +from .conftest import base_url + readme_path = Path(__file__).parent.parent.joinpath("README.md") +@pytest.mark.respx2(base_url=base_url) +@pytest.mark.asyncio +@pytest.mark.parametrize("is_async", [False, True]) +@pytest.mark.parametrize("as_list", [False, True]) +async def test_skills_upload_zip( + client: OpenAI, async_client: AsyncOpenAI, respx2_mock: MockRouter, is_async: bool, as_list: bool +) -> None: + buffer = io.BytesIO() + with zipfile.ZipFile(buffer, "w") as archive: + archive.writestr("SKILL.md", "---\nname: example\ndescription: Test skill\n---\n# Example\n") + content = buffer.getvalue() + file = ("skill.zip", content) + files = [file] if as_list else file + respx2_mock.post("/skills").mock(return_value=httpx2.Response(200, json={})) + response = ( + await async_client.skills.with_raw_response.create(files=files) + if is_async + else client.skills.with_raw_response.create(files=files) + ) + request = response.http_request + body = await request.aread() if is_async else request.read() + assert request.headers["content-type"].startswith("multipart/form-data;") + expected_field = b'name="files[]"' if as_list else b'name="files"' + assert expected_field in body + assert b'filename="skill.zip"' in body + assert body.count(content) == 1 + + def test_pathlib_includes_file_name() -> None: result = to_httpx_files({"file": readme_path}) assert result == {"file": ("README.md", readme_path.read_bytes())} From 325a948a545add0201e082e778ca11b90ddb9426 Mon Sep 17 00:00:00 2001 From: Mark Stuart Date: Wed, 23 Sep 2026 21:57:39 +0000 Subject: [PATCH 2/5] chore(api): correct fine-tuning bounds and Realtime response reference (#3949) ## Summary Corrects fine-tuning numeric bounds and Realtime client-secret response alternatives in the Python API reference. ## Changes - Use OpenAPI 3.1 numeric exclusive bounds for fine-tuning parameters. - Identify realtime and transcription session alternatives in client-secret responses. ## Why The API reference used boolean `exclusiveMinimum` values, which are invalid in OpenAPI 3.1. This corrects seven numeric lower bounds and restores their existing `auto` defaults. Explicit discriminator mappings also identify the existing `realtime` and `transcription` alternatives in client-secret responses. This is a reference-only correction: SDK source, public types, dependencies, and request/response serialization are unchanged. Source: [published OpenAPI correction](https://github.com/openai/openai-openapi/commit/946e365dd69d52ccfe49fd0a9e565504aef517bd). ## Compatibility review Reviewed head `add92714d353df33e1ee98a604800ce8b6e6d42d` against base `4d1274681db7f34f671ff9e71adc1461d22a927b`. - The complete tree diff contains only `.castiron.stats.yml` and `api_reference/openapi.transformed.yml`. All SDK source, public signatures, related model types, serializers, dependencies, and package/build configuration are unchanged. Neither changed file is consumed by the SDK runtime or enters its normal distributed code. - Paired baseline/candidate Python client and model probes pass (183 cases per revision, identical results). - The transformed reference passes 464 focused schema cases, including actual enclosing requests/responses, lower/upper boundaries, `auto`, omission, and both Realtime response variants. - [Current-head CI](https://github.com/openai/openai-python/actions/runs/35922654398) passes. Scope: this establishes no identified SDK-package compile-time or runtime compatibility regression from this patch. Tools that directly read the OpenAPI reference (validators, mock servers, or third-party generators) can observe the corrected bounds, defaults, and explicit mappings; those integrations are a separate compatibility surface. No deployed-service test or package release is claimed. Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com> --- .castiron.stats.yml | 10 ++++----- api_reference/openapi.transformed.yml | 31 +++++++++++++++------------ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/.castiron.stats.yml b/.castiron.stats.yml index e9b9830a3b..dbb0c415da 100644 --- a/.castiron.stats.yml +++ b/.castiron.stats.yml @@ -1,8 +1,8 @@ schema_version: 1 -generation_id: d9e3b632-5822-43f8-a0de-0cd04d09db33 -openapi_spec_hash: 687580b2f55d2dada661f0387a4b3e0d -openapi_transformed_spec_hash: 904296217a5077aa14766c6c58aa87d9 +generation_id: aa310748-8aec-4537-9913-7c71cb2237cb +openapi_spec_hash: 3fdbf56dcaf85efe1e621db8067f829a +openapi_transformed_spec_hash: 3ff7c45d6856b5ffccfd73b63ee4263d config_hash: 84cdcc959ee7140cc9a65e9b642c097b -codegen_sha: 41ac0d43560df6c0983b529a6112e2c437ead2d1 +codegen_sha: 7b758af07cc10c9cf05f332897c9b75f85162bf3 codegen_hash: 614193cc88f476d3dbfe7d149d8adf21489f235af4454fb1e93628fe43e1e351 -public_codegen_sha: 2722089d4e9342c45f1ddbda6e7b4b72511d961f +public_codegen_sha: 7eba580f1b2d7eb434697db16f576022d16b0388 diff --git a/api_reference/openapi.transformed.yml b/api_reference/openapi.transformed.yml index fdf4896149..1321ea33c1 100644 --- a/api_reference/openapi.transformed.yml +++ b/api_reference/openapi.transformed.yml @@ -36954,6 +36954,7 @@ components: description: | Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. + default: auto anyOf: - type: string enum: @@ -36961,8 +36962,7 @@ components: x-stainless-const: true title: Auto - type: number - minimum: 0 - exclusiveMinimum: true + exclusiveMinimum: 0 n_epochs: description: | The number of epochs to train the model for. An epoch refers to one full cycle @@ -41281,15 +41281,15 @@ components: beta: description: | The beta value for the DPO method. A higher beta value will increase the weight of the penalty between the policy and reference model. + default: auto anyOf: - type: string enum: - auto x-stainless-const: true - type: number - minimum: 0 maximum: 2 - exclusiveMinimum: true + exclusiveMinimum: 0 batch_size: description: | Number of examples in each batch. A larger batch size means that model parameters are updated less frequently, but with lower variance. @@ -41305,14 +41305,14 @@ components: learning_rate_multiplier: description: | Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. + default: auto anyOf: - type: string enum: - auto x-stainless-const: true - type: number - minimum: 0 - exclusiveMinimum: true + exclusiveMinimum: 0 n_epochs: description: | The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. @@ -41369,14 +41369,14 @@ components: learning_rate_multiplier: description: | Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. + default: auto anyOf: - type: string enum: - auto x-stainless-const: true - type: number - minimum: 0 - exclusiveMinimum: true + exclusiveMinimum: 0 n_epochs: description: | The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. @@ -41402,15 +41402,15 @@ components: compute_multiplier: description: | Multiplier on amount of compute used for exploring search space during training. + default: auto anyOf: - type: string enum: - auto x-stainless-const: true - type: number - minimum: 0.00001 maximum: 10 - exclusiveMinimum: true + exclusiveMinimum: 0.00001 eval_interval: description: | The number of training steps between evaluation runs. @@ -41469,14 +41469,14 @@ components: learning_rate_multiplier: description: | Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. + default: auto anyOf: - type: string enum: - auto x-stainless-const: true - type: number - minimum: 0 - exclusiveMinimum: true + exclusiveMinimum: 0 n_epochs: description: | The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. @@ -41649,6 +41649,7 @@ components: description: | Scaling factor for the learning rate. A smaller learning rate may be useful to avoid overfitting. + default: auto anyOf: - type: string enum: @@ -41656,8 +41657,7 @@ components: x-stainless-const: true title: Auto - type: number - minimum: 0 - exclusiveMinimum: true + exclusiveMinimum: 0 n_epochs: description: | The number of epochs to train the model for. An epoch refers to one full cycle @@ -51336,6 +51336,9 @@ components: The session configuration for either a realtime or transcription session. discriminator: propertyName: type + mapping: + realtime: '#/components/schemas/RealtimeSessionCreateResponseGA' + transcription: '#/components/schemas/RealtimeTranscriptionSessionCreateResponseGA' anyOf: - $ref: '#/components/schemas/RealtimeSessionCreateResponseGA' - $ref: '#/components/schemas/RealtimeTranscriptionSessionCreateResponseGA' From a95c95ed372476168e9893723ff694ead5db8586 Mon Sep 17 00:00:00 2001 From: Marcus Wood Date: Wed, 23 Sep 2026 23:11:09 +0000 Subject: [PATCH 3/5] chore(api): clarify approximate web search location defaults (#3953) ## Summary Clarifies how approximate user locations affect web search results. ## Changes - Document that omitted or null user locations default to the United States. - Explain how to avoid the fallback with an approximate location containing no location fields, or localize results with location fields. Co-authored-by: marcuswood-oai <323319819+marcuswood-oai@users.noreply.github.com> --- .castiron.stats.yml | 12 ++++++------ api_reference/openapi.transformed.yml | 12 ++++++++---- .../types/beta/beta_web_search_preview_tool.py | 12 ++++++++++-- .../beta/beta_web_search_preview_tool_param.py | 12 ++++++++++-- src/openai/types/beta/beta_web_search_tool.py | 14 ++++++++++++-- .../types/beta/beta_web_search_tool_param.py | 14 ++++++++++++-- .../types/responses/web_search_preview_tool.py | 12 ++++++++++-- .../responses/web_search_preview_tool_param.py | 12 ++++++++++-- src/openai/types/responses/web_search_tool.py | 14 ++++++++++++-- .../types/responses/web_search_tool_param.py | 14 ++++++++++++-- 10 files changed, 102 insertions(+), 26 deletions(-) diff --git a/.castiron.stats.yml b/.castiron.stats.yml index dbb0c415da..3187e77b4a 100644 --- a/.castiron.stats.yml +++ b/.castiron.stats.yml @@ -1,8 +1,8 @@ schema_version: 1 -generation_id: aa310748-8aec-4537-9913-7c71cb2237cb -openapi_spec_hash: 3fdbf56dcaf85efe1e621db8067f829a -openapi_transformed_spec_hash: 3ff7c45d6856b5ffccfd73b63ee4263d +generation_id: 7e63eb4a-5670-4cc0-b884-4076bfc986bf +openapi_spec_hash: 4bba843ccb59994fa67b0d84129af8ae +openapi_transformed_spec_hash: 52080a33f224bf8e7670301604d34c7e config_hash: 84cdcc959ee7140cc9a65e9b642c097b -codegen_sha: 7b758af07cc10c9cf05f332897c9b75f85162bf3 -codegen_hash: 614193cc88f476d3dbfe7d149d8adf21489f235af4454fb1e93628fe43e1e351 -public_codegen_sha: 7eba580f1b2d7eb434697db16f576022d16b0388 +codegen_sha: 51f0864c8108de1eaf5a823e8e152495885e8191 +codegen_hash: dc4765fced94aa65178e5fbda91d2844a712ac8d8e8b7fd8993fde98dbb1cb04 +public_codegen_sha: 65730dc4902028c25ee17020a1ea67f82e7e9658 diff --git a/api_reference/openapi.transformed.yml b/api_reference/openapi.transformed.yml index 1321ea33c1..49ca336ab0 100644 --- a/api_reference/openapi.transformed.yml +++ b/api_reference/openapi.transformed.yml @@ -65321,7 +65321,9 @@ components: - type: object title: Web search approximate location description: | - The approximate location of the user. + The approximate location of the user. If omitted or null, defaults to the + United States. To avoid this fallback, pass `{"type": "approximate"}` without + location fields. To localize results, provide the relevant location fields. properties: type: type: string @@ -68574,7 +68576,7 @@ components: user_location: anyOf: - $ref: '#/components/schemas/ApproximateLocation' - description: The user's location. + description: 'The approximate location of the user. If omitted or null, defaults to the United States. To avoid this fallback, pass `{"type": "approximate"}` without location fields. To localize results, provide the relevant location fields.' - type: 'null' search_context_size: $ref: '#/components/schemas/SearchContextSize' @@ -84509,7 +84511,7 @@ components: user_location: anyOf: - $ref: '#/components/schemas/BetaApproximateLocation' - description: The user's location. + description: 'The approximate location of the user. If omitted or null, defaults to the United States. To avoid this fallback, pass `{"type": "approximate"}` without location fields. To localize results, provide the relevant location fields.' - type: 'null' search_context_size: $ref: '#/components/schemas/BetaSearchContextSize' @@ -85482,7 +85484,9 @@ components: - type: object title: Web search approximate location description: | - The approximate location of the user. + The approximate location of the user. If omitted or null, defaults to the + United States. To avoid this fallback, pass `{"type": "approximate"}` without + location fields. To localize results, provide the relevant location fields. properties: type: type: string diff --git a/src/openai/types/beta/beta_web_search_preview_tool.py b/src/openai/types/beta/beta_web_search_preview_tool.py index 968e480885..967d7b7a38 100644 --- a/src/openai/types/beta/beta_web_search_preview_tool.py +++ b/src/openai/types/beta/beta_web_search_preview_tool.py @@ -9,7 +9,10 @@ class UserLocation(BaseModel): - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass `{"type": "approximate"}` without location fields. To localize results, provide the relevant location fields. + """ type: Literal["approximate"] """The type of location approximation. Always `approximate`.""" @@ -55,4 +58,9 @@ class BetaWebSearchPreviewTool(BaseModel): """ user_location: Optional[UserLocation] = None - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ diff --git a/src/openai/types/beta/beta_web_search_preview_tool_param.py b/src/openai/types/beta/beta_web_search_preview_tool_param.py index 40b245d566..c5fae46f6a 100644 --- a/src/openai/types/beta/beta_web_search_preview_tool_param.py +++ b/src/openai/types/beta/beta_web_search_preview_tool_param.py @@ -9,7 +9,10 @@ class UserLocation(TypedDict, total=False): - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass `{"type": "approximate"}` without location fields. To localize results, provide the relevant location fields. + """ type: Required[Literal["approximate"]] """The type of location approximation. Always `approximate`.""" @@ -55,4 +58,9 @@ class BetaWebSearchPreviewToolParam(TypedDict, total=False): """ user_location: Optional[UserLocation] - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ diff --git a/src/openai/types/beta/beta_web_search_tool.py b/src/openai/types/beta/beta_web_search_tool.py index bdf61e6d90..6adcf29869 100644 --- a/src/openai/types/beta/beta_web_search_tool.py +++ b/src/openai/types/beta/beta_web_search_tool.py @@ -22,7 +22,12 @@ class Filters(BaseModel): class UserLocation(BaseModel): - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the + United States. To avoid this fallback, pass `{"type": "approximate"}` without + location fields. To localize results, provide the relevant location fields. + """ city: Optional[str] = None """Free text input for the city of the user, e.g. `San Francisco`.""" @@ -77,4 +82,9 @@ class BetaWebSearchTool(BaseModel): """ user_location: Optional[UserLocation] = None - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ diff --git a/src/openai/types/beta/beta_web_search_tool_param.py b/src/openai/types/beta/beta_web_search_tool_param.py index e3a3ae5621..1d6cdf5965 100644 --- a/src/openai/types/beta/beta_web_search_tool_param.py +++ b/src/openai/types/beta/beta_web_search_tool_param.py @@ -24,7 +24,12 @@ class Filters(TypedDict, total=False): class UserLocation(TypedDict, total=False): - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the + United States. To avoid this fallback, pass `{"type": "approximate"}` without + location fields. To localize results, provide the relevant location fields. + """ city: Optional[str] """Free text input for the city of the user, e.g. `San Francisco`.""" @@ -79,4 +84,9 @@ class BetaWebSearchToolParam(TypedDict, total=False): """ user_location: Optional[UserLocation] - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ diff --git a/src/openai/types/responses/web_search_preview_tool.py b/src/openai/types/responses/web_search_preview_tool.py index 0de61b2821..5bd2005cbe 100644 --- a/src/openai/types/responses/web_search_preview_tool.py +++ b/src/openai/types/responses/web_search_preview_tool.py @@ -9,7 +9,10 @@ class UserLocation(BaseModel): - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass `{"type": "approximate"}` without location fields. To localize results, provide the relevant location fields. + """ type: Literal["approximate"] """The type of location approximation. Always `approximate`.""" @@ -55,4 +58,9 @@ class WebSearchPreviewTool(BaseModel): """ user_location: Optional[UserLocation] = None - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ diff --git a/src/openai/types/responses/web_search_preview_tool_param.py b/src/openai/types/responses/web_search_preview_tool_param.py index d18068586a..fc4f07c394 100644 --- a/src/openai/types/responses/web_search_preview_tool_param.py +++ b/src/openai/types/responses/web_search_preview_tool_param.py @@ -9,7 +9,10 @@ class UserLocation(TypedDict, total=False): - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass `{"type": "approximate"}` without location fields. To localize results, provide the relevant location fields. + """ type: Required[Literal["approximate"]] """The type of location approximation. Always `approximate`.""" @@ -55,4 +58,9 @@ class WebSearchPreviewToolParam(TypedDict, total=False): """ user_location: Optional[UserLocation] - """The user's location.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ diff --git a/src/openai/types/responses/web_search_tool.py b/src/openai/types/responses/web_search_tool.py index f6323e6642..bbdc014e7f 100644 --- a/src/openai/types/responses/web_search_tool.py +++ b/src/openai/types/responses/web_search_tool.py @@ -22,7 +22,12 @@ class Filters(BaseModel): class UserLocation(BaseModel): - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the + United States. To avoid this fallback, pass `{"type": "approximate"}` without + location fields. To localize results, provide the relevant location fields. + """ city: Optional[str] = None """Free text input for the city of the user, e.g. `San Francisco`.""" @@ -77,4 +82,9 @@ class WebSearchTool(BaseModel): """ user_location: Optional[UserLocation] = None - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ diff --git a/src/openai/types/responses/web_search_tool_param.py b/src/openai/types/responses/web_search_tool_param.py index 1129babeab..1e6568a113 100644 --- a/src/openai/types/responses/web_search_tool_param.py +++ b/src/openai/types/responses/web_search_tool_param.py @@ -24,7 +24,12 @@ class Filters(TypedDict, total=False): class UserLocation(TypedDict, total=False): - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the + United States. To avoid this fallback, pass `{"type": "approximate"}` without + location fields. To localize results, provide the relevant location fields. + """ city: Optional[str] """Free text input for the city of the user, e.g. `San Francisco`.""" @@ -79,4 +84,9 @@ class WebSearchToolParam(TypedDict, total=False): """ user_location: Optional[UserLocation] - """The approximate location of the user.""" + """The approximate location of the user. + + If omitted or null, defaults to the United States. To avoid this fallback, pass + `{"type": "approximate"}` without location fields. To localize results, provide + the relevant location fields. + """ From e79cf53878b1d8580fac3a46e375eb98d9ca161d Mon Sep 17 00:00:00 2001 From: Mark Stuart Date: Wed, 23 Sep 2026 23:39:14 +0000 Subject: [PATCH 4/5] chore(api): clarify Realtime modality array definitions (#3954) ## Summary Clarifies retained Realtime modality arrays in the API reference without changing SDK types or method signatures. ## Changes - Explicitly describe retained Realtime modality fields as arrays of text or audio values. - Preserve existing optionality and SDK behavior. Co-authored-by: markstuart-oai <323302876+markstuart-oai@users.noreply.github.com> --- .castiron.stats.yml | 10 +++++----- api_reference/openapi.transformed.yml | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.castiron.stats.yml b/.castiron.stats.yml index 3187e77b4a..274aa342a4 100644 --- a/.castiron.stats.yml +++ b/.castiron.stats.yml @@ -1,8 +1,8 @@ schema_version: 1 -generation_id: 7e63eb4a-5670-4cc0-b884-4076bfc986bf -openapi_spec_hash: 4bba843ccb59994fa67b0d84129af8ae -openapi_transformed_spec_hash: 52080a33f224bf8e7670301604d34c7e +generation_id: 4bda3ef4-13a5-473f-b0cd-6fa6b69a0db8 +openapi_spec_hash: 6fbcb590bdf88b5d464546b290ab35e7 +openapi_transformed_spec_hash: 4e4a94f25153ab253178d6c098cb4f0e config_hash: 84cdcc959ee7140cc9a65e9b642c097b -codegen_sha: 51f0864c8108de1eaf5a823e8e152495885e8191 +codegen_sha: c11ad8ad6a402c5cabfff79093c308035fe39644 codegen_hash: dc4765fced94aa65178e5fbda91d2844a712ac8d8e8b7fd8993fde98dbb1cb04 -public_codegen_sha: 65730dc4902028c25ee17020a1ea67f82e7e9658 +public_codegen_sha: d54ac7ae41705340870935d4d6484843cb5d9d29 diff --git a/api_reference/openapi.transformed.yml b/api_reference/openapi.transformed.yml index 49ca336ab0..3c69cd5bb0 100644 --- a/api_reference/openapi.transformed.yml +++ b/api_reference/openapi.transformed.yml @@ -54156,6 +54156,7 @@ components: - realtime.session description: The object type. Always `realtime.session`. modalities: + type: array description: | The set of modalities the model can respond with. To disable audio, set this to ["text"]. @@ -54369,6 +54370,7 @@ components: - value - expires_at modalities: + type: array description: | The set of modalities the model can respond with. To disable audio, set this to ["text"]. From d9f7b7a085d4f2173756590abeffeb7a8c7641dd Mon Sep 17 00:00:00 2001 From: "openai-sdks[bot]" <284451331+openai-sdks[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 00:00:28 +0000 Subject: [PATCH 5/5] release: 3.19.2 (#3951) Automated Release PR --- ## [3.19.2](https://github.com/openai/openai-python/compare/v3.19.1...v3.19.2) (2026-09-23) ### Bug Fixes * preserve single files for fallback extraction paths ([#3875](https://github.com/openai/openai-python/issues/3875)) ([bfd3680](https://github.com/openai/openai-python/commit/bfd3680c8d3b715bb3175b82cd0fa1c1fb53162f)) ### Chores * **api:** clarify approximate web search location defaults ([#3953](https://github.com/openai/openai-python/issues/3953)) ([a95c95e](https://github.com/openai/openai-python/commit/a95c95ed372476168e9893723ff694ead5db8586)) * **api:** clarify Realtime modality array definitions ([#3954](https://github.com/openai/openai-python/issues/3954)) ([e79cf53](https://github.com/openai/openai-python/commit/e79cf53878b1d8580fac3a46e375eb98d9ca161d)) * **api:** correct fine-tuning bounds and Realtime response reference ([#3949](https://github.com/openai/openai-python/issues/3949)) ([325a948](https://github.com/openai/openai-python/commit/325a948a545add0201e082e778ca11b90ddb9426)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: openai-sdks[bot] <284451331+openai-sdks[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGELOG.md | 14 ++++++++++++++ pyproject.toml | 2 +- src/openai/_version.py | 2 +- uv.lock | 2 +- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3362d3a312..ca66de7f50 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "3.19.1" + ".": "3.19.2" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index c54587372e..c0b5b98ae8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [3.19.2](https://github.com/openai/openai-python/compare/v3.19.1...v3.19.2) (2026-09-23) + + +### Bug Fixes + +* preserve single files for fallback extraction paths ([#3875](https://github.com/openai/openai-python/issues/3875)) ([bfd3680](https://github.com/openai/openai-python/commit/bfd3680c8d3b715bb3175b82cd0fa1c1fb53162f)) + + +### Chores + +* **api:** clarify approximate web search location defaults ([#3953](https://github.com/openai/openai-python/issues/3953)) ([a95c95e](https://github.com/openai/openai-python/commit/a95c95ed372476168e9893723ff694ead5db8586)) +* **api:** clarify Realtime modality array definitions ([#3954](https://github.com/openai/openai-python/issues/3954)) ([e79cf53](https://github.com/openai/openai-python/commit/e79cf53878b1d8580fac3a46e375eb98d9ca161d)) +* **api:** correct fine-tuning bounds and Realtime response reference ([#3949](https://github.com/openai/openai-python/issues/3949)) ([325a948](https://github.com/openai/openai-python/commit/325a948a545add0201e082e778ca11b90ddb9426)) + ## [3.19.1](https://github.com/openai/openai-python/compare/v3.19.0...v3.19.1) (2026-09-23) diff --git a/pyproject.toml b/pyproject.toml index 12fe29e078..fb70a50977 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai" -version = "3.19.1" +version = "3.19.2" description = "The official Python library for the openai API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/openai/_version.py b/src/openai/_version.py index 02512a1a2a..e7c432efa8 100644 --- a/src/openai/_version.py +++ b/src/openai/_version.py @@ -1,2 +1,2 @@ __title__ = "openai" -__version__ = "3.19.1" # x-release-please-version +__version__ = "3.19.2" # x-release-please-version diff --git a/uv.lock b/uv.lock index fba61f3f08..0e69bdb0f9 100644 --- a/uv.lock +++ b/uv.lock @@ -1535,7 +1535,7 @@ wheels = [ [[package]] name = "openai" -version = "3.19.1" # x-release-please-version +version = "3.19.2" # x-release-please-version source = { editable = "." } dependencies = [ { name = "anyio" },