feat(shell): compact thinking indicator with animated dots#1857
feat(shell): compact thinking indicator with animated dots#1857
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the shell’s streaming UI to replace the previous multi-line “thinking” preview with a compact single-line indicator that still communicates progress (elapsed time, token count, and token rate), and records a concise summary line when thinking ends.
Changes:
- Replace thinking-mode rendering with a single-line
Thinkingindicator featuring animated dot frames and optional tok/s pulse. - Stop rendering raw thinking content in the live area; instead commit a one-line
Thought for Xs · N tokenstrace when the block ends. - Add release-note entries describing the updated thinking indicator in English and Chinese changelogs.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/kimi_cli/ui/shell/visualize/_blocks.py |
Implements the new compact thinking indicator animation and final summary-line behavior in _ContentBlock. |
docs/zh/release-notes/changelog.md |
Documents the shell thinking-indicator UI change in zh release notes. |
docs/en/release-notes/changelog.md |
Documents the shell thinking-indicator UI change in en release notes. |
CHANGELOG.md |
Adds the same release note entry to the top-level changelog. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| bullets; composing mode shows the dots spinner over the | ||
| uncommitted markdown tail. |
| def _compose_thinking(self) -> Text: | ||
| """Render the thinking line: italic Thinking + bullets + metadata.""" | ||
| elapsed = time.monotonic() - self._start_time | ||
| elapsed_str = format_elapsed(elapsed) | ||
| tokens_int = int(self._token_count) | ||
| count_str = f"{format_token_count(tokens_int)} tokens" | ||
| frame = _bullet_frame_for(elapsed) | ||
|
|
||
| parts: list[tuple[str, str | Style]] = [ | ||
| ("Thinking", "italic"), | ||
| (f" {frame}", "cyan"), | ||
| (f" {elapsed_str}", "grey50"), | ||
| (f" · {count_str}", "grey50"), | ||
| ] | ||
|
|
||
| # Live tok/s pulse — a real heartbeat signal that confirms the model | ||
| # is still streaming even when the raw content is hidden. | ||
| if elapsed > 0.5 and tokens_int > 0: | ||
| rate = int(tokens_int / elapsed) | ||
| if rate > 0: | ||
| parts.append((f" · {rate} tok/s", "grey50")) | ||
|
|
||
| return Text.assemble(*parts) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fe7b02437f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if rate > 0: | ||
| parts.append((f" · {rate} tok/s", "grey50")) | ||
|
|
||
| return Text.assemble(*parts) |
There was a problem hiding this comment.
Keep thinking indicator animated between stream chunks
Returning a plain Text here makes the bullet frame and tok/s pulse update only when _LiveView recomposes on new wire events; during sparse thinking streams (long gaps between chunks), Rich Live re-renders the same static text and the indicator appears frozen. This is a regression from the prior spinner-based behavior, which continued animating at refresh_per_second=10 even without incoming chunks, so users lose liveness feedback during long reasoning pauses.
Useful? React with 👍 / 👎.
|
你妈让你把 thinking 过程可视化 关了的? Did your mother ask you to turn off the visualization of your thinking process? |
Description
Streamline the thinking indicator into a compact single-line layout.
The previous multi-line preview is replaced with a
Thinkinglabel, ananimated dot sequence, elapsed time, token count, and a live tokens/second
pulse — keeping clear progress feedback in a much smaller footprint. When
the thinking block ends, a one-line
Thought for Xs · N tokenstrace iscommitted to history.
Implementation lives entirely in
_ContentBlock(
src/kimi_cli/ui/shell/visualize/_blocks.py) and only affects theis_think=Truebranch — the composing path is unchanged. The animationis driven by
time.monotonic()and frame-index modulo, with noper-frame state to maintain.