Skip to content

feat(coding-agent): render Mermaid diagrams inline in the terminal - #1893

Merged
xeophon merged 8 commits into
mainfrom
snimu/inline-mermaid
Aug 30, 2026
Merged

feat(coding-agent): render Mermaid diagrams inline in the terminal#1893
xeophon merged 8 commits into
mainfrom
snimu/inline-mermaid

Conversation

@snimu

@snimu snimu commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Renders top-level ```mermaid code blocks in assistant messages as inline Unicode diagrams in the terminal, controlled by a new "Mermaid diagrams" setting (off / `final` / `streaming`, default `streaming`).

How it works

  • packages/tui Markdown gains an optional transform(markdown, availableWidth) hook (+13/-2, no behavior change when unset). This is the one place the exact content width is known, which the renderer needs for its too-wide fallback; the render cache is keyed on (text, width), so resizes re-run the transform.
  • mermaid.ts ports the renderer from upstream pi-mono near-verbatim: lex with marked, render mermaid blocks with grok-mermaid, theme the spans (border/text/edge/label/title), and re-emit each diagram row as a backtick-fenced code span joined by markdown hard breaks. The backtick-fencing logic handles backticks inside diagram labels; diagrams wider than the available width fall back to the raw code block; renderer warnings append a themed note on final (non-streaming) render only.
  • One transform instance is created in interactive mode, reading the mode live from the settings manager, and passed to assistant message components at both construction sites. Thinking blocks are excluded structurally: their Markdown children are constructed without the transform (collapsed thinking has no Markdown child at all).
  • Streaming semantics: off never transforms, final only once the message settles, streaming also during streaming. The streaming flag rides the existing reconcile signature, so the streaming-to-final transition rebuilds and emits warning lines exactly once. message_end (including aborted/error stops) and the agent_end safety net both settle the flag; session replay renders as final.
  • grok-mermaid is pinned exactly (0.2.3): its rendered output has changed observably within a patch line, and this repo's tests assert on that output.

Tests

16 tests in test/mermaid.test.ts: the ported upstream transformer suite (mode gating, unsupported/oversized fallback, theme span mapping, streaming partial render, warning fallback and summarization) plus component-level coverage for the integration seam: thinking exclusion, final-mode deferral until message_end driven through the real event handler, exact-fit width boundary, backtick-label preservation, and warning lines appearing only on the final update.

Linear: ENG-5673


Note

Low Risk
Display-only markdown rendering and a new user preference; no auth or data-path changes, with graceful fallback to raw code blocks when diagrams are too wide or fail to render.

Overview
Adds inline Unicode Mermaid diagrams in assistant message text via a new grok-mermaid dependency and a markdown.mermaid setting (off / final / streaming, default streaming).

packages/tui Markdown now accepts an optional transform(markdown, availableWidth) hook so callers can rewrite source before parse/render (used for width-aware diagram fallback). The coding agent wires createMermaidMarkdownTransform into AssistantMessageComponent for text blocks only; isStreaming is threaded through updates and the reconcile signature so final mode waits until the message settles before replacing ```mermaid blocks.

Interactive settings expose Mermaid diagrams; changing the mode invalidates chat rendering. SettingsManager gains get/set for the mode and drops invalid non-object markdown config on load.

Reviewed by Cursor Bugbot for commit 8ea550d. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Render Mermaid diagrams inline in terminal via grok-mermaid

  • Adds a new createMermaidMarkdownTransform factory in mermaid.ts that detects top-level Mermaid code blocks in assistant markdown and replaces them with Unicode diagrams using the grok-mermaid dependency, applying per-span theming and width-aware fitting.
  • Introduces a markdown.mermaid setting with three modes: off, final (render only after streaming completes), and streaming (default). The settings UI in settings-selector.ts exposes a selector; changing the mode invalidates and re-renders existing chat content.
  • Adds an optional transform(markdown, availableWidth) hook to MarkdownOptions in markdown.ts so callers can rewrite source markdown before parsing, with awareness of the exact content width.
  • AssistantMessageComponent now accepts a mermaidTransform and re-renders on streaming-to-final transitions via computeSignature; InteractiveMode passes isStreaming flags through updateContent so final mode defers rendering until message_end.
  • Risk: SettingsManager normalization now deletes markdown values that are not objects; existing configs with a non-object markdown field will lose that field silently on next save.

Macroscope summarized 8ea550d.

snimu added 3 commits August 29, 2026 11:57
…rams

Ports pi-mono's Mermaid rendering (grok-mermaid) into prime-agent:
- pi-tui Markdown gains an options.transform hook that rewrites source
  Markdown with the exact content width before parsing (ported from
  upstream pi-tui).
- New mermaid.ts transform replaces top-level mermaid code blocks with
  themed Unicode diagrams, falls back to the raw block when the diagram
  is wider than the message, and appends a themed warning line for
  partially rendered final diagrams.
- AssistantMessageComponent applies the transform to text blocks only
  (never thinking blocks) and tracks streaming state so the
  streaming-to-final transition re-renders.
- New markdown.mermaid setting (off/final/streaming, default streaming)
  with a settings-selector entry.

Linear: ENG-5673
Adversarial review mutation testing found three surviving mutants:
- width guard flipped to >= (exact-fit diagrams would fall back)
- codeSpan fence reduced to a single backtick (backtick labels break)
- isStreaming inverted at the message_end call site (final mode never renders)

Adds an exact-width boundary test, a backtick-label test, and a
handleEvent-level final-mode transition test that kill them.
Comment thread packages/coding-agent/src/core/settings-manager.ts
Comment thread packages/coding-agent/src/core/settings-manager.ts

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 15d9ace. Configure here.

Comment thread packages/coding-agent/src/modes/interactive/components/mermaid.ts
snimu added 5 commits August 29, 2026 12:29
Normalize a malformed markdown settings value at the migration boundary
(mirroring the telemetry handling) so changing the Mermaid mode cannot
throw, and add the missing tui changelog fragment.
@snimu
snimu requested a review from xeophon August 30, 2026 12:52
@xeophon
xeophon merged commit c382f09 into main Aug 30, 2026
23 checks passed
@xeophon
xeophon deleted the snimu/inline-mermaid branch August 30, 2026 15:18
PR9000 pushed a commit to PR9000/prime-agent that referenced this pull request Sep 1, 2026
…rimeIntellect-ai#1893)

* feat(coding-agent): render Mermaid code blocks as inline Unicode diagrams

Ports pi-mono's Mermaid rendering (grok-mermaid) into prime-agent:
- pi-tui Markdown gains an options.transform hook that rewrites source
  Markdown with the exact content width before parsing (ported from
  upstream pi-tui).
- New mermaid.ts transform replaces top-level mermaid code blocks with
  themed Unicode diagrams, falls back to the raw block when the diagram
  is wider than the message, and appends a themed warning line for
  partially rendered final diagrams.
- AssistantMessageComponent applies the transform to text blocks only
  (never thinking blocks) and tracks streaming state so the
  streaming-to-final transition re-renders.
- New markdown.mermaid setting (off/final/streaming, default streaming)
  with a settings-selector entry.

Linear: ENG-5673

* test(coding-agent): kill mermaid mutation survivors

Adversarial review mutation testing found three surviving mutants:
- width guard flipped to >= (exact-fit diagrams would fall back)
- codeSpan fence reduced to a single backtick (backtick labels break)
- isStreaming inverted at the message_end call site (final mode never renders)

Adds an exact-width boundary test, a backtick-label test, and a
handleEvent-level final-mode transition test that kill them.

* build(coding-agent): pin grok-mermaid exactly for renderer-output stability

* test(coding-agent): collapse redundant mermaid coverage

* docs(coding-agent): tighten mermaid comments

* fix(coding-agent): tolerate non-object markdown settings values

Normalize a malformed markdown settings value at the migration boundary
(mirroring the telemetry handling) so changing the Mermaid mode cannot
throw, and add the missing tui changelog fragment.

* test(coding-agent): drop mermaid.test.ts

* chore(coding-agent): one-line mermaid codeSpan comments
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