yoi/tickets/tui-task-display.md

7.5 KiB
Raw Blame History

TUI に Task ストア状態を表示する

背景

tickets/session-todo.md で導入した tools::TaskStoreTaskCreate / List / Get / Update ツール群は Pod 側に実装済みで、compaction や resume を跨ぐ永続化も整っている。一方で TUI 側にはまだ表示パスが無く、LLM が Task を作成・更新しても、ユーザーは tool_call ブロックを目で追う以外に状態を把握できない。

tickets/session-todo-reminder.md は LLM 側のナッジ(<system-reminder> 注入に専念しており、UI 側からのフィードバックループはスコープ外。Task ツール群を「ユーザーから見える進捗ステータス」として機能させるためには、TUI に常時見える表示が要る。

前提

  • TaskStore / TaskSnapshot / TaskEntry / TaskStatus および TaskStore::from_historytools クレートに公開済み
  • TaskStore::from_historyTaskCreate / TaskUpdate の tool_call 引数と、compact 時に挿入される [Session TaskStore snapshot] system message から決定的に状態を再構成する
  • TUI は protocol 経由で tool_call の name と最終 arguments を受信済み(ToolCallBlock { name, arguments }。system message も Block::SystemMessage として観測している
  • TUI のレイアウトは crates/tui/src/ui.rshistory / separator / status / input を縦に積む構成

方針

  • TaskStore は TUI 側で再構成する。Pod から専用 Event を push せず、すでに TUI に届いている tool_call と system message から TaskStore::from_history 相当のロジックを回す
    • protocol 表面を増やさない、Pod 側の push 経路も増やさない
    • resume / 再接続時はサーバから来る history replay 経路に乗っかれば自動で復元される
    • 単一情報源historyに揃うため、Pod と TUI で snapshot がズレない
  • TUI 上の表示は 2 ヶ所
    • history 直下のミニビュー: history と separator の間に挟む段。タスクが 1 件以上あるときだけ描画し、0 件なら領域ごと畳む。activepending + inprogress)優先で最大 2〜3 件を 状態マーク + subject 1 行ずつ、加えて件数サマリ 1 行
    • サイドペイン(全件): トグルキーで右側に開閉。pending / inprogress / completed / deleted を区別して全件列挙、description も含める
  • tools クレートには依存させない。TUI は表示専門レイヤなので、依存すると llm-worker や全ファイルツール一式まで引き込んで割に合わない。TUI 内に薄い mirrorTaskEntry / TaskStatus / 小さい TaskStore)を持ち、TaskCreate / TaskUpdate の引数 JSON と [Session TaskStore snapshot] system message を直接 parse する。snapshot のフォーマットは toolsrender_snapshot が source of truth で、resume 時に tools 自身が再 parse する契約になっているので、TUI 側もこの契約に乗る形になる。LLM コンテキスト加工原則との整合は自明history の純粋な再現変換であり context への割り込みではない)

要件

TUI 側の TaskStore 取り回し

  • App に最新 TaskStore(または TaskSnapshot)を保持するフィールドを追加する。型は TUI 内 mirrortools 依存なし)
  • 受信パスで以下を観測して TaskStore に反映する
    • ToolCall 完了時、name == "TaskCreate" / "TaskUpdate" なら argumentstools 側と同じスキーマで parse し、create / update を適用
    • SystemMessage 観測時、本文が [Session TaskStore snapshot] で始まるなら埋め込み JSON ブロックを抽出して snapshot に置き換え
  • 初回 history replay の際も同じ経路を通せば、TUI 起動時点の状態が自動的に復元される
  • 部分的引数streaming 中は適用しない。tool_call が完了して arguments が確定したタイミングだけ反映する
  • 不正な JSON や未知のフィールドは黙って無視する(toolsreplay_history と同じく落ちない)

TUI ミニビュー

  • 配置は history / mini-view / separator / status / input の縦積みhistory 直下、separator より上)
  • タスクが 1 件以上あるときだけ描画する。0 件なら領域ごと畳んで既存レイアウトと同じ高さに戻る
  • activepending + inprogress)を優先して最大 2〜3 件、状態マーク + subject を 1 行ずつ表示。subject が改行を含む場合は先頭行のみ
  • 件数サマリ 1 行(pending / inprogress / completed / deleted の内訳)

TUI サイドペイン

  • トグルキー: Ctrl-T
  • 横分割レイアウトは history 領域内で行う。status / input / separator は引き続き全幅で残し、completion popup や入力体験への影響を最小化する
  • 開いている間は全件を表示。各エントリは taskid / status / subject / description を含める
  • スクロール対応(タスク数が画面高を超えてもよい)

レイアウトと一貫性

  • ミニビューとサイドペインは同じ最新 TaskStore を見る(表示間でズレないこと)
  • 既存の history / status / input の幅・高さ計算が壊れないこと
  • completion popup@ / # / /)と表示位置が干渉しないこと

完了条件

  • LLM が TaskCreate / TaskUpdate を呼ぶと、TUI が tool_call 完了タイミングで状態を反映し、ミニビューに即時反映される
  • トグルキーでサイドペインが開閉し、completed / deleted を含む全件が確認できる
  • resume / 再接続時、history replay 経路から TaskStore が自動復元され、ミニビューとサイドペインに反映される
  • compact 後の history末尾に snapshot system messageでも、それを起点に正しく再構成される
  • ミニビュー / サイドペインの導入で既存レイアウトhistory / status / input、completion popupが崩れない

範囲外

  • protocol への新規 Event 追加。本チケットでは行わない(必要が出たら別途検討)
  • TUI からの Task 編集(追加・更新・削除)。表示専用、編集経路は LLM ツール経由のみ
  • 表示密度モードDetail / Normal / Overviewへの連動。ミニビューは常時、サイドペインはトグル制
  • LLM 側のナッジ(tickets/session-todo-reminder.md で別途実装)
  • サイドエージェント / sidechain の TaskStore 表示main Pod の TaskStore のみ対象)

参照

  • 参考実装: crates/tools/src/task.rsTaskStore::from_history / parse_compact_snapshot_text / TaskStatus / TaskEntry / render_snapshot。TUI 側はこれらを依存として取り込まず、同等のロジックを薄く再実装する
  • TUI 側受信パス: crates/tui/src/app.rsEvent::ToolCallDone / Event::SystemMessage / Event::History)、crates/tui/src/ui.rscrates/tui/src/block.rsToolCallBlock / SystemMessage
  • 設計指針: AGENTS.md「LLM コンテキストの加工原則」history からの決定的再構成は許容変換)
  • 関連チケット: tickets/session-todo.mdTask ツール本体)、tickets/session-todo-reminder.mdLLM 側ナッジ)

Review