From 136f287ebba6579790d5f2e56ef55fe73f417cf0 Mon Sep 17 00:00:00 2001 From: Claude Lin & Lay Date: Fri, 21 Aug 2026 19:13:31 +0900 Subject: [PATCH] feat(diagnostics): render the session as a real terminal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 診断面のセッション出力が制御コードの羅列になって読めない問題の修正。 原因は精度ではなく方式。従来は制御シーケンスを除去して行を追記する行指向の 扱いをしていたが、Claude Code はフルスクリーンの TUI であり、カーソル移動・ 画面消去・部分再描画・代替スクリーンバッファを前提に出力する。行の連なりでは ないため、除去して追記すると再描画の断片が積み上がるだけになる。行指向の 表示器で TUI を映そうとしていること自体が誤りだった。 xterm.js + addon-fit に置き換えた。liplus-desktop で実績のある構成で、依存も その二つに留めている。pty-data は terminal.write、キー入力は onData から write_pty、リサイズは fit + ResizeObserver から resize_pty。Ctrl+V は webview が native paste を端末へ渡さないため clipboard plugin で橋渡しする。 これに伴い、制御シーケンス除去のコードと専用キーボタン(Enter / 矢印 / Esc / Ctrl+C)を削除した。端末が直接キーを受けるため不要になった。 仕様上の位置づけを docs で明示した。却下されている設計は「アプリが CLI の出力を 解析して発言を取り出す」ものであり、端末表示はそれに当たらない。部屋に並ぶ 発言は channel notification と say_to_room からのみ来る。端末は表示器であって 情報源ではない。会話面に端末を置かないことは維持している。 従来の一文は「ターミナルエミュレータを置かない制約と衝突しない」と書いており、 出力解析の禁止と端末表示の禁止を混同しうる形だった。axis を分けて書き直した。 #24 --- README.md | 4 +- docs/0-requirements.md | 19 +++-- index.html | 24 ++---- package-lock.json | 17 ++++ package.json | 4 +- src/main.ts | 186 +++++++++++++++++++++-------------------- src/styles.css | 58 ++++--------- 7 files changed, 151 insertions(+), 161 deletions(-) diff --git a/README.md b/README.md index d9aec01..41e2c80 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,9 @@ npm run tauri dev タブの下に作業ディレクトリの入力欄があります。初回はホームディレクトリが入っているので、セッションを動かしたいディレクトリへ変更してください。この値はタブ設定として保存されます。 -「診断」を開くと、部屋ソケットの待受状態、セッションの生死、CLI の出力が確認できます。ここにはセッションへの入力欄もあります。CLI はフォルダごとに初回の信頼確認を出すため、**最初の一回はここから答える必要があります**。Enter / ↑ / ↓ / Esc / Ctrl+C のボタンも用意しています。 +「診断」を開くと、部屋ソケットの待受状態、セッションの生死、そして**起動した CLI の端末**が確認できます。端末はそのまま操作できます。CLI はフォルダごとに初回の信頼確認を出すため、最初の一回はここから答えてください。 + +この端末は表示と操作のためのものです。ここに映る内容が部屋の発言になることはありません。部屋に並ぶのは channel 経由の発言だけです。 タイトルバーでセッションを選び「セッション参加」を押すと、次の 2 つが行われます。 diff --git a/docs/0-requirements.md b/docs/0-requirements.md index 81587ff..574e9f1 100644 --- a/docs/0-requirements.md +++ b/docs/0-requirements.md @@ -152,7 +152,7 @@ liplus-desktop の `stream_parser.rs` および `spawn_stream_pty` / `spawn_stre - サーバの `.mcp.json` 登録(既存内容はマージして保持)と、成立条件を満たす CLI 起動フラグの適用 - 部屋の作法(`instructions`)の初版 - チャットルーム UI(メッセージ一覧、発言者表示、入力欄、参加者表示) -- 診断面(部屋ソケットの待受状態、セッションの生死と終了コード、CLI 出力、セッションへの入力路) +- 診断面(部屋ソケットの待受状態、セッションの生死と終了コード、CLI の端末表示と入力) - Windows CI(`npm ci` と Rust コンパイル確認)、Release 公開時の CD ### 未検証 @@ -172,9 +172,18 @@ liplus-desktop の `stream_parser.rs` および `spawn_stream_pty` / `spawn_stre 会話面とは別枠として、部屋ソケットの待受状態・セッションの生死・CLI の出力を表示する診断面を持つ。既定は折りたたみで、セッションの起動失敗や異常終了を検出したときは自動で開く。 -これは「ターミナルエミュレータを置かない」制約と衝突しない。会話面に CLI の生出力を流さないという制約は、何が発言かという axis の話であり、診断面は「部屋の下の機構が生きているか」という別の問いに答える。部屋が沈黙しているとき、その沈黙が正常な待機なのか機構の停止なのかは、会話面だけからは区別できない。 +診断面は起動した CLI をそのまま端末として表示する。CLI はフルスクリーンの TUI であり、カーソル移動・画面消去・部分再描画を前提に出力する。行指向の表示器で映すと再描画の断片が積み上がるだけになるため、端末エミュレータ(xterm.js)で描く。 -診断面はセッションへの入力路も持つ。文字入力に加えて Enter / ↑ / ↓ / Esc / Ctrl+C を送れる。 +これは却下された設計とは別のものである。区別すべき二つ: + +- **却下**: アプリが CLI の出力を解析して発言を取り出す(liplus-desktop の `stream_parser.rs` のモデル)。部屋に並ぶものの出所が channel ではなくなる。 +- **採用**: 起動した CLI をそのまま映す。解析しない。部屋のメッセージ経路には一切関与しない。 + +部屋に並ぶ発言は channel notification と `say_to_room` からのみ来る。端末は表示器であって情報源ではない。会話面(`#room`)に端末を置かないことは維持する。 + +診断面は「部屋の下の機構が生きているか」という、会話面が答えられない問いに答える。部屋が沈黙しているとき、その沈黙が正常な待機なのか機構の停止なのかは、会話面だけからは区別できない。 + +端末はセッションへの入力路でもある。キー入力はそのまま PTY へ渡り、ウィンドウのリサイズは CLI 側へ伝わる。 これも会話面とは別の axis にある。CLI はフォルダごとに初回の信頼確認を出すため、この経路が無いとどの作業ディレクトリでもセッションは起動せず、部屋が立ち上がること自体が構造的に不可能になる。 @@ -209,8 +218,8 @@ CI が実行するもの: 上流から順に確認する。各段は下流の前提であるため、順序を飛ばさない。 1. **部屋ソケットが待ち受けているか。** タイトルバーの「診断」を開き、部屋ソケットの行を見る。`127.0.0.1: で待受中` でなければ以降はすべて不成立。 -2. **セッションが生きているか。** 同じ診断のセッション行を見る。`終了(終了コード N)` なら CLI が落ちている。直下のセッション出力に理由が残る。CLI が確認プロンプトで止まっている場合は、診断面の入力路から答える。 -3. **サイドカーが接続したか。** 参加者表示にセッション名が出る。出ない場合はセッション出力に `room socket: connected as ""` があるかを見る。 +2. **セッションが生きているか。** 同じ診断のセッション行を見る。`終了(終了コード N)` なら CLI が落ちている。直下の端末に理由が残る。CLI が確認プロンプトで止まっている場合は、端末へ直接答える。 +3. **サイドカーが接続したか。** 参加者表示にセッション名が出る。出ない場合は端末に `room socket: connected as ""` があるかを見る。 4. **サイドカー単体が壊れていないか。** `npm run sidecar:test` を実行する。偽の部屋ソケットを立てて両面を駆動するため、通ればサイドカーではなくアプリ側の問題に絞れる。 5. **`.mcp.json` の登録が効いているか。** セッションの作業ディレクトリの `.mcp.json` に `liplus-chat-room` が入っているかを見る。`--mcp-config` によるファイル渡しでは channel 側が名前を解決できないため、正式登録以外の経路は成立しない。 6. **起動フラグが単独指定になっているか。** `--dangerously-load-development-channels server:liplus-chat-room` 以外に `--channels` が付いていると、同一サーバが二重登録され全体が不通になる。タブ設定に `--channels` / `--print` / `--input-format` / `--output-format` がある場合、セッション起動はエラーで止まる(黙って外すと動いたように見えるため)。 diff --git a/index.html b/index.html index 61051d1..1130c5d 100644 --- a/index.html +++ b/index.html @@ -30,9 +30,10 @@
- +