4.7 KiB
4.7 KiB
TUI: Assistant 応答の Markdown スタイル表示
背景
LLM の出力は実質 Markdown だが、TUI は Block::AssistantText { text } を
push_padded_lines で 1 行ずつ素のテキストとして
Style(MessageKind::Assistant) に流しているだけで、**強調** /
`code` / # 見出し / - list 等の記号がそのまま見える状態になっている
(crates/tui/src/ui.rs:592-595, 640-648)。スタイルが付かないため、
構造のあるアシスタント応答は読みにくい。
ratatui 0.30 の Vec<Line<'static>> で表現できる範囲のスタイル付けで
十分目的を満たせる。既存の wrap_line_into(crates/tui/src/ui.rs:473-)が
span 単位のラップを既に実装しているため、Markdown レンダラは
スタイル付きの Vec<Line> を返すだけでよく、ラップ/スクロール/overview
畳み込みの仕組みを変える必要はない。
方針
pulldown-cmarkをtuiクレートの依存に追加し、Event ストリームを 既存のMessageKind/ratatui::style::Style体系へ畳み込む小さな 自前レンダラをcrates/tui/src/markdown.rsに置く。- レンダラの公開面は
render(text: &str, base: Style) -> Vec<Line<'static>>程度の 1 関数。Block::AssistantTextのMode::Detail/Mode::Normal描画から呼ぶ。Mode::Overviewは現行通り 1 行畳み込み(Markdown 記号 含めて表示しても情報量はほぼ同じなので素のテキストでよい)。 - ストリーミング中の不完全要素(未閉鎖の
**や開きっぱなしのフェンス) は CommonMark の流儀(テキスト扱い/EOF で閉じる)に任せる。挙動が 破綻する場合だけ末尾要素を素のテキストにフォールバックする小さな 後処理を入れる余地を残す。 tui-markdownクレートは採用しない。syntect 依存でビルドが肥大する 割にカスタマイズが効かず、本クレートの色味(MessageKindパレット)との整合を握りにくいため。
対応する Markdown 要素
最小限の "対応できる範囲" を以下に限定する。CommonMark + GFM の一部。
- 強調:
**bold**/*italic*/~~strike~~(GFM) - インラインコード:
`code` - フェンスコードブロック:
```lang/```(言語タグは無視、 ブロック全体を等幅・低彩度の背景/前景で塗る) - 見出し: H1〜H4(H5/H6 は H4 と同等)
- 箇条書きリスト:
-/*/+、ネスト可(深さ分インデント) - 順序リスト:
1./1)、ネスト可(番号は元の値で表示) - 引用:
> ...(ネスト可) - 水平線:
---/*** - リンク:
[text](url)のtextをリンク色で着色(URL は表示しない)
範囲外
- 表(GFM table)
- 画像
(テキストとしても表示しない) - HTML パススルー(タグはそのまま生テキストで出る)
- 数式(
$...$/$$...$$) - コードブロックの syntax highlighting
- リンクのターミナルクリック(OSC 8)/URL の自動表示
Thinking本文 /SystemMessageへの適用 (同じmarkdown::renderを後で差せばよい。本チケットはBlock::AssistantTextのみ)- ライブストリーム最中の "途中要素のフォールバック" の作り込み (CommonMark のデフォルト挙動で破綻が見えたら別チケット)
完了条件
- アシスタント応答に含まれる上記要素が、それぞれ視認可能な スタイルで描画される。
- ストリーミング中、テキストが追記されるたびに描画が更新され、 フェンスコードブロックの開きが先に着いて中身が後から流れる ようなケースでも、テキスト全体の見た目が大きく崩れない。
Mode::Detail/Mode::Normalで Markdown スタイルが、Mode::Overviewでは従来通りの 1 行畳み込みが出る。- 既存の
wrap_line_intoによるラップ・右パディング・スクロール が引き続き機能する(行幅計算が乱れない)。
影響範囲
crates/tui/Cargo.toml:pulldown-cmarkを追加(cargo add経由)。crates/tui/src/markdown.rs: 新設。render(&str, Style) -> Vec<Line<'static>>。crates/tui/src/ui.rs:Block::AssistantText分岐で Markdown レンダラを呼ぶ。Mode::Overviewは現行のまま。crates/tui/src/main.rsまたはlib.rs: 新モジュールの宣言。
Review
- 状態: Approve
- レビュー詳細: ./tui-assistant-markdown.review.md
- 日付: 2026-05-05