From 3446b27cdb05537868d2ef30dd7943057a33777b Mon Sep 17 00:00:00 2001 From: Lilly Luo Date: Fri, 4 Sep 2026 14:00:59 +0000 Subject: [PATCH 1/2] fix nested config items in codex app --- src/ucode/codex_config.py | 25 ++++++++++++++++--------- tests/test_codex_config.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/ucode/codex_config.py b/src/ucode/codex_config.py index 25070cce..816efb63 100644 --- a/src/ucode/codex_config.py +++ b/src/ucode/codex_config.py @@ -3,19 +3,26 @@ from __future__ import annotations import tomlkit +from tomlkit.items import Item -def _toml_value(value: str | int | float | bool | list[object] | dict[str, object]) -> str: +def _toml_item(value: object) -> Item: + """Convert nested Python values without creating regular TOML tables.""" if isinstance(value, dict): item = tomlkit.inline_table() - item.update(value) - return item.as_string() - if isinstance(value, list) and any(isinstance(entry, dict) for entry in value): - wrapper = tomlkit.inline_table() - wrapper["value"] = value - rendered = wrapper.as_string() - return rendered.removeprefix("{value = ").removesuffix("}") - return tomlkit.item(value).as_string() + for key, entry in value.items(): + item[key] = _toml_item(entry) + return item + if isinstance(value, list): + item = tomlkit.array() + for entry in value: + item.append(_toml_item(entry)) + return item + return tomlkit.item(value) + + +def _toml_value(value: str | int | float | bool | list[object] | dict[str, object]) -> str: + return _toml_item(value).as_string() def codex_config_args(config: dict) -> list[str]: diff --git a/tests/test_codex_config.py b/tests/test_codex_config.py index 445b95fb..191d71b9 100644 --- a/tests/test_codex_config.py +++ b/tests/test_codex_config.py @@ -1,5 +1,7 @@ from __future__ import annotations +import tomlkit + from ucode.agents import codex from ucode.codex_config import codex_config_args @@ -29,3 +31,30 @@ def test_layers_provider_overrides_without_replacing_user_config(self, monkeypat assert "/ai-gateway/codex/v1" in provider_override assert 'command = "' in provider_override assert '"myprof"' in provider_override + + key, rendered_provider = provider_override.split("=", 1) + parsed = tomlkit.parse(f"{key} = {rendered_provider}") + provider = parsed["model_providers"]["ucode-databricks"] + assert provider["auth"]["timeout_ms"] == 5000 + assert provider["http_headers"]["User-Agent"].startswith("ucode/0.1.0") + + def test_renders_nested_tables_inside_arrays(self): + args = codex_config_args( + { + "hooks": { + "PreToolUse": [ + { + "matcher": "Read", + "hooks": [{"type": "command", "command": "route"}], + } + ] + } + } + ) + + assert args[0] == "--config" + key, rendered_hooks = args[1].split("=", 1) + parsed = tomlkit.parse(f"{key} = {rendered_hooks}") + hook = parsed["hooks"]["PreToolUse"][0] + assert hook["matcher"] == "Read" + assert hook["hooks"][0]["command"] == "route" From 8d6d2c280d2238052f72df777bd32208980e35a5 Mon Sep 17 00:00:00 2001 From: Lilly Luo Date: Fri, 4 Sep 2026 16:45:47 +0000 Subject: [PATCH 2/2] Fix Codex config serializer typing --- src/ucode/codex_config.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ucode/codex_config.py b/src/ucode/codex_config.py index 816efb63..7e3d4eb0 100644 --- a/src/ucode/codex_config.py +++ b/src/ucode/codex_config.py @@ -5,8 +5,10 @@ import tomlkit from tomlkit.items import Item +type TomlValue = str | int | float | bool | list[TomlValue] | dict[str, TomlValue] -def _toml_item(value: object) -> Item: + +def _toml_item(value: TomlValue) -> Item: """Convert nested Python values without creating regular TOML tables.""" if isinstance(value, dict): item = tomlkit.inline_table() @@ -18,10 +20,16 @@ def _toml_item(value: object) -> Item: for entry in value: item.append(_toml_item(entry)) return item + if isinstance(value, bool): + return tomlkit.item(value) + if isinstance(value, int): + return tomlkit.item(value) + if isinstance(value, float): + return tomlkit.item(value) return tomlkit.item(value) -def _toml_value(value: str | int | float | bool | list[object] | dict[str, object]) -> str: +def _toml_value(value: TomlValue) -> str: return _toml_item(value).as_string()