README.id.md

September 13, 2026 · View on GitHub

DSH Android

DSH Android

Perangkat Android langsung di dalam percakapan DeepSeek Harness — emulator atau ponsel USB, digerakkan sepenuhnya melalui adb.
20 alat agen • aliran langsung dalam proses, tanpa helper eksternal • panel navigasi tiga tombol • build & jalankan Gradle • Vision OCR

npm: @zseven-w/dsh-android · Rilis plugin saat ini: 0.1.0-rc.4 · Diuji dengan 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 — perangkat Android langsung di dalam percakapan

Perangkat Android yang dialirkan dan dikendalikan dari dalam percakapan DSH — panggilan alat agen di tengah, panel perangkat langsung di kanan

Mengapa DSH Android

DSH Android memberi agen perangkat Android sungguhan di dalam percakapan — dan memberi Anda pikselnya. Agen dapat memulai aliran pada emulator atau ponsel yang terhubung USB, membangun dan memasang proyek Gradle, menggerakkan UI lewat resource-id/teks atau lewat OCR, membaca logcat, serta memeriksa proses dan memori, sementara aliran langsung perangkat dirender di panel samping persisten tempat Anda bisa mengetuk, menyeret, memutar, dan menekan Back / Home / Recents langsung pada video. Tanpa blok gambar dan tanpa file rekaman layar: byte visual hanya mencapai UI melalui URL bertanda tangan dan kedaluwarsa yang disajikan server web DSH.

Hanya ada satu jalur kode. adb devices -l melaporkan sebuah serial, dan serial itulah satu-satunya identitas sebuah perangkat — emulator-5554, serial USB, atau target ip:port semuanya berperilaku identik. Plugin ini tidak terikat pada produk emulator mana pun (AVD, Genymotion, WSA, ladang perangkat awan), dan tidak ada pemisahan simulator/perangkat asli yang perlu dipikirkan.

📱 Perangkat langsung dalam percakapanAliran PNG multipart/x-mixed-replace yang diproduksi dalam proses dan disajikan langsung dari buffer bingkai terbaru melalui rute /_dsh/dsh-android/* bertanda tangan.
🔌 Tanpa helper aliran eksternal, tanpa port internalSatu proses anak adb exec-out persisten menjalankan while :; do screencap -p; done; host sendiri yang memecah PNG bersambung menjadi bingkai. Tidak ada server aliran loopback untuk diproksikan, tidak ada rentang port untuk dikelola, dan tidak ada apa pun untuk diadopsi setelah keluar secara kasar.
🧩 Satu jalur kode adbEmulator dan ponsel adalah hal yang sama bagi adb maupun bagi plugin ini. Tanpa tumpukan ganda simctl/WebDriverAgent, tanpa ritual build-dan-percayai sebelum perangkat fisik bisa dipakai.
🛠️ 20 alat agenPerangkat, nyalakan/matikan, tangkapan layar, interaksi, build & jalankan Gradle, pencantuman/peluncuran aplikasi, pohon UI uiautomator + ketuk per elemen, aksi baris daftar/umpan, temukan/ketuk/tunggu teks dengan Vision OCR, logcat, proses, backtrace ANR/crash, meminfo, info aplikasi.
👆 Panel navigasi tiga tombolKetuk dan seret pada video langsung; bilah alat dengan ◁ Back · ○ Home · □ Recents plus putar, tangkapan layar, dan segarkan; menu perangkat untuk panel notifikasi, pengaturan cepat, kunci, bangunkan, dan asisten.
🖼️ Multimodal bawaanPada model yang mampu memproses gambar, setiap alat penangkap (screenshot, interact, tap_element, tap_text, tap_row) mengembalikan tangkapan layar ITU SENDIRI sebagai image block — model melihat layar secara langsung. OCR tetap ada untuk ketukan teks berpresisi piksel dan rute khusus teks; model khusus teks tetap menerima ringkasan JSON biasa.
🔐 Rute bertanda tangan khusus loopbackSetiap rute mewajibkan peer loopback, Host loopback (DNS rebinding ditolak), dan pemeriksaan Fetch-Metadata/Origin — sebelum kapabilitas apa pun diperiksa. Kapabilitas HMAC-SHA256 kedaluwarsa dalam 10 menit.
🔍 Otomasi semantik + visualandroid_ui_tree membuang hierarki uiautomator dan android_tap_element mengetuk berdasarkan resource-id, teks, atau content-description; saat pohon kosong atau teksnya tercetak di dalam gambar, android_find_text / android_tap_text meng-OCR layar alih-alih menebak koordinat.

Alat

Ke-20 alat terdaftar di setiap host dan hanya mengembalikan JSON polos — byte visual hanya mencapai UI melalui presentationMeta + rute bertanda tangan, tidak pernah sebagai blok gambar. Saat adb tidak dapat diselesaikan, alat tetap terdaftar dan setiap panggilan gagal dengan error penjelas yang menyebutkan cara memperbaikinya.

Koordinat selalu ternormalisasi 0..1 terhadap bingkai yang dialirkan. Bingkai mengikuti rotasi layar (aplikasi lanskap dialirkan 2400×1080 pada perangkat 1080×2400) dan input tap berbagi ruang yang sama, sehingga tidak ada perhitungan rotasi di sisi klien di mana pun dalam plugin ini.

Alat inti

AlatFungsinyaParameter utama
android_devicesMencantumkan setiap perangkat yang dilaporkan adb devices -l (serial, status, emulator/fisik, model, versi Android, level API, nama AVD) plus nama AVD di mesin ini di bawah avds. Gunakan untuk menemukan serial yang diterima alat lain. Enumerasi yang gagal melempar error alih-alih mengembalikan daftar kosong.—
android_bootMemulai aliran langsung. Teruskan serial yang ONLINE untuk langsung mengalirkannya, atau nama AVD untuk meluncurkan emulator itu lebih dulu lalu mengalirkannya setelah selesai boot (bisa beberapa menit saat mulai dingin). Aliran tetap hidup selama percakapan sehingga panel dapat menampilkan perangkat secara langsung.device (wajib — sebuah serial atau nama AVD)
android_shutdownMematikan emulator (adb emu kill) dan menghentikan aliran bila aliran menarget perangkat tersebut. Perangkat fisik ditolak beserta alasannya: adb tidak dapat mematikan daya sebuah ponsel.device
android_screenshotMenangkap PNG dan mengembalikan ringkasan JSON singkat (path, byte, dimensi, perangkat); gambar dirender di kartu dan panel, tidak pernah sebagai blok gambar.device (opsional — perangkat yang dialirkan, jika tidak maka satu-satunya yang daring)
android_interactBerinteraksi dengan perangkat yang dialirkan: ketuk pada koordinat ternormalisasi 0..1, ketik teks, tekan tombol navigasi atau perangkat keras (back, home, recents, power, volume_up, volume_down, menu, enter, delete), kirim gestur usap, atau gulir. Setelah aksi tenang (~300 ms) tangkapan layar baru memperlihatkan efeknya.action (wajib — tap/type/button/gesture/scroll), x/y, text, name, json, device
android_list_appsMencantumkan paket yang terpasang pada perangkat (pm list packages), lengkap dengan nama versi dari dumpsys package dan label manusiawi bila dapat diselesaikan — nama paket pihak ketiga tidak dapat ditebak, jadi cantumkan dulu atau teruskan name ke android_launch_app.device, query (substring tanpa membedakan huruf besar/kecil, termasuk CJK), include_system (default false)
android_launch_appMeluncurkan aplikasi terpasang lewat packageName, atau lewat name (substring label tanpa membedakan huruf besar/kecil, diselesaikan lewat pencantuman yang sama). Tepat salah satu dari keduanya. relaunch menghentikan paksa aplikasi lebih dulu.packageName atau name (tepat satu), device, relaunch
android_build_runMembangun proyek Gradle (./gradlew assembleDebug), memasang APK debug hasilnya (adb install -r), dan meluncurkannya. Build penuh memakan waktu beberapa menit; saat gagal, hasilnya memuat ekor keluaran error Gradle.projectPath (wajib), device

Alat pohon UI dan baris (uiautomator)

AlatFungsinyaParameter utama
android_ui_treeMembuang hierarki uiautomator dari aplikasi terdepan sebagai node — type (ekor nama kelas), text, contentDesc, resourceId, bounds dalam piksel, enabled, focused — dibatasi ~40 KB (level terdalam dipangkas dan truncated disetel).device, max_depth, filter (substring tanpa membedakan huruf besar/kecil pada teks/content-description/resource-id)
android_tap_elementMengetuk elemen berdasarkan identitas — resource_id cocok dengan resource-id node; text cocok dengan teks atau content-description-nya. Cocok persis dulu, lalu substring tanpa membedakan huruf besar/kecil; duplikat bersarang diciutkan menjadi satu target dan kecocokan ambigu mencantumkan hingga 8 kandidat alih-alih memilih salah satu. Elemen yang nonaktif ditolak. Ketukan mendarat di tengah elemen, lalu tangkapan layar ~300 ms memperlihatkan efeknya; teruskan expect_text / expect_gone dan ketukan beserta verifikasinya menjadi satu perjalanan pulang-pergi.device, resource_id, text, expect_text, expect_gone
android_ui_rowsMembaca layar daftar/umpan (RecyclerView dan kerabatnya) sebagai BARIS, bukan pohon mentah: anak-anak berbentuk sama yang berulang menjadi baris yang membawa indeks, frame dalam piksel, label gabungan, dan penghitung yang diurai dari label itu (angka + token pengklasifikasi, bahasa Tionghoa atau Inggris — tanpa kosakata aplikasi yang dikodekan). Kunci penghitung dapat bolak-balik: teruskan sebuah kunci persis seperti yang tercantum ke android_tap_row.expect_count.device, max_depth
android_tap_rowMengetuk pada posisi relatif di dalam satu baris yang terlihat (index dari android_ui_rows; x/y sebagai pecahan frame baris itu, default 0.5 = tengah). Frame berasal dari pembacaan pohon yang SEGAR, jadi tidak ada koordinat absolut yang ditebak, dan indeks di luar rentang GAGAL alih-alih dijepit. Dengan expect_count={key, delta} alat membaca ulang baris setelah ~800 ms dan memverifikasi penghitung bergeser tepat ±1; kunci yang tidak dikenal MENOLAK ketukan sebelum terjadi.device, index (wajib), x, y, expect_count ({key, delta})

Alat OCR, log, dan debug

AlatFungsinyaParameter utama
android_find_textMeng-OCR layar SAAT INI dengan helper Vision yang dikompilasi plugin (pengenalan akurat, zh-Hans + en-US). Gunakan saat pohon UI kosong atau menurun, untuk teks yang dirender sebagai grafis (angka badge, harga yang tercetak dalam gambar), atau untuk memverifikasi secara independen apa yang ada di layar. Mengembalikan {device, size, items:[{text, confidence, rect}]} dengan rect berupa kotak piksel berasal kiri-atas, terurut berdasarkan keyakinan dan dibatasi ~40 KB. Khusus host macOS.device, query (substring tanpa membedakan huruf besar/kecil), min_confidence (default 0.3)
android_tap_textMeng-OCR layar SAAT INI dan mengetuk pusat kecocokan teks terbaik — aturan persis → mengandung → daftar kandidat yang sama seperti android_tap_element, untuk teks yang tidak terlihat pohon UI. Pusat piksel yang cocok dinormalisasi terhadap ukuran bingkai lalu dikirim sebagai ketukan; setelah ~300 ms tangkapan layar baru memperlihatkan efeknya. Khusus host macOS.device, query (wajib), min_confidence, expect_text, expect_gone
android_wait_forMenunggu sampai sebuah teks muncul atau hilang, mem-polling pipeline tangkap + OCR yang sama setiap 600 ms hingga kondisinya terpenuhi atau waktu habis (bawaan 8 dtk, maks. 60 dtk). Timeout adalah jawaban normal matched:false, tidak pernah error. Khusus host macOS.device, text (wajib), mode (appear/disappear), timeout_ms, min_confidence
android_logsMembaca apa yang dicatat perangkat: snapshot (logcat -d -v time pada jendela waktu terakhir, default 2m) atau follow (tangkapan langsung terbatas selama duration_seconds, default 10, maksimal 60 — tidak pernah aliran yang menggantung). Saring ke satu aplikasi dengan bundle_id (nama paket Android, diselesaikan menjadi pid-nya). Output dibatasi ~300 baris / 30 KB dengan petunjuk penyempitan.device, mode (snapshot/follow), duration, duration_seconds, bundle_id, grep
android_processesMencantumkan proses yang berjalan pada perangkat (ps -A) sebagai {pid, name} — sumber pid untuk android_backtrace.device, filter (substring tanpa membedakan huruf besar/kecil pada nama proses)
android_backtraceMeminta proses membuang tumpukannya (kill -3) dan membaca jejak ANR hasilnya dari /data/anr/. Sebagian besar perangkat non-root menolak direktori itu, sehingga alat menurun ke buffer crash (logcat -b crash -d) dan melaporkan secara jujur mesin mana yang menjawab serta apa yang tidak dapat dilihatnya.device, pid atau bundle_id
android_meminfoMengurai dumpsys meminfo <package>: total PSS, pembagian Java/native/grafis, dan kategori teratas — jawaban Android untuk ringkasan kebocoran.device, bundle_id (wajib)
android_app_infoFakta aplikasi terpasang dari dumpsys package <package>: nama dan kode versi, direktori data, path kode, waktu pemasangan pertama, dan tanda sistem. Aplikasi yang tidak ada mengembalikan installed: false plus catatan yang menyebut android_list_apps — bukan melempar error.device, bundle_id (wajib)

Permukaan tampilan

  • Panel samping. Tampilan langsung berada di panel kanan persisten (dok tetap yang menyingkirkan percakapan, atau hamparan terpusat pada viewport sempit). Panel merender aliran PNG langsung dan menerima klik-untuk-mengetuk serta seret-untuk-gestur langsung pada video, dengan bilah alat yang memuat ◁ Back, ○ Home, □ Recents, putar, tangkapan layar, dan segarkan. Menu perangkat menjalankan lima aksi tingkat perangkat (panel notifikasi, pengaturan cepat, kunci, bangunkan, asisten). Pemilih perangkat mencantumkan setiap perangkat adb dalam SATU daftar, dikelompokkan menurut jenis, dengan AVD yang luring ditampilkan sebagai petunjuk yang mengarah ke android_boot alih-alih boot-saat-diklik. Mode ukuran dan gaya bingkai (tanpa bingkai / bezel / cangkang ponsel) bekerja seperti pada kembaran iOS-nya; panel menyesuaikan rasio aspeknya dari ukuran alami bingkai itu sendiri, sehingga rotasi tidak butuh konfigurasi apa pun.
  • Kartu percakapan ringkas. Hasil alat dirender sebagai kartu satu baris tanpa citra sebaris: nama perangkat, sublabel aksi, lencana status, dan isyarat “buka di panel samping”. Mengeklik baris membuka panel.
  • Kapsul status di atas input. Saat panel tertutup dan sebuah aliran daring, pil kecil muncul di atas kolom input dan membuka panel saat diklik.
  • Mode standar dan Mode Code. Sesi standar memakai presentationMeta yang diproyeksikan host; dispatch Mode Code bersarang tidak membawa meta, jadi klien merekonstruksi meta yang identik dari JSON hasil yang tahan lama — panel, kartu, dan kapsul bekerja di kedua mode.

Keamanan

  • Peramban tidak pernah berbicara dengan adb, dan tidak ada port internal untuk diajak bicara. Aliran diproduksi di dalam proses ini dan disajikan dari memori; setiap byte melintasi origin server web DSH melalui rute /_dsh/dsh-android/* milik plugin: /stream/<token> (PNG multipart langsung), /screenshot/<token> (PNG ter-cache), plus /grant, /switch-device, /devices, /capture, /status, /control, dan /device-action. Ini adalah permukaan serangan yang jelas lebih kecil daripada server aliran loopback yang diproksikan.
  • Pagar loopback rangkap tiga, diterapkan sebelum kapabilitas apa pun dibaca. Peer transport harus berupa alamat loopback, header Host harus menyebut otoritas loopback (sehingga Host DNS-rebinding ditolak), dan Fetch-Metadata/Origin harus same-origin. Host dan Origin adalah data yang dikendalikan pemanggil dan tidak pernah dipercaya begitu saja.
  • Kapabilitas HMAC-SHA256 yang kedaluwarsa dalam 10 menit, berformat base64url(payload).base64url(mac) dan ditandatangani dengan kunci 32 byte per-rumah-DSH (<DSH_HOME>/cache/dsh-android/stream-access.key, mode 0600, dibuat secara atomik). Kapabilitas yang dicetak untuk satu perangkat berhenti bekerja begitu perangkat lain mengambil slot aliran, dan kapabilitas tangkapan layar tidak dapat diputar ulang terhadap rute aliran.
  • Rute tangkapan layar hanya menyajikan tepat satu direktori. Path ditelusuri dengan lstat (tautan simbolis apa pun ditolak), diakhiri pemeriksaan pembendungan realpath, dibuka dengan O_NOFOLLOW, dibatasi ukurannya, dan divalidasi ulang setelah pembacaan — sehingga file yang ditukar menjadi symlink antara pencetakan dan pengambilan tidak pernah disajikan.
  • /grant tidak pernah mem-boot apa pun. Ia hanya memulai loop bingkai untuk perangkat yang sudah daring, dan menolak (409 device_busy) merebut aliran dari perangkat lain. Berpindah perangkat menuntut gestur /switch-device yang eksplisit; mem-boot AVD tetap menjadi urusan alat android_boot.
  • Keep-alive dan berhenti saat idle. Loop bingkai yang crash dimulai ulang di latar belakang (~5 dtk jeda); tanpa konsumen, aliran berhenti sendiri setelah 5 menit. Penghentian yang disengaja tidak pernah dilawan.

Persyaratan

  • Node ≥ 24.11.0.
  • adb, dari platform-tools Android SDK, diselesaikan dalam urutan ini: variabel lingkungan ADB → adb di PATH → <ANDROID_HOME>/<ANDROID_SDK_ROOT>/akar SDK bawaan per OS + /platform-tools/adb. Pasang dengan sdkmanager "platform-tools", dengan Android Studio, atau dengan brew install --cask android-platform-tools. Tanpa adb, plugin tetap dimuat dan ke-20 alat terdaftar; setiap panggilan lalu menjelaskan apa yang kurang.
  • Sebuah perangkat: emulator produk apa pun, atau ponsel dengan USB debugging aktif. Peluncur emulator bersifat opsional dan hanya android_boot-lewat-nama-AVD yang membutuhkannya — selebihnya bekerja dengan apa pun yang bisa dilihat adb.
  • DSH ≥ 0.1.0-rc.6 dengan bundel web untuk panel. Profil headless juga bekerja: ke-20 alat berfungsi normal, hanya tanpa tampilan langsung.
  • Host macOS untuk OCR (hanya android_find_text / android_tap_text / android_wait_for yang membutuhkannya): plugin mengompilasi assets/ocr.swift bawaannya dengan swiftc pada pemakaian pertama ke ~/Library/Caches/dsh-android/bin/ocr. Pada host Linux dan Windows, ketiga alat itu melaporkan bahwa OCR membutuhkan framework Vision macOS; 17 alat lainnya tidak terpengaruh. Penimpaan: DSHPLUGIN_ANDROID_OCR_DIR, DSHPLUGIN_ANDROID_OCR_SWIFT, DSHPLUGIN_ANDROID_SWIFTC.
  • ADBKeyboard (opsional, untuk masukan CJK dan emoji): adb shell input text hanya mendukung ASCII. Pasang ADBKeyboard di perangkat dan pilih sebagai IME aktif, maka teks non-ASCII dikirim melalui antarmuka broadcast-nya. Tanpanya, pengetikan non-ASCII DITOLAK beserta petunjuk pemasangan — tidak pernah salah ketik secara diam-diam.

Perangkat fisik

Tidak ada padanan WebDriverAgent yang harus dibangun, ditandatangani, dipercaya, atau ditandatangani ulang setiap tujuh hari. Aktifkan USB debugging, colokkan ponselnya, terima permintaan otorisasi di perangkat, dan ia muncul di android_devices dengan setiap alat bekerja terhadapnya. Perangkat yang tidak terotorisasi dilaporkan apa adanya beserta petunjuk permintaannya, bukan sebagai kegagalan misterius.

Tiga catatan jujur:

  • Laju bingkai lebih rendah lewat USB — kira-kira 2–5 fps pada ponsel dibanding 5–10 fps pada emulator, karena setiap bingkai melintasi tautan USB sebagai PNG utuh.
  • Pengetikan CJK butuh ADBKeyboard (lihat di atas); ini berlaku sama untuk emulator maupun ponsel.
  • android_shutdown tidak dapat mematikan daya ponsel. adb tidak punya kata kerja semacam itu; alat mengatakannya terus terang alih-alih berpura-pura.

Performa

Diukur pada emulator (Android 14, 1080×2400):

Loop screencap persisten≈ 8 fps
Bingkai pertama ensureStreaming~200 ms
Perjalanan pulang-pergi input tap~130 ms

Satu proses anak persisten itulah yang membelinya: memunculkan satu adb per bingkai memakan ~50–100 ms sebelum ada piksel yang bergerak. Harapkan ~5–10 fps pada emulator dan ~2–5 fps pada ponsel USB, tergantung mesin dan kerapatan layarnya.

Pasang di DSH

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

Atau tambahkan sebagai dependensi paket profil yang sudah ada:

pnpm add @zseven-w/dsh-android

Mulai cepat

  1. Temukan perangkat — “Cantumkan perangkat Android.” → android_devices.
  2. Mulai aliran — “Alirkan emulator-5554.” → android_boot. Panel terbuka dengan perangkat tampil langsung. (Nama AVD akan mem-boot emulator itu lebih dulu.)
  3. Ketuk pada video — ketuk atau seret langsung pada panel, atau biarkan agen yang menggerakkan: “Buka Pengaturan, lalu ketuk Display.” → android_interact, atau android_ui_tree + android_tap_element untuk ketukan berbasis identitas, atau android_find_text + android_tap_text saat pohonnya buta.
  4. Build dan jalankan aplikasi Anda — “Build dan jalankan /path/to/MyApp.” → android_build_run. Build Gradle penuh memakan waktu beberapa menit; saat selesai, aplikasi diluncurkan dan Anda menontonnya langsung di panel.
  5. Baca log — “Tampilkan dua menit terakhir logcat untuk com.example.app.” → android_logs.

Pemecahan masalah

  • Semua alat mengatakan adb tidak tersedia — pesan errornya menyebutkan ketiga tingkat resolusi. Setel ADB=/path/to/adb, taruh adb di PATH, atau pasang platform-tools SDK (sdkmanager "platform-tools").
  • Perangkat berstatus unauthorized — terima permintaan USB debugging di layar perangkat. android_devices melaporkan statusnya secara jujur alih-alih menyembunyikan perangkatnya.
  • android_boot tidak menemukan AVD — peluncur emulator tidak dapat ditemukan. Jalankan emulator dengan cara apa pun; ia muncul di android_devices begitu adb melihatnya, dan android_boot lalu memakai serialnya.
  • Teks non-ASCII ditolak — pasang ADBKeyboard dan pilih sebagai metode masukan (lihat Persyaratan). Penolakan itu disengaja: input text akan membuang atau merusak karakternya secara diam-diam.
  • android_find_text mengatakan OCR tidak tersedia — OCR butuh host macOS (framework Vision milik Apple). Ke-17 alat non-OCR bekerja di mana saja.
  • Aliran berhenti sendiri — itu kebijakan idle, bukan crash: tanpa konsumen (panel tertutup, tidak ada kartu terpasang, tidak ada rute aktif) aliran berhenti setelah 5 menit dan dimulai ulang pada panggilan alat berikutnya atau saat panel dibuka. Loop yang crash dimulai ulang sendiri dalam ~5 detik.
  • Rotasi tampak salah di launcher — launcher dan Pengaturan mengunci dirinya ke potret dan mengabaikan user_rotation. Itu perilaku normal Android, bukan bug plugin; putarlah di dalam aplikasi yang mengizinkannya.

Pengembangan

pnpm install
pnpm run build      # host tsc + client bundle → lib/
pnpm run typecheck
pnpm test           # every static suite; no device required

Pengujian asap di scripts/ melatih lib/ yang telah dibangun. Semuanya statis kecuali dev-emulator-smoke.mjs, yang butuh perangkat dan melaporkan SKIP (exit 0) saat tidak ada.

SkripCakupannya
node scripts/dev-adb-smoke.mjsResolusi adb (env / PATH / SDK) terhadap biner shim, penguraian devices -l, exec-out yang aman untuk biner, pemecah bingkai PNG beserta resinkronisasinya, escaping input-text, dan siklus hidup host (aliran, kontrol, berhenti saat idle, dispose) terhadap toolchain palsu.
node scripts/dev-routes-static-smoke.mjsRute bertanda tangan terhadap host palsu: grant relatif, token kedaluwarsa/palsu/lintas-jenis, pagar loopback, amplop 405/415/400, penolakan perangkat berkode, validasi /control, bentuk rotasi, pembendungan tangkapan layar, dan aliran multipart langsung.
node scripts/dev-tools-smoke.mjsAlat inti terhadap host palsu melalui seam createAndroidTools.
node scripts/dev-uitree-smoke.mjsAlat pohon UI dan baris: penguraian XML uiautomator, selektor, pembatasan kedalaman, heuristik baris dan penghitung.
node scripts/dev-logs-smoke.mjssnapshot/follow android_logs, filter, batas, dan pemungutan proses.
node scripts/dev-panel-smoke.mjsKomponen panel, mode ukuran, gaya bingkai, logika dok/pemicu/kapsul (SSR saja).
node scripts/dev-emulator-smoke.mjs [serial]Perangkat langsung: bingkai pertama, laju bingkai berkelanjutan, perjalanan pulang-pergi ketukan, dispose.

Pemecahan masalah

Aliran kosong / putih pada emulator

Jika panel mengalirkan gambar putih (atau hitam) polos sementara android_ui_tree masih melihat elemen UI sungguhan, pembacaan balik framebuffer GPU-host milik emulator rusak di mesin Anda (masalah gfxstream yang dikenal pada sebagian host macOS — screencap sendiri mengembalikan bingkai kosong, sehingga setiap alat layar terpengaruh). Luncurkan ulang emulator dengan perenderan perangkat lunak:

emulator -avd <name> -gpu swiftshader_indirect

atau setel hw.gpu.mode=swiftshader_indirect di config.ini milik AVD tersebut. Perangkat fisik tidak pernah terpengaruh.

Peta jalan

  • Sumber dengan laju bingkai lebih tinggi. Seam StreamSource sengaja dibuat dapat dicolok: jalur scrcpy-server + WebCodecs H.264 dapat menggantikan aliran PNG per bingkai tanpa menyentuh rute, alat, maupun panel.
  • Muat ulang panas pratinjau Compose. Kembaran iOS-nya menukar-panas pratinjau SwiftUI sebagai dylib; Compose hari ini tidak punya primitif hot-swap yang setara, jadi ini tetap menjadi rencana masa depan alih-alih fitur yang dikirim tapi rapuh.

Ekosistem

  • DSH iOS Simulator — arsitektur yang sama untuk Simulator iOS dan iPhone yang terhubung USB
  • DSH Crew — delegasikan pekerjaan ke agen DSH dari Claude Code / Codex
  • DSH Noema — memori jangka panjang untuk DSH
  • DSH OpenPencil — periksa dan edit dokumen desain .op di dalam percakapan

Kredit & lisensi

  • Android SDK platform-tools (adb) — diselesaikan saat runtime, tidak pernah didistribusikan ulang: lisensi SDK Google tidak mengizinkan pemaketannya.
  • ADBKeyboard — Senzhk — IME opsional di perangkat yang menopang pengetikan non-ASCII (Apache-2.0; tidak dipaketkan).
  • Arsitektur dan postur rute dibagi dengan dsh-ios, yang menjadi asal porting plugin ini.
  • Lihat THIRD_PARTY_NOTICES.md untuk pemberitahuan lengkap.

Lisensi: MIT