Skip to content
Merged
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
10 changes: 4 additions & 6 deletions renderers/kimi_k25.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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 (
Expand Down
53 changes: 53 additions & 0 deletions tests/test_kimi_k25_tool_schema.py
Original file line number Diff line number Diff line change
@@ -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
Loading