From aa9e8f026295abaefc320fcf3c56e83f12666a3c Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Tue, 12 May 2026 01:10:29 +0300 Subject: [PATCH] [8/8] Add Python SDK Ruff formatting (#22021) ## Why The Python SDK needs the same tight formatter/lint loop as the rest of the repo: a safe Ruff autofix pass, Ruff formatting, editor save behavior, and CI checks that catch drift. Without that loop, SDK changes can land with formatting or import ordering that differs from what reviewers and CI expect. ## What - Add Ruff configuration to `sdk/python/pyproject.toml`, excluding generated protocol code and notebooks from the normal lint/format pass. - Update `just fmt` so it still formats Rust and also runs Python SDK Ruff autofix and formatting. - Add Python SDK CI steps for `ruff check` and `ruff format --check` before pytest. - Recommend the Ruff VS Code extension and enable Python format/fix/organize-on-save so Cmd+S uses the same tooling. - Apply the resulting Ruff formatting to SDK Python files, examples, and the checked-in generated `v2_all.py` output emitted by the pinned generator. - Add a guard test for the `just fmt` recipe so it keeps working from both Rust and Python SDK working directories. ## Stack 1. #21891 `[1/8]` Pin Python SDK runtime dependency 2. #21893 `[2/8]` Generate Python SDK types from pinned runtime 3. #21895 `[3/8]` Run Python SDK tests in CI 4. #21896 `[4/8]` Define Python SDK public API surface 5. #21905 `[5/8]` Rename Python SDK package to `openai-codex` 6. #21910 `[6/8]` Add high-level Python SDK approval mode 7. #22014 `[7/8]` Add Python SDK app-server integration harness 8. This PR `[8/8]` Add Python SDK Ruff formatting ## Verification - Added `test_root_fmt_recipe_formats_rust_and_python_sdk` for the shared format recipe. - Ran `just fmt` after the recipe update. --------- Co-authored-by: Codex --- .github/workflows/sdk.yml | 2 + .vscode/extensions.json | 1 + .vscode/settings.json | 8 + justfile | 4 +- sdk/python/_runtime_setup.py | 18 +- .../01_quickstart_constructor/async.py | 4 +- sdk/python/examples/02_turn_run/async.py | 4 +- .../examples/03_turn_stream_events/async.py | 8 +- .../examples/03_turn_stream_events/sync.py | 4 +- .../examples/05_existing_thread/async.py | 11 +- .../examples/05_existing_thread/sync.py | 7 +- .../06_thread_lifecycle_and_controls/async.py | 16 +- .../06_thread_lifecycle_and_controls/sync.py | 5 +- .../examples/07_image_and_text/async.py | 4 +- .../examples/08_local_image_and_text/async.py | 8 +- .../examples/08_local_image_and_text/sync.py | 4 +- .../10_error_handling_and_retry/async.py | 4 +- sdk/python/examples/11_cli_mini_app/async.py | 4 +- .../12_turn_params_kitchen_sink/async.py | 14 +- .../12_turn_params_kitchen_sink/sync.py | 14 +- .../13_model_select_and_turn_params/async.py | 20 +- .../13_model_select_and_turn_params/sync.py | 11 +- sdk/python/examples/14_turn_controls/async.py | 28 +- sdk/python/examples/14_turn_controls/sync.py | 20 +- sdk/python/examples/_bootstrap.py | 9 +- sdk/python/pyproject.toml | 25 +- sdk/python/scripts/update_sdk_artifacts.py | 86 +- sdk/python/src/openai_codex/__init__.py | 32 +- .../src/openai_codex/_message_router.py | 4 +- sdk/python/src/openai_codex/_version.py | 3 +- sdk/python/src/openai_codex/api.py | 80 +- sdk/python/src/openai_codex/async_client.py | 12 +- sdk/python/src/openai_codex/client.py | 36 +- sdk/python/src/openai_codex/errors.py | 6 +- .../src/openai_codex/generated/v2_all.py | 1092 +++++------------ sdk/python/tests/app_server_harness.py | 1 - sdk/python/tests/app_server_helpers.py | 1 + sdk/python/tests/test_app_server_approvals.py | 3 +- sdk/python/tests/test_app_server_inputs.py | 17 +- sdk/python/tests/test_app_server_lifecycle.py | 7 +- sdk/python/tests/test_app_server_run.py | 14 +- sdk/python/tests/test_app_server_streaming.py | 19 +- .../tests/test_app_server_turn_controls.py | 7 +- .../test_artifact_workflow_and_binaries.py | 86 +- .../tests/test_async_client_behavior.py | 2 + sdk/python/tests/test_client_rpc_methods.py | 4 +- sdk/python/tests/test_contract_generation.py | 5 +- .../tests/test_public_api_runtime_behavior.py | 8 +- .../tests/test_public_api_signatures.py | 35 +- .../tests/test_real_app_server_integration.py | 4 +- sdk/python/uv.lock | 2 +- 51 files changed, 660 insertions(+), 1163 deletions(-) diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index f6f65a7dc6..54ed8dc558 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -36,6 +36,8 @@ jobs: python -m venv /tmp/uv /tmp/uv/bin/python -m pip install uv==0.11.3 /tmp/uv/bin/uv sync --extra dev --frozen + /tmp/uv/bin/uv run --extra dev ruff check --output-format=github . + /tmp/uv/bin/uv run --extra dev ruff format --check . /tmp/uv/bin/uv run --extra dev pytest ' diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 8d6532aa7c..e92864a68a 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,7 @@ { "recommendations": [ "rust-lang.rust-analyzer", + "charliermarsh.ruff", "tamasfe.even-better-toml", "vadimcn.vscode-lldb", diff --git a/.vscode/settings.json b/.vscode/settings.json index 1e857367cb..d19746aec4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,6 +12,14 @@ "editor.defaultFormatter": "tamasfe.even-better-toml", "editor.formatOnSave": true, }, + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.ruff": "explicit", + "source.organizeImports.ruff": "explicit", + }, + }, // Array order for options in ~/.codex/config.toml such as `notify` and the // `args` for an MCP server is significant, so we disable reordering. "evenBetterToml.formatter.reorderArrays": false, diff --git a/justfile b/justfile index 71eed89a35..9297c372a3 100644 --- a/justfile +++ b/justfile @@ -30,9 +30,11 @@ app-server-test-client *args: cargo build -p codex-cli cargo run -p codex-app-server-test-client -- --codex-bin ./target/debug/codex "$@" -# format code +# Format Rust and Python SDK code. fmt: cargo fmt -- --config imports_granularity=Item 2>/dev/null + uv run --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python + uv run --project ../sdk/python --extra dev ruff format ../sdk/python fix *args: cargo clippy --fix --tests --allow-dirty "$@" diff --git a/sdk/python/_runtime_setup.py b/sdk/python/_runtime_setup.py index 6237d047df..db7007fa64 100644 --- a/sdk/python/_runtime_setup.py +++ b/sdk/python/_runtime_setup.py @@ -197,15 +197,9 @@ def _download_release_archive(version: str, temp_root: Path) -> Path: metadata = _release_metadata(version) assets = metadata.get("assets") if not isinstance(assets, list): - raise RuntimeSetupError( - f"Release {release_tag} returned malformed assets metadata." - ) + raise RuntimeSetupError(f"Release {release_tag} returned malformed assets metadata.") asset = next( - ( - item - for item in assets - if isinstance(item, dict) and item.get("name") == asset_name - ), + (item for item in assets if isinstance(item, dict) and item.get("name") == asset_name), None, ) if asset is None: @@ -279,9 +273,7 @@ def _extract_runtime_binary(archive_path: Path, temp_root: Path) -> Path: with zipfile.ZipFile(archive_path) as zip_file: zip_file.extractall(extract_dir) else: - raise RuntimeSetupError( - f"Unsupported release archive format: {archive_path.name}" - ) + raise RuntimeSetupError(f"Unsupported release archive format: {archive_path.name}") binary_name = runtime_binary_name() archive_stem = archive_path.name.removesuffix(".tar.gz").removesuffix(".zip") @@ -290,9 +282,7 @@ def _extract_runtime_binary(archive_path: Path, temp_root: Path) -> Path: for path in extract_dir.rglob("*") if path.is_file() and ( - path.name == binary_name - or path.name == archive_stem - or path.name.startswith("codex-") + path.name == binary_name or path.name == archive_stem or path.name.startswith("codex-") ) ] if not candidates: diff --git a/sdk/python/examples/01_quickstart_constructor/async.py b/sdk/python/examples/01_quickstart_constructor/async.py index 6b98adf025..9a5a48e8e5 100644 --- a/sdk/python/examples/01_quickstart_constructor/async.py +++ b/sdk/python/examples/01_quickstart_constructor/async.py @@ -22,7 +22,9 @@ async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: print("Server:", server_label(codex.metadata)) - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) result = await thread.run("Say hello in one sentence.") print("Items:", len(result.items)) print("Text:", result.final_response) diff --git a/sdk/python/examples/02_turn_run/async.py b/sdk/python/examples/02_turn_run/async.py index 73274c82d2..0f6ef94f91 100644 --- a/sdk/python/examples/02_turn_run/async.py +++ b/sdk/python/examples/02_turn_run/async.py @@ -21,7 +21,9 @@ from openai_codex import AsyncCodex, TextInput async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) turn = await thread.turn(TextInput("Give 3 bullets about SIMD.")) result = await turn.run() persisted = await thread.read(include_turns=True) diff --git a/sdk/python/examples/03_turn_stream_events/async.py b/sdk/python/examples/03_turn_stream_events/async.py index 0712a493d1..dcf57af4f2 100644 --- a/sdk/python/examples/03_turn_stream_events/async.py +++ b/sdk/python/examples/03_turn_stream_events/async.py @@ -21,7 +21,9 @@ from openai_codex import AsyncCodex, TextInput async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) turn = await thread.turn(TextInput("Explain SIMD in 3 short bullets.")) event_count = 0 @@ -44,7 +46,9 @@ async def main() -> None: saw_delta = True continue if event.method == "turn/completed": - completed_status = getattr(event.payload.turn.status, "value", str(event.payload.turn.status)) + completed_status = getattr( + event.payload.turn.status, "value", str(event.payload.turn.status) + ) if saw_delta: print() diff --git a/sdk/python/examples/03_turn_stream_events/sync.py b/sdk/python/examples/03_turn_stream_events/sync.py index a9fc25cdca..f96f5c6acd 100644 --- a/sdk/python/examples/03_turn_stream_events/sync.py +++ b/sdk/python/examples/03_turn_stream_events/sync.py @@ -40,7 +40,9 @@ with Codex(config=runtime_config()) as codex: saw_delta = True continue if event.method == "turn/completed": - completed_status = getattr(event.payload.turn.status, "value", str(event.payload.turn.status)) + completed_status = getattr( + event.payload.turn.status, "value", str(event.payload.turn.status) + ) if saw_delta: print() diff --git a/sdk/python/examples/05_existing_thread/async.py b/sdk/python/examples/05_existing_thread/async.py index fa33839790..4dc36531d8 100644 --- a/sdk/python/examples/05_existing_thread/async.py +++ b/sdk/python/examples/05_existing_thread/async.py @@ -5,7 +5,12 @@ _EXAMPLES_ROOT = Path(__file__).resolve().parents[1] if str(_EXAMPLES_ROOT) not in sys.path: sys.path.insert(0, str(_EXAMPLES_ROOT)) -from _bootstrap import assistant_text_from_turn, ensure_local_sdk_src, find_turn_by_id, runtime_config +from _bootstrap import ( + assistant_text_from_turn, + ensure_local_sdk_src, + find_turn_by_id, + runtime_config, +) ensure_local_sdk_src() @@ -16,7 +21,9 @@ from openai_codex import AsyncCodex, TextInput async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - original = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + original = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) first_turn = await original.turn(TextInput("Tell me one fact about Saturn.")) _ = await first_turn.run() diff --git a/sdk/python/examples/05_existing_thread/sync.py b/sdk/python/examples/05_existing_thread/sync.py index 0e70ca084f..ca441c4223 100644 --- a/sdk/python/examples/05_existing_thread/sync.py +++ b/sdk/python/examples/05_existing_thread/sync.py @@ -5,7 +5,12 @@ _EXAMPLES_ROOT = Path(__file__).resolve().parents[1] if str(_EXAMPLES_ROOT) not in sys.path: sys.path.insert(0, str(_EXAMPLES_ROOT)) -from _bootstrap import assistant_text_from_turn, ensure_local_sdk_src, find_turn_by_id, runtime_config +from _bootstrap import ( + assistant_text_from_turn, + ensure_local_sdk_src, + find_turn_by_id, + runtime_config, +) ensure_local_sdk_src() diff --git a/sdk/python/examples/06_thread_lifecycle_and_controls/async.py b/sdk/python/examples/06_thread_lifecycle_and_controls/async.py index 7f13441c15..ad73a896ee 100644 --- a/sdk/python/examples/06_thread_lifecycle_and_controls/async.py +++ b/sdk/python/examples/06_thread_lifecycle_and_controls/async.py @@ -16,8 +16,12 @@ from openai_codex import AsyncCodex, TextInput async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) - first = await (await thread.turn(TextInput("One sentence about structured planning."))).run() + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) + first = await ( + await thread.turn(TextInput("One sentence about structured planning.")) + ).run() second = await (await thread.turn(TextInput("Now restate it for a junior engineer."))).run() reopened = await codex.thread_resume(thread.id) @@ -36,7 +40,9 @@ async def main() -> None: model="gpt-5.4", config={"model_reasoning_effort": "high"}, ) - resumed_result = await (await resumed.turn(TextInput("Continue in one short sentence."))).run() + resumed_result = await ( + await resumed.turn(TextInput("Continue in one short sentence.")) + ).run() resumed_info = f"{resumed_result.id} {resumed_result.status}" except Exception as exc: resumed_info = f"skipped({type(exc).__name__})" @@ -44,7 +50,9 @@ async def main() -> None: forked_info = "n/a" try: forked = await codex.thread_fork(unarchived.id, model="gpt-5.4") - forked_result = await (await forked.turn(TextInput("Take a different angle in one short sentence."))).run() + forked_result = await ( + await forked.turn(TextInput("Take a different angle in one short sentence.")) + ).run() forked_info = f"{forked_result.id} {forked_result.status}" except Exception as exc: forked_info = f"skipped({type(exc).__name__})" diff --git a/sdk/python/examples/06_thread_lifecycle_and_controls/sync.py b/sdk/python/examples/06_thread_lifecycle_and_controls/sync.py index 6abe11bdaf..d01f165235 100644 --- a/sdk/python/examples/06_thread_lifecycle_and_controls/sync.py +++ b/sdk/python/examples/06_thread_lifecycle_and_controls/sync.py @@ -11,7 +11,6 @@ ensure_local_sdk_src() from openai_codex import Codex, TextInput - with Codex(config=runtime_config()) as codex: thread = codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) first = thread.turn(TextInput("One sentence about structured planning.")).run() @@ -41,7 +40,9 @@ with Codex(config=runtime_config()) as codex: forked_info = "n/a" try: forked = codex.thread_fork(unarchived.id, model="gpt-5.4") - forked_result = forked.turn(TextInput("Take a different angle in one short sentence.")).run() + forked_result = forked.turn( + TextInput("Take a different angle in one short sentence.") + ).run() forked_info = f"{forked_result.id} {forked_result.status}" except Exception as exc: forked_info = f"skipped({type(exc).__name__})" diff --git a/sdk/python/examples/07_image_and_text/async.py b/sdk/python/examples/07_image_and_text/async.py index 862915daf1..41fe96a830 100644 --- a/sdk/python/examples/07_image_and_text/async.py +++ b/sdk/python/examples/07_image_and_text/async.py @@ -23,7 +23,9 @@ REMOTE_IMAGE_URL = "https://raw.githubusercontent.com/github/explore/main/topics async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) turn = await thread.turn( [ TextInput("What is in this image? Give 3 bullets."), diff --git a/sdk/python/examples/08_local_image_and_text/async.py b/sdk/python/examples/08_local_image_and_text/async.py index a571bfa80d..c3abf4d2ee 100644 --- a/sdk/python/examples/08_local_image_and_text/async.py +++ b/sdk/python/examples/08_local_image_and_text/async.py @@ -23,11 +23,15 @@ from openai_codex import AsyncCodex, LocalImageInput, TextInput async def main() -> None: with temporary_sample_image_path() as image_path: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) turn = await thread.turn( [ - TextInput("Read this generated local image and summarize the colors/layout in 2 bullets."), + TextInput( + "Read this generated local image and summarize the colors/layout in 2 bullets." + ), LocalImageInput(str(image_path.resolve())), ] ) diff --git a/sdk/python/examples/08_local_image_and_text/sync.py b/sdk/python/examples/08_local_image_and_text/sync.py index 784778645e..45c5161cb8 100644 --- a/sdk/python/examples/08_local_image_and_text/sync.py +++ b/sdk/python/examples/08_local_image_and_text/sync.py @@ -23,7 +23,9 @@ with temporary_sample_image_path() as image_path: result = thread.turn( [ - TextInput("Read this generated local image and summarize the colors/layout in 2 bullets."), + TextInput( + "Read this generated local image and summarize the colors/layout in 2 bullets." + ), LocalImageInput(str(image_path.resolve())), ] ).run() diff --git a/sdk/python/examples/10_error_handling_and_retry/async.py b/sdk/python/examples/10_error_handling_and_retry/async.py index daf9e82549..65c95b2b63 100644 --- a/sdk/python/examples/10_error_handling_and_retry/async.py +++ b/sdk/python/examples/10_error_handling_and_retry/async.py @@ -60,7 +60,9 @@ async def retry_on_overload_async( async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) try: result = await retry_on_overload_async( diff --git a/sdk/python/examples/11_cli_mini_app/async.py b/sdk/python/examples/11_cli_mini_app/async.py index a4a13907ce..1b0a2cfd3a 100644 --- a/sdk/python/examples/11_cli_mini_app/async.py +++ b/sdk/python/examples/11_cli_mini_app/async.py @@ -45,7 +45,9 @@ async def main() -> None: print("Codex async mini CLI. Type /exit to quit.") async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) print("Thread:", thread.id) while True: diff --git a/sdk/python/examples/12_turn_params_kitchen_sink/async.py b/sdk/python/examples/12_turn_params_kitchen_sink/async.py index 95037f712d..30b72f3173 100644 --- a/sdk/python/examples/12_turn_params_kitchen_sink/async.py +++ b/sdk/python/examples/12_turn_params_kitchen_sink/async.py @@ -49,7 +49,9 @@ PROMPT = ( async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) turn = await thread.turn( TextInput(PROMPT), @@ -64,12 +66,16 @@ async def main() -> None: try: structured = json.loads(structured_text) except json.JSONDecodeError as exc: - raise RuntimeError(f"Expected JSON matching OUTPUT_SCHEMA, got: {structured_text!r}") from exc + raise RuntimeError( + f"Expected JSON matching OUTPUT_SCHEMA, got: {structured_text!r}" + ) from exc summary = structured.get("summary") actions = structured.get("actions") - if not isinstance(summary, str) or not isinstance(actions, list) or not all( - isinstance(action, str) for action in actions + if ( + not isinstance(summary, str) + or not isinstance(actions, list) + or not all(isinstance(action, str) for action in actions) ): raise RuntimeError( f"Expected structured output with string summary/actions, got: {structured!r}" diff --git a/sdk/python/examples/12_turn_params_kitchen_sink/sync.py b/sdk/python/examples/12_turn_params_kitchen_sink/sync.py index 20b5a7b757..dffe74a915 100644 --- a/sdk/python/examples/12_turn_params_kitchen_sink/sync.py +++ b/sdk/python/examples/12_turn_params_kitchen_sink/sync.py @@ -60,14 +60,20 @@ with Codex(config=runtime_config()) as codex: try: structured = json.loads(structured_text) except json.JSONDecodeError as exc: - raise RuntimeError(f"Expected JSON matching OUTPUT_SCHEMA, got: {structured_text!r}") from exc + raise RuntimeError( + f"Expected JSON matching OUTPUT_SCHEMA, got: {structured_text!r}" + ) from exc summary = structured.get("summary") actions = structured.get("actions") - if not isinstance(summary, str) or not isinstance(actions, list) or not all( - isinstance(action, str) for action in actions + if ( + not isinstance(summary, str) + or not isinstance(actions, list) + or not all(isinstance(action, str) for action in actions) ): - raise RuntimeError(f"Expected structured output with string summary/actions, got: {structured!r}") + raise RuntimeError( + f"Expected structured output with string summary/actions, got: {structured!r}" + ) print("Status:", result.status) print("summary:", summary) diff --git a/sdk/python/examples/13_model_select_and_turn_params/async.py b/sdk/python/examples/13_model_select_and_turn_params/async.py index f221dc0589..f2810d8fd9 100644 --- a/sdk/python/examples/13_model_select_and_turn_params/async.py +++ b/sdk/python/examples/13_model_select_and_turn_params/async.py @@ -5,7 +5,12 @@ _EXAMPLES_ROOT = Path(__file__).resolve().parents[1] if str(_EXAMPLES_ROOT) not in sys.path: sys.path.insert(0, str(_EXAMPLES_ROOT)) -from _bootstrap import assistant_text_from_turn, ensure_local_sdk_src, find_turn_by_id, runtime_config +from _bootstrap import ( + assistant_text_from_turn, + ensure_local_sdk_src, + find_turn_by_id, + runtime_config, +) ensure_local_sdk_src() @@ -35,7 +40,9 @@ PREFERRED_MODEL = "gpt-5.4" def _pick_highest_model(models): visible = [m for m in models if not m.hidden] or models - preferred = next((m for m in visible if m.model == PREFERRED_MODEL or m.id == PREFERRED_MODEL), None) + preferred = next( + (m for m in visible if m.model == PREFERRED_MODEL or m.id == PREFERRED_MODEL), None + ) if preferred is not None: return preferred known_names = {m.id for m in visible} | {m.model for m in visible} @@ -100,7 +107,9 @@ async def main() -> None: first_persisted_turn = find_turn_by_id(persisted.thread.turns, first.id) print("agent.message:", assistant_text_from_turn(first_persisted_turn)) - print("items:", 0 if first_persisted_turn is None else len(first_persisted_turn.items or [])) + print( + "items:", 0 if first_persisted_turn is None else len(first_persisted_turn.items or []) + ) second_turn = await thread.turn( TextInput("Return JSON for a safe feature-flag rollout plan."), @@ -117,7 +126,10 @@ async def main() -> None: second_persisted_turn = find_turn_by_id(persisted.thread.turns, second.id) print("agent.message.params:", assistant_text_from_turn(second_persisted_turn)) - print("items.params:", 0 if second_persisted_turn is None else len(second_persisted_turn.items or [])) + print( + "items.params:", + 0 if second_persisted_turn is None else len(second_persisted_turn.items or []), + ) if __name__ == "__main__": diff --git a/sdk/python/examples/13_model_select_and_turn_params/sync.py b/sdk/python/examples/13_model_select_and_turn_params/sync.py index 51a8b8f0ef..b1154ce171 100644 --- a/sdk/python/examples/13_model_select_and_turn_params/sync.py +++ b/sdk/python/examples/13_model_select_and_turn_params/sync.py @@ -5,7 +5,12 @@ _EXAMPLES_ROOT = Path(__file__).resolve().parents[1] if str(_EXAMPLES_ROOT) not in sys.path: sys.path.insert(0, str(_EXAMPLES_ROOT)) -from _bootstrap import assistant_text_from_turn, ensure_local_sdk_src, find_turn_by_id, runtime_config +from _bootstrap import ( + assistant_text_from_turn, + ensure_local_sdk_src, + find_turn_by_id, + runtime_config, +) ensure_local_sdk_src() @@ -33,7 +38,9 @@ PREFERRED_MODEL = "gpt-5.4" def _pick_highest_model(models): visible = [m for m in models if not m.hidden] or models - preferred = next((m for m in visible if m.model == PREFERRED_MODEL or m.id == PREFERRED_MODEL), None) + preferred = next( + (m for m in visible if m.model == PREFERRED_MODEL or m.id == PREFERRED_MODEL), None + ) if preferred is not None: return preferred known_names = {m.id for m in visible} | {m.model for m in visible} diff --git a/sdk/python/examples/14_turn_controls/async.py b/sdk/python/examples/14_turn_controls/async.py index 02cdfcd9d9..4f2777c2e4 100644 --- a/sdk/python/examples/14_turn_controls/async.py +++ b/sdk/python/examples/14_turn_controls/async.py @@ -20,8 +20,12 @@ from openai_codex import AsyncCodex, TextInput async def main() -> None: async with AsyncCodex(config=runtime_config()) as codex: - thread = await codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) - steer_turn = await thread.turn(TextInput("Count from 1 to 40 with commas, then one summary sentence.")) + thread = await codex.thread_start( + model="gpt-5.4", config={"model_reasoning_effort": "high"} + ) + steer_turn = await thread.turn( + TextInput("Count from 1 to 40 with commas, then one summary sentence.") + ) steer_result = "sent" try: _ = await steer_turn.steer(TextInput("Keep it brief and stop after 10 numbers.")) @@ -35,11 +39,17 @@ async def main() -> None: steer_event_count += 1 if event.method == "turn/completed": steer_completed_turn = event.payload.turn - steer_completed_status = getattr(event.payload.turn.status, "value", str(event.payload.turn.status)) + steer_completed_status = getattr( + event.payload.turn.status, "value", str(event.payload.turn.status) + ) - steer_preview = assistant_text_from_turn(steer_completed_turn).strip() or "[no assistant text]" + steer_preview = ( + assistant_text_from_turn(steer_completed_turn).strip() or "[no assistant text]" + ) - interrupt_turn = await thread.turn(TextInput("Count from 1 to 200 with commas, then one summary sentence.")) + interrupt_turn = await thread.turn( + TextInput("Count from 1 to 200 with commas, then one summary sentence.") + ) interrupt_result = "sent" try: _ = await interrupt_turn.interrupt() @@ -53,9 +63,13 @@ async def main() -> None: interrupt_event_count += 1 if event.method == "turn/completed": interrupt_completed_turn = event.payload.turn - interrupt_completed_status = getattr(event.payload.turn.status, "value", str(event.payload.turn.status)) + interrupt_completed_status = getattr( + event.payload.turn.status, "value", str(event.payload.turn.status) + ) - interrupt_preview = assistant_text_from_turn(interrupt_completed_turn).strip() or "[no assistant text]" + interrupt_preview = ( + assistant_text_from_turn(interrupt_completed_turn).strip() or "[no assistant text]" + ) print("steer.result:", steer_result) print("steer.final.status:", steer_completed_status) diff --git a/sdk/python/examples/14_turn_controls/sync.py b/sdk/python/examples/14_turn_controls/sync.py index 59d7b45d4c..03180ba8eb 100644 --- a/sdk/python/examples/14_turn_controls/sync.py +++ b/sdk/python/examples/14_turn_controls/sync.py @@ -17,7 +17,9 @@ from openai_codex import Codex, TextInput with Codex(config=runtime_config()) as codex: thread = codex.thread_start(model="gpt-5.4", config={"model_reasoning_effort": "high"}) - steer_turn = thread.turn(TextInput("Count from 1 to 40 with commas, then one summary sentence.")) + steer_turn = thread.turn( + TextInput("Count from 1 to 40 with commas, then one summary sentence.") + ) steer_result = "sent" try: _ = steer_turn.steer(TextInput("Keep it brief and stop after 10 numbers.")) @@ -31,11 +33,15 @@ with Codex(config=runtime_config()) as codex: steer_event_count += 1 if event.method == "turn/completed": steer_completed_turn = event.payload.turn - steer_completed_status = getattr(event.payload.turn.status, "value", str(event.payload.turn.status)) + steer_completed_status = getattr( + event.payload.turn.status, "value", str(event.payload.turn.status) + ) steer_preview = assistant_text_from_turn(steer_completed_turn).strip() or "[no assistant text]" - interrupt_turn = thread.turn(TextInput("Count from 1 to 200 with commas, then one summary sentence.")) + interrupt_turn = thread.turn( + TextInput("Count from 1 to 200 with commas, then one summary sentence.") + ) interrupt_result = "sent" try: _ = interrupt_turn.interrupt() @@ -49,9 +55,13 @@ with Codex(config=runtime_config()) as codex: interrupt_event_count += 1 if event.method == "turn/completed": interrupt_completed_turn = event.payload.turn - interrupt_completed_status = getattr(event.payload.turn.status, "value", str(event.payload.turn.status)) + interrupt_completed_status = getattr( + event.payload.turn.status, "value", str(event.payload.turn.status) + ) - interrupt_preview = assistant_text_from_turn(interrupt_completed_turn).strip() or "[no assistant text]" + interrupt_preview = ( + assistant_text_from_turn(interrupt_completed_turn).strip() or "[no assistant text]" + ) print("steer.result:", steer_result) print("steer.final.status:", steer_completed_status) diff --git a/sdk/python/examples/_bootstrap.py b/sdk/python/examples/_bootstrap.py index df2f1b87eb..af115119ac 100644 --- a/sdk/python/examples/_bootstrap.py +++ b/sdk/python/examples/_bootstrap.py @@ -2,7 +2,6 @@ from __future__ import annotations import contextlib import importlib.util -import os import sys import tempfile import zlib @@ -107,11 +106,15 @@ def temporary_sample_image_path() -> Iterator[Path]: def server_label(metadata: object) -> str: server = getattr(metadata, "serverInfo", None) server_name = ((getattr(server, "name", None) or "") if server is not None else "").strip() - server_version = ((getattr(server, "version", None) or "") if server is not None else "").strip() + server_version = ( + (getattr(server, "version", None) or "") if server is not None else "" + ).strip() if server_name and server_version: return f"{server_name} {server_version}" - user_agent = ((getattr(metadata, "userAgent", None) or "") if metadata is not None else "").strip() + user_agent = ( + (getattr(metadata, "userAgent", None) or "") if metadata is not None else "" + ).strip() return user_agent or "unknown" diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index aeb8a2cf39..b7c890d06e 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -30,7 +30,7 @@ Repository = "https://github.com/openai/codex" Issues = "https://github.com/openai/codex/issues" [project.optional-dependencies] -dev = ["pytest>=8.0", "datamodel-code-generator==0.31.2", "ruff>=0.11"] +dev = ["pytest>=8.0", "datamodel-code-generator==0.31.2", "ruff>=0.15.8"] [tool.hatch.build] exclude = [ @@ -61,6 +61,29 @@ include = [ addopts = "-q" testpaths = ["tests"] +[tool.ruff] +target-version = "py310" +required-version = ">=0.15.8" +line-length = 100 +extend-exclude = [ + "notebooks/**", + "src/openai_codex/generated/**", +] + +[tool.ruff.lint] +select = ["E", "F", "I", "B", "C4"] +ignore = ["E501"] +preview = true +extend-safe-fixes = ["ALL"] +unfixable = ["F841"] + +[tool.ruff.lint.per-file-ignores] +"examples/**/*.py" = ["E402"] +"tests/test_real_app_server_integration.py" = ["E402"] + +[tool.ruff.lint.isort] +combine-as-imports = true + [tool.uv] exclude-newer = "7 days" exclude-newer-package = { openai-codex-cli-bin = "2026-05-10T00:00:00Z" } diff --git a/sdk/python/scripts/update_sdk_artifacts.py b/sdk/python/scripts/update_sdk_artifacts.py index 1889026a01..a40a4aa9c3 100755 --- a/sdk/python/scripts/update_sdk_artifacts.py +++ b/sdk/python/scripts/update_sdk_artifacts.py @@ -88,9 +88,7 @@ def pinned_runtime_version() -> str: pyproject_text = sdk_pyproject_path().read_text() match = re.search(r"(?ms)^dependencies = \[(.*?)\]$", pyproject_text) if match is None: - raise RuntimeError( - "Could not find dependencies array in sdk/python/pyproject.toml" - ) + raise RuntimeError("Could not find dependencies array in sdk/python/pyproject.toml") pins = re.findall( rf'"{re.escape(RUNTIME_DISTRIBUTION_NAME)}==([^"]+)"', @@ -126,8 +124,7 @@ def pinned_runtime_codex_path() -> Path: from codex_cli_bin import bundled_codex_path except ImportError as exc: raise RuntimeError( - f"Installed {RUNTIME_DISTRIBUTION_NAME} package does not expose " - "bundled_codex_path." + f"Installed {RUNTIME_DISTRIBUTION_NAME} package does not expose bundled_codex_path." ) from exc codex_path = bundled_codex_path() @@ -148,9 +145,7 @@ def normalize_codex_version(version: str) -> str: normalized = re.sub(r"-rc\.?([0-9]+)$", r"rc\1", normalized) if not re.fullmatch(r"[0-9]+(?:\.[0-9]+)*(?:(?:a|b|rc)[0-9]+)?", normalized): - raise RuntimeError( - f"Could not normalize Codex version {version!r} to a PEP 440 version" - ) + raise RuntimeError(f"Could not normalize Codex version {version!r} to a PEP 440 version") return normalized @@ -231,9 +226,7 @@ def _rewrite_project_name(pyproject_text: str, name: str) -> str: def _rewrite_sdk_runtime_dependency(pyproject_text: str, runtime_version: str) -> str: match = re.search(r"^dependencies = \[(.*?)\]$", pyproject_text, flags=re.MULTILINE) if match is None: - raise RuntimeError( - "Could not find dependencies array in sdk/python/pyproject.toml" - ) + raise RuntimeError("Could not find dependencies array in sdk/python/pyproject.toml") raw_items = [item.strip() for item in match.group(1).split(",") if item.strip()] raw_items = [ @@ -285,9 +278,7 @@ def stage_python_runtime_package( out_bin.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(binary_path, out_bin) if not _is_windows(): - out_bin.chmod( - out_bin.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH - ) + out_bin.chmod(out_bin.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) for resource_binary in resource_binaries: # Some release targets need helper executables beside the main binary # (for example Linux bwrap or Windows sandbox helpers). Keep this @@ -361,11 +352,7 @@ def _enum_literals(value: Any) -> list[str] | None: if not isinstance(value, dict): return None enum = value.get("enum") - if ( - not isinstance(enum, list) - or not enum - or not all(isinstance(item, str) for item in enum) - ): + if not isinstance(enum, list) or not enum or not all(isinstance(item, str) for item in enum): return None return list(enum) @@ -403,11 +390,7 @@ def _variant_definition_name(base: str, variant: dict[str, Any]) -> str | None: return f"{_to_pascal_case(pascal or key)}{base}" required = variant.get("required") - if ( - isinstance(required, list) - and len(required) == 1 - and isinstance(required[0], str) - ): + if isinstance(required, list) and len(required) == 1 and isinstance(required[0], str): return f"{_to_pascal_case(required[0])}{base}" enum_literals = _enum_literals(variant) @@ -419,9 +402,7 @@ def _variant_definition_name(base: str, variant: dict[str, Any]) -> str | None: return None -def _variant_collision_key( - base: str, variant: dict[str, Any], generated_name: str -) -> str: +def _variant_collision_key(base: str, variant: dict[str, Any], generated_name: str) -> str: parts = [f"base={base}", f"generated={generated_name}"] props = variant.get("properties") if isinstance(props, dict): @@ -433,11 +414,7 @@ def _variant_collision_key( parts.append(f"only_property={next(iter(props))}") required = variant.get("required") - if ( - isinstance(required, list) - and len(required) == 1 - and isinstance(required[0], str) - ): + if isinstance(required, list) and len(required) == 1 and isinstance(required[0], str): parts.append(f"required_only={required[0]}") enum_literals = _enum_literals(variant) @@ -619,13 +596,9 @@ def generate_v2_all(schema_dir: Path) -> None: def _notification_specs(schema_dir: Path) -> list[tuple[str, str]]: """Map each server notification method to its generated payload model class.""" - server_notifications = json.loads( - (schema_dir / "ServerNotification.json").read_text() - ) + server_notifications = json.loads((schema_dir / "ServerNotification.json").read_text()) one_of = server_notifications.get("oneOf", []) - generated_source = ( - sdk_root() / "src" / "openai_codex" / "generated" / "v2_all.py" - ).read_text() + generated_source = (sdk_root() / "src" / "openai_codex" / "generated" / "v2_all.py").read_text() specs: list[tuple[str, str]] = [] @@ -662,9 +635,7 @@ def _notification_turn_id_specs( specs: list[tuple[str, str]], ) -> tuple[list[str], list[str]]: """Classify notification payloads by where their turn id is carried.""" - server_notifications = json.loads( - (schema_dir / "ServerNotification.json").read_text() - ) + server_notifications = json.loads((schema_dir / "ServerNotification.json").read_text()) definitions = server_notifications.get("definitions", {}) if not isinstance(definitions, dict): return ([], []) @@ -699,13 +670,7 @@ def _type_tuple_source(class_names: list[str]) -> str: def generate_notification_registry(schema_dir: Path) -> None: """Regenerate notification dispatch metadata from the runtime notification schema.""" - out = ( - sdk_root() - / "src" - / "openai_codex" - / "generated" - / "notification_registry.py" - ) + out = sdk_root() / "src" / "openai_codex" / "generated" / "notification_registry.py" specs = _notification_specs(schema_dir) class_names = sorted({class_name for _, class_name in specs}) direct_turn_id_types, nested_turn_types = _notification_turn_id_specs( @@ -787,9 +752,7 @@ class PublicFieldSpec: class CliOps: generate_types: Callable[[], None] stage_python_sdk_package: Callable[[Path, str], Path] - stage_python_runtime_package: Callable[ - [Path, str, Path, str | None, Sequence[Path]], Path - ] + stage_python_runtime_package: Callable[[Path, str, Path, str | None, Sequence[Path]], Path] current_sdk_version: Callable[[], str] @@ -891,14 +854,9 @@ def _approval_mode_override_signature_lines() -> list[str]: return [" approval_mode: ApprovalMode | None = None,"] -def _approval_mode_assignment_line( - helper_name: str, *, indent: str = " " -) -> str: +def _approval_mode_assignment_line(helper_name: str, *, indent: str = " ") -> str: """Return the local mapping from public mode to app-server params.""" - return ( - f"{indent}approval_policy, approvals_reviewer = " - f"{helper_name}(approval_mode)" - ) + return f"{indent}approval_policy, approvals_reviewer = {helper_name}(approval_mode)" def _approval_mode_model_arg_lines(*, indent: str = " ") -> list[str]: @@ -909,9 +867,7 @@ def _approval_mode_model_arg_lines(*, indent: str = " ") -> list[str] ] -def _model_arg_lines( - fields: list[PublicFieldSpec], *, indent: str = " " -) -> list[str]: +def _model_arg_lines(fields: list[PublicFieldSpec], *, indent: str = " ") -> list[str]: return [f"{indent}{field.wire_name}={field.py_name}," for field in fields] @@ -1224,9 +1180,7 @@ def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(description="Single SDK maintenance entrypoint") subparsers = parser.add_subparsers(dest="command", required=True) - subparsers.add_parser( - "generate-types", help="Regenerate Python protocol-derived types" - ) + subparsers.add_parser("generate-types", help="Regenerate Python protocol-derived types") stage_sdk_parser = subparsers.add_parser( "stage-sdk", @@ -1324,9 +1278,7 @@ def _resolve_codex_version(args: argparse.Namespace) -> str: normalized_versions = [normalize_codex_version(version) for version in versions] if len(set(normalized_versions)) != 1: - raise RuntimeError( - "SDK and runtime package versions must match; pass one --codex-version" - ) + raise RuntimeError("SDK and runtime package versions must match; pass one --codex-version") return normalized_versions[0] diff --git a/sdk/python/src/openai_codex/__init__.py b/sdk/python/src/openai_codex/__init__.py index c55afbc15f..4a68fabbef 100644 --- a/sdk/python/src/openai_codex/__init__.py +++ b/sdk/python/src/openai_codex/__init__.py @@ -1,18 +1,4 @@ -from .client import AppServerConfig -from .errors import ( - AppServerError, - AppServerRpcError, - InternalRpcError, - InvalidParamsError, - InvalidRequestError, - JsonRpcError, - MethodNotFoundError, - ParseError, - RetryLimitExceededError, - ServerBusyError, - TransportClosedError, - is_retryable_error, -) +from ._version import __version__ from .api import ( ApprovalMode, AsyncCodex, @@ -30,8 +16,22 @@ from .api import ( Thread, TurnHandle, ) +from .client import AppServerConfig +from .errors import ( + AppServerError, + AppServerRpcError, + InternalRpcError, + InvalidParamsError, + InvalidRequestError, + JsonRpcError, + MethodNotFoundError, + ParseError, + RetryLimitExceededError, + ServerBusyError, + TransportClosedError, + is_retryable_error, +) from .retry import retry_on_overload -from ._version import __version__ __all__ = [ "__version__", diff --git a/sdk/python/src/openai_codex/_message_router.py b/sdk/python/src/openai_codex/_message_router.py index fb466f958c..7d4554bb8a 100644 --- a/sdk/python/src/openai_codex/_message_router.py +++ b/sdk/python/src/openai_codex/_message_router.py @@ -122,9 +122,7 @@ class MessageRouter: if notification.method == "turn/completed": self._pending_turn_notifications.pop(turn_id, None) return - self._pending_turn_notifications.setdefault(turn_id, deque()).append( - notification - ) + self._pending_turn_notifications.setdefault(turn_id, deque()).append(notification) return turn_queue.put(notification) diff --git a/sdk/python/src/openai_codex/_version.py b/sdk/python/src/openai_codex/_version.py index 54d150426d..f6e94c2ed0 100644 --- a/sdk/python/src/openai_codex/_version.py +++ b/sdk/python/src/openai_codex/_version.py @@ -1,8 +1,7 @@ from __future__ import annotations import re -from importlib.metadata import PackageNotFoundError -from importlib.metadata import version as distribution_version +from importlib.metadata import PackageNotFoundError, version as distribution_version from pathlib import Path DISTRIBUTION_NAME = "openai-codex" diff --git a/sdk/python/src/openai_codex/api.py b/sdk/python/src/openai_codex/api.py index 683575c7e2..3d47de2a0e 100644 --- a/sdk/python/src/openai_codex/api.py +++ b/sdk/python/src/openai_codex/api.py @@ -5,6 +5,23 @@ from dataclasses import dataclass from enum import Enum from typing import AsyncIterator, Iterator, NoReturn +from ._inputs import ( + ImageInput as ImageInput, + Input, + InputItem as InputItem, + LocalImageInput as LocalImageInput, + MentionInput as MentionInput, + RunInput, + SkillInput as SkillInput, + TextInput as TextInput, + _normalize_run_input, + _to_wire_input, +) +from ._run import ( + RunResult, + _collect_async_run_result, + _collect_run_result, +) from .async_client import AsyncAppServerClient from .client import AppServerClient, AppServerConfig from .generated.v2_all import ( @@ -30,8 +47,8 @@ from .generated.v2_all import ( ThreadSortKey, ThreadSource, ThreadSourceKind, - ThreadStartSource, ThreadStartParams, + ThreadStartSource, Turn as AppServerTurn, TurnCompletedNotification, TurnInterruptResponse, @@ -39,23 +56,6 @@ from .generated.v2_all import ( TurnSteerResponse, ) from .models import InitializeResponse, JsonObject, Notification, ServerInfo -from ._inputs import ( - ImageInput as ImageInput, - Input, - InputItem as InputItem, - LocalImageInput as LocalImageInput, - MentionInput as MentionInput, - RunInput, - SkillInput as SkillInput, - TextInput as TextInput, - _normalize_run_input, - _to_wire_input, -) -from ._run import ( - RunResult, - _collect_async_run_result, - _collect_run_result, -) def _split_user_agent(user_agent: str) -> tuple[str | None, str | None]: @@ -151,11 +151,7 @@ class Codex: normalized_server_name = (server_name or "").strip() normalized_server_version = (server_version or "").strip() - if ( - not user_agent - or not normalized_server_name - or not normalized_server_version - ): + if not user_agent or not normalized_server_name or not normalized_server_version: raise RuntimeError( "initialize response missing required metadata " f"(user_agent={user_agent!r}, server_name={normalized_server_name!r}, server_version={normalized_server_version!r})" @@ -262,9 +258,7 @@ class Codex: sandbox: SandboxMode | None = None, service_tier: str | None = None, ) -> Thread: - approval_policy, approvals_reviewer = _approval_mode_override_settings( - approval_mode - ) + approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode) params = ThreadResumeParams( thread_id=thread_id, approval_policy=approval_policy, @@ -298,9 +292,7 @@ class Codex: service_tier: str | None = None, thread_source: ThreadSource | None = None, ) -> Thread: - approval_policy, approvals_reviewer = _approval_mode_override_settings( - approval_mode - ) + approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode) params = ThreadForkParams( thread_id=thread_id, approval_policy=approval_policy, @@ -470,9 +462,7 @@ class AsyncCodex: service_tier: str | None = None, ) -> AsyncThread: await self._ensure_initialized() - approval_policy, approvals_reviewer = _approval_mode_override_settings( - approval_mode - ) + approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode) params = ThreadResumeParams( thread_id=thread_id, approval_policy=approval_policy, @@ -507,9 +497,7 @@ class AsyncCodex: thread_source: ThreadSource | None = None, ) -> AsyncThread: await self._ensure_initialized() - approval_policy, approvals_reviewer = _approval_mode_override_settings( - approval_mode - ) + approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode) params = ThreadForkParams( thread_id=thread_id, approval_policy=approval_policy, @@ -597,9 +585,7 @@ class Thread: summary: ReasoningSummary | None = None, ) -> TurnHandle: wire_input = _to_wire_input(input) - approval_policy, approvals_reviewer = _approval_mode_override_settings( - approval_mode - ) + approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode) params = TurnStartParams( thread_id=self.id, input=wire_input, @@ -683,9 +669,7 @@ class AsyncThread: ) -> AsyncTurnHandle: await self._codex._ensure_initialized() wire_input = _to_wire_input(input) - approval_policy, approvals_reviewer = _approval_mode_override_settings( - approval_mode - ) + approval_policy, approvals_reviewer = _approval_mode_override_settings(approval_mode) params = TurnStartParams( thread_id=self.id, input=wire_input, @@ -711,9 +695,7 @@ class AsyncThread: async def read(self, *, include_turns: bool = False) -> ThreadReadResponse: await self._codex._ensure_initialized() - return await self._codex._client.thread_read( - self.id, include_turns=include_turns - ) + return await self._codex._client.thread_read(self.id, include_turns=include_turns) async def set_name(self, name: str) -> ThreadSetNameResponse: await self._codex._ensure_initialized() @@ -758,10 +740,7 @@ class TurnHandle: try: for event in stream: payload = event.payload - if ( - isinstance(payload, TurnCompletedNotification) - and payload.turn.id == self.id - ): + if isinstance(payload, TurnCompletedNotification) and payload.turn.id == self.id: completed = payload finally: stream.close() @@ -812,10 +791,7 @@ class AsyncTurnHandle: try: async for event in stream: payload = event.payload - if ( - isinstance(payload, TurnCompletedNotification) - and payload.turn.id == self.id - ): + if isinstance(payload, TurnCompletedNotification) and payload.turn.id == self.id: completed = payload finally: await stream.aclose() diff --git a/sdk/python/src/openai_codex/async_client.py b/sdk/python/src/openai_codex/async_client.py index 581d14abe9..2c38a43087 100644 --- a/sdk/python/src/openai_codex/async_client.py +++ b/sdk/python/src/openai_codex/async_client.py @@ -127,9 +127,7 @@ class AsyncAppServerClient: """List threads using the wrapped sync client.""" return await self._call_sync(self._sync.thread_list, params) - async def thread_read( - self, thread_id: str, include_turns: bool = False - ) -> ThreadReadResponse: + async def thread_read(self, thread_id: str, include_turns: bool = False) -> ThreadReadResponse: """Read a thread using the wrapped sync client.""" return await self._call_sync(self._sync.thread_read, thread_id, include_turns) @@ -164,13 +162,9 @@ class AsyncAppServerClient: params: V2TurnStartParams | JsonObject | None = None, ) -> TurnStartResponse: """Start a turn using the wrapped sync client.""" - return await self._call_sync( - self._sync.turn_start, thread_id, input_items, params - ) + return await self._call_sync(self._sync.turn_start, thread_id, input_items, params) - async def turn_interrupt( - self, thread_id: str, turn_id: str - ) -> TurnInterruptResponse: + async def turn_interrupt(self, thread_id: str, turn_id: str) -> TurnInterruptResponse: """Interrupt a turn using the wrapped sync client.""" return await self._call_sync(self._sync.turn_interrupt, thread_id, turn_id) diff --git a/sdk/python/src/openai_codex/client.py b/sdk/python/src/openai_codex/client.py index 26d23e3fa7..a4b1e4acaf 100644 --- a/sdk/python/src/openai_codex/client.py +++ b/sdk/python/src/openai_codex/client.py @@ -12,6 +12,8 @@ from typing import Callable, Iterator, TypeVar from pydantic import BaseModel +from ._message_router import MessageRouter +from ._version import __version__ as SDK_VERSION from .errors import AppServerError, TransportClosedError from .generated.notification_registry import NOTIFICATION_MODELS from .generated.v2_all import ( @@ -43,9 +45,7 @@ from .models import ( Notification, UnknownNotification, ) -from ._message_router import MessageRouter from .retry import retry_on_overload -from ._version import __version__ as SDK_VERSION ModelT = TypeVar("ModelT", bound=BaseModel) ApprovalHandler = Callable[[str, JsonObject | None], JsonObject] @@ -76,9 +76,7 @@ def _params_dict( return dumped if isinstance(params, dict): return params - raise TypeError( - f"Expected generated params model or dict, got {type(params).__name__}" - ) + raise TypeError(f"Expected generated params model or dict, got {type(params).__name__}") def _installed_codex_path() -> Path: @@ -248,9 +246,7 @@ class AppServerClient: waiter = self._router.create_response_waiter(request_id) try: - self._write_message( - {"id": request_id, "method": method, "params": params or {}} - ) + self._write_message({"id": request_id, "method": method, "params": params or {}}) except BaseException: self._router.discard_response_waiter(request_id) raise @@ -293,20 +289,14 @@ class AppServerClient: params: V2ThreadResumeParams | JsonObject | None = None, ) -> ThreadResumeResponse: payload = {"threadId": thread_id, **_params_dict(params)} - return self.request( - "thread/resume", payload, response_model=ThreadResumeResponse - ) + return self.request("thread/resume", payload, response_model=ThreadResumeResponse) def thread_list( self, params: V2ThreadListParams | JsonObject | None = None ) -> ThreadListResponse: - return self.request( - "thread/list", _params_dict(params), response_model=ThreadListResponse - ) + return self.request("thread/list", _params_dict(params), response_model=ThreadListResponse) - def thread_read( - self, thread_id: str, include_turns: bool = False - ) -> ThreadReadResponse: + def thread_read(self, thread_id: str, include_turns: bool = False) -> ThreadReadResponse: return self.request( "thread/read", {"threadId": thread_id, "includeTurns": include_turns}, @@ -461,16 +451,12 @@ class AppServerClient: model = NOTIFICATION_MODELS.get(method) if model is None: - return Notification( - method=method, payload=UnknownNotification(params=params_dict) - ) + return Notification(method=method, payload=UnknownNotification(params=params_dict)) try: payload = model.model_validate(params_dict) except Exception: # noqa: BLE001 - return Notification( - method=method, payload=UnknownNotification(params=params_dict) - ) + return Notification(method=method, payload=UnknownNotification(params=params_dict)) return Notification(method=method, payload=payload) def _normalize_input_items( @@ -483,9 +469,7 @@ class AppServerClient: return [input_items] return input_items - def _default_approval_handler( - self, method: str, params: JsonObject | None - ) -> JsonObject: + def _default_approval_handler(self, method: str, params: JsonObject | None) -> JsonObject: """Accept approval requests when the caller did not provide a handler.""" if method == "item/commandExecution/requestApproval": return {"decision": "accept"} diff --git a/sdk/python/src/openai_codex/errors.py b/sdk/python/src/openai_codex/errors.py index 24972e4fd7..104e35f2e9 100644 --- a/sdk/python/src/openai_codex/errors.py +++ b/sdk/python/src/openai_codex/errors.py @@ -66,11 +66,7 @@ def _is_server_overloaded(data: Any) -> bool: return data.lower() == "server_overloaded" if isinstance(data, dict): - direct = ( - data.get("codex_error_info") - or data.get("codexErrorInfo") - or data.get("errorInfo") - ) + direct = data.get("codex_error_info") or data.get("codexErrorInfo") or data.get("errorInfo") if isinstance(direct, str) and direct.lower() == "server_overloaded": return True if isinstance(direct, dict): diff --git a/sdk/python/src/openai_codex/generated/v2_all.py b/sdk/python/src/openai_codex/generated/v2_all.py index f573f667a7..363d87495c 100644 --- a/sdk/python/src/openai_codex/generated/v2_all.py +++ b/sdk/python/src/openai_codex/generated/v2_all.py @@ -191,8 +191,7 @@ class AppsListParams(BaseModel): populate_by_name=True, ) cursor: Annotated[ - str | None, - Field(description="Opaque pagination cursor returned by a previous call."), + str | None, Field(description="Opaque pagination cursor returned by a previous call.") ] = None force_refetch: Annotated[ bool | None, @@ -203,10 +202,7 @@ class AppsListParams(BaseModel): ] = None limit: Annotated[ int | None, - Field( - description="Optional page size; defaults to a reasonable server-side value.", - ge=0, - ), + Field(description="Optional page size; defaults to a reasonable server-side value.", ge=0), ] = None thread_id: Annotated[ str | None, @@ -323,9 +319,7 @@ class HttpConnectionFailedCodexErrorInfo(BaseModel): extra="forbid", populate_by_name=True, ) - http_connection_failed: Annotated[ - HttpConnectionFailed, Field(alias="httpConnectionFailed") - ] + http_connection_failed: Annotated[HttpConnectionFailed, Field(alias="httpConnectionFailed")] class ResponseStreamConnectionFailed(BaseModel): @@ -442,21 +436,13 @@ class UnknownCommandAction(BaseModel): class CommandAction( RootModel[ - ReadCommandAction - | ListFilesCommandAction - | SearchCommandAction - | UnknownCommandAction + ReadCommandAction | ListFilesCommandAction | SearchCommandAction | UnknownCommandAction ] ): model_config = ConfigDict( populate_by_name=True, ) - root: ( - ReadCommandAction - | ListFilesCommandAction - | SearchCommandAction - | UnknownCommandAction - ) + root: ReadCommandAction | ListFilesCommandAction | SearchCommandAction | UnknownCommandAction class CommandExecOutputStream(Enum): @@ -525,16 +511,12 @@ class CommandExecWriteParams(BaseModel): close_stdin: Annotated[ bool | None, Field( - alias="closeStdin", - description="Close stdin after writing `deltaBase64`, if present.", + alias="closeStdin", description="Close stdin after writing `deltaBase64`, if present." ), ] = None delta_base64: Annotated[ str | None, - Field( - alias="deltaBase64", - description="Optional base64-encoded stdin bytes to write.", - ), + Field(alias="deltaBase64", description="Optional base64-encoded stdin bytes to write."), ] = None process_id: Annotated[ str, @@ -630,9 +612,7 @@ class SessionFlagsConfigLayerSource(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - type: Annotated[ - Literal["sessionFlags"], Field(title="SessionFlagsConfigLayerSourceType") - ] + type: Annotated[Literal["sessionFlags"], Field(title="SessionFlagsConfigLayerSourceType")] class LegacyManagedConfigTomlFromFileConfigLayerSource(BaseModel): @@ -721,19 +701,13 @@ class AgentConfiguredHookHandler(BaseModel): class ConfiguredHookHandler( RootModel[ - CommandConfiguredHookHandler - | PromptConfiguredHookHandler - | AgentConfiguredHookHandler + CommandConfiguredHookHandler | PromptConfiguredHookHandler | AgentConfiguredHookHandler ] ): model_config = ConfigDict( populate_by_name=True, ) - root: ( - CommandConfiguredHookHandler - | PromptConfiguredHookHandler - | AgentConfiguredHookHandler - ) + root: CommandConfiguredHookHandler | PromptConfiguredHookHandler | AgentConfiguredHookHandler class ConfiguredHookMatcherGroup(BaseModel): @@ -783,9 +757,7 @@ class DeprecationNoticeNotification(BaseModel): ) details: Annotated[ str | None, - Field( - description="Optional extra guidance, such as migration steps or rationale." - ), + Field(description="Optional extra guidance, such as migration steps or rationale."), ] = None summary: Annotated[str, Field(description="Concise summary of what is deprecated.")] @@ -796,8 +768,7 @@ class InputTextDynamicToolCallOutputContentItem(BaseModel): ) text: str type: Annotated[ - Literal["inputText"], - Field(title="InputTextDynamicToolCallOutputContentItemType"), + Literal["inputText"], Field(title="InputTextDynamicToolCallOutputContentItemType") ] @@ -807,24 +778,19 @@ class InputImageDynamicToolCallOutputContentItem(BaseModel): ) image_url: Annotated[str, Field(alias="imageUrl")] type: Annotated[ - Literal["inputImage"], - Field(title="InputImageDynamicToolCallOutputContentItemType"), + Literal["inputImage"], Field(title="InputImageDynamicToolCallOutputContentItemType") ] class DynamicToolCallOutputContentItem( RootModel[ - InputTextDynamicToolCallOutputContentItem - | InputImageDynamicToolCallOutputContentItem + InputTextDynamicToolCallOutputContentItem | InputImageDynamicToolCallOutputContentItem ] ): model_config = ConfigDict( populate_by_name=True, ) - root: ( - InputTextDynamicToolCallOutputContentItem - | InputImageDynamicToolCallOutputContentItem - ) + root: InputTextDynamicToolCallOutputContentItem | InputImageDynamicToolCallOutputContentItem class DynamicToolCallStatus(Enum): @@ -861,8 +827,7 @@ class ExperimentalFeatureEnablementSetResponse(BaseModel): populate_by_name=True, ) enablement: Annotated[ - dict[str, bool], - Field(description="Feature enablement entries updated by this request."), + dict[str, bool], Field(description="Feature enablement entries updated by this request.") ] @@ -871,15 +836,11 @@ class ExperimentalFeatureListParams(BaseModel): populate_by_name=True, ) cursor: Annotated[ - str | None, - Field(description="Opaque pagination cursor returned by a previous call."), + str | None, Field(description="Opaque pagination cursor returned by a previous call.") ] = None limit: Annotated[ int | None, - Field( - description="Optional page size; defaults to a reasonable server-side value.", - ge=0, - ), + Field(description="Optional page size; defaults to a reasonable server-side value.", ge=0), ] = None @@ -897,9 +858,7 @@ class ExternalAgentConfigDetectParams(BaseModel): ) cwds: Annotated[ list[str] | None, - Field( - description="Zero or more working directories to include for repo-scoped detection." - ), + Field(description="Zero or more working directories to include for repo-scoped detection."), ] = None include_home: Annotated[ bool | None, @@ -984,9 +943,7 @@ class GlobPatternFileSystemPath(BaseModel): populate_by_name=True, ) pattern: str - type: Annotated[ - Literal["glob_pattern"], Field(title="GlobPatternFileSystemPathType") - ] + type: Annotated[Literal["glob_pattern"], Field(title="GlobPatternFileSystemPathType")] class RootFileSystemSpecialPath(BaseModel): @@ -1069,16 +1026,12 @@ class FsChangedNotification(BaseModel): changed_paths: Annotated[ list[AbsolutePathBuf], Field( - alias="changedPaths", - description="File or directory paths associated with this event.", + alias="changedPaths", description="File or directory paths associated with this event." ), ] watch_id: Annotated[ str, - Field( - alias="watchId", - description="Watch identifier previously provided to `fs/watch`.", - ), + Field(alias="watchId", description="Watch identifier previously provided to `fs/watch`."), ] @@ -1087,12 +1040,10 @@ class FsCopyParams(BaseModel): populate_by_name=True, ) destination_path: Annotated[ - AbsolutePathBuf, - Field(alias="destinationPath", description="Absolute destination path."), + AbsolutePathBuf, Field(alias="destinationPath", description="Absolute destination path.") ] recursive: Annotated[ - bool | None, - Field(description="Required for directory copies; ignored for file copies."), + bool | None, Field(description="Required for directory copies; ignored for file copies.") ] = None source_path: Annotated[ AbsolutePathBuf, Field(alias="sourcePath", description="Absolute source path.") @@ -1110,14 +1061,10 @@ class FsCreateDirectoryParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - path: Annotated[ - AbsolutePathBuf, Field(description="Absolute directory path to create.") - ] + path: Annotated[AbsolutePathBuf, Field(description="Absolute directory path to create.")] recursive: Annotated[ bool | None, - Field( - description="Whether parent directories should also be created. Defaults to `true`." - ), + Field(description="Whether parent directories should also be created. Defaults to `true`."), ] = None @@ -1147,22 +1094,13 @@ class FsGetMetadataResponse(BaseModel): ), ] is_directory: Annotated[ - bool, - Field( - alias="isDirectory", description="Whether the path resolves to a directory." - ), + bool, Field(alias="isDirectory", description="Whether the path resolves to a directory.") ] is_file: Annotated[ - bool, - Field( - alias="isFile", description="Whether the path resolves to a regular file." - ), + bool, Field(alias="isFile", description="Whether the path resolves to a regular file.") ] is_symlink: Annotated[ - bool, - Field( - alias="isSymlink", description="Whether the path itself is a symbolic link." - ), + bool, Field(alias="isSymlink", description="Whether the path itself is a symbolic link.") ] modified_at_ms: Annotated[ int, @@ -1185,17 +1123,10 @@ class FsReadDirectoryEntry(BaseModel): ), ] is_directory: Annotated[ - bool, - Field( - alias="isDirectory", - description="Whether this entry resolves to a directory.", - ), + bool, Field(alias="isDirectory", description="Whether this entry resolves to a directory.") ] is_file: Annotated[ - bool, - Field( - alias="isFile", description="Whether this entry resolves to a regular file." - ), + bool, Field(alias="isFile", description="Whether this entry resolves to a regular file.") ] @@ -1203,9 +1134,7 @@ class FsReadDirectoryParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - path: Annotated[ - AbsolutePathBuf, Field(description="Absolute directory path to read.") - ] + path: Annotated[AbsolutePathBuf, Field(description="Absolute directory path to read.")] class FsReadDirectoryResponse(BaseModel): @@ -1240,16 +1169,12 @@ class FsRemoveParams(BaseModel): ) force: Annotated[ bool | None, - Field( - description="Whether missing paths should be ignored. Defaults to `true`." - ), + Field(description="Whether missing paths should be ignored. Defaults to `true`."), ] = None path: Annotated[AbsolutePathBuf, Field(description="Absolute path to remove.")] recursive: Annotated[ bool | None, - Field( - description="Whether directory removal should recurse. Defaults to `true`." - ), + Field(description="Whether directory removal should recurse. Defaults to `true`."), ] = None @@ -1266,10 +1191,7 @@ class FsUnwatchParams(BaseModel): ) watch_id: Annotated[ str, - Field( - alias="watchId", - description="Watch identifier previously provided to `fs/watch`.", - ), + Field(alias="watchId", description="Watch identifier previously provided to `fs/watch`."), ] @@ -1284,9 +1206,7 @@ class FsWatchParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - path: Annotated[ - AbsolutePathBuf, Field(description="Absolute file or directory path to watch.") - ] + path: Annotated[AbsolutePathBuf, Field(description="Absolute file or directory path to watch.")] watch_id: Annotated[ str, Field( @@ -1301,8 +1221,7 @@ class FsWatchResponse(BaseModel): populate_by_name=True, ) path: Annotated[ - AbsolutePathBuf, - Field(description="Canonicalized path associated with the watch."), + AbsolutePathBuf, Field(description="Canonicalized path associated with the watch.") ] @@ -1425,8 +1344,7 @@ class McpToolCallGuardianApprovalReviewAction(BaseModel): tool_name: Annotated[str, Field(alias="toolName")] tool_title: Annotated[str | None, Field(alias="toolTitle")] = None type: Annotated[ - Literal["mcpToolCall"], - Field(title="McpToolCallGuardianApprovalReviewActionType"), + Literal["mcpToolCall"], Field(title="McpToolCallGuardianApprovalReviewActionType") ] @@ -1461,12 +1379,9 @@ class GuardianWarningNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - message: Annotated[ - str, Field(description="Concise guardian warning message for the user.") - ] + message: Annotated[str, Field(description="Concise guardian warning message for the user.")] thread_id: Annotated[ - str, - Field(alias="threadId", description="Thread target for the guardian warning."), + str, Field(alias="threadId", description="Thread target for the guardian warning.") ] @@ -1562,9 +1477,7 @@ class HooksListParams(BaseModel): ) cwds: Annotated[ list[str] | None, - Field( - description="When empty, defaults to the current session working directory." - ), + Field(description="When empty, defaults to the current session working directory."), ] = None @@ -1652,12 +1565,8 @@ class ChatgptLoginAccountParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - codex_streamlined_login: Annotated[ - bool | None, Field(alias="codexStreamlinedLogin") - ] = None - type: Annotated[ - Literal["chatgpt"], Field(title="Chatgptv2::LoginAccountParamsType") - ] + codex_streamlined_login: Annotated[bool | None, Field(alias="codexStreamlinedLogin")] = None + type: Annotated[Literal["chatgpt"], Field(title="Chatgptv2::LoginAccountParamsType")] class ChatgptDeviceCodeLoginAccountParams(BaseModel): @@ -1665,8 +1574,7 @@ class ChatgptDeviceCodeLoginAccountParams(BaseModel): populate_by_name=True, ) type: Annotated[ - Literal["chatgptDeviceCode"], - Field(title="ChatgptDeviceCodev2::LoginAccountParamsType"), + Literal["chatgptDeviceCode"], Field(title="ChatgptDeviceCodev2::LoginAccountParamsType") ] @@ -1696,8 +1604,7 @@ class ChatgptAuthTokensLoginAccountParams(BaseModel): ), ] = None type: Annotated[ - Literal["chatgptAuthTokens"], - Field(title="ChatgptAuthTokensv2::LoginAccountParamsType"), + Literal["chatgptAuthTokens"], Field(title="ChatgptAuthTokensv2::LoginAccountParamsType") ] @@ -1725,9 +1632,7 @@ class ApiKeyLoginAccountResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - type: Annotated[ - Literal["apiKey"], Field(title="ApiKeyv2::LoginAccountResponseType") - ] + type: Annotated[Literal["apiKey"], Field(title="ApiKeyv2::LoginAccountResponseType")] class ChatgptLoginAccountResponse(BaseModel): @@ -1742,9 +1647,7 @@ class ChatgptLoginAccountResponse(BaseModel): ), ] login_id: Annotated[str, Field(alias="loginId")] - type: Annotated[ - Literal["chatgpt"], Field(title="Chatgptv2::LoginAccountResponseType") - ] + type: Annotated[Literal["chatgpt"], Field(title="Chatgptv2::LoginAccountResponseType")] class ChatgptDeviceCodeLoginAccountResponse(BaseModel): @@ -1753,15 +1656,11 @@ class ChatgptDeviceCodeLoginAccountResponse(BaseModel): ) login_id: Annotated[str, Field(alias="loginId")] type: Annotated[ - Literal["chatgptDeviceCode"], - Field(title="ChatgptDeviceCodev2::LoginAccountResponseType"), + Literal["chatgptDeviceCode"], Field(title="ChatgptDeviceCodev2::LoginAccountResponseType") ] user_code: Annotated[ str, - Field( - alias="userCode", - description="One-time code the user must enter after signing in.", - ), + Field(alias="userCode", description="One-time code the user must enter after signing in."), ] verification_url: Annotated[ str, @@ -1777,8 +1676,7 @@ class ChatgptAuthTokensLoginAccountResponse(BaseModel): populate_by_name=True, ) type: Annotated[ - Literal["chatgptAuthTokens"], - Field(title="ChatgptAuthTokensv2::LoginAccountResponseType"), + Literal["chatgptAuthTokens"], Field(title="ChatgptAuthTokensv2::LoginAccountResponseType") ] @@ -1816,21 +1714,13 @@ class ManagedHooksRequirements(BaseModel): permission_request: Annotated[ list[ConfiguredHookMatcherGroup], Field(alias="PermissionRequest") ] - post_compact: Annotated[ - list[ConfiguredHookMatcherGroup], Field(alias="PostCompact") - ] - post_tool_use: Annotated[ - list[ConfiguredHookMatcherGroup], Field(alias="PostToolUse") - ] + post_compact: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="PostCompact")] + post_tool_use: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="PostToolUse")] pre_compact: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="PreCompact")] pre_tool_use: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="PreToolUse")] - session_start: Annotated[ - list[ConfiguredHookMatcherGroup], Field(alias="SessionStart") - ] + session_start: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="SessionStart")] stop: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="Stop")] - user_prompt_submit: Annotated[ - list[ConfiguredHookMatcherGroup], Field(alias="UserPromptSubmit") - ] + user_prompt_submit: Annotated[list[ConfiguredHookMatcherGroup], Field(alias="UserPromptSubmit")] managed_dir: Annotated[str | None, Field(alias="managedDir")] = None windows_managed_dir: Annotated[str | None, Field(alias="windowsManagedDir")] = None @@ -1879,9 +1769,7 @@ class MarketplaceRemoveResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - installed_root: Annotated[AbsolutePathBuf | None, Field(alias="installedRoot")] = ( - None - ) + installed_root: Annotated[AbsolutePathBuf | None, Field(alias="installedRoot")] = None marketplace_name: Annotated[str, Field(alias="marketplaceName")] @@ -2075,8 +1963,7 @@ class ModelListParams(BaseModel): populate_by_name=True, ) cursor: Annotated[ - str | None, - Field(description="Opaque pagination cursor returned by a previous call."), + str | None, Field(description="Opaque pagination cursor returned by a previous call.") ] = None include_hidden: Annotated[ bool | None, @@ -2087,10 +1974,7 @@ class ModelListParams(BaseModel): ] = None limit: Annotated[ int | None, - Field( - description="Optional page size; defaults to a reasonable server-side value.", - ge=0, - ), + Field(description="Optional page size; defaults to a reasonable server-side value.", ge=0), ] = None @@ -2192,14 +2076,11 @@ class NetworkRequirements(BaseModel): description="Legacy compatibility view derived from `unix_sockets`.", ), ] = None - allow_upstream_proxy: Annotated[bool | None, Field(alias="allowUpstreamProxy")] = ( - None - ) + allow_upstream_proxy: Annotated[bool | None, Field(alias="allowUpstreamProxy")] = None allowed_domains: Annotated[ list[str] | None, Field( - alias="allowedDomains", - description="Legacy compatibility view derived from `domains`.", + alias="allowedDomains", description="Legacy compatibility view derived from `domains`." ), ] = None dangerously_allow_all_unix_sockets: Annotated[ @@ -2211,15 +2092,12 @@ class NetworkRequirements(BaseModel): denied_domains: Annotated[ list[str] | None, Field( - alias="deniedDomains", - description="Legacy compatibility view derived from `domains`.", + alias="deniedDomains", description="Legacy compatibility view derived from `domains`." ), ] = None domains: Annotated[ dict[str, Any] | None, - Field( - description="Canonical network permission map for `experimental_network`." - ), + Field(description="Canonical network permission map for `experimental_network`."), ] = None enabled: bool | None = None http_port: Annotated[int | None, Field(alias="httpPort", ge=0)] = None @@ -2338,14 +2216,10 @@ class ProfilePermissionProfileSelectionParams(BaseModel): ) id: str modifications: list[PermissionProfileModificationParams] | None = None - type: Annotated[ - Literal["profile"], Field(title="ProfilePermissionProfileSelectionParamsType") - ] + type: Annotated[Literal["profile"], Field(title="ProfilePermissionProfileSelectionParamsType")] -class PermissionProfileSelectionParams( - RootModel[ProfilePermissionProfileSelectionParams] -): +class PermissionProfileSelectionParams(RootModel[ProfilePermissionProfileSelectionParams]): model_config = ConfigDict( populate_by_name=True, ) @@ -2405,13 +2279,9 @@ class PluginInstallParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - marketplace_path: Annotated[ - AbsolutePathBuf | None, Field(alias="marketplacePath") - ] = None + marketplace_path: Annotated[AbsolutePathBuf | None, Field(alias="marketplacePath")] = None plugin_name: Annotated[str, Field(alias="pluginName")] - remote_marketplace_name: Annotated[ - str | None, Field(alias="remoteMarketplaceName") - ] = None + remote_marketplace_name: Annotated[str | None, Field(alias="remoteMarketplaceName")] = None class PluginInstallPolicy(Enum): @@ -2445,8 +2315,7 @@ class PluginInterface(BaseModel): composer_icon_url: Annotated[ str | None, Field( - alias="composerIconUrl", - description="Remote composer icon URL from the plugin catalog.", + alias="composerIconUrl", description="Remote composer icon URL from the plugin catalog." ), ] = None default_prompt: Annotated[ @@ -2460,28 +2329,22 @@ class PluginInterface(BaseModel): display_name: Annotated[str | None, Field(alias="displayName")] = None logo: Annotated[ AbsolutePathBuf | None, - Field( - description="Local logo path, resolved from the installed plugin package." - ), + Field(description="Local logo path, resolved from the installed plugin package."), ] = None logo_url: Annotated[ - str | None, - Field(alias="logoUrl", description="Remote logo URL from the plugin catalog."), + str | None, Field(alias="logoUrl", description="Remote logo URL from the plugin catalog.") ] = None long_description: Annotated[str | None, Field(alias="longDescription")] = None privacy_policy_url: Annotated[str | None, Field(alias="privacyPolicyUrl")] = None screenshot_urls: Annotated[ list[str], Field( - alias="screenshotUrls", - description="Remote screenshot URLs from the plugin catalog.", + alias="screenshotUrls", description="Remote screenshot URLs from the plugin catalog." ), ] screenshots: Annotated[ list[AbsolutePathBuf], - Field( - description="Local screenshot paths, resolved from the installed plugin package." - ), + Field(description="Local screenshot paths, resolved from the installed plugin package."), ] short_description: Annotated[str | None, Field(alias="shortDescription")] = None terms_of_service_url: Annotated[str | None, Field(alias="termsOfServiceUrl")] = None @@ -2517,13 +2380,9 @@ class PluginReadParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - marketplace_path: Annotated[ - AbsolutePathBuf | None, Field(alias="marketplacePath") - ] = None + marketplace_path: Annotated[AbsolutePathBuf | None, Field(alias="marketplacePath")] = None plugin_name: Annotated[str, Field(alias="pluginName")] - remote_marketplace_name: Annotated[ - str | None, Field(alias="remoteMarketplaceName") - ] = None + remote_marketplace_name: Annotated[str | None, Field(alias="remoteMarketplaceName")] = None class PluginShareDeleteParams(BaseModel): @@ -2721,9 +2580,7 @@ class RateLimitWindow(BaseModel): ) resets_at: Annotated[int | None, Field(alias="resetsAt")] = None used_percent: Annotated[int, Field(alias="usedPercent")] - window_duration_mins: Annotated[int | None, Field(alias="windowDurationMins")] = ( - None - ) + window_duration_mins: Annotated[int | None, Field(alias="windowDurationMins")] = None class RealtimeConversationVersion(Enum): @@ -2790,9 +2647,7 @@ class ReasoningTextReasoningItemContent(BaseModel): populate_by_name=True, ) text: str - type: Annotated[ - Literal["reasoning_text"], Field(title="ReasoningTextReasoningItemContentType") - ] + type: Annotated[Literal["reasoning_text"], Field(title="ReasoningTextReasoningItemContentType")] class TextReasoningItemContent(BaseModel): @@ -2803,9 +2658,7 @@ class TextReasoningItemContent(BaseModel): type: Annotated[Literal["text"], Field(title="TextReasoningItemContentType")] -class ReasoningItemContent( - RootModel[ReasoningTextReasoningItemContent | TextReasoningItemContent] -): +class ReasoningItemContent(RootModel[ReasoningTextReasoningItemContent | TextReasoningItemContent]): model_config = ConfigDict( populate_by_name=True, ) @@ -2818,14 +2671,11 @@ class SummaryTextReasoningItemReasoningSummary(BaseModel): ) text: str type: Annotated[ - Literal["summary_text"], - Field(title="SummaryTextReasoningItemReasoningSummaryType"), + Literal["summary_text"], Field(title="SummaryTextReasoningItemReasoningSummaryType") ] -class ReasoningItemReasoningSummary( - RootModel[SummaryTextReasoningItemReasoningSummary] -): +class ReasoningItemReasoningSummary(RootModel[SummaryTextReasoningItemReasoningSummary]): model_config = ConfigDict( populate_by_name=True, ) @@ -2953,9 +2803,7 @@ class ResourceContent(RootModel[ResourceContent1 | ResourceContent2]): ) root: Annotated[ ResourceContent1 | ResourceContent2, - Field( - description="Contents returned when reading a resource from an MCP server." - ), + Field(description="Contents returned when reading a resource from an MCP server."), ] @@ -2986,19 +2834,13 @@ class LocalShellCallResponseItem(BaseModel): populate_by_name=True, ) action: LocalShellAction - call_id: Annotated[ - str | None, Field(description="Set when using the Responses API.") - ] = None + call_id: Annotated[str | None, Field(description="Set when using the Responses API.")] = None id: Annotated[ str | None, - Field( - description="Legacy id field retained for compatibility with older payloads." - ), + Field(description="Legacy id field retained for compatibility with older payloads."), ] = None status: LocalShellStatus - type: Annotated[ - Literal["local_shell_call"], Field(title="LocalShellCallResponseItemType") - ] + type: Annotated[Literal["local_shell_call"], Field(title="LocalShellCallResponseItemType")] class FunctionCallResponseItem(BaseModel): @@ -3010,9 +2852,7 @@ class FunctionCallResponseItem(BaseModel): id: str | None = None name: str namespace: str | None = None - type: Annotated[ - Literal["function_call"], Field(title="FunctionCallResponseItemType") - ] + type: Annotated[Literal["function_call"], Field(title="FunctionCallResponseItemType")] class ToolSearchCallResponseItem(BaseModel): @@ -3024,9 +2864,7 @@ class ToolSearchCallResponseItem(BaseModel): execution: str id: str | None = None status: str | None = None - type: Annotated[ - Literal["tool_search_call"], Field(title="ToolSearchCallResponseItemType") - ] + type: Annotated[Literal["tool_search_call"], Field(title="ToolSearchCallResponseItemType")] class CustomToolCallResponseItem(BaseModel): @@ -3038,9 +2876,7 @@ class CustomToolCallResponseItem(BaseModel): input: str name: str status: str | None = None - type: Annotated[ - Literal["custom_tool_call"], Field(title="CustomToolCallResponseItemType") - ] + type: Annotated[Literal["custom_tool_call"], Field(title="CustomToolCallResponseItemType")] class ToolSearchOutputResponseItem(BaseModel): @@ -3051,9 +2887,7 @@ class ToolSearchOutputResponseItem(BaseModel): execution: str status: str tools: list - type: Annotated[ - Literal["tool_search_output"], Field(title="ToolSearchOutputResponseItemType") - ] + type: Annotated[Literal["tool_search_output"], Field(title="ToolSearchOutputResponseItemType")] class ImageGenerationCallResponseItem(BaseModel): @@ -3065,8 +2899,7 @@ class ImageGenerationCallResponseItem(BaseModel): revised_prompt: str | None = None status: str type: Annotated[ - Literal["image_generation_call"], - Field(title="ImageGenerationCallResponseItemType"), + Literal["image_generation_call"], Field(title="ImageGenerationCallResponseItemType") ] @@ -3083,9 +2916,7 @@ class ContextCompactionResponseItem(BaseModel): populate_by_name=True, ) encrypted_content: str | None = None - type: Annotated[ - Literal["context_compaction"], Field(title="ContextCompactionResponseItemType") - ] + type: Annotated[Literal["context_compaction"], Field(title="ContextCompactionResponseItemType")] class OtherResponseItem(BaseModel): @@ -3101,18 +2932,14 @@ class SearchResponsesApiWebSearchAction(BaseModel): ) queries: list[str] | None = None query: str | None = None - type: Annotated[ - Literal["search"], Field(title="SearchResponsesApiWebSearchActionType") - ] + type: Annotated[Literal["search"], Field(title="SearchResponsesApiWebSearchActionType")] class OpenPageResponsesApiWebSearchAction(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - type: Annotated[ - Literal["open_page"], Field(title="OpenPageResponsesApiWebSearchActionType") - ] + type: Annotated[Literal["open_page"], Field(title="OpenPageResponsesApiWebSearchActionType")] url: str | None = None @@ -3122,8 +2949,7 @@ class FindInPageResponsesApiWebSearchAction(BaseModel): ) pattern: str | None = None type: Annotated[ - Literal["find_in_page"], - Field(title="FindInPageResponsesApiWebSearchActionType"), + Literal["find_in_page"], Field(title="FindInPageResponsesApiWebSearchActionType") ] url: str | None = None @@ -3132,9 +2958,7 @@ class OtherResponsesApiWebSearchAction(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - type: Annotated[ - Literal["other"], Field(title="OtherResponsesApiWebSearchActionType") - ] + type: Annotated[Literal["other"], Field(title="OtherResponsesApiWebSearchActionType")] class ResponsesApiWebSearchAction( @@ -3185,9 +3009,7 @@ class CommitReviewTarget(BaseModel): sha: str title: Annotated[ str | None, - Field( - description="Optional human-readable label (e.g., commit subject) for UIs." - ), + Field(description="Optional human-readable label (e.g., commit subject) for UIs."), ] = None type: Annotated[Literal["commit"], Field(title="CommitReviewTargetType")] @@ -3229,9 +3051,7 @@ class DangerFullAccessSandboxPolicy(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - type: Annotated[ - Literal["dangerFullAccess"], Field(title="DangerFullAccessSandboxPolicyType") - ] + type: Annotated[Literal["dangerFullAccess"], Field(title="DangerFullAccessSandboxPolicyType")] class ReadOnlySandboxPolicy(BaseModel): @@ -3246,12 +3066,8 @@ class ExternalSandboxSandboxPolicy(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - network_access: Annotated[NetworkAccess | None, Field(alias="networkAccess")] = ( - "restricted" - ) - type: Annotated[ - Literal["externalSandbox"], Field(title="ExternalSandboxSandboxPolicyType") - ] + network_access: Annotated[NetworkAccess | None, Field(alias="networkAccess")] = "restricted" + type: Annotated[Literal["externalSandbox"], Field(title="ExternalSandboxSandboxPolicyType")] class WorkspaceWriteSandboxPolicy(BaseModel): @@ -3259,16 +3075,10 @@ class WorkspaceWriteSandboxPolicy(BaseModel): populate_by_name=True, ) exclude_slash_tmp: Annotated[bool | None, Field(alias="excludeSlashTmp")] = False - exclude_tmpdir_env_var: Annotated[ - bool | None, Field(alias="excludeTmpdirEnvVar") - ] = False + exclude_tmpdir_env_var: Annotated[bool | None, Field(alias="excludeTmpdirEnvVar")] = False network_access: Annotated[bool | None, Field(alias="networkAccess")] = False - type: Annotated[ - Literal["workspaceWrite"], Field(title="WorkspaceWriteSandboxPolicyType") - ] - writable_roots: Annotated[ - list[AbsolutePathBuf] | None, Field(alias="writableRoots") - ] = [] + type: Annotated[Literal["workspaceWrite"], Field(title="WorkspaceWriteSandboxPolicyType")] + writable_roots: Annotated[list[AbsolutePathBuf] | None, Field(alias="writableRoots")] = [] class SandboxPolicy( @@ -3319,8 +3129,7 @@ class ItemAgentMessageDeltaServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["item/agentMessage/delta"], - Field(title="Item/agentMessage/deltaNotificationMethod"), + Literal["item/agentMessage/delta"], Field(title="Item/agentMessage/deltaNotificationMethod") ] params: AgentMessageDeltaNotification @@ -3329,9 +3138,7 @@ class ItemPlanDeltaServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["item/plan/delta"], Field(title="Item/plan/deltaNotificationMethod") - ] + method: Annotated[Literal["item/plan/delta"], Field(title="Item/plan/deltaNotificationMethod")] params: PlanDeltaNotification @@ -3339,9 +3146,7 @@ class ProcessExitedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["process/exited"], Field(title="Process/exitedNotificationMethod") - ] + method: Annotated[Literal["process/exited"], Field(title="Process/exitedNotificationMethod")] params: ProcessExitedNotification @@ -3426,9 +3231,7 @@ class FsChangedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["fs/changed"], Field(title="Fs/changedNotificationMethod") - ] + method: Annotated[Literal["fs/changed"], Field(title="Fs/changedNotificationMethod")] params: FsChangedNotification @@ -3479,9 +3282,7 @@ class ModelReroutedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["model/rerouted"], Field(title="Model/reroutedNotificationMethod") - ] + method: Annotated[Literal["model/rerouted"], Field(title="Model/reroutedNotificationMethod")] params: ModelReroutedNotification @@ -3490,8 +3291,7 @@ class ModelVerificationServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["model/verification"], - Field(title="Model/verificationNotificationMethod"), + Literal["model/verification"], Field(title="Model/verificationNotificationMethod") ] params: ModelVerificationNotification @@ -3500,9 +3300,7 @@ class GuardianWarningServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["guardianWarning"], Field(title="GuardianWarningNotificationMethod") - ] + method: Annotated[Literal["guardianWarning"], Field(title="GuardianWarningNotificationMethod")] params: GuardianWarningNotification @@ -3543,8 +3341,7 @@ class AccountLoginCompletedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["account/login/completed"], - Field(title="Account/login/completedNotificationMethod"), + Literal["account/login/completed"], Field(title="Account/login/completedNotificationMethod") ] params: AccountLoginCompletedNotification @@ -3655,9 +3452,7 @@ class SkillsConfigWriteParams(BaseModel): ) enabled: bool name: Annotated[str | None, Field(description="Name-based selector.")] = None - path: Annotated[ - AbsolutePathBuf | None, Field(description="Path-based selector.") - ] = None + path: Annotated[AbsolutePathBuf | None, Field(description="Path-based selector.")] = None class SkillsConfigWriteResponse(BaseModel): @@ -3673,9 +3468,7 @@ class SkillsListParams(BaseModel): ) cwds: Annotated[ list[str] | None, - Field( - description="When empty, defaults to the current session working directory." - ), + Field(description="When empty, defaults to the current session working directory."), ] = None force_reload: Annotated[ bool | None, @@ -3747,8 +3540,7 @@ class TextPosition(BaseModel): populate_by_name=True, ) column: Annotated[ - int, - Field(description="1-based column number (in Unicode scalar values).", ge=0), + int, Field(description="1-based column number (in Unicode scalar values).", ge=0) ] line: Annotated[int, Field(description="1-based line number.", ge=0)] @@ -3771,10 +3563,7 @@ class ThreadApproveGuardianDeniedActionParams(BaseModel): populate_by_name=True, ) event: Annotated[ - Any, - Field( - description="Serialized `codex_protocol::protocol::GuardianAssessmentEvent`." - ), + Any, Field(description="Serialized `codex_protocol::protocol::GuardianAssessmentEvent`.") ] thread_id: Annotated[str, Field(alias="threadId")] @@ -3916,14 +3705,11 @@ class CommandExecutionThreadItem(BaseModel): description="A best-effort parsing of the command to understand the action(s) it will perform. This returns a list of CommandAction objects because a single shell command may be composed of many commands piped together.", ), ] - cwd: Annotated[ - AbsolutePathBuf, Field(description="The command's working directory.") - ] + cwd: Annotated[AbsolutePathBuf, Field(description="The command's working directory.")] duration_ms: Annotated[ int | None, Field( - alias="durationMs", - description="The duration of the command execution in milliseconds.", + alias="durationMs", description="The duration of the command execution in milliseconds." ), ] = None exit_code: Annotated[ @@ -3939,9 +3725,7 @@ class CommandExecutionThreadItem(BaseModel): ] = None source: CommandExecutionSource | None = "agent" status: CommandExecutionStatus - type: Annotated[ - Literal["commandExecution"], Field(title="CommandExecutionThreadItemType") - ] + type: Annotated[Literal["commandExecution"], Field(title="CommandExecutionThreadItemType")] class McpToolCallThreadItem(BaseModel): @@ -3951,10 +3735,7 @@ class McpToolCallThreadItem(BaseModel): arguments: Any duration_ms: Annotated[ int | None, - Field( - alias="durationMs", - description="The duration of the MCP tool call in milliseconds.", - ), + Field(alias="durationMs", description="The duration of the MCP tool call in milliseconds."), ] = None error: McpToolCallError | None = None id: str @@ -3977,8 +3758,7 @@ class DynamicToolCallThreadItem(BaseModel): duration_ms: Annotated[ int | None, Field( - alias="durationMs", - description="The duration of the dynamic tool call in milliseconds.", + alias="durationMs", description="The duration of the dynamic tool call in milliseconds." ), ] = None id: str @@ -3986,9 +3766,7 @@ class DynamicToolCallThreadItem(BaseModel): status: DynamicToolCallStatus success: bool | None = None tool: str - type: Annotated[ - Literal["dynamicToolCall"], Field(title="DynamicToolCallThreadItemType") - ] + type: Annotated[Literal["dynamicToolCall"], Field(title="DynamicToolCallThreadItemType")] class ImageViewThreadItem(BaseModel): @@ -4009,9 +3787,7 @@ class ImageGenerationThreadItem(BaseModel): revised_prompt: Annotated[str | None, Field(alias="revisedPrompt")] = None saved_path: Annotated[AbsolutePathBuf | None, Field(alias="savedPath")] = None status: str - type: Annotated[ - Literal["imageGeneration"], Field(title="ImageGenerationThreadItemType") - ] + type: Annotated[Literal["imageGeneration"], Field(title="ImageGenerationThreadItemType")] class EnteredReviewModeThreadItem(BaseModel): @@ -4020,9 +3796,7 @@ class EnteredReviewModeThreadItem(BaseModel): ) id: str review: str - type: Annotated[ - Literal["enteredReviewMode"], Field(title="EnteredReviewModeThreadItemType") - ] + type: Annotated[Literal["enteredReviewMode"], Field(title="EnteredReviewModeThreadItemType")] class ExitedReviewModeThreadItem(BaseModel): @@ -4031,9 +3805,7 @@ class ExitedReviewModeThreadItem(BaseModel): ) id: str review: str - type: Annotated[ - Literal["exitedReviewMode"], Field(title="ExitedReviewModeThreadItemType") - ] + type: Annotated[Literal["exitedReviewMode"], Field(title="ExitedReviewModeThreadItemType")] class ContextCompactionThreadItem(BaseModel): @@ -4041,9 +3813,7 @@ class ContextCompactionThreadItem(BaseModel): populate_by_name=True, ) id: str - type: Annotated[ - Literal["contextCompaction"], Field(title="ContextCompactionThreadItemType") - ] + type: Annotated[Literal["contextCompaction"], Field(title="ContextCompactionThreadItemType")] class ThreadListCwdFilter(RootModel[str | list[str]]): @@ -4058,8 +3828,7 @@ class ThreadLoadedListParams(BaseModel): populate_by_name=True, ) cursor: Annotated[ - str | None, - Field(description="Opaque pagination cursor returned by a previous call."), + str | None, Field(description="Opaque pagination cursor returned by a previous call.") ] = None limit: Annotated[ int | None, Field(description="Optional page size; defaults to no limit.", ge=0) @@ -4071,8 +3840,7 @@ class ThreadLoadedListResponse(BaseModel): populate_by_name=True, ) data: Annotated[ - list[str], - Field(description="Thread ids for sessions currently loaded in memory."), + list[str], Field(description="Thread ids for sessions currently loaded in memory.") ] next_cursor: Annotated[ str | None, @@ -4157,9 +3925,7 @@ class ThreadRealtimeAudioChunk(BaseModel): item_id: Annotated[str | None, Field(alias="itemId")] = None num_channels: Annotated[int, Field(alias="numChannels", ge=0)] sample_rate: Annotated[int, Field(alias="sampleRate", ge=0)] - samples_per_channel: Annotated[ - int | None, Field(alias="samplesPerChannel", ge=0) - ] = None + samples_per_channel: Annotated[int | None, Field(alias="samplesPerChannel", ge=0)] = None class ThreadRealtimeClosedNotification(BaseModel): @@ -4206,9 +3972,7 @@ class WebsocketThreadRealtimeStartTransport(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - type: Annotated[ - Literal["websocket"], Field(title="WebsocketThreadRealtimeStartTransportType") - ] + type: Annotated[Literal["websocket"], Field(title="WebsocketThreadRealtimeStartTransportType")] class WebrtcThreadRealtimeStartTransport(BaseModel): @@ -4221,15 +3985,11 @@ class WebrtcThreadRealtimeStartTransport(BaseModel): description="SDP offer generated by a WebRTC RTCPeerConnection after configuring audio and the realtime events data channel." ), ] - type: Annotated[ - Literal["webrtc"], Field(title="WebrtcThreadRealtimeStartTransportType") - ] + type: Annotated[Literal["webrtc"], Field(title="WebrtcThreadRealtimeStartTransportType")] class ThreadRealtimeStartTransport( - RootModel[ - WebsocketThreadRealtimeStartTransport | WebrtcThreadRealtimeStartTransport - ] + RootModel[WebsocketThreadRealtimeStartTransport | WebrtcThreadRealtimeStartTransport] ): model_config = ConfigDict( populate_by_name=True, @@ -4253,9 +4013,7 @@ class ThreadRealtimeTranscriptDeltaNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - delta: Annotated[ - str, Field(description="Live transcript delta from the realtime event.") - ] + delta: Annotated[str, Field(description="Live transcript delta from the realtime event.")] role: str thread_id: Annotated[str, Field(alias="threadId")] @@ -4265,9 +4023,7 @@ class ThreadRealtimeTranscriptDoneNotification(BaseModel): populate_by_name=True, ) role: str - text: Annotated[ - str, Field(description="Final complete text for the transcript part.") - ] + text: Annotated[str, Field(description="Final complete text for the transcript part.")] thread_id: Annotated[str, Field(alias="threadId")] @@ -4275,9 +4031,7 @@ class ThreadResumeParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - approval_policy: Annotated[AskForApproval | None, Field(alias="approvalPolicy")] = ( - None - ) + approval_policy: Annotated[AskForApproval | None, Field(alias="approvalPolicy")] = None approvals_reviewer: Annotated[ ApprovalsReviewer | None, Field( @@ -4288,12 +4042,9 @@ class ThreadResumeParams(BaseModel): base_instructions: Annotated[str | None, Field(alias="baseInstructions")] = None config: dict[str, Any] | None = None cwd: str | None = None - developer_instructions: Annotated[ - str | None, Field(alias="developerInstructions") - ] = None + developer_instructions: Annotated[str | None, Field(alias="developerInstructions")] = None model: Annotated[ - str | None, - Field(description="Configuration overrides for the resumed thread, if any."), + str | None, Field(description="Configuration overrides for the resumed thread, if any.") ] = None model_provider: Annotated[str | None, Field(alias="modelProvider")] = None personality: Personality | None = None @@ -4412,21 +4163,13 @@ class ActiveThreadStatus(BaseModel): class ThreadStatus( RootModel[ - NotLoadedThreadStatus - | IdleThreadStatus - | SystemErrorThreadStatus - | ActiveThreadStatus + NotLoadedThreadStatus | IdleThreadStatus | SystemErrorThreadStatus | ActiveThreadStatus ] ): model_config = ConfigDict( populate_by_name=True, ) - root: ( - NotLoadedThreadStatus - | IdleThreadStatus - | SystemErrorThreadStatus - | ActiveThreadStatus - ) + root: NotLoadedThreadStatus | IdleThreadStatus | SystemErrorThreadStatus | ActiveThreadStatus class ThreadStatusChangedNotification(BaseModel): @@ -4597,23 +4340,13 @@ class MentionUserInput(BaseModel): class UserInput( RootModel[ - TextUserInput - | ImageUserInput - | LocalImageUserInput - | SkillUserInput - | MentionUserInput + TextUserInput | ImageUserInput | LocalImageUserInput | SkillUserInput | MentionUserInput ] ): model_config = ConfigDict( populate_by_name=True, ) - root: ( - TextUserInput - | ImageUserInput - | LocalImageUserInput - | SkillUserInput - | MentionUserInput - ) + root: TextUserInput | ImageUserInput | LocalImageUserInput | SkillUserInput | MentionUserInput class Verbosity(Enum): @@ -4878,9 +4611,7 @@ class ThreadResumeRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["thread/resume"], Field(title="Thread/resumeRequestMethod") - ] + method: Annotated[Literal["thread/resume"], Field(title="Thread/resumeRequestMethod")] params: ThreadResumeParams @@ -4889,9 +4620,7 @@ class ThreadArchiveRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["thread/archive"], Field(title="Thread/archiveRequestMethod") - ] + method: Annotated[Literal["thread/archive"], Field(title="Thread/archiveRequestMethod")] params: ThreadArchiveParams @@ -4900,9 +4629,7 @@ class ThreadUnsubscribeRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["thread/unsubscribe"], Field(title="Thread/unsubscribeRequestMethod") - ] + method: Annotated[Literal["thread/unsubscribe"], Field(title="Thread/unsubscribeRequestMethod")] params: ThreadUnsubscribeParams @@ -4911,9 +4638,7 @@ class ThreadNameSetRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["thread/name/set"], Field(title="Thread/name/setRequestMethod") - ] + method: Annotated[Literal["thread/name/set"], Field(title="Thread/name/setRequestMethod")] params: ThreadSetNameParams @@ -4923,8 +4648,7 @@ class ThreadMetadataUpdateRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["thread/metadata/update"], - Field(title="Thread/metadata/updateRequestMethod"), + Literal["thread/metadata/update"], Field(title="Thread/metadata/updateRequestMethod") ] params: ThreadMetadataUpdateParams @@ -4934,9 +4658,7 @@ class ThreadUnarchiveRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["thread/unarchive"], Field(title="Thread/unarchiveRequestMethod") - ] + method: Annotated[Literal["thread/unarchive"], Field(title="Thread/unarchiveRequestMethod")] params: ThreadUnarchiveParams @@ -4946,8 +4668,7 @@ class ThreadCompactStartRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["thread/compact/start"], - Field(title="Thread/compact/startRequestMethod"), + Literal["thread/compact/start"], Field(title="Thread/compact/startRequestMethod") ] params: ThreadCompactStartParams @@ -4980,9 +4701,7 @@ class ThreadRollbackRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["thread/rollback"], Field(title="Thread/rollbackRequestMethod") - ] + method: Annotated[Literal["thread/rollback"], Field(title="Thread/rollbackRequestMethod")] params: ThreadRollbackParams @@ -4991,9 +4710,7 @@ class ThreadLoadedListRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["thread/loaded/list"], Field(title="Thread/loaded/listRequestMethod") - ] + method: Annotated[Literal["thread/loaded/list"], Field(title="Thread/loaded/listRequestMethod")] params: ThreadLoadedListParams @@ -5040,9 +4757,7 @@ class MarketplaceAddRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["marketplace/add"], Field(title="Marketplace/addRequestMethod") - ] + method: Annotated[Literal["marketplace/add"], Field(title="Marketplace/addRequestMethod")] params: MarketplaceAddParams @@ -5051,9 +4766,7 @@ class MarketplaceRemoveRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["marketplace/remove"], Field(title="Marketplace/removeRequestMethod") - ] + method: Annotated[Literal["marketplace/remove"], Field(title="Marketplace/removeRequestMethod")] params: MarketplaceRemoveParams @@ -5091,9 +4804,7 @@ class PluginSkillReadRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["plugin/skill/read"], Field(title="Plugin/skill/readRequestMethod") - ] + method: Annotated[Literal["plugin/skill/read"], Field(title="Plugin/skill/readRequestMethod")] params: PluginSkillReadParams @@ -5102,9 +4813,7 @@ class PluginShareListRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["plugin/share/list"], Field(title="Plugin/share/listRequestMethod") - ] + method: Annotated[Literal["plugin/share/list"], Field(title="Plugin/share/listRequestMethod")] params: PluginShareListParams @@ -5151,9 +4860,7 @@ class FsCreateDirectoryRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["fs/createDirectory"], Field(title="Fs/createDirectoryRequestMethod") - ] + method: Annotated[Literal["fs/createDirectory"], Field(title="Fs/createDirectoryRequestMethod")] params: FsCreateDirectoryParams @@ -5162,9 +4869,7 @@ class FsGetMetadataRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["fs/getMetadata"], Field(title="Fs/getMetadataRequestMethod") - ] + method: Annotated[Literal["fs/getMetadata"], Field(title="Fs/getMetadataRequestMethod")] params: FsGetMetadataParams @@ -5173,9 +4878,7 @@ class FsReadDirectoryRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["fs/readDirectory"], Field(title="Fs/readDirectoryRequestMethod") - ] + method: Annotated[Literal["fs/readDirectory"], Field(title="Fs/readDirectoryRequestMethod")] params: FsReadDirectoryParams @@ -5231,9 +4934,7 @@ class PluginInstallRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["plugin/install"], Field(title="Plugin/installRequestMethod") - ] + method: Annotated[Literal["plugin/install"], Field(title="Plugin/installRequestMethod")] params: PluginInstallParams @@ -5242,9 +4943,7 @@ class PluginUninstallRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["plugin/uninstall"], Field(title="Plugin/uninstallRequestMethod") - ] + method: Annotated[Literal["plugin/uninstall"], Field(title="Plugin/uninstallRequestMethod")] params: PluginUninstallParams @@ -5253,9 +4952,7 @@ class TurnInterruptRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["turn/interrupt"], Field(title="Turn/interruptRequestMethod") - ] + method: Annotated[Literal["turn/interrupt"], Field(title="Turn/interruptRequestMethod")] params: TurnInterruptParams @@ -5286,8 +4983,7 @@ class ExperimentalFeatureListRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["experimentalFeature/list"], - Field(title="ExperimentalFeature/listRequestMethod"), + Literal["experimentalFeature/list"], Field(title="ExperimentalFeature/listRequestMethod") ] params: ExperimentalFeatureListParams @@ -5310,8 +5006,7 @@ class McpServerOauthLoginRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["mcpServer/oauth/login"], - Field(title="McpServer/oauth/loginRequestMethod"), + Literal["mcpServer/oauth/login"], Field(title="McpServer/oauth/loginRequestMethod") ] params: McpServerOauthLoginParams @@ -5322,8 +5017,7 @@ class ConfigMcpServerReloadRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["config/mcpServer/reload"], - Field(title="Config/mcpServer/reloadRequestMethod"), + Literal["config/mcpServer/reload"], Field(title="Config/mcpServer/reloadRequestMethod") ] params: None = None @@ -5334,8 +5028,7 @@ class McpServerResourceReadRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["mcpServer/resource/read"], - Field(title="McpServer/resource/readRequestMethod"), + Literal["mcpServer/resource/read"], Field(title="McpServer/resource/readRequestMethod") ] params: McpResourceReadParams @@ -5357,8 +5050,7 @@ class WindowsSandboxSetupStartRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["windowsSandbox/setupStart"], - Field(title="WindowsSandbox/setupStartRequestMethod"), + Literal["windowsSandbox/setupStart"], Field(title="WindowsSandbox/setupStartRequestMethod") ] params: WindowsSandboxSetupStartParams @@ -5369,8 +5061,7 @@ class WindowsSandboxReadinessRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["windowsSandbox/readiness"], - Field(title="WindowsSandbox/readinessRequestMethod"), + Literal["windowsSandbox/readiness"], Field(title="WindowsSandbox/readinessRequestMethod") ] params: None = None @@ -5392,8 +5083,7 @@ class AccountLoginCancelRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["account/login/cancel"], - Field(title="Account/login/cancelRequestMethod"), + Literal["account/login/cancel"], Field(title="Account/login/cancelRequestMethod") ] params: CancelLoginAccountParams @@ -5403,9 +5093,7 @@ class AccountLogoutRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["account/logout"], Field(title="Account/logoutRequestMethod") - ] + method: Annotated[Literal["account/logout"], Field(title="Account/logoutRequestMethod")] params: None = None @@ -5415,8 +5103,7 @@ class AccountRateLimitsReadRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["account/rateLimits/read"], - Field(title="Account/rateLimits/readRequestMethod"), + Literal["account/rateLimits/read"], Field(title="Account/rateLimits/readRequestMethod") ] params: None = None @@ -5438,9 +5125,7 @@ class FeedbackUploadRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["feedback/upload"], Field(title="Feedback/uploadRequestMethod") - ] + method: Annotated[Literal["feedback/upload"], Field(title="Feedback/uploadRequestMethod")] params: FeedbackUploadParams @@ -5449,9 +5134,7 @@ class CommandExecWriteRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["command/exec/write"], Field(title="Command/exec/writeRequestMethod") - ] + method: Annotated[Literal["command/exec/write"], Field(title="Command/exec/writeRequestMethod")] params: CommandExecWriteParams @@ -5461,8 +5144,7 @@ class CommandExecTerminateRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["command/exec/terminate"], - Field(title="Command/exec/terminateRequestMethod"), + Literal["command/exec/terminate"], Field(title="Command/exec/terminateRequestMethod") ] params: CommandExecTerminateParams @@ -5494,8 +5176,7 @@ class ConfigRequirementsReadRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["configRequirements/read"], - Field(title="ConfigRequirements/readRequestMethod"), + Literal["configRequirements/read"], Field(title="ConfigRequirements/readRequestMethod") ] params: None = None @@ -5514,9 +5195,7 @@ class FuzzyFileSearchRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["fuzzyFileSearch"], Field(title="FuzzyFileSearchRequestMethod") - ] + method: Annotated[Literal["fuzzyFileSearch"], Field(title="FuzzyFileSearchRequestMethod")] params: FuzzyFileSearchParams @@ -5610,9 +5289,7 @@ class CommandExecOutputDeltaNotification(BaseModel): description="Client-supplied, connection-scoped `processId` from the original `command/exec` request.", ), ] - stream: Annotated[ - CommandExecOutputStream, Field(description="Output stream for this chunk.") - ] + stream: Annotated[CommandExecOutputStream, Field(description="Output stream for this chunk.")] class CommandExecParams(BaseModel): @@ -5623,8 +5300,7 @@ class CommandExecParams(BaseModel): list[str], Field(description="Command argv vector. Empty arrays are rejected.") ] cwd: Annotated[ - str | None, - Field(description="Optional working directory. Defaults to the server cwd."), + str | None, Field(description="Optional working directory. Defaults to the server cwd.") ] = None disable_output_cap: Annotated[ bool | None, @@ -5714,9 +5390,7 @@ class CommandExecResizeParams(BaseModel): description="Client-supplied, connection-scoped `processId` from the original `command/exec` request.", ), ] - size: Annotated[ - CommandExecTerminalSize, Field(description="New PTY size in character cells.") - ] + size: Annotated[CommandExecTerminalSize, Field(description="New PTY size in character cells.")] class ConfigEdit(BaseModel): @@ -5759,12 +5433,12 @@ class ConfigRequirements(BaseModel): allowed_web_search_modes: Annotated[ list[WebSearchMode] | None, Field(alias="allowedWebSearchModes") ] = None - enforce_residency: Annotated[ - ResidencyRequirement | None, Field(alias="enforceResidency") - ] = None - feature_requirements: Annotated[ - dict[str, Any] | None, Field(alias="featureRequirements") - ] = None + enforce_residency: Annotated[ResidencyRequirement | None, Field(alias="enforceResidency")] = ( + None + ) + feature_requirements: Annotated[dict[str, Any] | None, Field(alias="featureRequirements")] = ( + None + ) class ConfigRequirementsReadResponse(BaseModel): @@ -5805,15 +5479,11 @@ class ConfigWarningNotification(BaseModel): ] = None path: Annotated[ str | None, - Field( - description="Optional path to the config file that triggered the warning." - ), + Field(description="Optional path to the config file that triggered the warning."), ] = None range: Annotated[ TextRange | None, - Field( - description="Optional range for the error location inside the config file." - ), + Field(description="Optional range for the error location inside the config file."), ] = None summary: Annotated[str, Field(description="Concise summary of the warning.")] @@ -5827,9 +5497,7 @@ class InputImageContentItem(BaseModel): type: Annotated[Literal["input_image"], Field(title="InputImageContentItemType")] -class ContentItem( - RootModel[InputTextContentItem | InputImageContentItem | OutputTextContentItem] -): +class ContentItem(RootModel[InputTextContentItem | InputImageContentItem | OutputTextContentItem]): model_config = ConfigDict( populate_by_name=True, ) @@ -5848,10 +5516,7 @@ class ExperimentalFeature(BaseModel): ] = None default_enabled: Annotated[ bool, - Field( - alias="defaultEnabled", - description="Whether this feature is enabled by default.", - ), + Field(alias="defaultEnabled", description="Whether this feature is enabled by default."), ] description: Annotated[ str | None, @@ -5867,17 +5532,11 @@ class ExperimentalFeature(BaseModel): ), ] = None enabled: Annotated[ - bool, - Field( - description="Whether this feature is currently enabled in the loaded config." - ), - ] - name: Annotated[ - str, Field(description="Stable key used in config.toml and CLI flag toggles.") + bool, Field(description="Whether this feature is currently enabled in the loaded config.") ] + name: Annotated[str, Field(description="Stable key used in config.toml and CLI flag toggles.")] stage: Annotated[ - ExperimentalFeatureStage, - Field(description="Lifecycle stage of this feature flag."), + ExperimentalFeatureStage, Field(description="Lifecycle stage of this feature flag.") ] @@ -5936,22 +5595,18 @@ class InputImageFunctionCallOutputContentItem(BaseModel): detail: ImageDetail | None = None image_url: str type: Annotated[ - Literal["input_image"], - Field(title="InputImageFunctionCallOutputContentItemType"), + Literal["input_image"], Field(title="InputImageFunctionCallOutputContentItemType") ] class FunctionCallOutputContentItem( - RootModel[ - InputTextFunctionCallOutputContentItem | InputImageFunctionCallOutputContentItem - ] + RootModel[InputTextFunctionCallOutputContentItem | InputImageFunctionCallOutputContentItem] ): model_config = ConfigDict( populate_by_name=True, ) root: Annotated[ - InputTextFunctionCallOutputContentItem - | InputImageFunctionCallOutputContentItem, + InputTextFunctionCallOutputContentItem | InputImageFunctionCallOutputContentItem, Field( description="Responses API compatible content items that can be returned by a tool call. This is a subset of ContentItem with the types we support as function call outputs." ), @@ -5985,9 +5640,7 @@ class CommandGuardianApprovalReviewAction(BaseModel): command: str cwd: AbsolutePathBuf source: GuardianCommandSource - type: Annotated[ - Literal["command"], Field(title="CommandGuardianApprovalReviewActionType") - ] + type: Annotated[Literal["command"], Field(title="CommandGuardianApprovalReviewActionType")] class ExecveGuardianApprovalReviewAction(BaseModel): @@ -5998,9 +5651,7 @@ class ExecveGuardianApprovalReviewAction(BaseModel): cwd: AbsolutePathBuf program: str source: GuardianCommandSource - type: Annotated[ - Literal["execve"], Field(title="ExecveGuardianApprovalReviewActionType") - ] + type: Annotated[Literal["execve"], Field(title="ExecveGuardianApprovalReviewActionType")] class NetworkAccessGuardianApprovalReviewAction(BaseModel): @@ -6012,8 +5663,7 @@ class NetworkAccessGuardianApprovalReviewAction(BaseModel): protocol: NetworkApprovalProtocol target: str type: Annotated[ - Literal["networkAccess"], - Field(title="NetworkAccessGuardianApprovalReviewActionType"), + Literal["networkAccess"], Field(title="NetworkAccessGuardianApprovalReviewActionType") ] @@ -6097,8 +5747,7 @@ class ListMcpServerStatusParams(BaseModel): populate_by_name=True, ) cursor: Annotated[ - str | None, - Field(description="Opaque pagination cursor returned by a previous call."), + str | None, Field(description="Opaque pagination cursor returned by a previous call.") ] = None detail: Annotated[ McpServerStatusDetail | None, @@ -6108,9 +5757,7 @@ class ListMcpServerStatusParams(BaseModel): ] = None limit: Annotated[ int | None, - Field( - description="Optional page size; defaults to a server-defined value.", ge=0 - ), + Field(description="Optional page size; defaults to a server-defined value.", ge=0), ] = None @@ -6127,9 +5774,7 @@ class McpServerStatus(BaseModel): ) auth_status: Annotated[McpAuthStatus, Field(alias="authStatus")] name: str - resource_templates: Annotated[ - list[ResourceTemplate], Field(alias="resourceTemplates") - ] + resource_templates: Annotated[list[ResourceTemplate], Field(alias="resourceTemplates")] resources: list[Resource] tools: dict[str, Tool] @@ -6148,9 +5793,7 @@ class MigrationDetails(BaseModel): ) commands: list[CommandMigration] | None = [] hooks: list[HookMigration] | None = [] - mcp_servers: Annotated[ - list[McpServerMigration] | None, Field(alias="mcpServers") - ] = [] + mcp_servers: Annotated[list[McpServerMigration] | None, Field(alias="mcpServers")] = [] plugins: list[PluginsMigration] | None = [] sessions: list[SessionMigration] | None = [] subagents: list[SubagentMigration] | None = [] @@ -6162,35 +5805,25 @@ class Model(BaseModel): ) additional_speed_tiers: Annotated[ list[str] | None, - Field( - alias="additionalSpeedTiers", - description="Deprecated: use `serviceTiers` instead.", - ), + Field(alias="additionalSpeedTiers", description="Deprecated: use `serviceTiers` instead."), ] = [] - availability_nux: Annotated[ - ModelAvailabilityNux | None, Field(alias="availabilityNux") - ] = None - default_reasoning_effort: Annotated[ - ReasoningEffort, Field(alias="defaultReasoningEffort") - ] + availability_nux: Annotated[ModelAvailabilityNux | None, Field(alias="availabilityNux")] = None + default_reasoning_effort: Annotated[ReasoningEffort, Field(alias="defaultReasoningEffort")] description: str display_name: Annotated[str, Field(alias="displayName")] hidden: bool id: str - input_modalities: Annotated[ - list[InputModality] | None, Field(alias="inputModalities") - ] = ["text", "image"] + input_modalities: Annotated[list[InputModality] | None, Field(alias="inputModalities")] = [ + "text", + "image", + ] is_default: Annotated[bool, Field(alias="isDefault")] model: str - service_tiers: Annotated[ - list[ModelServiceTier] | None, Field(alias="serviceTiers") - ] = [] + service_tiers: Annotated[list[ModelServiceTier] | None, Field(alias="serviceTiers")] = [] supported_reasoning_efforts: Annotated[ list[ReasoningEffortOption], Field(alias="supportedReasoningEfforts") ] - supports_personality: Annotated[bool | None, Field(alias="supportsPersonality")] = ( - False - ) + supports_personality: Annotated[bool | None, Field(alias="supportsPersonality")] = False upgrade: str | None = None upgrade_info: Annotated[ModelUpgradeInfo | None, Field(alias="upgradeInfo")] = None @@ -6231,12 +5864,9 @@ class RestrictedPermissionProfileFileSystemPermissions(BaseModel): populate_by_name=True, ) entries: list[FileSystemSandboxEntry] - glob_scan_max_depth: Annotated[ - int | None, Field(alias="globScanMaxDepth", ge=1) - ] = None + glob_scan_max_depth: Annotated[int | None, Field(alias="globScanMaxDepth", ge=1)] = None type: Annotated[ - Literal["restricted"], - Field(title="RestrictedPermissionProfileFileSystemPermissionsType"), + Literal["restricted"], Field(title="RestrictedPermissionProfileFileSystemPermissionsType") ] @@ -6350,9 +5980,7 @@ class WebSearchCallResponseItem(BaseModel): action: ResponsesApiWebSearchAction | None = None id: str | None = None status: str | None = None - type: Annotated[ - Literal["web_search_call"], Field(title="WebSearchCallResponseItemType") - ] + type: Annotated[Literal["web_search_call"], Field(title="WebSearchCallResponseItemType")] class ReviewStartParams(BaseModel): @@ -6374,8 +6002,7 @@ class ThreadStatusChangedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/status/changed"], - Field(title="Thread/status/changedNotificationMethod"), + Literal["thread/status/changed"], Field(title="Thread/status/changedNotificationMethod") ] params: ThreadStatusChangedNotification @@ -6384,9 +6011,7 @@ class ThreadArchivedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["thread/archived"], Field(title="Thread/archivedNotificationMethod") - ] + method: Annotated[Literal["thread/archived"], Field(title="Thread/archivedNotificationMethod")] params: ThreadArchivedNotification @@ -6404,9 +6029,7 @@ class ThreadClosedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["thread/closed"], Field(title="Thread/closedNotificationMethod") - ] + method: Annotated[Literal["thread/closed"], Field(title="Thread/closedNotificationMethod")] params: ThreadClosedNotification @@ -6414,9 +6037,7 @@ class SkillsChangedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["skills/changed"], Field(title="Skills/changedNotificationMethod") - ] + method: Annotated[Literal["skills/changed"], Field(title="Skills/changedNotificationMethod")] params: SkillsChangedNotification @@ -6425,8 +6046,7 @@ class ThreadNameUpdatedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/name/updated"], - Field(title="Thread/name/updatedNotificationMethod"), + Literal["thread/name/updated"], Field(title="Thread/name/updatedNotificationMethod") ] params: ThreadNameUpdatedNotification @@ -6436,8 +6056,7 @@ class ThreadGoalClearedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/goal/cleared"], - Field(title="Thread/goal/clearedNotificationMethod"), + Literal["thread/goal/cleared"], Field(title="Thread/goal/clearedNotificationMethod") ] params: ThreadGoalClearedNotification @@ -6446,9 +6065,7 @@ class HookStartedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["hook/started"], Field(title="Hook/startedNotificationMethod") - ] + method: Annotated[Literal["hook/started"], Field(title="Hook/startedNotificationMethod")] params: HookStartedNotification @@ -6478,8 +6095,7 @@ class ProcessOutputDeltaServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["process/outputDelta"], - Field(title="Process/outputDeltaNotificationMethod"), + Literal["process/outputDelta"], Field(title="Process/outputDeltaNotificationMethod") ] params: ProcessOutputDeltaNotification @@ -6500,8 +6116,7 @@ class ServerRequestResolvedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["serverRequest/resolved"], - Field(title="ServerRequest/resolvedNotificationMethod"), + Literal["serverRequest/resolved"], Field(title="ServerRequest/resolvedNotificationMethod") ] params: ServerRequestResolvedNotification @@ -6510,9 +6125,7 @@ class AccountUpdatedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["account/updated"], Field(title="Account/updatedNotificationMethod") - ] + method: Annotated[Literal["account/updated"], Field(title="Account/updatedNotificationMethod")] params: AccountUpdatedNotification @@ -6528,9 +6141,7 @@ class ConfigWarningServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["configWarning"], Field(title="ConfigWarningNotificationMethod") - ] + method: Annotated[Literal["configWarning"], Field(title="ConfigWarningNotificationMethod")] params: ConfigWarningNotification @@ -6539,8 +6150,7 @@ class ThreadRealtimeStartedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/realtime/started"], - Field(title="Thread/realtime/startedNotificationMethod"), + Literal["thread/realtime/started"], Field(title="Thread/realtime/startedNotificationMethod") ] params: ThreadRealtimeStartedNotification @@ -6594,8 +6204,7 @@ class ThreadRealtimeSdpServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/realtime/sdp"], - Field(title="Thread/realtime/sdpNotificationMethod"), + Literal["thread/realtime/sdp"], Field(title="Thread/realtime/sdpNotificationMethod") ] params: ThreadRealtimeSdpNotification @@ -6605,8 +6214,7 @@ class ThreadRealtimeErrorServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/realtime/error"], - Field(title="Thread/realtime/errorNotificationMethod"), + Literal["thread/realtime/error"], Field(title="Thread/realtime/errorNotificationMethod") ] params: ThreadRealtimeErrorNotification @@ -6616,8 +6224,7 @@ class ThreadRealtimeClosedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/realtime/closed"], - Field(title="Thread/realtime/closedNotificationMethod"), + Literal["thread/realtime/closed"], Field(title="Thread/realtime/closedNotificationMethod") ] params: ThreadRealtimeClosedNotification @@ -6708,9 +6315,7 @@ class ThreadForkParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - approval_policy: Annotated[AskForApproval | None, Field(alias="approvalPolicy")] = ( - None - ) + approval_policy: Annotated[AskForApproval | None, Field(alias="approvalPolicy")] = None approvals_reviewer: Annotated[ ApprovalsReviewer | None, Field( @@ -6721,13 +6326,10 @@ class ThreadForkParams(BaseModel): base_instructions: Annotated[str | None, Field(alias="baseInstructions")] = None config: dict[str, Any] | None = None cwd: str | None = None - developer_instructions: Annotated[ - str | None, Field(alias="developerInstructions") - ] = None + developer_instructions: Annotated[str | None, Field(alias="developerInstructions")] = None ephemeral: bool | None = None model: Annotated[ - str | None, - Field(description="Configuration overrides for the forked thread, if any."), + str | None, Field(description="Configuration overrides for the forked thread, if any.") ] = None model_provider: Annotated[str | None, Field(alias="modelProvider")] = None sandbox: SandboxMode | None = None @@ -6779,9 +6381,7 @@ class AgentMessageThreadItem(BaseModel): populate_by_name=True, ) id: str - memory_citation: Annotated[MemoryCitation | None, Field(alias="memoryCitation")] = ( - None - ) + memory_citation: Annotated[MemoryCitation | None, Field(alias="memoryCitation")] = None phase: MessagePhase | None = None text: str type: Annotated[Literal["agentMessage"], Field(title="AgentMessageThreadItemType")] @@ -6808,18 +6408,13 @@ class CollabAgentToolCallThreadItem(BaseModel): description="Last known status of the target agents, when available.", ), ] - id: Annotated[ - str, Field(description="Unique identifier for this collab tool call.") - ] + id: Annotated[str, Field(description="Unique identifier for this collab tool call.")] model: Annotated[ - str | None, - Field(description="Model requested for the spawned agent, when applicable."), + str | None, Field(description="Model requested for the spawned agent, when applicable.") ] = None prompt: Annotated[ str | None, - Field( - description="Prompt text sent as part of the collab tool call, when available." - ), + Field(description="Prompt text sent as part of the collab tool call, when available."), ] = None reasoning_effort: Annotated[ ReasoningEffort | None, @@ -6838,17 +6433,13 @@ class CollabAgentToolCallThreadItem(BaseModel): sender_thread_id: Annotated[ str, Field( - alias="senderThreadId", - description="Thread ID of the agent issuing the collab request.", + alias="senderThreadId", description="Thread ID of the agent issuing the collab request." ), ] status: Annotated[ - CollabAgentToolCallStatus, - Field(description="Current status of the collab tool call."), - ] - tool: Annotated[ - CollabAgentTool, Field(description="Name of the collab tool that was invoked.") + CollabAgentToolCallStatus, Field(description="Current status of the collab tool call.") ] + tool: Annotated[CollabAgentTool, Field(description="Name of the collab tool that was invoked.")] type: Annotated[ Literal["collabAgentToolCall"], Field(title="CollabAgentToolCallThreadItemType") ] @@ -6918,8 +6509,7 @@ class ThreadListParams(BaseModel): ), ] = None cursor: Annotated[ - str | None, - Field(description="Opaque pagination cursor returned by a previous call."), + str | None, Field(description="Opaque pagination cursor returned by a previous call.") ] = None cwd: Annotated[ ThreadListCwdFilter | None, @@ -6929,10 +6519,7 @@ class ThreadListParams(BaseModel): ] = None limit: Annotated[ int | None, - Field( - description="Optional page size; defaults to a reasonable server-side value.", - ge=0, - ), + Field(description="Optional page size; defaults to a reasonable server-side value.", ge=0), ] = None model_providers: Annotated[ list[str] | None, @@ -6957,9 +6544,7 @@ class ThreadListParams(BaseModel): ] = None sort_key: Annotated[ ThreadSortKey | None, - Field( - alias="sortKey", description="Optional sort key; defaults to created_at." - ), + Field(alias="sortKey", description="Optional sort key; defaults to created_at."), ] = None source_kinds: Annotated[ list[ThreadSourceKind] | None, @@ -6981,9 +6566,7 @@ class ThreadStartParams(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - approval_policy: Annotated[AskForApproval | None, Field(alias="approvalPolicy")] = ( - None - ) + approval_policy: Annotated[AskForApproval | None, Field(alias="approvalPolicy")] = None approvals_reviewer: Annotated[ ApprovalsReviewer | None, Field( @@ -6994,9 +6577,7 @@ class ThreadStartParams(BaseModel): base_instructions: Annotated[str | None, Field(alias="baseInstructions")] = None config: dict[str, Any] | None = None cwd: str | None = None - developer_instructions: Annotated[ - str | None, Field(alias="developerInstructions") - ] = None + developer_instructions: Annotated[str | None, Field(alias="developerInstructions")] = None ephemeral: bool | None = None model: str | None = None model_provider: Annotated[str | None, Field(alias="modelProvider")] = None @@ -7004,9 +6585,9 @@ class ThreadStartParams(BaseModel): sandbox: SandboxMode | None = None service_name: Annotated[str | None, Field(alias="serviceName")] = None service_tier: Annotated[str | None, Field(alias="serviceTier")] = None - session_start_source: Annotated[ - ThreadStartSource | None, Field(alias="sessionStartSource") - ] = None + session_start_source: Annotated[ThreadStartSource | None, Field(alias="sessionStartSource")] = ( + None + ) thread_source: Annotated[ ThreadSource | None, Field( @@ -7021,9 +6602,7 @@ class ThreadTokenUsage(BaseModel): populate_by_name=True, ) last: TokenUsageBreakdown - model_context_window: Annotated[int | None, Field(alias="modelContextWindow")] = ( - None - ) + model_context_window: Annotated[int | None, Field(alias="modelContextWindow")] = None total: TokenUsageBreakdown @@ -7056,9 +6635,7 @@ class TurnError(BaseModel): populate_by_name=True, ) additional_details: Annotated[str | None, Field(alias="additionalDetails")] = None - codex_error_info: Annotated[ - CodexErrorInfo | None, Field(alias="codexErrorInfo") - ] = None + codex_error_info: Annotated[CodexErrorInfo | None, Field(alias="codexErrorInfo")] = None message: str @@ -7100,20 +6677,15 @@ class TurnStartParams(BaseModel): ] = None cwd: Annotated[ str | None, - Field( - description="Override the working directory for this turn and subsequent turns." - ), + Field(description="Override the working directory for this turn and subsequent turns."), ] = None effort: Annotated[ ReasoningEffort | None, - Field( - description="Override the reasoning effort for this turn and subsequent turns." - ), + Field(description="Override the reasoning effort for this turn and subsequent turns."), ] = None input: list[UserInput] model: Annotated[ - str | None, - Field(description="Override the model for this turn and subsequent turns."), + str | None, Field(description="Override the model for this turn and subsequent turns.") ] = None output_schema: Annotated[ Any | None, @@ -7124,9 +6696,7 @@ class TurnStartParams(BaseModel): ] = None personality: Annotated[ Personality | None, - Field( - description="Override the personality for this turn and subsequent turns." - ), + Field(description="Override the personality for this turn and subsequent turns."), ] = None sandbox_policy: Annotated[ SandboxPolicy | None, @@ -7144,9 +6714,7 @@ class TurnStartParams(BaseModel): ] = None summary: Annotated[ ReasoningSummary | None, - Field( - description="Override the reasoning summary for this turn and subsequent turns." - ), + Field(description="Override the reasoning summary for this turn and subsequent turns."), ] = None thread_id: Annotated[str, Field(alias="threadId")] @@ -7187,9 +6755,7 @@ class AdditionalFileSystemPermissions(BaseModel): populate_by_name=True, ) entries: list[FileSystemSandboxEntry] | None = None - glob_scan_max_depth: Annotated[ - int | None, Field(alias="globScanMaxDepth", ge=1) - ] = None + glob_scan_max_depth: Annotated[int | None, Field(alias="globScanMaxDepth", ge=1)] = None read: Annotated[ list[AbsolutePathBuf] | None, Field(description="This will be removed in favor of `entries`."), @@ -7207,9 +6773,7 @@ class AppInfo(BaseModel): app_metadata: Annotated[AppMetadata | None, Field(alias="appMetadata")] = None branding: AppBranding | None = None description: str | None = None - distribution_channel: Annotated[str | None, Field(alias="distributionChannel")] = ( - None - ) + distribution_channel: Annotated[str | None, Field(alias="distributionChannel")] = None id: str install_url: Annotated[str | None, Field(alias="installUrl")] = None is_accessible: Annotated[bool | None, Field(alias="isAccessible")] = False @@ -7224,9 +6788,7 @@ class AppInfo(BaseModel): logo_url: Annotated[str | None, Field(alias="logoUrl")] = None logo_url_dark: Annotated[str | None, Field(alias="logoUrlDark")] = None name: str - plugin_display_names: Annotated[ - list[str] | None, Field(alias="pluginDisplayNames") - ] = [] + plugin_display_names: Annotated[list[str] | None, Field(alias="pluginDisplayNames")] = [] class AppListUpdatedNotification(BaseModel): @@ -7322,8 +6884,7 @@ class McpServerStatusListRequest(BaseModel): ) id: RequestId method: Annotated[ - Literal["mcpServerStatus/list"], - Field(title="McpServerStatus/listRequestMethod"), + Literal["mcpServerStatus/list"], Field(title="McpServerStatus/listRequestMethod") ] params: ListMcpServerStatusParams @@ -7353,9 +6914,7 @@ class ConfigValueWriteRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["config/value/write"], Field(title="Config/value/writeRequestMethod") - ] + method: Annotated[Literal["config/value/write"], Field(title="Config/value/writeRequestMethod")] params: ConfigValueWriteParams @@ -7387,14 +6946,11 @@ class ConfigWriteResponse(BaseModel): ) file_path: Annotated[ AbsolutePathBuf, - Field( - alias="filePath", - description="Canonical path to the config file that was written.", - ), + Field(alias="filePath", description="Canonical path to the config file that was written."), ] - overridden_metadata: Annotated[ - OverriddenMetadata | None, Field(alias="overriddenMetadata") - ] = None + overridden_metadata: Annotated[OverriddenMetadata | None, Field(alias="overriddenMetadata")] = ( + None + ) status: WriteStatus version: str @@ -7520,33 +7076,25 @@ class ManagedPermissionProfile(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - file_system: Annotated[ - PermissionProfileFileSystemPermissions, Field(alias="fileSystem") - ] + file_system: Annotated[PermissionProfileFileSystemPermissions, Field(alias="fileSystem")] network: PermissionProfileNetworkPermissions type: Annotated[Literal["managed"], Field(title="ManagedPermissionProfileType")] class PermissionProfile( - RootModel[ - ManagedPermissionProfile | DisabledPermissionProfile | ExternalPermissionProfile - ] + RootModel[ManagedPermissionProfile | DisabledPermissionProfile | ExternalPermissionProfile] ): model_config = ConfigDict( populate_by_name=True, ) - root: ( - ManagedPermissionProfile | DisabledPermissionProfile | ExternalPermissionProfile - ) + root: ManagedPermissionProfile | DisabledPermissionProfile | ExternalPermissionProfile class PluginShareContext(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - creator_account_user_id: Annotated[ - str | None, Field(alias="creatorAccountUserId") - ] = None + creator_account_user_id: Annotated[str | None, Field(alias="creatorAccountUserId")] = None creator_name: Annotated[str | None, Field(alias="creatorName")] = None discoverability: PluginShareDiscoverability | None = None remote_plugin_id: Annotated[str, Field(alias="remotePluginId")] @@ -7563,9 +7111,7 @@ class PluginShareSaveParams(BaseModel): discoverability: PluginShareDiscoverability | None = None plugin_path: Annotated[AbsolutePathBuf, Field(alias="pluginPath")] remote_plugin_id: Annotated[str | None, Field(alias="remotePluginId")] = None - share_targets: Annotated[ - list[PluginShareTarget] | None, Field(alias="shareTargets") - ] = None + share_targets: Annotated[list[PluginShareTarget] | None, Field(alias="shareTargets")] = None class PluginSummary(BaseModel): @@ -7622,9 +7168,7 @@ class RequestPermissionProfile(BaseModel): extra="forbid", populate_by_name=True, ) - file_system: Annotated[ - AdditionalFileSystemPermissions | None, Field(alias="fileSystem") - ] = None + file_system: Annotated[AdditionalFileSystemPermissions | None, Field(alias="fileSystem")] = None network: AdditionalNetworkPermissions | None = None @@ -7635,8 +7179,7 @@ class FunctionCallOutputResponseItem(BaseModel): call_id: str output: FunctionCallOutputBody type: Annotated[ - Literal["function_call_output"], - Field(title="FunctionCallOutputResponseItemType"), + Literal["function_call_output"], Field(title="FunctionCallOutputResponseItemType") ] @@ -7648,8 +7191,7 @@ class CustomToolCallOutputResponseItem(BaseModel): name: str | None = None output: FunctionCallOutputBody type: Annotated[ - Literal["custom_tool_call_output"], - Field(title="CustomToolCallOutputResponseItemType"), + Literal["custom_tool_call_output"], Field(title="CustomToolCallOutputResponseItemType") ] @@ -7705,8 +7247,7 @@ class ThreadGoalUpdatedServerNotification(BaseModel): populate_by_name=True, ) method: Annotated[ - Literal["thread/goal/updated"], - Field(title="Thread/goal/updatedNotificationMethod"), + Literal["thread/goal/updated"], Field(title="Thread/goal/updatedNotificationMethod") ] params: ThreadGoalUpdatedNotification @@ -7726,9 +7267,7 @@ class HookCompletedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["hook/completed"], Field(title="Hook/completedNotificationMethod") - ] + method: Annotated[Literal["hook/completed"], Field(title="Hook/completedNotificationMethod")] params: HookCompletedNotification @@ -7746,9 +7285,7 @@ class ItemStartedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["item/started"], Field(title="Item/startedNotificationMethod") - ] + method: Annotated[Literal["item/started"], Field(title="Item/startedNotificationMethod")] params: ItemStartedNotification @@ -7756,9 +7293,7 @@ class ItemCompletedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["item/completed"], Field(title="Item/completedNotificationMethod") - ] + method: Annotated[Literal["item/completed"], Field(title="Item/completedNotificationMethod")] params: ItemCompletedNotification @@ -7813,9 +7348,7 @@ class SubAgentSessionSource(BaseModel): sub_agent: Annotated[SubAgentSource, Field(alias="subAgent")] -class SessionSource( - RootModel[SessionSourceValue | CustomSessionSource | SubAgentSessionSource] -): +class SessionSource(RootModel[SessionSourceValue | CustomSessionSource | SubAgentSessionSource]): model_config = ConfigDict( populate_by_name=True, ) @@ -7829,8 +7362,7 @@ class Turn(BaseModel): completed_at: Annotated[ int | None, Field( - alias="completedAt", - description="Unix timestamp (in seconds) when the turn completed.", + alias="completedAt", description="Unix timestamp (in seconds) when the turn completed." ), ] = None duration_ms: Annotated[ @@ -7841,13 +7373,11 @@ class Turn(BaseModel): ), ] = None error: Annotated[ - TurnError | None, - Field(description="Only populated when the Turn's status is failed."), + TurnError | None, Field(description="Only populated when the Turn's status is failed.") ] = None id: str items: Annotated[ - list[ThreadItem], - Field(description="Thread items currently included in this turn payload."), + list[ThreadItem], Field(description="Thread items currently included in this turn payload.") ] items_view: Annotated[ TurnItemsView | None, @@ -7858,10 +7388,7 @@ class Turn(BaseModel): ] = "full" started_at: Annotated[ int | None, - Field( - alias="startedAt", - description="Unix timestamp (in seconds) when the turn started.", - ), + Field(alias="startedAt", description="Unix timestamp (in seconds) when the turn started."), ] = None status: TurnStatus @@ -7894,9 +7421,7 @@ class PluginShareSaveRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["plugin/share/save"], Field(title="Plugin/share/saveRequestMethod") - ] + method: Annotated[Literal["plugin/share/save"], Field(title="Plugin/share/saveRequestMethod")] params: PluginShareSaveParams @@ -7905,9 +7430,7 @@ class ConfigBatchWriteRequest(BaseModel): populate_by_name=True, ) id: RequestId - method: Annotated[ - Literal["config/batchWrite"], Field(title="Config/batchWriteRequestMethod") - ] + method: Annotated[Literal["config/batchWrite"], Field(title="Config/batchWriteRequestMethod")] params: ConfigBatchWriteParams @@ -8076,9 +7599,7 @@ class PluginDetail(BaseModel): description: str | None = None hooks: list[PluginHookSummary] marketplace_name: Annotated[str, Field(alias="marketplaceName")] - marketplace_path: Annotated[ - AbsolutePathBuf | None, Field(alias="marketplacePath") - ] = None + marketplace_path: Annotated[AbsolutePathBuf | None, Field(alias="marketplacePath")] = None mcp_servers: Annotated[list[str], Field(alias="mcpServers")] skills: list[SkillSummary] summary: PluginSummary @@ -8110,9 +7631,7 @@ class PluginShareListItem(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - local_plugin_path: Annotated[ - AbsolutePathBuf | None, Field(alias="localPluginPath") - ] = None + local_plugin_path: Annotated[AbsolutePathBuf | None, Field(alias="localPluginPath")] = None plugin: PluginSummary @@ -8150,9 +7669,7 @@ class TurnStartedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["turn/started"], Field(title="Turn/startedNotificationMethod") - ] + method: Annotated[Literal["turn/started"], Field(title="Turn/startedNotificationMethod")] params: TurnStartedNotification @@ -8160,9 +7677,7 @@ class TurnCompletedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["turn/completed"], Field(title="Turn/completedNotificationMethod") - ] + method: Annotated[Literal["turn/completed"], Field(title="Turn/completedNotificationMethod")] params: TurnCompletedNotification @@ -8207,11 +7722,7 @@ class Thread(BaseModel): ), ] = None cli_version: Annotated[ - str, - Field( - alias="cliVersion", - description="Version of the CLI that created the thread.", - ), + str, Field(alias="cliVersion", description="Version of the CLI that created the thread.") ] created_at: Annotated[ int, @@ -8220,9 +7731,7 @@ class Thread(BaseModel): description="Unix timestamp (in seconds) when the thread was created.", ), ] - cwd: Annotated[ - AbsolutePathBuf, Field(description="Working directory captured for the thread.") - ] + cwd: Annotated[AbsolutePathBuf, Field(description="Working directory captured for the thread.")] ephemeral: Annotated[ bool, Field( @@ -8251,17 +7760,10 @@ class Thread(BaseModel): description="Model provider used for this thread (for example, 'openai').", ), ] - name: Annotated[ - str | None, Field(description="Optional user-facing thread title.") - ] = None - path: Annotated[ - str | None, Field(description="[UNSTABLE] Path to the thread on disk.") - ] = None + name: Annotated[str | None, Field(description="Optional user-facing thread title.")] = None + path: Annotated[str | None, Field(description="[UNSTABLE] Path to the thread on disk.")] = None preview: Annotated[ - str, - Field( - description="Usually the first user message in the thread, if available." - ), + str, Field(description="Usually the first user message in the thread, if available.") ] session_id: Annotated[ str, @@ -8276,9 +7778,7 @@ class Thread(BaseModel): description="Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.)." ), ] - status: Annotated[ - ThreadStatus, Field(description="Current runtime status for the thread.") - ] + status: Annotated[ThreadStatus, Field(description="Current runtime status for the thread.")] thread_source: Annotated[ ThreadSource | None, Field( @@ -8323,9 +7823,7 @@ class ThreadForkResponse(BaseModel): ] = [] model: str model_provider: Annotated[str, Field(alias="modelProvider")] - reasoning_effort: Annotated[ - ReasoningEffort | None, Field(alias="reasoningEffort") - ] = None + reasoning_effort: Annotated[ReasoningEffort | None, Field(alias="reasoningEffort")] = None sandbox: Annotated[ SandboxPolicy, Field( @@ -8393,9 +7891,7 @@ class ThreadResumeResponse(BaseModel): ] = [] model: str model_provider: Annotated[str, Field(alias="modelProvider")] - reasoning_effort: Annotated[ - ReasoningEffort | None, Field(alias="reasoningEffort") - ] = None + reasoning_effort: Annotated[ReasoningEffort | None, Field(alias="reasoningEffort")] = None sandbox: Annotated[ SandboxPolicy, Field( @@ -8440,9 +7936,7 @@ class ThreadStartResponse(BaseModel): ] = [] model: str model_provider: Annotated[str, Field(alias="modelProvider")] - reasoning_effort: Annotated[ - ReasoningEffort | None, Field(alias="reasoningEffort") - ] = None + reasoning_effort: Annotated[ReasoningEffort | None, Field(alias="reasoningEffort")] = None sandbox: Annotated[ SandboxPolicy, Field( @@ -8637,9 +8131,7 @@ class ClientRequest( | ConfigRequirementsReadRequest | AccountReadRequest | FuzzyFileSearchRequest, - Field( - description="Request from the client to the server.", title="ClientRequest" - ), + Field(description="Request from the client to the server.", title="ClientRequest"), ] @@ -8647,9 +8139,7 @@ class PluginListResponse(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - featured_plugin_ids: Annotated[ - list[str] | None, Field(alias="featuredPluginIds") - ] = [] + featured_plugin_ids: Annotated[list[str] | None, Field(alias="featuredPluginIds")] = [] marketplace_load_errors: Annotated[ list[MarketplaceLoadErrorInfo] | None, Field(alias="marketplaceLoadErrors") ] = [] @@ -8660,9 +8150,7 @@ class ThreadStartedServerNotification(BaseModel): model_config = ConfigDict( populate_by_name=True, ) - method: Annotated[ - Literal["thread/started"], Field(title="Thread/startedNotificationMethod") - ] + method: Annotated[Literal["thread/started"], Field(title="Thread/startedNotificationMethod")] params: ThreadStartedNotification diff --git a/sdk/python/tests/app_server_harness.py b/sdk/python/tests/app_server_harness.py index 6fb0f608be..26fa8cf7ef 100644 --- a/sdk/python/tests/app_server_harness.py +++ b/sdk/python/tests/app_server_harness.py @@ -12,7 +12,6 @@ from typing import Any from openai_codex import AppServerConfig - Json = dict[str, Any] diff --git a/sdk/python/tests/app_server_helpers.py b/sdk/python/tests/app_server_helpers.py index e11390d527..10db00901c 100644 --- a/sdk/python/tests/app_server_helpers.py +++ b/sdk/python/tests/app_server_helpers.py @@ -11,6 +11,7 @@ from app_server_harness import ( ev_response_created, sse, ) + from openai_codex.generated.v2_all import ( AgentMessageDeltaNotification, ItemCompletedNotification, diff --git a/sdk/python/tests/test_app_server_approvals.py b/sdk/python/tests/test_app_server_approvals.py index 61e5703dd7..bc8c36a6bf 100644 --- a/sdk/python/tests/test_app_server_approvals.py +++ b/sdk/python/tests/test_app_server_approvals.py @@ -3,9 +3,10 @@ from __future__ import annotations import asyncio from app_server_harness import AppServerHarness +from app_server_helpers import response_approval_policy + from openai_codex import ApprovalMode, AsyncCodex, Codex from openai_codex.generated.v2_all import AskForApprovalValue, ThreadResumeParams -from app_server_helpers import response_approval_policy def test_thread_resume_inherits_deny_all_approval_mode(tmp_path) -> None: diff --git a/sdk/python/tests/test_app_server_inputs.py b/sdk/python/tests/test_app_server_inputs.py index 5e560062e5..56505e4817 100644 --- a/sdk/python/tests/test_app_server_inputs.py +++ b/sdk/python/tests/test_app_server_inputs.py @@ -1,9 +1,10 @@ from __future__ import annotations from app_server_harness import AppServerHarness -from openai_codex import Codex, ImageInput, LocalImageInput, SkillInput, TextInput from app_server_helpers import TINY_PNG_BYTES +from openai_codex import Codex, ImageInput, LocalImageInput, SkillInput, TextInput + def test_remote_image_input_reaches_responses_api( tmp_path, @@ -28,8 +29,7 @@ def test_remote_image_input_reaches_responses_api( assert { "final_response": result.final_response, - "contains_user_prompt": "Describe the remote image." - in request.message_input_texts("user"), + "contains_user_prompt": "Describe the remote image." in request.message_input_texts("user"), "image_urls": request.message_image_urls("user"), } == { "final_response": "remote image received", @@ -62,8 +62,7 @@ def test_local_image_input_reaches_responses_api( assert { "final_response": result.final_response, - "contains_user_prompt": "Describe the local image." - in request.message_input_texts("user"), + "contains_user_prompt": "Describe the local image." in request.message_input_texts("user"), "image_url_is_png_data_url": request.message_image_urls("user")[-1].startswith( "data:image/png;base64," ), @@ -81,9 +80,7 @@ def test_skill_input_injects_loaded_skill_body(tmp_path) -> None: with AppServerHarness(tmp_path) as harness: skill_file = harness.workspace / ".agents" / "skills" / "demo" / "SKILL.md" skill_file.parent.mkdir(parents=True) - skill_file.write_text( - f"---\nname: demo\ndescription: demo skill\n---\n\n{skill_body}\n" - ) + skill_file.write_text(f"---\nname: demo\ndescription: demo skill\n---\n\n{skill_body}\n") skill_path = skill_file.resolve() harness.responses.enqueue_assistant_message( "skill received", @@ -100,9 +97,7 @@ def test_skill_input_injects_loaded_skill_body(tmp_path) -> None: request = harness.responses.single_request() skill_blocks = [ - text - for text in request.message_input_texts("user") - if text.startswith("") + text for text in request.message_input_texts("user") if text.startswith("") ] assert { "final_response": result.final_response, diff --git a/sdk/python/tests/test_app_server_lifecycle.py b/sdk/python/tests/test_app_server_lifecycle.py index 644b97585a..0baddccc57 100644 --- a/sdk/python/tests/test_app_server_lifecycle.py +++ b/sdk/python/tests/test_app_server_lifecycle.py @@ -3,9 +3,10 @@ from __future__ import annotations import asyncio from app_server_harness import AppServerHarness -from openai_codex import AsyncCodex, Codex from app_server_helpers import request_kind +from openai_codex import AsyncCodex, Codex + def _thread_message_summary(read_response) -> list[tuple[str, str]]: """Return persisted user/agent messages from a thread read response.""" @@ -58,9 +59,7 @@ def test_thread_list_filters_archived_threads(tmp_path) -> None: expected_ids = {active_thread.id, archived_thread.id} assert { - "active_ids": sorted( - thread.id for thread in active_list.data if thread.id in expected_ids - ), + "active_ids": sorted(thread.id for thread in active_list.data if thread.id in expected_ids), "archived_ids": sorted( thread.id for thread in archived_list.data if thread.id in expected_ids ), diff --git a/sdk/python/tests/test_app_server_run.py b/sdk/python/tests/test_app_server_run.py index 8a45edf5ef..a0ac3eca16 100644 --- a/sdk/python/tests/test_app_server_run.py +++ b/sdk/python/tests/test_app_server_run.py @@ -3,7 +3,6 @@ from __future__ import annotations import asyncio import pytest - from app_server_harness import ( AppServerHarness, ev_assistant_message, @@ -13,13 +12,14 @@ from app_server_harness import ( ev_response_created, sse, ) -from openai_codex import AsyncCodex, Codex -from openai_codex.generated.v2_all import MessagePhase from app_server_helpers import ( agent_message_texts_from_items, assistant_message_with_phase, ) +from openai_codex import AsyncCodex, Codex +from openai_codex.generated.v2_all import MessagePhase + def test_sync_thread_run_uses_mock_responses( tmp_path, @@ -250,9 +250,7 @@ def test_async_run_result_uses_last_unknown_phase_message(tmp_path) -> None: ) async with AsyncCodex(config=harness.app_server_config()) as codex: - result = await (await codex.thread_start()).run( - "case: async last unknown phase" - ) + result = await (await codex.thread_start()).run("case: async last unknown phase") assert { "final_response": result.final_response, @@ -288,9 +286,7 @@ def test_async_run_result_does_not_promote_commentary_only_to_final( ) async with AsyncCodex(config=harness.app_server_config()) as codex: - result = await (await codex.thread_start()).run( - "case: async commentary only" - ) + result = await (await codex.thread_start()).run("case: async commentary only") assert { "final_response": result.final_response, diff --git a/sdk/python/tests/test_app_server_streaming.py b/sdk/python/tests/test_app_server_streaming.py index 81e2b44d30..ae217adb6a 100644 --- a/sdk/python/tests/test_app_server_streaming.py +++ b/sdk/python/tests/test_app_server_streaming.py @@ -3,12 +3,6 @@ from __future__ import annotations import asyncio from app_server_harness import AppServerHarness -from openai_codex import AsyncCodex, Codex, TextInput -from openai_codex.generated.v2_all import ( - AgentMessageDeltaNotification, - TurnCompletedNotification, - TurnStatus, -) from app_server_helpers import ( agent_message_texts, next_async_delta, @@ -16,13 +10,18 @@ from app_server_helpers import ( streaming_response, ) +from openai_codex import AsyncCodex, Codex, TextInput +from openai_codex.generated.v2_all import ( + AgentMessageDeltaNotification, + TurnCompletedNotification, + TurnStatus, +) + def test_sync_stream_routes_text_deltas_and_completion(tmp_path) -> None: """A sync turn stream should expose deltas, completed items, and completion.""" with AppServerHarness(tmp_path) as harness: - harness.responses.enqueue_sse( - streaming_response("stream-1", "msg-stream-1", ["hel", "lo"]) - ) + harness.responses.enqueue_sse(streaming_response("stream-1", "msg-stream-1", ["he", "llo"])) with Codex(config=harness.app_server_config()) as codex: thread = codex.thread_start() @@ -42,7 +41,7 @@ def test_sync_stream_routes_text_deltas_and_completion(tmp_path) -> None: if isinstance(event.payload, TurnCompletedNotification) ], } == { - "deltas": ["hel", "lo"], + "deltas": ["he", "llo"], "agent_messages": ["hello"], "completed_statuses": [TurnStatus.completed], } diff --git a/sdk/python/tests/test_app_server_turn_controls.py b/sdk/python/tests/test_app_server_turn_controls.py index 40ada74ea3..af02f6b74f 100644 --- a/sdk/python/tests/test_app_server_turn_controls.py +++ b/sdk/python/tests/test_app_server_turn_controls.py @@ -1,9 +1,10 @@ from __future__ import annotations from app_server_harness import AppServerHarness +from app_server_helpers import agent_message_texts, streaming_response + from openai_codex import Codex, TextInput from openai_codex.generated.v2_all import TurnStatus -from app_server_helpers import agent_message_texts, streaming_response def test_turn_steer_adds_follow_up_input(tmp_path) -> None: @@ -30,9 +31,7 @@ def test_turn_steer_adds_follow_up_input(tmp_path) -> None: "steered_turn_id": steer.turn_id, "turn_id": turn.id, "agent_messages": agent_message_texts(events), - "last_user_texts": [ - request.message_input_texts("user")[-1] for request in requests - ], + "last_user_texts": [request.message_input_texts("user")[-1] for request in requests], } == { "steered_turn_id": turn.id, "turn_id": turn.id, diff --git a/sdk/python/tests/test_artifact_workflow_and_binaries.py b/sdk/python/tests/test_artifact_workflow_and_binaries.py index 8cc30f06fd..4a8e4df4d1 100644 --- a/sdk/python/tests/test_artifact_workflow_and_binaries.py +++ b/sdk/python/tests/test_artifact_workflow_and_binaries.py @@ -5,12 +5,12 @@ import importlib.util import io import json import sys -import tomllib import urllib.error from pathlib import Path from typing import Sequence import pytest +import tomllib ROOT = Path(__file__).resolve().parents[1] @@ -32,9 +32,7 @@ def _load_runtime_setup_module(): runtime_setup_path = ROOT / "_runtime_setup.py" spec = importlib.util.spec_from_file_location("_runtime_setup", runtime_setup_path) if spec is None or spec.loader is None: - raise AssertionError( - f"Failed to load runtime setup module: {runtime_setup_path}" - ) + raise AssertionError(f"Failed to load runtime setup module: {runtime_setup_path}") module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) @@ -47,6 +45,40 @@ def test_generation_has_single_maintenance_entrypoint_script() -> None: assert scripts == ["update_sdk_artifacts.py"] +def test_root_fmt_recipe_formats_rust_and_python_sdk() -> None: + """The repo fmt command should work from Rust and Python SDK directories.""" + justfile = ROOT.parents[1] / "justfile" + lines = justfile.read_text().splitlines() + fmt_index = lines.index("fmt:") + next_recipe_index = next( + index + for index in range(fmt_index + 1, len(lines)) + if lines[index] and not lines[index].startswith((" ", "\t", "#")) + ) + fmt_recipe = lines[fmt_index:next_recipe_index] + actual = { + "working_directory": lines[0], + "previous_attribute": lines[fmt_index - 1], + "commands": [line.strip() for line in fmt_recipe[1:] if line.strip()], + } + expected = { + "working_directory": 'set working-directory := "codex-rs"', + "previous_attribute": "# Format Rust and Python SDK code.", + "commands": [ + "cargo fmt -- --config imports_granularity=Item 2>/dev/null", + "uv run --project ../sdk/python --extra dev ruff check --fix --fix-only ../sdk/python", + "uv run --project ../sdk/python --extra dev ruff format ../sdk/python", + ], + } + + assert actual == expected, ( + "The root `just fmt` recipe must run Rust fmt and Python SDK Ruff. " + "Fix the `fmt` recipe in `justfile`, then run `just fmt`.\n" + f"Expected: {json.dumps(expected, indent=2)}\n" + f"Actual: {json.dumps(actual, indent=2)}" + ) + + def test_generate_types_wires_all_generation_steps() -> None: """The type generation command should refresh every schema-derived artifact.""" source = (ROOT / "scripts" / "update_sdk_artifacts.py").read_text() @@ -56,8 +88,7 @@ def test_generate_types_wires_all_generation_steps() -> None: ( node for node in tree.body - if isinstance(node, ast.FunctionDef) - and node.name == "generate_types_from_schema_dir" + if isinstance(node, ast.FunctionDef) and node.name == "generate_types_from_schema_dir" ), None, ) @@ -94,8 +125,7 @@ def test_schema_normalization_only_flattens_string_literal_oneofs( flattened = [ name for name, definition in definitions.items() - if isinstance(definition, dict) - and script._flatten_string_enum_one_of(definition.copy()) + if isinstance(definition, dict) and script._flatten_string_enum_one_of(definition.copy()) ] assert flattened == [ @@ -172,8 +202,7 @@ def test_examples_readme_points_to_runtime_version_source_of_truth() -> None: def test_runtime_distribution_name_is_consistent() -> None: script = _load_update_script_module() runtime_setup = _load_runtime_setup_module() - from openai_codex import client as client_module - from openai_codex import _version + from openai_codex import _version, client as client_module assert script.SDK_DISTRIBUTION_NAME == "openai-codex" assert runtime_setup.SDK_PACKAGE_NAME == "openai-codex" @@ -232,22 +261,6 @@ def test_release_metadata_retries_without_invalid_auth( assert authorizations == ["Bearer invalid-token", None] -def test_source_sdk_package_pins_published_runtime() -> None: - """The source package metadata should pin the runtime wheel that ships schemas.""" - pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text()) - - assert { - "sdk_version": pyproject["project"]["version"], - "dependencies": pyproject["project"]["dependencies"], - } == { - "sdk_version": "0.131.0a4", - "dependencies": [ - "pydantic>=2.12", - "openai-codex-cli-bin==0.131.0a4", - ], - } - - def test_runtime_setup_uses_pep440_package_version_and_codex_release_tags() -> None: """The SDK uses PEP 440 package pins and converts only when fetching releases.""" runtime_setup = _load_runtime_setup_module() @@ -259,17 +272,12 @@ def test_runtime_setup_uses_pep440_package_version_and_codex_release_tags() -> N f"{runtime_setup.PACKAGE_NAME}=={pyproject['project']['version']}" in pyproject["project"]["dependencies"] ) - assert ( - runtime_setup._normalized_package_version("rust-v0.116.0-alpha.1") - == "0.116.0a1" - ) + assert runtime_setup._normalized_package_version("rust-v0.116.0-alpha.1") == "0.116.0a1" assert runtime_setup._release_tag("0.116.0a1") == "rust-v0.116.0-alpha.1" def test_runtime_package_is_wheel_only_and_builds_platform_specific_wheels() -> None: - pyproject = tomllib.loads( - (ROOT.parent / "python-runtime" / "pyproject.toml").read_text() - ) + pyproject = tomllib.loads((ROOT.parent / "python-runtime" / "pyproject.toml").read_text()) hook_source = (ROOT.parent / "python-runtime" / "hatch_build.py").read_text() hook_tree = ast.parse(hook_source) initialize_fn = next( @@ -411,9 +419,7 @@ def test_stage_runtime_release_copies_resource_binaries(tmp_path: Path) -> None: ) assert { - path.relative_to( - staged / "src" / "codex_cli_bin" / "bin" - ).as_posix(): path.read_text() + path.relative_to(staged / "src" / "codex_cli_bin" / "bin").as_posix(): path.read_text() for path in (staged / "src" / "codex_cli_bin" / "bin").iterdir() } == { script.runtime_binary_name(): "fake codex\n", @@ -502,9 +508,7 @@ def test_staged_sdk_and_runtime_versions_match(tmp_path: Path) -> None: sdk_pyproject = tomllib.loads((sdk_stage / "pyproject.toml").read_text()) runtime_pyproject = tomllib.loads((runtime_stage / "pyproject.toml").read_text()) - assert ( - sdk_pyproject["project"]["version"] == runtime_pyproject["project"]["version"] - ) + assert sdk_pyproject["project"]["version"] == runtime_pyproject["project"]["version"] assert sdk_pyproject["project"]["dependencies"] == [ "pydantic>=2.12", "openai-codex-cli-bin==0.116.0a1", @@ -629,9 +633,7 @@ def test_stage_runtime_stages_binary_without_type_generation(tmp_path: Path) -> script.run_command(args, ops) - assert calls == [ - "stage_runtime:0.116.0a1:musllinux_1_1_x86_64:helper,fallback-helper" - ] + assert calls == ["stage_runtime:0.116.0a1:musllinux_1_1_x86_64:helper,fallback-helper"] def test_default_runtime_is_resolved_from_installed_runtime_package( diff --git a/sdk/python/tests/test_async_client_behavior.py b/sdk/python/tests/test_async_client_behavior.py index 4e48fbbfee..662d0a2716 100644 --- a/sdk/python/tests/test_async_client_behavior.py +++ b/sdk/python/tests/test_async_client_behavior.py @@ -12,6 +12,7 @@ from openai_codex.models import Notification, UnknownNotification def test_async_client_allows_concurrent_transport_calls() -> None: """Async wrappers should offload sync calls so concurrent awaits can overlap.""" + async def scenario() -> int: """Run two blocking sync calls and report peak overlap.""" client = AsyncAppServerClient() @@ -36,6 +37,7 @@ def test_async_client_allows_concurrent_transport_calls() -> None: def test_async_client_turn_notification_methods_delegate_to_sync_client() -> None: """Async turn routing methods should preserve sync-client registration semantics.""" + async def scenario() -> tuple[list[tuple[str, str]], Notification, str]: """Record the sync-client calls made by async turn notification wrappers.""" client = AsyncAppServerClient() diff --git a/sdk/python/tests/test_client_rpc_methods.py b/sdk/python/tests/test_client_rpc_methods.py index f2c5020d55..0a11774baa 100644 --- a/sdk/python/tests/test_client_rpc_methods.py +++ b/sdk/python/tests/test_client_rpc_methods.py @@ -111,9 +111,7 @@ def test_unknown_notifications_fall_back_to_unknown_payloads() -> None: def test_invalid_notification_payload_falls_back_to_unknown() -> None: client = AppServerClient() - event = client._coerce_notification( - "thread/tokenUsage/updated", {"threadId": "missing"} - ) + event = client._coerce_notification("thread/tokenUsage/updated", {"threadId": "missing"}) assert event.method == "thread/tokenUsage/updated" assert isinstance(event.payload, UnknownNotification) diff --git a/sdk/python/tests/test_contract_generation.py b/sdk/python/tests/test_contract_generation.py index 142a68c9a0..f809d05294 100644 --- a/sdk/python/tests/test_contract_generation.py +++ b/sdk/python/tests/test_contract_generation.py @@ -31,10 +31,7 @@ def _snapshot_target(root: Path, rel_path: Path) -> dict[str, bytes] | bytes | N def _snapshot_targets(root: Path) -> dict[str, dict[str, bytes] | bytes | None]: """Capture all checked-in generated artifacts before and after regeneration.""" - return { - str(rel_path): _snapshot_target(root, rel_path) - for rel_path in GENERATED_TARGETS - } + return {str(rel_path): _snapshot_target(root, rel_path) for rel_path in GENERATED_TARGETS} def test_generated_files_are_up_to_date(): diff --git a/sdk/python/tests/test_public_api_runtime_behavior.py b/sdk/python/tests/test_public_api_runtime_behavior.py index fb52da59b3..4e79cb6104 100644 --- a/sdk/python/tests/test_public_api_runtime_behavior.py +++ b/sdk/python/tests/test_public_api_runtime_behavior.py @@ -7,13 +7,13 @@ from typing import Any import pytest import openai_codex.api as public_api_module -from openai_codex.generated.v2_all import TurnStartParams -from openai_codex.models import InitializeResponse from openai_codex.api import ( ApprovalMode, AsyncCodex, Codex, ) +from openai_codex.generated.v2_all import TurnStartParams +from openai_codex.models import InitializeResponse ROOT = Path(__file__).resolve().parents[1] @@ -129,9 +129,7 @@ def test_async_codex_initializes_only_once_under_concurrency() -> None: def _approval_mode_turn_params(approval_mode: ApprovalMode) -> TurnStartParams: """Build real generated turn params from one public approval mode.""" - approval_policy, approvals_reviewer = public_api_module._approval_mode_settings( - approval_mode - ) + approval_policy, approvals_reviewer = public_api_module._approval_mode_settings(approval_mode) return TurnStartParams( thread_id="thread-1", input=[], diff --git a/sdk/python/tests/test_public_api_signatures.py b/sdk/python/tests/test_public_api_signatures.py index f17ec5d4fc..f38c2b8c94 100644 --- a/sdk/python/tests/test_public_api_signatures.py +++ b/sdk/python/tests/test_public_api_signatures.py @@ -2,15 +2,16 @@ from __future__ import annotations import importlib.resources as resources import inspect -import tomllib from pathlib import Path from typing import Any +import tomllib + import openai_codex import openai_codex.types as public_types from openai_codex import ( - AppServerConfig, ApprovalMode, + AppServerConfig, AsyncCodex, AsyncThread, Codex, @@ -107,9 +108,7 @@ def _assert_no_any_annotations(fn: object) -> None: signature = inspect.signature(fn) for param in signature.parameters.values(): if param.annotation is Any: - raise AssertionError( - f"{fn} has public parameter typed as Any: {param.name}" - ) + raise AssertionError(f"{fn} has public parameter typed as Any: {param.name}") if signature.return_annotation is Any: raise AssertionError(f"{fn} has public return annotation typed as Any") @@ -150,9 +149,9 @@ def test_package_includes_py_typed_marker() -> None: def test_package_root_exports_only_public_api() -> None: """The package root should expose the supported SDK surface, not internals.""" assert openai_codex.__all__ == EXPECTED_ROOT_EXPORTS - assert {name: hasattr(openai_codex, name) for name in EXPECTED_ROOT_EXPORTS} == { - name: True for name in EXPECTED_ROOT_EXPORTS - } + assert {name: hasattr(openai_codex, name) for name in EXPECTED_ROOT_EXPORTS} == dict.fromkeys( + EXPECTED_ROOT_EXPORTS, True + ) assert { "AppServerClient": hasattr(openai_codex, "AppServerClient"), "AsyncAppServerClient": hasattr(openai_codex, "AsyncAppServerClient"), @@ -184,9 +183,9 @@ def test_package_star_import_matches_public_api() -> None: def test_types_module_exports_curated_public_types() -> None: """The public type module should be the supported place for app-server models.""" assert public_types.__all__ == EXPECTED_TYPES_EXPORTS - assert {name: hasattr(public_types, name) for name in EXPECTED_TYPES_EXPORTS} == { - name: True for name in EXPECTED_TYPES_EXPORTS - } + assert {name: hasattr(public_types, name) for name in EXPECTED_TYPES_EXPORTS} == dict.fromkeys( + EXPECTED_TYPES_EXPORTS, True + ) def test_types_star_import_matches_public_types() -> None: @@ -390,9 +389,9 @@ def test_new_thread_methods_default_to_auto_review() -> None: AsyncCodex.thread_start, ] - assert {fn: _keyword_default(fn, "approval_mode") for fn in funcs} == { - fn: ApprovalMode.auto_review for fn in funcs - } + assert {fn: _keyword_default(fn, "approval_mode") for fn in funcs} == dict.fromkeys( + funcs, ApprovalMode.auto_review + ) def test_existing_thread_methods_default_to_preserving_approval_settings() -> None: @@ -408,9 +407,7 @@ def test_existing_thread_methods_default_to_preserving_approval_settings() -> No AsyncThread.run, ] - assert {fn: _keyword_default(fn, "approval_mode") for fn in funcs} == { - fn: None for fn in funcs - } + assert {fn: _keyword_default(fn, "approval_mode") for fn in funcs} == dict.fromkeys(funcs) def test_lifecycle_methods_are_codex_scoped() -> None: @@ -462,6 +459,4 @@ def test_initialize_metadata_requires_non_empty_information() -> None: except RuntimeError as exc: assert "missing required metadata" in str(exc) else: - raise AssertionError( - "expected RuntimeError when initialize metadata is missing" - ) + raise AssertionError("expected RuntimeError when initialize metadata is missing") diff --git a/sdk/python/tests/test_real_app_server_integration.py b/sdk/python/tests/test_real_app_server_integration.py index 262c0289fe..292ba9632a 100644 --- a/sdk/python/tests/test_real_app_server_integration.py +++ b/sdk/python/tests/test_real_app_server_integration.py @@ -539,7 +539,9 @@ def test_real_examples_run_and_assert( assert "actions:" in out assert "Items:" in out elif folder == "13_model_select_and_turn_params": - assert "selected.model:" in out and "agent.message.params:" in out and "items.params:" in out + assert ( + "selected.model:" in out and "agent.message.params:" in out and "items.params:" in out + ) elif folder == "14_turn_controls": assert "steer.result:" in out and "steer.final.status:" in out assert "interrupt.result:" in out and "interrupt.final.status:" in out diff --git a/sdk/python/uv.lock b/sdk/python/uv.lock index 6752310310..1bec43ba56 100644 --- a/sdk/python/uv.lock +++ b/sdk/python/uv.lock @@ -302,7 +302,7 @@ requires-dist = [ { name = "openai-codex-cli-bin", specifier = "==0.131.0a4" }, { name = "pydantic", specifier = ">=2.12" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" }, - { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.11" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15.8" }, ] provides-extras = ["dev"]