Skip to content

feat(tui): render assistant transcript with Markdown via OpenTUI markdown component#39

Open
knqiufan wants to merge 1 commit into
stepfun-ai:mainfrom
knqiufan:feat/tui-markdown-rendering
Open

feat(tui): render assistant transcript with Markdown via OpenTUI markdown component#39
knqiufan wants to merge 1 commit into
stepfun-ai:mainfrom
knqiufan:feat/tui-markdown-rendering

Conversation

@knqiufan

@knqiufan knqiufan commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #35

The TUI transcript panel previously rendered all messages (including assistant responses) as plain text via <text> + <span>, losing all Markdown formatting — code blocks, tables, bold/italic, lists, and links were displayed as raw characters.

@opentui/react already ships a <markdown> JSX component backed by MarkdownRenderable (with marked parsing + tree-sitter syntax highlighting), but it was never used in the transcript.

Changes

  • Role-based rendering: Assistant messages now render through the <markdown> component with full Markdown support (code blocks, tables, bold/italic, lists, links). User/tool/system messages retain existing plain-text rendering unchanged.
  • Extract transcript data-building logic into src/tui/transcript-items.ts: TranscriptItem interface, buildTranscriptItems, buildWelcomeTranscriptItem, resolveTranscriptIdentity, resolveTranscriptBackground, wrapMultiline, sliceByDisplayWidth — all previously private to app.tsx, now independently importable and testable.
  • Add src/tui/transcript-syntax-style.ts: buildSyntaxStyleFromTheme() maps TUI theme colors to SyntaxStyle for code highlighting, so code blocks follow the active theme.
  • Extend TranscriptItem with content: string (raw Markdown text) and useMarkdown: boolean fields.
  • Update TranscriptEntry component: when useMarkdown is true, renders badge line + <markdown> block with table/code support; when false, keeps the original plain-text path.
  • Add 21 unit tests in src/tui/transcript-items.test.ts covering buildTranscriptItems (per-role behavior), resolveTranscriptIdentity, resolveTranscriptBackground, buildWelcomeTranscriptItem, wrapMultiline, and sliceByDisplayWidth.

Before / After

Markdown element Before After
Code blocks (```) Plain text Syntax-highlighted via tree-sitter
Tables Plain text Rendered with borders and column layout
Bold / Italic Raw ** / _ Rendered as <strong> / <em>
Links Raw URL text Rendered as clickable link
Lists / Headings No hierarchy Proper block-level rendering
Inline code No distinction Styled inline code
User/tool/system Plain text Plain text (unchanged)

Test plan

  • Run pnpm vitest run src/tui/transcript-items.test.ts — 21 new tests pass
  • Run lint, dep-guard, deadcode, tsc, prettier — all pass on this branch
  • Start TUI (step exec), send a prompt that returns Markdown with code blocks — verify syntax highlighting renders
  • Send a prompt that returns a Markdown table — verify table renders with borders
  • Send a prompt with bold/italic text — verify text modifiers render
  • Verify user input still renders as plain text (no Markdown parsing)
  • Verify tool output still renders with compact preview (truncation logic unchanged)
  • Switch themes (/theme sage, /theme default) — verify code highlighting colors update
  • Scroll through long Markdown content in transcript — verify scrollbox behavior

@ZouR-Ma

ZouR-Ma commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the contribution!

To get this ready to merge:

  • Reference an issue in the description with Closes #<number> (our link-check CI requires it; open one first if needed).
  • Make sure pnpm check passes locally (lint, type-check, dependency/dead-code guards, formatting, and tests — also enforced in CI).

Full conventions:
https://github.com/stepfun-ai/Step-Realtime-CLI/blob/main/CONTRIBUTING.md

@knqiufan

knqiufan commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @ZouR-Ma for the review guidance!

Ready for review when you have a moment.

@ZouR-Ma

ZouR-Ma commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Status update: #32 has landed on main and touched app.tsx, and since you moved buildTranscriptItems into a new module, this PR now conflicts and needs a rebase first. We still want this feature — the list before it lands is the same as before, plus a new item 0:

  1. (Must) Rebase to resolve the conflict. #32 is on main now; when you rebase, carry its hidden-entry filter (.filter((entry) => !entry.hidden)) into buildTranscriptItems in transcript-items.ts and add a matching case to the new test file.
  2. (Must) Verify and handle Markdown behavior under streaming. Transient assistant entries (local-opentui-bridge.ts:185-189) grow incrementally during streaming and now feed into <markdown streaming={false}> — a full re-parse per delta, with unterminated code fences rendering broken mid-stream. Pick one: wire the streaming prop; render in-flight entries as plain text and switch on completion; or test the long-code-block streaming scenario and post the results.
  3. (Must) Execute the seven manual test-plan items, with at least one pass on the installed step binary rather than pnpm tui:dev. The unit tests cover data building, not rendering, and the tree-sitter/Markdown assets go through the tsdown bundle — the empty-chunk incident in #25 shows that pipeline has bitten before.
  4. (Must) Reopen issue #35. It was closed ahead of time; it should stay open and be auto-closed by this PR on merge — we can flip it back on our side.

CI is green across all three platforms, so that's not a concern. We want this feature — ping us once the rebase and verification are in.

@knqiufan
knqiufan force-pushed the feat/tui-markdown-rendering branch from ac379b4 to 77350ff Compare July 17, 2026 16:58
@github-actions github-actions Bot added the area/cli src/cli, src/commands, src/runtime, src/bootstrap, src/*.ts label Jul 17, 2026
…down component

The TUI transcript panel previously rendered all messages as plain
text, losing formatting such as code blocks, tables, bold/italic,
lists, and links in assistant responses.

This commit introduces role-based rendering: assistant messages now
use the built-in markdown component from @opentui/react with
tree-sitter syntax highlighting and theme-aware styling, while
user/tool/system messages retain their existing plain-text rendering.

Key changes:
- Extract transcript data-building logic into transcript-items.ts
  (buildTranscriptItems, wrapMultiline, sliceByDisplayWidth, etc.)
- Add transcript-syntax-style.ts with buildSyntaxStyleFromTheme()
  that maps TUI theme colors to SyntaxStyle for code highlighting
- Extend TranscriptItem with content/useMarkdown fields
- Update TranscriptEntry to branch on useMarkdown: true renders
  markdown with table/code support, false keeps plain-text path
- Add 21 unit tests covering all extracted functions

Closes stepfun-ai#35
@knqiufan
knqiufan force-pushed the feat/tui-markdown-rendering branch from 77350ff to 6e3fc71 Compare July 17, 2026 17:00
@knqiufan

knqiufan commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed follow-up. I have rebased #39 onto current main (87c3445) and resolved the app.tsx conflict.

Changes made:

  • Preserved fix(tui): hide plugin-injected system reminders from transcript #32's hidden-entry filter in transcript-items.ts and added coverage for hidden entries.
  • Preserved the current collapsible tool and reasoning transcript behavior.
  • Wired Markdown streaming state from the local OpenTUI bridge: transient assistant entries use streaming mode while deltas arrive, then finalize after the assistant message (including the tool-call boundary). Added coverage for an incomplete fenced code block during streaming.

Validation:

  • pnpm check passes: 90 test files, 1,532 tests passed (24 skipped).
  • The local TUI starts successfully from this branch.

Supplementary instruction:
PR#35 The Reopen control for the current account is disabled and requires maintenance personnel to perform the operation.

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

Labels

area/cli src/cli, src/commands, src/runtime, src/bootstrap, src/*.ts area/tui src/tui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI transcript 不支持 Markdown 渲染,agent 响应中的代码块、表格、粗体等丢失格式

2 participants