README.ja.md

September 13, 2026 · View on GitHub

DSH Android

DSH Android

DeepSeek Harness の会話の中に、ライブで動く Android デバイスを——エミュレータでも USB 接続の実機でも、すべて adb 経由で操作。
20 個のエージェントツール • プロセス内ライブストリーム、外部ヘルパー不要 • 3 ボタンナビゲーションパネル • Gradle ビルド&実行 • Vision OCR

npm: @zseven-w/dsh-android · 現在のプラグインリリース: 0.1.0-rc.4 · DSH 0.1.1-rc.1 で動作確認済み

English · 简体中文 · 繁體中文 · 日本語 · 한국어 · Français · Español · Deutsch · Português · Русский · हिन्दी · Türkçe · ไทย · Tiếng Việt · Bahasa Indonesia


DSH Android — 会話の中のライブ Android デバイス

DSH の会話の中からストリーミングして操作する Android デバイス——中央がエージェントのツール呼び出し、右側がライブデバイスパネル

DSH Android を使う理由

DSH Android は、会話の中でエージェントに本物の Android デバイスを渡し、同時にあなたにはピクセルを渡します。エージェントはエミュレータでも USB 接続の実機でもストリームを開始し、Gradle プロジェクトをビルドしてインストールし、resource-id/テキストまたは OCR で UI を操作し、logcat を読み、プロセスとメモリを調べられます。その間、デバイスのライブ映像は常駐のサイドバーパネルに描画され、あなたは動画の上で直接タップ、ドラッグ、回転ができ、戻る / ホーム / 履歴も押せます。画像ブロックも画面録画ファイルもありません。視覚的なバイトが UI に届く経路は、DSH ウェブサーバーが提供する署名付きの短命 URL だけです。

コードパスはただ 1 本です。adb devices -l が報告する serial がデバイスの唯一の identity であり、emulator-5554 も USB の serial も ip:port のターゲットもまったく同じように振る舞います。プラグインは特定のエミュレータ製品(AVD、Genymotion、WSA、クラウドのデバイスファーム)に縛られておらず、「シミュレータか実機か」という二分法を考える必要もありません。

📱 会話の中のライブデバイスプロセス内で生成した multipart/x-mixed-replace PNG ストリームを、最新フレームのバッファから署名付き /_dsh/dsh-android/* ルート経由でそのまま配信します。
🔌 外部ストリームヘルパーなし、内部ポートなし常駐する 1 つの adb exec-out 子プロセスが while :; do screencap -p; done を実行し、連結された PNG はホスト自身がフレームに分割します。プロキシすべきループバックのストリームサーバーも、管理すべきポート範囲も、異常終了後に引き取るべきものもありません。
🧩 単一の adb コードパスadb にとってエミュレータと実機は同じものであり、このプラグインにとっても同じです。simctl/WebDriverAgent の二重スタックも、実機を使う前のビルドと信頼の儀式もありません。
🛠️ 20 個のエージェントツールデバイス一覧、起動/シャットダウン、スクリーンショット、操作、Gradle ビルド&実行、アプリの一覧/起動、uiautomator UI ツリー + 要素指定タップ、リスト/フィードの行操作、Vision OCR の検索/タップ/待機、logcat、プロセス、ANR/クラッシュのバックトレース、meminfo、アプリ情報。
👆 3 ボタンナビゲーションパネルライブ映像の上でタップとドラッグ。ツールバーには ◁ 戻る · ○ ホーム · □ 履歴、さらに回転、スクリーンショット、更新。デバイスメニューから通知シェード、クイック設定、ロック、ウェイク、アシスタントを実行できます。
🖼️ ネイティブなマルチモーダル画像入力に対応したモデルでは、キャプチャ系のツール(screenshot、interact、tap_element、tap_text、tap_row)がスクリーンショットそのものを image block として返します——モデルが画面を直接「見る」わけです。OCR はピクセル精度のテキストタップとテキスト専用の経路のために残ります。テキストのみのモデルには、これまでどおりプレーンな JSON サマリーが返ります。
🔐 署名付きのループバック専用ルートすべてのルートは、ケーパビリティを確認する前にループバックのピア、ループバックの Host(DNS リバインディングは拒否)、Fetch-Metadata/Origin チェックを要求します。HMAC-SHA256 ケーパビリティは 10 分以内に失効します。
🔍 セマンティック + ビジュアルの二系統自動化android_ui_treeuiautomator の階層をダンプし、android_tap_elementresource-id、テキスト、content-description でタップします。ツリーが空、あるいはテキストが画像に焼き込まれている場合は、座標を推測する代わりに android_find_text / android_tap_text が画面を OCR します。

ツール

20 個のツールはどのホストでも登録され、プレーンな JSON を返します——視覚的なバイトが UI に届くのは presentationMeta + 署名付きルート経由のみで、画像ブロックとしては決して届きません。adb を解決できない場合もツールは登録されたままで、呼び出しのたびに直し方を名指しする説明付きエラーで失敗します。

座標はどこでもストリームフレームの正規化 0..1 です。フレームはディスプレイの回転に追従し(横向きアプリは 1080×2400 のデバイス上で 2400×1080 として配信されます)、input tap も同じ座標空間を共有するため、このプラグインのどこにもクライアント側の回転計算は存在しません。

コアツール

ツール機能主なパラメータ
android_devicesadb devices -l が報告するすべてのデバイス(serial、状態、エミュレータ/実機、モデル、Android バージョン、API レベル、AVD 名)を列挙し、さらにマシン上の AVD 名を avds に付けて返します。他のツールが取る serial を見つけるために使います。列挙に失敗した場合は空リストではなく例外を投げます。
android_bootライブストリームを開始します。ONLINE の serial を渡せば即座にストリーミングし、AVD 名を渡せばそのエミュレータを先に起動して、起動完了後にストリーミングします(コールドスタートは数分かかります)。ストリームは会話の間ずっと維持されるので、パネルはデバイスをライブ表示し続けられます。device(必須——serial または AVD 名)
android_shutdownエミュレータをシャットダウンし(adb emu kill)、そのデバイスをストリーム中なら停止します。実機は理由付きで拒否されます。adb に電話機の電源を切る手段はありません。device
android_screenshotPNG をキャプチャし、小さな JSON サマリー(パス、バイト数、サイズ、デバイス)を返します。画像はカードとパネルに描画され、画像ブロックとしては決して返りません。device(省略可——ストリーム中のデバイス、なければ唯一オンラインのもの)
android_interactストリーム中のデバイスを操作します: 正規化 0..1 座標でのタップ、テキスト入力、ナビゲーション/ハードウェアキー(backhomerecentspowervolume_upvolume_downmenuenterdelete)の押下、スワイプジェスチャの送信、スクロール。操作が落ち着いた後(約 300 ms)に新しいスクリーンショットで効果を示します。action(必須——tap/type/button/gesture/scroll)、x/ytextnamejsondevice
android_list_appsデバイスにインストールされたパッケージ(pm list packages)を、dumpsys package のバージョン名と、解決できる場合は人間向けラベル付きで列挙します——サードパーティのパッケージ名は推測できないので、まず一覧するか、android_launch_appname を渡してください。devicequery(大文字小文字を区別しない部分一致。CJK も可)、include_system(既定 false)
android_launch_appインストール済みアプリを packageName で、または name(同じ一覧を通して解決される、大文字小文字を区別しないラベルの部分一致)で起動します。どちらか一方のみ。relaunch を付けると先にアプリを強制停止します。packageName または name(いずれか一方)、devicerelaunch
android_build_runGradle プロジェクトをビルドし(./gradlew assembleDebug)、生成された debug APK をインストールして(adb install -r)起動します。フルビルドには数分かかります。失敗時は結果に Gradle のエラー出力の末尾が含まれます。projectPath(必須)、device

UI ツリーと行ツール(uiautomator

ツール機能主なパラメータ
android_ui_treeフォアグラウンドアプリの uiautomator 階層をノードとしてダンプします——type(クラス名の末尾)、textcontentDescresourceId、ピクセル単位の boundsenabledfocused——上限は約 40 KB(最も深い階層から間引かれ、truncated が設定されます)。devicemax_depthfilter(text/content-description/resource-id に対する大文字小文字を区別しない部分一致)
android_tap_element要素を identity でタップします——resource_id はノードの resource-id に、text はテキストまたは content-description に一致します。まず完全一致、次に大文字小文字を区別しない部分一致。入れ子の重複は 1 つのターゲットにまとめられ、あいまいな場合は勝手に選ばず最大 8 件の候補を列挙します。無効な要素は拒否されます。タップは要素の中心に落ち、その約 300 ms 後のスクリーンショットが効果を示します。expect_text / expect_gone を渡せば、タップと検証が 1 往復にまとまります。deviceresource_idtextexpect_textexpect_gone
android_ui_rowsリスト/フィード画面(RecyclerView など)を生のツリーではなくとして読み取ります: 同じ形をした繰り返しの子要素が行になり、インデックス、ピクセルフレーム、集約されたラベル、そしてそのラベルから解析されたカウンター(数値 + 助数詞。日本語・中国語・英語いずれも可——アプリ固有の語彙はハードコードしません)を持ちます。カウンターのキーはそのまま往復できます: 列挙されたキーを一字一句そのまま android_tap_row.expect_count に渡してください。devicemax_depth
android_tap_row表示されている 1 行の中の相対位置をタップします(indexandroid_ui_rows から。x/y はその行のフレームに対する割合で、既定は 0.5 = 中心)。フレームは新しく読み直したツリーから取得するため絶対座標を推測せず、範囲外のインデックスはクランプせず FAIL します。expect_count={key, delta} を付けると、約 800 ms 後に行を読み直してカウンターがちょうど ±1 動いたことを検証します。未知のキーはタップが起こる前に拒否されます。deviceindex(必須)、xyexpect_count{key, delta}

OCR・ログ・デバッグツール

ツール機能主なパラメータ
android_find_textプラグインが自前でコンパイルした Vision ヘルパーで現在の画面を OCR します(accurate 認識、zh-Hans + en-US)。UI ツリーが空または退化しているとき、テキストがグラフィックとして描かれているとき(バッジの数字、画像に焼き込まれた価格)、あるいは画面の内容を独立に検証したいときに使います。{device, size, items:[{text, confidence, rect}]} を返し、rect は左上原点のピクセル矩形で、信頼度順にソートされ約 40 KB で打ち切られます。macOS ホストのみ。devicequery(大文字小文字を区別しない部分一致)、min_confidence(既定 0.3)
android_tap_text現在の画面を OCR し、最良のテキスト一致の中心をタップします——完全一致 → 部分一致 → 候補列挙という android_tap_element とまったく同じルールで、UI ツリーからは見えないテキストに使えます。一致したピクセル中心はフレームサイズで正規化されてタップとして送られ、約 300 ms 後のスクリーンショットが効果を示します。macOS ホストのみ。devicequery(必須)、min_confidenceexpect_textexpect_gone
android_wait_forテキストが現れるまたは消えるまで待機します。同じキャプチャ + OCR パイプラインを 600 ms ごとにポーリングし、条件が成立するかタイムアウトするまで続けます(既定 8 秒、最大 60 秒)。タイムアウトは正常な matched:false という答えであり、エラーではありません。macOS ホストのみ。devicetext(必須)、modeappear/disappear)、timeout_msmin_confidence
android_logsデバイスのログを読みます: snapshot(直近のウィンドウに対する logcat -d -v time、既定 2m)または followduration_seconds の間だけ有界にライブ取得。既定 10、最大 60——ぶら下がり続けるストリームには決してなりません)。bundle_id(Android のパッケージ名。pid に解決されます)で 1 つのアプリに絞り込めます。出力は約 300 行 / 30 KB で打ち切られ、絞り込みのヒントが付きます。devicemodesnapshot/follow)、durationduration_secondsbundle_idgrep
android_processesデバイスで実行中のプロセス(ps -A)を {pid, name} として列挙します——android_backtrace に渡す pid の入手元です。devicefilter(プロセス名に対する大文字小文字を区別しない部分一致)
android_backtraceプロセスに自身のスタックをダンプさせ(kill -3)、生成された ANR トレースを /data/anr/ から読み取ります。root 化されていない多くのデバイスはこのディレクトリを拒否するため、その場合はクラッシュバッファ(logcat -b crash -d)に縮退し、どのエンジンが答えたのか、何が見えていないのかを正直に報告します。devicepid または bundle_id
android_meminfodumpsys meminfo <package> を解析します: TOTAL PSS、Java/native/graphics の内訳、上位カテゴリ——リークサマリーに対する Android 側の答えです。devicebundle_id(必須)
android_app_infodumpsys package <package> から得られるインストール済みアプリの事実: バージョン名とコード、データディレクトリ、コードパス、初回インストール時刻、システムフラグ。アプリが存在しない場合は installed: falseandroid_list_apps を名指しする note を返し、例外は投げません。devicebundle_id(必須)

表示面

  • サイドバーパネル。 ライブ映像は常駐の右側パネルに表示されます(会話を押しのける固定ドック。狭いビューポートでは中央のオーバーレイ)。ライブ PNG ストリームを描画し、動画の上でのクリックでタップ、ドラッグでジェスチャを直接受け付けます。ツールバーには ◁ 戻る○ ホーム□ 履歴、回転、スクリーンショット、更新があります。デバイスメニューからはデバイスレベルの 5 つの操作(通知シェード、クイック設定、ロック、ウェイク、アシスタント)を実行できます。デバイスピッカーはすべての adb デバイスを種別ごとにグループ化したひとつのリストに並べ、オフラインの AVD はクリックで起動するのではなく android_boot を指すヒントとして表示します。サイズモードとフレームスタイル(フレームなし / ベゼル / 実機風の筐体)は iOS 版と同じように動作し、パネルはフレーム自身の自然なサイズからアスペクト比を導くため、回転に設定は不要です。
  • コンパクトな会話カード。 ツール結果はインライン画像なしの 1 行カードとして描画されます: デバイス名、アクションのサブラベル、ステータスバッジ、そして「サイドバーで開く」キュー。行をクリックするとパネルが開きます。
  • 入力欄の上のステータスカプセル。 パネルが閉じていてストリームがオンラインの間、入力欄の上に小さなピルが表示され、クリックでパネルが開きます。
  • 標準モードと Code モード。 標準セッションはホストが投影する presentationMeta を使います。ネストした Code モードのディスパッチは meta を運ばないため、クライアントは永続化された結果 JSON から同一の meta を再構築します——パネル、カード、カプセルは両方のモードで機能します。

セキュリティ

  • ブラウザが adb と通信することはなく、そもそも通信できる内部ポートが存在しません。 ストリームはこのプロセス内で生成されメモリから配信され、すべてのバイトは DSH ウェブサーバーのオリジンにあるプラグイン所有の /_dsh/dsh-android/* ルートを通ります: /stream/<token>(ライブ multipart PNG)、/screenshot/<token>(キャッシュ済み PNG)、さらに /grant/switch-device/devices/capture/status/control/device-action。これはループバックのストリームサーバーをプロキシする構成より厳密に小さい攻撃面です。
  • 三重のループバック柵を、ケーパビリティを読む前に適用します。 トランスポートのピアはループバックアドレスでなければならず、Host ヘッダーはループバックの authority を指していなければならず(したがって DNS リバインディングの Host は拒否されます)、Fetch-Metadata/Origin は同一オリジンでなければなりません。Host と Origin は呼び出し側が制御できるデータなので、それ単独で信用することは決してありません。
  • 10 分以内に失効する HMAC-SHA256 ケーパビリティ。形式は base64url(payload).base64url(mac) で、DSH ホームごとの 32 バイト鍵(<DSH_HOME>/cache/dsh-android/stream-access.key、モード 0600、原子的に作成)で署名されます。あるデバイス向けに発行されたケーパビリティは、別のデバイスがストリームスロットを取った瞬間に効かなくなり、スクリーンショット用のケーパビリティをストリームルートに再生することもできません。
  • スクリーンショットルートが配信するディレクトリはただ 1 つです。 パスは lstat でたどられ(シンボリックリンクは一切拒否)、realpath による包含チェックで締めくくられ、O_NOFOLLOW で開かれ、サイズを制限され、読み取り後に再検証されます——したがって発行から取得の間にシンボリックリンクへ差し替えられたファイルが配信されることはありません。
  • /grant は何も起動しません。 すでにオンラインのデバイスに対してフレームループを開始するだけで、他のデバイスからストリームを奪い取ることは 409 device_busy で拒否します。デバイスの切り替えには明示的な /switch-device の操作が必要で、AVD の起動は android_boot ツールの仕事のままです。
  • キープアライブとアイドル停止。 クラッシュしたフレームループはバックグラウンドで再起動します(約 5 秒の遅延)。コンシューマがゼロなら、ストリームは 5 分後に自ら停止します。意図的な停止が妨げられることはありません。

要件

  • Node ≥ 24.11.0。
  • adb(Android SDK platform-tools 付属)。解決順序は次のとおりです: ADB 環境変数 → PATH 上の adb<ANDROID_HOME>/<ANDROID_SDK_ROOT>/OS ごとの既定 SDK ルート + /platform-tools/adbsdkmanager "platform-tools"、Android Studio、または brew install --cask android-platform-tools でインストールできます。adb がなくてもプラグインはロードされ 20 個のツールも登録され、呼び出しのたびに何が足りないかを説明します。
  • デバイス 1 台: 製品を問わないエミュレータ、または USB デバッグを有効にした実機。emulator ランチャーは任意で、必要なのは「AVD 名で android_boot を呼ぶ」場合だけです——それ以外は adb から見えるデバイスであれば何でも動きます。
  • パネルには DSH ≥ 0.1.0-rc.6 と Web バンドルが必要です。ヘッドレスプロファイルでも動作します: 20 個のツールはすべて通常どおり機能し、ライブ映像だけがありません。
  • OCR には macOS ホスト(必要なのは android_find_text / android_tap_text / android_wait_for の 3 つだけ): プラグインは初回使用時に同梱の assets/ocr.swiftswiftc~/Library/Caches/dsh-android/bin/ocr にコンパイルします。Linux と Windows のホストでは、この 3 つのツールが OCR には macOS の Vision フレームワークが必要だと報告します。残りの 17 個は影響を受けません。上書き用の環境変数: DSHPLUGIN_ANDROID_OCR_DIRDSHPLUGIN_ANDROID_OCR_SWIFTDSHPLUGIN_ANDROID_SWIFTC
  • ADBKeyboard(任意。CJK と絵文字の入力用): adb shell input text は ASCII しか扱えません。デバイスに ADBKeyboard をインストールしてアクティブな IME に選ぶと、非 ASCII テキストがそのブロードキャストインターフェース経由で届きます。ない場合、非 ASCII の入力はインストールのヒント付きで拒否されます——黙って文字化けさせることは決してありません。

実機

WebDriverAgent のようにビルド・署名・信頼し、7 日ごとに再署名するものは存在しません。USB デバッグを有効にし、電話機を接続し、デバイス上の認可プロンプトを承認すれば、android_devices に現れてすべてのツールがそのまま使えます。未認可のデバイスは謎の失敗ではなく、プロンプトのヒント付きでそのように報告されます。

正直に伝えるべき制約が 3 つあります:

  • USB ではフレームレートが下がります——実機で概ね 2–5 fps、エミュレータで 5–10 fps。すべてのフレームがフル PNG のまま USB リンクを渡るためです。
  • CJK の入力には ADBKeyboard が必要です(上記参照)。これはエミュレータでも実機でも同じです。
  • android_shutdown は電話機の電源を切れません。 adb にその動詞はないので、ツールはできるふりをせずそう言います。

パフォーマンス

エミュレータでの実測値(Android 14、1080×2400):

常駐 screencap ループ≈ 8 fps
ensureStreaming の初回フレーム~200 ms
input tap の往復~130 ms

この数字を支えているのは常駐する 1 つの子プロセスです。フレームごとに adb を spawn すると、ピクセルが動き出す前に ~50–100 ms を失います。エミュレータで ~5–10 fps、USB 接続の実機で ~2–5 fps を、マシンと画面密度に応じて見込んでください。

DSH にインストール

dsh plugin --profile web add @zseven-w/dsh-android@latest
dsh web

あるいは既存のプロファイルパッケージの依存関係として追加します:

pnpm add @zseven-w/dsh-android

クイックスタート

  1. デバイスを探す——「Android デバイスを一覧表示して。」 → android_devices
  2. ストリームを開始——「emulator-5554 をストリーミングして。」 → android_boot。パネルが開き、デバイスがライブ表示されます。(AVD 名を渡すとそのエミュレータを先に起動します。)
  3. 動画の上でタップ——パネル上で直接タップまたはドラッグするか、エージェントに操作させます: 「設定を開いて、ディスプレイをタップして。」 → android_interact、identity ベースのタップなら android_ui_tree + android_tap_element、ツリーが見えないときは android_find_text + android_tap_text
  4. アプリをビルドして実行——「/path/to/MyApp をビルドして実行して。」 → android_build_run。Gradle のフルビルドには数分かかります。完了するとアプリが起動し、パネルでライブに確認できます。
  5. ログを読む——「com.example.app の直近 2 分の logcat を見せて。」 → android_logs

トラブルシューティング

  • すべてのツールが adb を利用できないと言う——エラーが 3 段階の解決順序を名指しします。ADB=/path/to/adb を設定するか、adbPATH に置くか、SDK platform-tools をインストールしてください(sdkmanager "platform-tools")。
  • デバイスが unauthorized——デバイスの画面で USB デバッグの認可プロンプトを承認してください。android_devices はデバイスを隠さず、状態を正直に報告します。
  • android_boot が AVD を見つけられない——emulator ランチャーが見つからなかったということです。手段は問わずエミュレータを起動してください。adb が認識した時点で android_devices に現れ、android_boot はその serial を取ります。
  • 非 ASCII のテキストが拒否される——ADBKeyboard をインストールして入力メソッドに選んでください(要件を参照)。この拒否は意図的です: input text は該当文字を黙って落とすか壊してしまいます。
  • android_find_text が OCR を利用できないと言う——OCR には macOS ホスト(Apple の Vision フレームワーク)が必要です。OCR 以外の 17 個のツールはどこでも動きます。
  • ストリームが勝手に止まる——それはクラッシュではなくアイドルポリシーです。コンシューマがゼロ(パネルが閉じている、カードがマウントされていない、アクティブなルートがない)になるとストリームは 5 分後に停止し、次のツール呼び出しやパネルを開く操作で再開します。クラッシュしたループは約 5 秒以内に自ら再起動します。
  • ランチャーで回転がおかしい——ランチャーや設定アプリは自身を縦向きに固定し、user_rotation を無視します。これはプラグインのバグではなく Android の正常な挙動です。回転を許可しているアプリの中で試してください。

開発

pnpm install
pnpm run build      # ホストの tsc + クライアントバンドル → lib/
pnpm run typecheck
pnpm test           # すべての静的スイート。デバイス不要

scripts/ のスモークスイートはビルド済みの lib/ を検証します。デバイスが必要でデバイスがなければ SKIP(終了コード 0)を報告する dev-emulator-smoke.mjs を除き、すべて静的です。

スクリプトカバー内容
node scripts/dev-adb-smoke.mjsシムのバイナリに対する adb の解決(env / PATH / SDK)、devices -l のパース、バイナリセーフな exec-out、PNG フレーム分割器とその再同期、input text のエスケープ、そして偽のツールチェーンに対するホストのライフサイクル(ストリーム、制御、アイドル停止、破棄)。
node scripts/dev-routes-static-smoke.mjs偽ホストに対する署名付きルート: 相対 grant、失効/偽造/種別違いのトークン、ループバック柵、405/415/400 のエンベロープ、コード化されたデバイス拒否、/control の検証、rotate の形状、スクリーンショットの封じ込め、ライブ multipart ストリーム。
node scripts/dev-tools-smoke.mjscreateAndroidTools の継ぎ目を通した、偽ホストに対するコアツール。
node scripts/dev-uitree-smoke.mjsUI ツリーと行ツール: uiautomator XML のパース、セレクタ、深さの上限、行とカウンターのヒューリスティック。
node scripts/dev-logs-smoke.mjsandroid_logs の snapshot/follow、フィルタ、上限、プロセスの回収。
node scripts/dev-panel-smoke.mjsパネルのコンポーネント、サイズモード、フレームスタイル、ドック/トリガー/カプセルのロジック(SSR のみ)。
node scripts/dev-emulator-smoke.mjs [serial]実デバイス: 初回フレーム、持続フレームレート、タップの往復、破棄。

追加のトラブルシューティング

エミュレータで画面が真っ白/真っ黒になる

android_ui_tree は実際の UI 要素を見えているのに、パネルが真っ白(または真っ黒)の 画像をストリーミングする場合、そのマシンではエミュレータのホスト GPU フレームバッファ 読み戻しが壊れています(一部の macOS ホストで知られる gfxstream の問題です—— screencap 自体が空白フレームを返すため、画面系のツールはすべて影響を受けます)。 ソフトウェアレンダリングでエミュレータを起動し直してください:

emulator -avd <name> -gpu swiftshader_indirect

または AVD の config.inihw.gpu.mode=swiftshader_indirect を設定します。実機が 影響を受けることはありません。

ロードマップ

  • より高フレームレートのソース。 StreamSource の継ぎ目は意図的に差し替え可能にしてあります: scrcpy-server + WebCodecs の H.264 経路なら、ルートもツールもパネルも触らずにフレームごとの PNG ストリームを置き換えられます。
  • Compose プレビューのホットリロード。 iOS 版は SwiftUI のプレビューを dylib としてホットスワップしますが、Compose には今日それに相当するホットスワップのプリミティブがありません。そのため、これは出荷済みで不安定な機能ではなく将来の項目にとどめています。

エコシステム

  • DSH iOS Simulator — iOS シミュレータと USB 接続の iPhone に向けた同じアーキテクチャ
  • DSH Crew — Claude Code / Codex から DSH エージェントに作業を委譲
  • DSH Noema — DSH の長期記憶
  • DSH OpenPencil — 会話の中で .op デザイン文書を閲覧・編集

クレジットとライセンス

  • Android SDK platform-toolsadb)—— 実行時に解決し、再配布は一切しません: Google の SDK ライセンスは同梱を認めていません。
  • ADBKeyboard —— Senzhk —— 非 ASCII 入力を支える任意のデバイス側 IME(Apache-2.0。同梱していません)。
  • アーキテクチャとルートのセキュリティ姿勢は dsh-ios と共有しており、本プラグインはそこから移植されました。
  • 完全な通知は THIRD_PARTY_NOTICES.md を参照してください。

ライセンス: MIT