Skip to content

fix: shorten_middle output exceeds target width by ellipsis length#2492

Open
nankingjing wants to merge 1 commit into
MoonshotAI:mainfrom
nankingjing:fix/shorten-middle-width
Open

fix: shorten_middle output exceeds target width by ellipsis length#2492
nankingjing wants to merge 1 commit into
MoonshotAI:mainfrom
nankingjing:fix/shorten-middle-width

Conversation

@nankingjing

@nankingjing nankingjing commented Jul 11, 2026

Copy link
Copy Markdown

Problem

The shorten_middle function in src/kimi_cli/utils/string.py does not account for the
3-character "..." ellipsis when computing the left and right slice widths.
This causes the output to always be longer than the requested width by up to
3 characters.

Reproducer

>>> from kimi_cli.utils.string import shorten_middle
>>> shorten_middle("abcdefghij", 1)
'...j'       # length 4, expected at most 1
>>> shorten_middle("abcdefghij", 5)
'ab...hij'   # length 8, expected at most 5
>>> shorten_middle("abcdefghij", 8)
'abcd...hij' # length 11, expected at most 8

Root cause

Line 35: text[: width // 2] + "..." + text[-width // 2 :]

  • The 3-character "..." is not subtracted from width, so the output is always
    width + 3 characters long (for width >= 3).
  • For small widths where width < 3, Python's floor division of negative numbers
    (-width // 2) gives unexpected slice indices (e.g. -1 // 2 == -1, -2 // 2 == -1),
    producing even more misleading results.

Fix

Subtract 3 from the available width before computing half-widths, and handle the
edge case where width < 3 by falling back to a plain prefix slice:

available = max(0, width - 3)
left = available // 2
right = available - left
return text[:left] + "..." + text[-right:] if right > 0 else text[:width]

Call site impact

The known caller (src/kimi_cli/tools/__init__.py:97) uses width=50, where the
current code would produce 53-character output instead of 50.

Verification

Tested locally with the same Python file:

>>> def fixed_shorten_middle(text, width, remove_newline=True):
...     if len(text) <= width:
...         return text
...     import re
...     if remove_newline:
...         text = re.sub(r"[\r\n]+", " ", text)
...     available = max(0, width - 3)
...     left = available // 2
...     right = available - left
...     return text[:left] + "..." + text[-right:] if right > 0 else text[:width]
...
>>> fixed_shorten_middle("abcdefghij", 5)
'a...j'       # length 5, within width ✅
>>> fixed_shorten_middle("abcdefghij", 1)
'a'           # length 1, within width ✅
>>> fixed_shorten_middle("abcdefghij", 8)
'ab...hij'    # length 8, within width ✅
>>> fixed_shorten_middle("abcdefghij", 50)
'abcdefghij'  # already short enough, returned as-is ✅

Open in Devin Review

The shorten_middle function does not account for the 3-character "..."
ellipsis when computing the left and right slice widths. This causes the
output to always be longer than the requested width by up to 3 characters.

For very small widths (0, 1, 2), Python's floor division of negative
numbers also produces misleading slice indices that give unexpected results.

Fix: subtract 3 from the available width before computing half-widths,
and handle the edge case where width < 3 by falling back to a plain
prefix slice.

@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 potential bugs to report.

View in Devin Review to see 1 additional finding.

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