Skip to content

fix(string): strip newlines in shorten_middle before the length check#2449

Open
Ricardo-M-L wants to merge 1 commit into
MoonshotAI:mainfrom
Ricardo-M-L:fix/shorten-middle-strip-newlines-before-length
Open

fix(string): strip newlines in shorten_middle before the length check#2449
Ricardo-M-L wants to merge 1 commit into
MoonshotAI:mainfrom
Ricardo-M-L:fix/shorten-middle-strip-newlines-before-length

Conversation

@Ricardo-M-L

@Ricardo-M-L Ricardo-M-L commented Jun 13, 2026

Copy link
Copy Markdown

Problem

shorten_middle(text, width, remove_newline=True) is used by extract_key_argument to render a single-line summary of a tool call's key argument:

key_argument = shorten_middle(key_argument, width=50)

But the function returns early on short input before collapsing newlines:

def shorten_middle(text, width, remove_newline=True):
    if len(text) <= width:
        return text                       # <-- newlines never stripped here
    if remove_newline:
        text = _NEWLINE_RE.sub(" ", text)
    return text[: width // 2] + "..." + text[-width // 2 :]

So any key argument shorter than width that contains a newline — a multi-line Bash command, a Grep pattern, a multi-line SearchWeb query — is returned with its newlines intact, and the tool status line wraps across multiple lines instead of staying on one.

Reproduction (current behavior on main):

>>> shorten_middle("ls -la\npwd\necho done", 50)   # 20 chars, well under width
'ls -la\npwd\necho done'   # newlines leak into the single-line summary

Fix

Collapse newlines first, then do the length check and middle-truncation:

def shorten_middle(text, width, remove_newline=True):
    if remove_newline:
        text = _NEWLINE_RE.sub(" ", text)
    if len(text) <= width:
        return text
    return text[: width // 2] + "..." + text[-width // 2 :]

The length check now also operates on the post-flattening length, which is what actually gets displayed. Behavior with remove_newline=False is unchanged.

Tests

shorten_middle had no tests; added coverage to tests/utils/test_shorten.py:

  • short text passthrough,
  • newline stripping in short text (the bug),
  • remove_newline=False keeps newlines,
  • middle-ellipsis on long text.

Verification

$ uv run pytest tests/utils/test_shorten.py -q
13 passed

$ uv run pytest tests/tools/test_extract_key_argument.py -q   # caller, no regression
9 passed

$ uv run ruff check src/kimi_cli/utils/string.py tests/utils/test_shorten.py
All checks passed!

Open in Devin Review

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 <noreply@anthropic.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant