Skip to content

🎨 Palette: Dynamic Reasoning Spinner#53

Open
badMade wants to merge 2 commits into
mainfrom
palette/ux-dynamic-reasoning-spinner-11951746077518678892
Open

🎨 Palette: Dynamic Reasoning Spinner#53
badMade wants to merge 2 commits into
mainfrom
palette/ux-dynamic-reasoning-spinner-11951746077518678892

Conversation

@badMade

@badMade badMade commented Apr 24, 2026

Copy link
Copy Markdown
Owner

💡 What

Added a dynamic animated 🧠 Reasoning... spinner that appears whenever the model enters an extended reasoning phase (ThinkingDelta).

🎯 Why

To clearly visually differentiate the generic waiting "Thinking" state from the active extended "Reasoning" state as requested in the TUI Enhancement Plan Phase 2.2.

♿ Accessibility / UX

  • Added clear visual distinction for extended model operation without clogging the screen with static "Thinking hidden" messages during standard queries.
  • Implemented the animation inline to prevent screen tearing or cursor jank, taking care to clear the line immediately when the Thinking block ends.

PR created automatically by Jules for task 11951746077518678892 started by @badMade

This implements Phase 2.2 of the TUI Enhancement Plan. During an extended reasoning step (`ThinkingDelta`), the standard `🦀 Thinking...` indicator is dynamically replaced by a `🧠 Reasoning...` indicator. This is animated by cycling through frames and overwriting the current line using standard ANSI escapes so it fits seamlessly into the current synchronous stream processor without changing the underlying thread/async structures.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 24, 2026 03:56
@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a distinct “Reasoning…” animated indicator during streaming thinking phases to better differentiate extended model reasoning from the generic “Thinking” state in the Rust TUI.

Changes:

  • Made Spinner configurable with pluggable frame sets and introduced REASONING_FRAMES.
  • Updated streaming handling to render an inline animated “Reasoning…” line on ThinkingDelta and clear it on block end.
  • Renamed “Thinking hidden” summaries to “Reasoning hidden” (including updating a test) and added a short palette note under .Jules/.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
rust/crates/rusty-claude-cli/src/render.rs Adds configurable spinner frames + new reasoning frame set.
rust/crates/rusty-claude-cli/src/main.rs Renders an inline animated “Reasoning…” indicator during streaming thinking deltas; updates hidden-summary wording + test.
.Jules/palette.md Documents the rationale/approach for inline streaming spinners.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

pub fn set_frames(&mut self, frames: &'static [&'static str]) {
self.frames = frames;

Copilot AI Apr 24, 2026

Copy link

Choose a reason for hiding this comment

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

set_frames accepts any slice, including an empty one (&[]). If an empty slice is set, tick() will panic due to self.frames.len() being 0 (modulo / index). Consider rejecting empty slices (e.g., return a Result, or debug_assert!(!frames.is_empty()) + keep current frames) to make the API safe.

Suggested change
self.frames = frames;
debug_assert!(!frames.is_empty(), "spinner frames must not be empty");
if !frames.is_empty() {
self.frames = frames;
}

Copilot uses AI. Check for mistakes.
Comment on lines 6526 to 6530
if !block_has_thinking_summary {
render_thinking_block_summary(out, None, false)?;
// We do NOT render the static block summary here anymore,
// we just start animating the reasoning spinner.
block_has_thinking_summary = true;
}

Copilot AI Apr 24, 2026

Copy link

Choose a reason for hiding this comment

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

This change stops printing the static summary on ThinkingDelta, but push_output_block() still renders a summary on ContentBlockStart for OutputContentBlock::Thinking (which is typically thinking: "" in streaming). That will still emit a "Reasoning (0 chars hidden)" line before the animation, which contradicts the stated goal of avoiding static thinking/hidden messages during standard queries. Consider suppressing the summary for streaming thinking blocks and relying solely on the animated line (or render a summary only at block end when the final char count is known).

Copilot uses AI. Check for mistakes.
Comment thread rust/crates/rusty-claude-cli/src/main.rs Outdated
Comment on lines +6531 to +6542
if self.emit_output {
let frame = Spinner::REASONING_FRAMES
[reasoning_frame_idx % Spinner::REASONING_FRAMES.len()];
reasoning_frame_idx += 1;

write!(
out,
"\r\x1b[2K\x1b[38;5;208m{frame} Reasoning...\x1b[0m"
)
.and_then(|()| out.flush())
.map_err(|error| RuntimeError::new(error.to_string()))?;
}

Copilot AI Apr 24, 2026

Copy link

Choose a reason for hiding this comment

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

ThinkingDelta can arrive in many small chunks; this implementation writes + flushes on every delta, which can become a high-frequency stdout flush loop and slow down streaming. Consider throttling updates (e.g., only advance/render a frame every N ms using Instant, or every N deltas) while still clearing on ContentBlockStop.

Copilot uses AI. Check for mistakes.
This implements Phase 2.2 of the TUI Enhancement Plan. During an extended reasoning step (`ThinkingDelta`), the standard static block summary is replaced with a dynamically animated `🧠 Reasoning...` spinner. The animation is performed by emitting standard ANSI escape sequences directly into the streaming `ContentBlockDelta` logic in `AnthropicRuntimeClient::consume_stream`, seamlessly rendering animation without redesigning the CLI threads.

This clearly visually differentiates the "Thinking" state from the active "Reasoning" state as requested.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@badMade badMade marked this pull request as ready for review April 26, 2026 21:38
Copilot AI review requested due to automatic review settings April 26, 2026 21:38
@badMade

badMade commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

@claude code review

@badMade

badMade commented Apr 26, 2026

Copy link
Copy Markdown
Owner Author

@codex code review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 347ea83906

ℹ️ 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".

[reasoning_frame_idx % Spinner::REASONING_FRAMES.len()];
reasoning_frame_idx += 1;

write!(out, "\r\x1b[2K\x1b[38;5;208m{frame} Reasoning...\x1b[0m")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Replace raw ANSI spinner writes with terminal-safe rendering

The new reasoning indicator in consume_stream writes raw escape sequences directly to out ("\r\x1b[2K..."), which bypasses the terminal abstraction used elsewhere (Spinner::tick via crossterm). In environments that do not interpret ANSI control codes (notably some Windows consoles or redirected logs), this will surface literal escape bytes/carriage returns and degrade output readability; using crossterm commands (or gating on ANSI capability) avoids this regression.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@copilot, make changes based on the above suggestion.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@codex, make changes based on:

@copilot, make changes based on:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

Testing

  • cargo fmt --package rusty-claude-cli (failed initially because command was run from repo root without a Cargo.toml there).
  • cargo fmt --manifest-path rust/Cargo.toml -p rusty-claude-cli
  • cargo check --manifest-path rust/Cargo.toml -p rusty-claude-cli

Committed as:

  • e505452Use crossterm commands for reasoning spinner rendering.

Also created the follow-up PR message via make_pr with title:

  • Follow-up: terminal-safe reasoning spinner rendering.

View task →

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@badMade

badMade commented Apr 30, 2026

Copy link
Copy Markdown
Owner Author

@gemini-code-assist, what are the steps and line numbers to make this fix?

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

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.

2 participants