[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-105366":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":14,"stars7d":14,"stars30d":14,"stars90d":15,"forks30d":15,"starsTrendScore":16,"compositeScore":17,"rankGlobal":9,"rankLanguage":9,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":19,"hasPages":19,"topics":21,"createdAt":9,"pushedAt":9,"updatedAt":30,"readmeContent":31,"aiSummary":9,"trendingCount":15,"starSnapshotCount":15,"syncStatus":14,"lastSyncTime":32,"discoverSource":33},105366,"DSHAPP","pht88888888\u002FDSHAPP","pht88888888","DSH Android 客户端：内置 Termux 环境跑 Node，在 Node 上跑 DSH 引擎，WebView 加载官方 Web GUI",null,"JavaScript",65,4,62,2,0,6,43.3,"MIT License",false,"main",[22,23,24,25,26,27,28,29],"ai-agent","android","coding-agent","geckoview","kotlin","llm","termux","webview","2026-11-01 00:15:10","# DSH for Android\n\n**在 Android 手机上跑一个完整的 AI 编码 Agent。**\n\n[English](README.en.md) · [文档](docs\u002Fagents\u002FREADME.md) · [参与贡献](CONTRIBUTING.md)\n\n---\n\n## 这是什么\n\nDSH for Android 把 [DSH](https:\u002F\u002Fgithub.com\u002Fdeepseek-ai)（DeepSeek Harness）桌面端引擎\n原样搬进手机：内置 Termux 环境跑一个 Node，在 Node 上跑 DSH 引擎，再用 WebView\n加载 DSH 自带的 Web GUI。\n\n**它不自绘聊天界面。** UI 完全复用官方前端，只在窄屏下由内置插件做移动端适配 ——\n所以你得到的不是「手机版阉割界面」，而是**与桌面端同一个前端**，只是能装进口袋。\n\n```\nAPK\n ├─ Termux bootstrap        bash \u002F dpkg \u002F apt + 64 个 .so\n ├─ Node 运行时              Termux 官方 arm64 node 26.4.0\n ├─ DSH 引擎                 node_modules，完整解包到私有目录\n ├─ 原生插件（自编译）        require-builtin \u002F flock \u002F node-pty\n ├─ Web 内核（gecko 版）      GeckoView，不依赖系统 WebView\n └─ 内置插件                 移动端适配 \u002F 悬浮球 \u002F UI 调试 \u002F 日志 \u002F 记忆 …\n```\n\n## 特性\n\n- **完整的 Agent 能力** —— `bash`、文件读写、`grep`\u002F`glob`、终端 PTY 全部可用，\n  不是只读聊天框。\n- **双 Web 内核** —— `system` 版用设备自带 WebView（小），`gecko` 版内置 GeckoView\n  （大一倍，但老设备、系统 WebView 被裁的设备也能用）。**两个包可同装一台机器。**\n- **移动端 UI 适配** —— 官方前端 + 窄屏适配插件，不是另写一套界面。\n- **悬浮球** —— 随时唤起，支持自定义外观、帧动画、视频图层。\n- **UI 调试工具** —— 让模型自己看屏幕、点按钮，实现端到端自测。\n- **救援模式** —— 插件写坏导致 App 打不开时，四级降级阶梯 + App 内自助摘除。\n- **日志与诊断** —— 三层存储、崩溃现场快照、一键导出诊断包。\n\n## 快速开始\n\n### 安装\n\n从 [Releases](..\u002F..\u002Freleases) 下载 APK，侧载安装。\n\n| 包 | applicationId | 适用 |\n|---|---|---|\n| `DSH\u003C版本>.apk` | `com.dsh.android` | 绝大多数设备，体积小 |\n| `DSH\u003C版本>-gecko.apk` | `com.dsh.webview` | 老设备 \u002F 系统 WebView 不可用时 |\n\n两个包 **applicationId 不同，可以同时安装**，数据目录互相独立。\n\n> ⚠️ **仅支持 arm64-v8a，且 targetSdk = 28。** 这是硬约束，不是疏忽 ——\n> 见下方[两条硬约束](#两条硬约束)。\n\n### 从源码构建\n\n```powershell\n$env:JAVA_HOME = \"\u003C你的 JDK 17 路径>\"   # 必须显式设置\n\n.\\gradlew.bat :app:assembleSystemDebug --console=plain\n# → app\\build\\outputs\\apk\\system\\debug\\app-system-debug.apk\n\n.\\gradlew.bat :app:assembleGeckoDebug --console=plain\n# → app\\build\\outputs\\apk\\gecko\\debug\\app-gecko-debug.apk\n```\n\n**环境**：JDK 17 · AGP 8.8.2 · Kotlin 2.0.21 · Gradle 8.13 · compileSdk 35 · minSdk 26\n\n### ⚠️ 构建资产需要自备\n\n`app\u002Fsrc\u002Fmain\u002Fassets\u002F` 下约 **135 MB** 的构建资产**不在本仓库**（`.gitignore` 排除，\n避免仓库臃肿）。**没有它们构建不出可用的 APK。**\n\n| 资产 | 大小 | 来源 |\n|---|---|---|\n| `engine.bin` | 55 MB | DSH 引擎 `node_modules` 打包 |\n| `node-runtime.bin` | 30 MB | Termux 官方 arm64 node |\n| `bootstrap-aarch64.zip` | 23 MB | Termux bootstrap |\n| `webview-compat.zip` | 9.3 MB | 按 chrome73 降级编译的前端 bundle |\n| `pnpm-android-arm64.zip` | 5.6 MB | pnpm 11.28.3 纯 JS 版 |\n| `adb-wireless-arm64.zip` | 5.3 MB | Termux 官方 adb |\n| `sharp-wasm32.zip` | 3.5 MB | sharp 的 wasm32 变体 |\n| `ripgrep-android-arm64.zip` | 2.0 MB | 官方 linux-arm64 静态 rg |\n| 其余 24 个 | \u003C 1 MB | 自编译 native 绑定 \u002F 内置插件 zip |\n\n**每个资产的来源、生成方式与校验方法**见\n[docs\u002Fagents\u002Fregen-assets.md](docs\u002Fagents\u002Fregen-assets.md)。\n其中 `keyinject.bin`（内置号池）是**可选的** —— 没有它 App 照常运行，只是不内置 API 账号。\n\n## 两条硬约束\n\n这两条是**平台事实**，不是可以「优化掉」的设计。改动前必读。\n\n### ① 包名必须恰好 15 字符\n\n`applicationId` = `com.dsh.android`（15 字符）。\n\nTermux 官方二进制把 `\u002Fdata\u002Fdata\u002Fcom.termux\u002Ffiles`（27 字节）烤进 ELF 的 `.dynstr`，\n而 `TermuxBootstrap.patchElfInPlace()` 只能做**等长原地覆盖**。替换串\n`\u002Fdata\u002Fdata\u002F\u003C包名>\u002F` = 12 + N 字节 = 27 ⇒ **N = 15**。\n\n长度不等时该函数**静默 `return 0`**，不抛异常；症状是运行时\n`CANNOT LINK EXECUTABLE` 或 `dpkg: Permission denied`。\n\n### ② targetSdk 必须 ≤ 28\n\n**不能升到 29+。** Android 10（API 29）起，targetSdk ≥ 29 的应用不允许 `execve()`\n自身私有目录里的文件（W^X \u002F SELinux `untrusted_app` 域禁止 `app_data_file`\n`execute_no_trans`）。\n\n而 node \u002F bash \u002F dpkg 全都装在 `filesDir` 下的 `$PREFIX` 里 —— 一升级就全线\n`Permission denied`。Termux 官方 App 同样停在 28。\n\n**代价**：只能侧载，无法上架 Google Play。\n\n## 架构\n\n```\nMainActivity (WebView \u002F GeckoView)\n      │  加载 http:\u002F\u002F127.0.0.1:\u003Cport>\n      ▼\n  DSH Web GUI  ←── 官方前端 + 移动端适配插件\n      │\n      ▼  HTTP\n  DSH 引擎（Node）\n      │\n      ├─ tool: bash      → 经 boo-sandbox-run 沙箱\n      ├─ tool: read\u002Fwrite → 经 liblinkcompat.so 转译 link\n      ├─ tool: grep\u002Fglob → 静态 ripgrep\n      └─ tool: ui\u002Fbubble → 原生桥（文件信箱）\n      │\n      ▼\n  $PREFIX（Termux 环境，filesDir 下）\n```\n\n### 为什么需要这么多 native 层\n\nAndroid 的 `process.platform` 是 `'android'` 而非 `'linux'`，而 DSH 官方的原生插件\n与平台判断都是按 `linux`\u002F`darwin`\u002F`win32` 三选一写的。凡是「官方只认 linux、但代码\n本身与 libc 无关」的地方，都要为 android 补一份。\n\n更麻烦的是**三处 Android 主动不给的能力**，只能靠 `LD_PRELOAD` 在 libc 边界绕开：\n\n| 层 | 解决什么 | 文档 |\n|---|---|---|\n| `liblinkcompat.so` | SELinux 不给 `link()` 权限（`EACCES`\u002F`EINVAL`） | [link-compat.md](docs\u002Fagents\u002Flink-compat.md) |\n| `boo-sandbox-run` + `libboosandbox.so` | Android 没有 bwrap\u002FLandlock，但 `bash` 工具要求沙箱 | [sandbox.md](docs\u002Fagents\u002Fsandbox.md) |\n| `libkeyinject.so` | 内置 API 号池，密钥在 TLS 层替换，不落盘不进 JS | [key-pool.md](docs\u002Fagents\u002Fkey-pool.md) |\n\n## 目录结构\n\n```\napp\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fdsh\u002Fandroid\u002F     原生宿主（Kotlin）\napp\u002Fsrc\u002Fmain\u002Fjni\u002F                      native 层（C，LD_PRELOAD）\napp\u002Fsrc\u002Fmain\u002Fassets\u002F                   构建资产（⚠️ 不在仓库，见上）\napp\u002Fsrc\u002Fsystem\u002F · app\u002Fsrc\u002Fgecko\u002F       两个 Web 内核的 flavor 源集\nmobile-ui-plugin\u002F                      内置插件源码（TypeScript\u002FJS）\nremote-plugin\u002F                         配对服务端 + 端到端测试\ntools\u002F                                 构建与校验脚本\ndocs\u002Fagents\u002F                           开发文档（35 篇，按需检索）\n```\n\n## 文档\n\n**别整份读 `docs\u002Fagents\u002F`** —— 按「你要改什么」查索引：\n[docs\u002Fagents\u002FREADME.md](docs\u002Fagents\u002FREADME.md)\n\n| 你要改什么 | 先看 |\n|---|---|\n| 任何 native \u002F 子进程相关 | [platform-android.md](docs\u002Fagents\u002Fplatform-android.md) |\n| `bash` 工具报 \"no sandbox backend\" | [sandbox.md](docs\u002Fagents\u002Fsandbox.md) |\n| `write` 工具报 `EACCES\u002FEINVAL: link` | [link-compat.md](docs\u002Fagents\u002Flink-compat.md) |\n| 改任何 `.zip` \u002F `.bin` 资产 | [asset-stamps.md](docs\u002Fagents\u002Fasset-stamps.md) |\n| 构建发行包 \u002F 签名 \u002F 发布 | [build-and-ship.md](docs\u002Fagents\u002Fbuild-and-ship.md) |\n| 插件改坏导致 App 打不开 | [rescue-mode.md](docs\u002Fagents\u002Frescue-mode.md) |\n\n## 已知边界\n\n- **沙箱不隔离 PID 命名空间** —— `--unshare-pid` 需要 CAP_SYS_ADMIN，普通应用拿不到。\n  文件写边界是完整的。\n- **仅 arm64-v8a** —— 没有 arm32 \u002F x86 构建。\n- **只能侧载** —— targetSdk 28，上不了 Google Play（见硬约束②）。\n- **APK 较大** —— system 版约 137 MB，gecko 版约 216 MB（引擎与内核随包分发）。\n- **首次启动较慢** —— 要解包 Termux 环境与引擎，视设备约 10–60 秒。\n\n完整清单见 [boundaries.md](docs\u002Fagents\u002Fboundaries.md)。\n\n## 参与贡献\n\n欢迎 Issue 与 PR。动手前请读 [CONTRIBUTING.md](CONTRIBUTING.md) ——\n本项目有两条**改错不报错但真机必炸**的硬约束，以及「改了资产必须同步改版本戳」\n这类静默失败陷阱。\n\n## 致谢\n\n本项目站在这些项目的肩膀上：\n\n- [DSH \u002F DeepSeek Harness](https:\u002F\u002Fgithub.com\u002Fdeepseek-ai) —— 引擎与 Web 前端\n- [Termux](https:\u002F\u002Fgithub.com\u002Ftermux) —— bootstrap、node、adb 运行时\n- [Mozilla GeckoView](https:\u002F\u002Fwiki.mozilla.org\u002FMobile\u002FGeckoView) —— 内置 Web 内核\n- [ripgrep](https:\u002F\u002Fgithub.com\u002FBurntSushi\u002Fripgrep) · [sharp](https:\u002F\u002Fgithub.com\u002Flovell\u002Fsharp)\n  · [pnpm](https:\u002F\u002Fgithub.com\u002Fpnpm\u002Fpnpm) · [Shizuku](https:\u002F\u002Fgithub.com\u002FRikkaApps\u002FShizuku)\n\n## 许可证\n\n[MIT](LICENSE)\n","2026-10-31 04:26:33","CREATED_QUERY"]