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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/agents/extensions/experimental/codex/codex_tool.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import asyncio
import copy
import dataclasses
import inspect
import json
Expand Down Expand Up @@ -694,7 +695,7 @@ def _resolve_output_schema(
return _build_codex_output_schema(descriptor)

if isinstance(option, Mapping):
schema = dict(option)
schema = copy.deepcopy(dict(option))
if "type" in schema and schema.get("type") != "object":
raise UserError('Codex output schema must be a JSON object schema with type "object".')
return ensure_strict_json_schema(schema)
Expand Down
14 changes: 14 additions & 0 deletions tests/extensions/experiemental/codex/test_codex_tool.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import asyncio
import copy
import dataclasses
import importlib
import inspect
Expand Down Expand Up @@ -1516,6 +1517,19 @@ def test_codex_tool_resolve_output_schema_validation_errors() -> None:
codex_tool_module._resolve_output_schema({"type": "string"})


def test_codex_tool_resolve_output_schema_does_not_mutate_input() -> None:
nested = {"type": "object", "properties": {"y": {"type": "string"}}}
option = {"type": "object", "properties": {"inner": nested}}
option_snapshot = copy.deepcopy(option)

result = codex_tool_module._resolve_output_schema(option)

assert option == option_snapshot
assert nested == {"type": "object", "properties": {"y": {"type": "string"}}}
assert result is not None
assert result["properties"]["inner"] is not nested


def test_codex_tool_resolve_output_schema_descriptor() -> None:
descriptor = {
"title": "Report",
Expand Down
Loading