Skip to content

fix(cli): buffer reasoning tokens to avoid one-token-per-line display - #3878

Merged
Re-bin merged 2 commits into
HKUDS:mainfrom
li-yazhou:fix/cli-reasoning-buffered-display
May 17, 2026
Merged

Re-bin merged 2 commits into
HKUDS:mainfrom
li-yazhou:fix/cli-reasoning-buffered-display

Conversation

@li-yazhou

Copy link
Copy Markdown
Contributor

Problem

In CLI mode, streaming reasoning tokens from models like DeepSeek-V4 are
printed one per line with a ✻ prefix, producing output like:

🐈 nanobot
✻ The
✻  user
✻  is
✻  asking
✻  me
✻  to
✻  confirm
✻  whether
✻  the
✻  nan
✻ obot
✻  agent
✻ .

This is because _print_cli_reasoning calls console.print() for every
individual delta token, and Rich's Console.print() adds a newline
each time.

Solution

Add a module-level buffer (_reasoning_buf) that accumulates incoming
reasoning deltas and only flushes to the display when:

  • A newline is encountered
  • Sentence-ending punctuation (. / ! / ? / 。 / ! / ?) is reached
  • The buffer exceeds ~60 characters

A new _flush_reasoning() helper handles the actual print, and both
the direct hook path (_cli_progress) and the bus path
(_maybe_print_interactive_progress) flush remaining content when
reasoning_end is signaled.

After

✻ The user is asking me to confirm whether the nanobot agent

Changes

  • nanobot/cli/commands.py — 3 modifications:
    1. Module-level _reasoning_buf variable
    2. _print_cli_reasoning → buffer + flush; new _flush_reasoning
    3. Handle reasoning_end in both _cli_progress and
      _maybe_print_interactive_progress

@li-yazhou

Copy link
Copy Markdown
Contributor Author

The effect before adding the buffer is shown in the image below.

image

@chengyongru chengyongru added the bug Something isn't working label May 17, 2026

@Re-bin Re-bin left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is ready to merge. The original fix addresses the CLI reasoning-token display issue, and the follow-up commit keeps the buffering state local to each CLI progress path instead of using module-level mutable state. I also added focused regression coverage for buffering until a sentence boundary and flushing on reasoning_end.

Verified locally:

  • CLI/reasoning/channel focused tests: 43 passed
  • Full pytest after installing the missing local test dependency lxml_html_clean: 3201 passed, 4 skipped

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants