# dsh-mobile-upgrade

[English](../../README.md) | [简体中文](../zh-Hans/README.md) | [繁體中文](../zh-Hant/README.md) | 日本語 | [한국어](../ko/README.md) | [Español](../es/README.md) | [Français](../fr/README.md) | [Deutsch](../de/README.md) | [Русский](../ru/README.md)

[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)（`dsh`）web プロファイルのためのモバイル UI 改善プラグイン。描画はほぼすべてホスト自身のスロットと状態シグナルを通じて行われます — レイアウトの乗っ取りも、チャット内容の DOM ポーリングもありません。いくつかのオーバーレイは意図的に固定位置の純 DOM です — 左下の接続チップ/カード、自己更新バナー、共通トースト。ホストの React ツリーが凍結しているまさにその間も生き続ける必要があるからです。

## 得られるもの

- **再起動行** — 設定 → 全般に「サービスを再起動」を追加。最初に確認し、`dsh` プロセスを再起動し、サービスが再応答したらページを自動リロードします。
- **狭い画面のドロワー** — 1024px 以下では折りたたむとサイドバー全体が画面の外へ退避し、折りたたみ時の見た目はプラグイン自身のフローティングボタンが担います。それは 56px の丸い半透明な純 DOM 要素で、サイドバーそのものではありません（旧設計はサイドバー自体をチップに縮めており、ホストの再構築やスキンの再スタイルで壊れていました）。ボタンは専用アイコンを持ちます — スタイルフックを剥いで複製したホストのクジラで、レールのマウントまでは内蔵アイコン — サイズはどのスキンにも変えられません。タップするとホストのレールに展開を促し、展開内容がマウントされ次第、全高のサイドバーをボタンの側からスライドインさせます。ドロワーが出ている間ボタンはフェードアウトし、閉じる操作（スクリム、セッション行、ドロワー上部のトグル）は同じフレームでパネルをスライドアウトさせボタンを戻します。パネルの幅は不変、スライドは transform のみで途中で固まることはなく、開いたドロワーはテーマ自身のサイドバートークンから不透明な面を合成するので、グラススキンが透過させてしまうことはありません。ボタンは左右どちらの端にもドラッグでき（位置は記憶）、ドロワーはその側から開きます。
- **スクロール可能な質問カード** — 1024px 以下では、保留中の質問が自分の選択肢を覆い隠してしまうことはなくなります。質問は専用のスクロール領域に収まるよう高さが上限付きになり、長い質問はその場でスクロールし、その下の選択肢リストは残った高さをそのまま使うため、選択肢、送信行、最小化／閉じるボタンは画面に残ったまま操作できます。短い質問はそのままの表示で、カードは引き続き内容にぴったり収まります。
- **ストーム時でも安全なリアクティビティ** — ドロワー/メニューのオブザーバーと設定ポーラーは、ストリーミングメッセージの殺到に対して上限付きのレートで反応し、ホストに到達できない間はバックオフします。再接続中にレールが再マウントされてもドロワー状態を保ってバタつかせず、ドロワーを閉じるタップは無効になったトグルに当たるのではなく、再マウントを通して再試行します — 多数のセッションが同時にストリーミングしても、開いていても閉じていても、入力が凍り付いたり、サイドバーがクリック不能になるまで痙攣したりしなくなります。
- **サブエージェントカタログのガード** — ホストはサブエージェントカタログを、リクエストごとにセッションコーパス全体を列挙して提供し（長い履歴では約1秒）、そのクライアントは選択、チップホバー、メンバーシップイベントのたびに問い合わせます。プラグインはこのリフレッシュをラップします。ライブセッションリストに子のいない親には一切問い合わせず、同じ親への再問い合わせは最大でも2.5秒に1回とし、リフレッシュの開始は間隔を空けます — サブエージェントのファンアウトが、コーパス全体のスキャンでホストを飢えさせることがなくなります。
- **クリックで開くリネージチップ** — デスクトップでは、サブエージェントチップ（「N subagents」とサブエージェントタイトルスイッチャー）は現在のホストではホバーでのみ開き、クリックには反応しません。プラグインはチップ上のクリックを、ホストがすでに理解しているホバーイベントのペアに変換します。これによりクリックでツリーを開閉できるようになります（祖先のパンくずはクリックでのナビゲートを維持します）。
- **狭い画面のヘッダーコレクター** — 1024px 以下では、セッションヘッダーのチップ（リネージ、ジョブ、プリセット）は端末より幅が広く、ホバー専用です。それらは1つのピル（`≡ タイトル · N agents · M jobs`）に折りたたまれ、タップすると全幅のシートが開きます。そこにはセッションのリネージ（各祖先はタップ可能で、それぞれの子孫数を伴う）、ファミリールートを根とするサブエージェントツリー — 行はライブセッションリストから描画され、ブランチはガードされたリフレッシュを通して必要に応じてカタログを取得します — と、このセッションのバックグラウンドジョブが並びます。デスクトップでは何も変わりません。
- **セルフアップデート** — クライアントバンドルはリビジョン単位でイミュータブルに配信されるため、スマートフォンのタブは古いビルドを何日も動かし続けることがあります。ページは、起動時のリビジョンをサーバーが現在公開しているリビジョンと比較し、ページがアイドルになってから（下書きの入力中は決して）自分自身をリロードするか、タップ可能なバナーを表示します。
- **セッションリストの描画スロットル** — ホストはアタッチされた全セッションのプロジェクション変更ごとに全値フレームを送り、実行中サブエージェントのタイミングビューはコミット済みイベントごとに変化するため、忙しいバックグラウンド群は毎秒 50〜150 フレームをページへ流し込みます。各フレームはこれまでセッションリスト全体を再描画していました（再構築は全サマリーと O(n²) のキャッシュスイープを回り、メインスレッド時間の大半を占めると測定 — ページは再読み込みまで固まっていました）。プラグインはこれらの再描画を適応的な後続インターバルに束ね、値は変更なくセッションごとのストトアへ流し続けます — バックグラウンドのストリーミングは、新規でも既存でも、どのセッションでもページを固めなくなります。
- **接続カード** — ホストの左下にある接続コントロールは、クリックしても目に見える反応がない：要求された再接続は同じ停滞したトランスポートに舞い戻り、復帰表示はクリック不能な div がタイマーで消えるだけ、狭い画面のレール/ドロワーサイドバーではそもそも描画されない。このプラグインは純 DOM のチップで左下にステータスを固定し（ホストの React ツリーが凍結していても生存）、その上に半常設のカードをポップアップする：ポインタがカード内にある間は消えず、離れれば自動で消える。カードには本当に効く二つの操作——接続サービスによる即時再接続と、ページ全体の手動リフレッシュ——が並ぶ。停滞・失敗した `/api/` リクエストも同じ場所に現れる：チップにはバッジと件数、カードにはリクエスト一覧と生存プローブ。どれだけリクエストが止まっても失敗しても、コンポーザーの横に警告が出ることはもうない。
- **機能ごとのトグル** — プラグインは 設定 → プラグイン に `dsh-mobile-upgrade` セクションを登録し、機能ごとのスイッチを提供します。

## スクリーンショット

フローティングボタン、セッションドロワー、狭い画面の設定タブ、狭い画面のヘッダーコレクター（注釈付き）：

| | |
|---|---|
| ![フローティングボタン](../../res/shot-floating-chip.png) | ![セッションドロワー](../../res/shot-drawer.png) |
| ![設定タブ](../../res/shot-settings-tabs.png) | ![ヘッダーコレクター](../../res/shot-header-collector.png) |

## インストール

```sh
dsh plugin --profile web add dsh-mobile-upgrade
```

`dsh web` を再起動し、スマートフォンで web プロファイルを開いてください。再起動行は 設定 → 全般 に、機能トグルは 設定 → プラグイン → dsh-mobile-upgrade にあります。添付ファイルはホスト自身のコンポーザー添付システムを使います。

`dsh` 0.2.0-rc.2 以降が必要です（ホスト内蔵の添付システムがこのプラグインのアップロード機能を置き換えました）。

## 設定

プラグインの設定カードは機能ごとに 1 つのスイッチを表示します（「機能トグル」参照）。`restartEnabled` は再起動ルートも制御します：

| キー | 既定値 | 意味 |
|---|---|---|
| `restartEnabled` | `true` | 再起動行とそのルートを提供する |

## 機能トグル

上記の各機能は 設定 → プラグイン → dsh-mobile-upgrade で切り替えられます（次回のページ読み込みで反映）。`localStorage` キー — `mfx-restart`、`mfx-drawer`、`mfx-net`、`mfx-questions`、`mfx-selfupdate`、`mfx-agents`、`mfx-header`、`mfx-listthrottle`, `mfx-conn` — でデバイスごとに上書きでき、値 `"0"` で無効になります。

## 既知の制限

- クライアントはホスト UI のハッシュ化された CSS クラス名（メニュー、ドロワートグル、プロバイダーエディター、セッションヘッダーのチップ）でフックしています。ホストのビルドがそれらのクラスを改名すると、プラグインが追いつくまで該当機能は縮退します。それ以外の機能には影響しません。質問カードの質問領域は、代わりにカード自身の `data-question-key` フックから特定されるため、CSS モジュールを再ハッシュするだけのホスト再ビルドでもそのまま動作し続けます。
- ヘッダーコレクターとリネージのクリックシムは、ホスト自身のデータ（ライブセッションリストとそのサブエージェントカタログ）の上に乗っています。ガードされたブランチ取得以外にリクエストを追加せず、モードがまだ読み込み中の行をタップした場合は、そのカタログが届き次第自力で完了します。
- 入力モダリティスイッチは自分でカスタマイズしたプロバイダールートにのみ書き込めます。カタログのみのルートは設計上読み取り専用です — カタログセクションを捏造するとモデルディレクトリが崩壊するためです。

## セキュリティに関する注意

プラグインの HTTP ルート（再起動、設定編集）は自身では認証を行いません — ロードされた `dsh` web サーフェスを信頼します。localhost 以外に公開する前に、UI の他の部分を守っているのと同じゲート（リバースプロキシ認証、ループバック束縛）の背後に置いてください。

## コミュニティリンク

- [Linux.Do](https://linux.do) — 技術を共有し、語り合うコミュニティ。

## ライセンス

[Synthetic Source License（SySL）Version 1.0](LICENSE) の下で配布されます。

> NOTICE: This software includes code generated by artificial intelligence. See the LICENSE file for the Synthetic Source License terms, including model disclosure requirements.
