Skip to content

feat(app): add expand-last thinking display option and format markdown - #3370

Open
mcowger wants to merge 7 commits into
getpaseo:mainfrom
mcowger:feat-expand-active-thinking
Open

feat(app): add expand-last thinking display option and format markdown#3370
mcowger wants to merge 7 commits into
getpaseo:mainfrom
mcowger:feat-expand-active-thinking

Conversation

@mcowger

@mcowger mcowger commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Type of change

  • New feature
  • Enhancement

Reasoning

Users often want to monitor agent reasoning while it is actively streaming and keep the most recent thinking block visible after it completes, without having every historic block across previous turns permanently expanded. Furthermore, certain models (e.g. Codex) output bold thinking headers without separating newlines (**title1****title2**), and previously thinking blocks were rendered as raw unformatted text rather than parsed Markdown.

This PR adds an Expand Last thinking display detail option so the latest thinking block remains expanded while streaming and stays expanded once complete, collapsing older thinking blocks. It also formats thinking headers cleanly and renders thinking content as rich compact Markdown.

Goals

  • Add Expand Last option to the thinking display setting alongside Collapsed and Always expand.
  • Automatically show the latest thinking block expanded (both during and after generation) while collapsing earlier blocks when Expand Last is selected.
  • Maintain backward compatibility for existing boolean settings in storage (true -> expanded, false -> collapsed, expand_active -> expand_last).
  • Normalize adjacent or jammed thinking headers (e.g. **title1****title2** -> **title1**\n\n**title2**) without breaking inline prose markdown.
  • Render thinking content as rich Markdown in tool call details using <MarkdownRenderer compact />.
  • Update all 9 localization resources with matching keys and translations.

Non-goals

  • Altering server-side reasoning storage or wire protocol structures.

QA

  • Verified storage parsing and migration in storage.test.ts for boolean flags and enum values (collapsed, expand_last, expanded, expand_active).
  • Verified header normalization in thinking-text-formatter.test.ts across adjacent headers, numbered steps, streaming inputs, and inline bold prose.
  • Verified localization key parity across all 9 languages with resources.test.ts.
  • Ran full workspace typecheck, lint, and format.

Checklist

Screenshot 2026-08-14 at 9 53 07 AM Screenshot 2026-08-14 at 9 52 41 AM

@greptile-apps

greptile-apps Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds an Expand Last reasoning-display mode, migrates stored settings, and renders formatted reasoning as compact Markdown. The formatter’s attempted Markdown-preservation fix remains incomplete.

  • Adds collapsed, expand-last, and always-expanded thinking display choices.
  • Migrates legacy boolean and expand_active settings.
  • Formats streamed reasoning and unknown tool input before Markdown rendering.
  • Updates Markdown styling and localization resources.

Confidence Score: 3/5

The PR is not yet safe to merge because valid Markdown can still be altered in rendered reasoning and tool details.

The formatter still converts legitimate adjacent emphasized prose into separate blocks and leaves supported tilde fences and multi-backtick code spans exposed to the same normalization. Although the earlier thread was marked “Addressed,” adjacent inline emphasis is a concrete counterexample that remains in the current implementation.

Files Needing Attention: packages/app/src/utils/thinking-text-formatter.ts

Important Files Changed

Filename Overview
packages/app/src/utils/thinking-text-formatter.ts Adds Markdown normalization, but still rewrites valid adjacent emphasis and does not protect all code delimiter forms.
packages/app/src/agent-stream/view.tsx Implements latest-thought selection and applies formatting and expansion policy to thought items.
packages/app/src/components/tool-call-details.tsx Adds compact Markdown rendering and bottom-following behavior for streamed details.
packages/app/src/hooks/use-settings/storage.ts Introduces the three-state thinking-display setting with legacy-value migration.
packages/app/src/screens/settings/appearance/appearance-section.tsx Replaces the boolean reasoning switch with a localized three-option dropdown.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Model reasoning or tool input] --> B[formatThinkingText]
  B --> C[MarkdownRenderer]
  C --> D[Thinking or tool-call details]
  E[Thinking display setting] --> F[Expansion policy]
  F --> D
Loading

Reviews (7): Last reviewed commit: "Merge branch 'main' into feat-expand-act..." | Re-trigger Greptile

Comment thread packages/app/src/utils/thinking-text-formatter.ts Outdated
@mcowger mcowger changed the title feat(app): add expand-active thinking display option and format markdown feat(app): add expand-last thinking display option and format markdown Aug 14, 2026
return "";
}

// Preserve code blocks (including in-progress streaming code blocks) and inline code spans

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.

P1 Code delimiters remain unprotected

When thinking or tool text contains adjacent bold-like characters inside a tilde-fenced block or a code span using multiple backticks, the preservation regex fails to recognize the code region and inserts blank lines into it, causing the rendered content to differ from the model or tool output.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@mcowger

mcowger commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

@boudra Could you review this one?


// Separate adjacent bold blocks (e.g. **title1****title2** or **title1** **title2**)
// Also handles streaming when the second bold tag is opened: **title1****streaming...
return part.replace(/(\*\*[^*\s\n](?:[^*\n]*?[^*\s\n])?\*\*)\s*(?=\*\*)/g, "$1\n\n");

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.

P1 Adjacent emphasis becomes separate blocks

When model reasoning or tool input contains legitimate adjacent emphasized prose such as Compare **foo** **bar** before continuing., this replacement inserts a blank line between the emphasized words, causing inline prose to render as separate Markdown blocks.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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