From 9e1d2c4ed727841ae8abf2db7fb2db2e1dc0133a Mon Sep 17 00:00:00 2001 From: Zafir Stojanovski Date: Tue, 19 May 2026 21:56:37 +0200 Subject: [PATCH 1/2] str(x) / repr(x) -> json.dumps(x) --- renderers/kimi_k25.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/renderers/kimi_k25.py b/renderers/kimi_k25.py index 31ee759..8a4a51e 100644 --- a/renderers/kimi_k25.py +++ b/renderers/kimi_k25.py @@ -213,7 +213,9 @@ def __init__(self, schema: dict[str, Any]): self.enum = schema["enum"] def to_typescript_style(self, indent: str = "") -> str: - return " | ".join(f'"{e}"' if isinstance(e, str) else str(e) for e in self.enum) + return " | ".join( + f'"{e}"' if isinstance(e, str) else json.dumps(e) for e in self.enum + ) class _AnyOfType(_BaseType): @@ -283,11 +285,7 @@ def __init__( def to_typescript_style(self, indent: str = "") -> str: comments = self.type_.format_docstring(indent) if self.default is not None: - default_repr = ( - json.dumps(self.default, ensure_ascii=False) - if not isinstance(self.default, (int, float, bool)) - else repr(self.default) - ) + default_repr = json.dumps(self.default, ensure_ascii=False) comments += f"{indent}// Default: {default_repr}\n" opt = "?" if self.optional else "" return ( From 36f25a6f2455897379cd23febb3bdeba7aad2532 Mon Sep 17 00:00:00 2001 From: hallerite Date: Wed, 20 May 2026 11:59:13 +0000 Subject: [PATCH 2/2] test(kimi_k25): regression test for bool/null literals in tool schema Locks in the json.dumps fix: bool defaults render as `true`/`false` and bool/null enum members render as `true`/`false`/`null` rather than Python's `True`/`False`/`None`. Co-Authored-By: Claude Opus 4.7 (1M context) --- tests/test_kimi_k25_tool_schema.py | 53 ++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/test_kimi_k25_tool_schema.py diff --git a/tests/test_kimi_k25_tool_schema.py b/tests/test_kimi_k25_tool_schema.py new file mode 100644 index 0000000..3830e18 --- /dev/null +++ b/tests/test_kimi_k25_tool_schema.py @@ -0,0 +1,53 @@ +"""Kimi K2.5 tool-schema TypeScript rendering: bool/null literal correctness. + +Regression for PR #55: ``_function_to_typescript`` used to leak Python +literals (``True`` / ``False`` / ``None``) into output advertised as +TypeScript. Both call sites — ``_EnumType.to_typescript_style`` (for +non-string enum members) and ``_TypedParam.to_typescript_style`` (for +bool defaults) — now route non-string values through ``json.dumps`` so +booleans and ``None`` render as ``true`` / ``false`` / ``null``. +""" + +from __future__ import annotations + +from renderers.kimi_k25 import _function_to_typescript + + +def test_bool_default_renders_as_json_literal(): + """Bool defaults must render as ``true`` / ``false``, not ``True`` / ``False``.""" + out = _function_to_typescript( + { + "name": "set_logging", + "parameters": { + "type": "object", + "properties": { + "verbose": {"type": "boolean", "default": True}, + "quiet": {"type": "boolean", "default": False}, + }, + }, + } + ) + assert "// Default: true" in out + assert "// Default: false" in out + assert "Default: True" not in out + assert "Default: False" not in out + + +def test_enum_non_string_members_render_as_json_literals(): + """``null`` / bool / int enum members must render as JSON literals, not Python ``repr``.""" + out = _function_to_typescript( + { + "name": "set_mode", + "parameters": { + "type": "object", + "properties": { + "mode": {"enum": ["auto", None, True, False, 0]}, + }, + }, + } + ) + assert '"auto" | null | true | false | 0' in out + # Python literals must not leak through. + assert "None" not in out + assert "True" not in out + assert "False" not in out