From 9973db57e0ab8862f488fadf86952e8f9b38bd5c Mon Sep 17 00:00:00 2001 From: yuj Date: Sat, 13 Jun 2026 11:32:05 +0800 Subject: [PATCH] fix(string): strip newlines in shorten_middle before the length check shorten_middle(remove_newline=True) is used by extract_key_argument to build a single-line summary of a tool call's key argument. It returned early when len(text) <= width *before* collapsing newlines, so any argument shorter than the width that contained a newline (e.g. a multi-line Bash command or Grep pattern) was returned with its newlines intact, breaking the single-line tool status display. Collapse newlines first, then do the length check and middle-truncation. This also makes the length check operate on the post-flattening length. Behavior with remove_newline=False is unchanged. shorten_middle was previously untested; add cases for the short-text passthrough, newline stripping in short text, remove_newline=False, and middle-ellipsis on long text. Co-Authored-By: Claude Fable 5 --- src/kimi_cli/utils/string.py | 7 +++++-- tests/utils/test_shorten.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/kimi_cli/utils/string.py b/src/kimi_cli/utils/string.py index e6fff6f7a..7d4dea807 100644 --- a/src/kimi_cli/utils/string.py +++ b/src/kimi_cli/utils/string.py @@ -28,10 +28,13 @@ def shorten(text: str, *, width: int, placeholder: str = "…") -> str: def shorten_middle(text: str, width: int, remove_newline: bool = True) -> str: """Shorten the text by inserting ellipsis in the middle.""" - if len(text) <= width: - return text + # Strip newlines first: callers rely on this to keep the result on a single + # line, and doing it before the length check ensures short multi-line inputs + # are flattened too (and that the check sees the post-flattening length). if remove_newline: text = _NEWLINE_RE.sub(" ", text) + if len(text) <= width: + return text return text[: width // 2] + "..." + text[-width // 2 :] diff --git a/tests/utils/test_shorten.py b/tests/utils/test_shorten.py index 6b35f7706..380e4a1f6 100644 --- a/tests/utils/test_shorten.py +++ b/tests/utils/test_shorten.py @@ -70,3 +70,34 @@ def test_placeholder_longer_than_cut(): result = shorten("hello", width=1, placeholder="...") assert len(result) <= 1 assert result == "h" + + +def test_shorten_middle_short_text_unchanged(): + from kimi_cli.utils.string import shorten_middle + + assert shorten_middle("hello", 50) == "hello" + + +def test_shorten_middle_strips_newlines_in_short_text(): + """remove_newline must apply even when the text is shorter than width.""" + from kimi_cli.utils.string import shorten_middle + + result = shorten_middle("ls -la\npwd\necho done", 50) + assert "\n" not in result + assert result == "ls -la pwd echo done" + + +def test_shorten_middle_can_keep_newlines(): + from kimi_cli.utils.string import shorten_middle + + result = shorten_middle("a\nb", 50, remove_newline=False) + assert result == "a\nb" + + +def test_shorten_middle_long_text_gets_ellipsis(): + from kimi_cli.utils.string import shorten_middle + + text = "x" * 100 + result = shorten_middle(text, 50) + assert "..." in result + assert result == "x" * 25 + "..." + "x" * 25