Skip to content

Releases: itiswdwa/dsh-android

v1.2.1

Choose a tag to compare

@github-actions github-actions released this 16 Oct 06:27

dsh-android 1.2.1

这一版是应用版本升级,主题是恢复模式 —— harness 起不来的时候,应用不再只能给你一个空白页。

1.2.0 的设备需要安装新的 APK。 恢复模式有一半在应用侧(面板、桥接口、自动进入),
热更新包送不过去;热包也不跨应用版本线,所以这一版的内容只随 APK 下发。

Added

  • 恢复模式:harness 起不来时也能进沙箱。连续几次启动失败后应用会自己切换过去 ——
    不加载 harness,直接起来一个 SSH 服务和一个 shell。同一 Wi-Fi 用 ssh -p 8022 root@<手机 IP>,
    插着数据线用 adb forward tcp:8022 tcp:8022,只有手机时就点面板里的「手机内控制台」
    (一个不依赖 harness 的行模式终端)。密码是每次进入时新生成、退出即失效的令牌
  • 恢复模式支持端口转发:在沙箱里把 harness 重新拉起来之后,
    用 ssh -p 8022 -L 3080:127.0.0.1:3080 就能从电脑的浏览器打开它 —— 手机自己渲染不出来时这条最省事
  • 面板里可以直接复制连接命令、换一个新令牌、退出恢复模式;SSH 主机密钥由每台设备自己生成
    (存在 /root/.dsh-recovery/),不再用载荷里那份所有安装都一样的

Changed

  • 沙箱终端服务的会话现在会回收:关掉的标签页、重载的页面以前会在沙箱里各留一个 shell,
    攒够 8 个之后新终端就再也开不出来
  • 桥接口新增 /recovery/*,/snapshot 带上恢复模式状态(给以后在设置页里做一张卡片留的)

Fixed

  • 退出恢复模式后 root 密码一定回到锁定:原来只靠脚本的信号处理和「进程退出后补一次」,
    而应用停沙箱是直接杀进程、紧接着 800 毫秒就启动下一个 guest,两处都可能被跳过;
    现在正常启动时也会锁一次,不依赖信号也不依赖时序
  • 一行畸形请求不再能让终端服务整个退出(恢复模式下它是唯一的入口)
  • 更新不会因为版本号倒退而卡住:versionCode 以前只靠公式(1.2.1 → 10201)或环境变量,
    而这条线已经原地重发到 10212 —— 现在它记在仓库的 VERSION_CODE 里,重建也还是 10213

运行时(t3)

  • 载荷里的 harness 升到 0.2.0-rc.2(npm 上的 latest;上游没有不带后缀的 0.2.0)。
    这是 t 的变化,所以必须装新 APK,热包送不过去。1.2.1 的 APK 同时是"恢复模式"和"t3 运行时"。
  • 升之前在这台设备上逐项验证过:硬链接补丁的四个发布点(三处 import 行、四个调用点、注入锚点)
    在 0.2.0-rc.2 里原样还在,所以补丁不会触发"上游改了"的拒绝;装完在 Node 22.23.2 上跑
    市场冒烟,对照组(不加载市场)与实验组(加载市场)各一次真实调用都正常;
    用真实 profile 分别起 0.1.7-rc.2 与 0.2.0-rc.2,两边页面都是 200 且 35334 字节逐字节相同
  • 补上了 prepare_rootfs.sh 缺的一步:guest 工具(git/curl/python3/tmux/openssh-server 等)
    以前是手工装进 rootfs 的,仓库脚本里没有 —— 也就是说照仓库脚本从头构建出来的载荷没有 sshd,
    而恢复模式正需要它。现在这一步在脚本里,并且装完硬校验(缺任何一个就构建失败,
    不会让一个"起不来恢复模式"的载荷发出去)

注意

  • 恢复模式期间 harness 不在运行:手机上看不到会话列表、也不能对话,它是在「修」而不是「用」
  • 修好之后记得点「退出恢复模式」,否则下次启动还是恢复模式
  • 不想装 APK 的话,已装的设备也可以在恢复模式里用 scripts/upgrade-dsh.sh 把 harness 单独升到
    0.2.0-rc.2(见 docs/UPGRADE-DSH.md);但换 t 之后载荷与设备不再一致,
    下次装全量包会把它覆盖回去

安装:下载本页的 dsh-android.apk,覆盖安装即可;会话、API Key、挂载与设置都会保留。
首次启动需要解包内置运行时(约 2 分钟),之后冷启动约 5 秒。完整说明见 README。

v1.2.0

Choose a tag to compare

@itiswdwa itiswdwa released this 14 Oct 05:12

dsh-android 1.2.0

这一版是应用版本升级,三块改动一起进来:终端重写(亮色白底、弃用 xterm、标签页)、
悬浮球改造(单窗口、状态外部驱动、一堆崩溃与裁切修复)、issue 修复与预装
(#1/#2/#3/#4,含沙箱预装 pnpm 与插件市场)。

1.1.5 的设备需要安装新的 APK。 热更新包不跨应用版本线(应用端按 <app>-t<terminal>- 前缀
判断,1.1.5 的机器不会收到 1.2.0 的热包),设置页里会显示"有新外壳"而不是热更新。

Changed

  • 终端重做:亮色主题下终端是白底(暗色保持原样);弃用 xterm,改成自写的终端渲染 ——
    中文输入法、长按选择复制、方向键/回车/回删、光标位置都按手机的用法重做;底部新增功能键行
    (Esc / Tab / Ctrl / 方向 / 粘贴 / 复制),按下有轻触反馈
  • 终端支持标签页:一个面板里多个会话用 tab 切换(可新建、关闭,最多 4 个);侧边栏「终端」
    重复点只激活已有终端,不再每点一次就新开一个 shell;关掉标签或插件卸载会把 pty 交还
  • 悬浮球改成单窗口:球、输入条、状态气泡现在是同一个窗口(收起=球矩形、展开=条、状态=按文字
    自适应的气泡),形变过程中不再被上层窗口盖住 —— 这是"两条胶囊、动效看不见"的根治
  • 球上的状态改为外部驱动:新增 ball_doing(每次工具调用必带),由独立的状态总结器插件按会话
    事件推到球上,不额外调用模型;干活的模型不再被要求自报状态。停留规则:下一条是"思考中"
    最多等 2 秒,是工具调用最少停 0.5 秒

Added

  • 沙箱预装 pnpm(自包含单文件,随运行时包下发):插件安装 / dsh plugin 这类操作用得上(issue #4)

Fixed

  • 方向键的光标不再"看不见落在哪":以前底部整行输入框会把 ←/→ 吃掉(一个字节都不发给 shell),
    而 xterm 自己的光标又是另一套逻辑;现在只有一条输入路径,屏幕上的光标就是 shell 的光标
  • 键盘收起后能稳定唤回:点一下终端屏幕即可输入;连续尝试失败会给出提示,而不是静默失效
  • 全新安装不再缺「安卓沙箱」设置页与终端按钮(issue #3):播种闸门从"目录是否存在"改成
    "profiles/web/package.json 是否存在"(热包会先把插件目录建出来,目录判断必然被跳过)
  • 已经装坏的设备会被自动补齐:启动时按文件补齐 profile(缺哪行补哪行,从不覆盖用户自己的
    bundle 列表),并把丢失的插件注册行加回去 —— 以前入口都在没注册的插件里,用户无法自救
  • 现有设备自动获得三个内置插件:状态总结器、浏览器预览、插件市场(随热包下发,profile 行自动补)
  • issue #2:装瘦包 / 从没检查过更新的机器上,「下载运行时」按钮点着没反应、文案也看不懂 ——
    按钮原来只认更新清单里的地址,而"装了瘦包、从没检查过更新"恰好是空的。现在它回退到 release 资产
    (releases/latest/download/payload.zip 与 payload.manifest),文案改成一屏可照做的中文引导:
    为什么需要运行时、大约多大、直接下到 App 私有目录(不用自己找位置、解压、手动导入)、下完自动导入、
    看到"已安装"后终端就能用,失败会写明原因并可重试(只改插件引导层,未动 App Java)
  • 侧边栏 ⋯ 菜单:点会话右侧「三个点」时菜单闪现后消失、还直接进了那个会话 —— 根因是我们
    自己的手机布局补丁在 capture 阶段就把抽屉收了起来(菜单的锚点被抽走)。已修并重新注入
  • 球的加载指示真的在转:换成会转的圆环(鲸鱼居中),"思考中"也转圈;固定文案不再每 1.4 秒换词
  • 对勾徽标不再被裁:done 收回成球时 ✓ 收进圆内,不再被圆的边切掉半个
  • 气泡按行数长高(40 / 52 / 72dp):两行字不再被硬塞进球的 40dp 里
  • 不再"莫名其妙重启":morph() 动画完成回调为空时的空指针已兜底,并把所有调用点补齐
  • 球会话不再逼你去 DSH 点选项:球专用会话结构性移除提问卡片、免审批,配 floating-ball
    skill(一句话结论 + 纯文本编号澄清);收件箱自愈 —— 球会话被删掉后,下一句会自动开新线程,
    不再永久哑掉

注意

  • 瘦包(slim)用户:pnpm 随运行时包(payload)一起发,装完瘦包不会自动重新下载 payload。
    要拿到 pnpm(以及本次 payload 内的改动),需要重新下载一次运行时(设置 → 检查更新,约 230 MB);
    在那之前热包只会带来插件、技能与沙箱脚本的改动。装了完整包的不受影响
  • 底部功能键行的轻触反馈、「应用过的热包在重启后不被 APK 内建内容覆盖」、以及侧边栏 ⋯ 菜单
    这三条修复都要等新 APK 装上才生效
    (它们分别落在 App 的 Java 与前端 assets 里);只装热包不生效

安装:下载本页的 dsh-android.apk,覆盖安装即可;会话、API Key、挂载与设置都会保留。
首次启动需要解包内置运行时(约 2 分钟),之后冷启动约 5 秒。完整说明见 README。

v1.1.5

Choose a tag to compare

@itiswdwa itiswdwa released this 30 Sep 03:02

dsh-android 1.1.5

这一版把此前三个热包(1.1.4-sp1/sp2/sp3)的内容一并收了进来,另外换了新的版本编号方式。

Added

  • 手机助手:可以直接让助手操作这台手机。应用内新增无障碍服务(读屏、点击、输入、滑动),
    以及一个常驻的悬浮球:点一下说话、长按打字,说完把话交给会话,助手用屏幕上的文字
    (而不是猜坐标)去点按钮、在别的应用里输入。设置页新增「手机助手」,三项授权逐个有状态与入口
  • 沙箱里新增 ui 命令,给助手用:ui tree 看当前屏幕、ui click "发送" 按文字点、
    ui type 输入、ui key back、ui swipe、ui open 微信。走无障碍,不需要 Shizuku
  • 终端版本:沙箱运行时(rootfs、node、dsh、装进去的工具)现在有自己的版本号,与界面版本无关

Changed

  • 版本号改成三段:1.1.5-t2-sp0 —— 应用版本 · 终端版本 · 热包序号。
    t2 是这套运行时,它只在运行时本身变化时才动;sp0 表示这一版还没有热更新
  • 常驻通知:换成产品图标,正文写出状态与端口,并在通知栏直接提供「停止 / 启动」
  • 沙箱里自带 git、curl、python3、ssh、tmux 等常用工具,装上就能用

Fixed

  • 沙箱里的 apt 可以用了:Android 不允许应用创建硬链接,而 dpkg 每写一次数据库都要先用
    link() 备份 status,于是 apt install 必然失败。现在 guest 全局加载一个兼容层
    (/opt/dsh/android/liblinkfix.so):link() 被拒时退回复制文件、chown() 按沙箱内即 root 的
    约定回报成功、stat() 为复制出来的第二个名字补上链接数(groupadd 靠它判断锁)
  • 无障碍服务的屏幕描述有界(节点数与深度都有上限),不会把整棵树塞给模型

安装:下载本页的 dsh-android.apk,覆盖安装即可;会话、API Key、挂载与设置都会保留。
首次启动需要解包内置运行时(约 2 分钟),之后冷启动约 5 秒。完整说明见 README。

t2

t2

Choose a tag to compare

@itiswdwa itiswdwa released this 30 Sep 03:49

沙箱运行时 t2。

这是 dsh-android-slim.apk 首次启动时会下载的那份 rootfs(Ubuntu + Node + dsh + 常用工具),已经装过完整 APK 的设备不需要它。

v1.1.4

Choose a tag to compare

@itiswdwa itiswdwa released this 29 Sep 15:22

dsh-android 1.1.4

Fixed

  • 插件更新后界面仍是旧版:应用改为直接写入 harness 读取插件的目录,不再经过沙箱内的复制步骤;
    那一步之前任何环节没发生,harness 就会继续加载旧插件(8efe1fd)

Added

  • 设置页顶部常显版本号(应用 1.1.4 · 热包 1.1.4-sp1 · 内置):设备上跑的到底是哪一版,
    以前只能靠猜是"功能没写"还是"装了旧版"

安装:下载本页的 dsh-android.apk,覆盖安装即可;会话、API Key、挂载与设置都会保留。
首次启动需要解包内置运行时(约 2 分钟),之后冷启动约 5 秒。完整说明见 README。



1.1.4-sp1 - 2026-09-30

Changed

  • 「安卓沙箱」设置页改按 harness 原生设计重绘:按钮、开关、状态点、标签、卡片全部改用 harness
    自带的组件库与主题令牌,与旁边的「通用设置」同一套观感,浅色/深色自动跟随(4ae032c)
  • 发行版卡片用标签标出「当前使用」与「内置」,不再只靠标签页上一个小圆点判断

Fixed

  • 英文界面下设置页夹带中文:挂载的「启用/停用」与日志的空状态改用语言表

[1.1.4-sp2] - 2026-09-30

包含 1.1.4-sp1 的全部改动。(20ac8f9)

Changed

  • 热更新包的版本号改用 <应用版本>-sp<序号>(1.1.4-sp1、1.1.4-sp2……),
    此前显示的那串 16 位内容哈希不再对外展示
  • 设置页顶部的版本号改为完整显示:原先把 1.1.4-sp1 截断成 1.1.4-sp

[1.1.4-sp3] - 2026-09-30

沙箱里的 apt/dpkg 现在能正常工作;代价是硬链接的"两个名字共享内容"变成了复制,包管理器不依赖那一层。

Fixed

  • 沙箱里 apt install / dpkg --configure -a 必定失败(error creating new backup file '/var/lib/dpkg/status-old': Permission denied):Android 不允许应用进程创建硬链接,而 dpkg
    每写一次数据库都要先用 link() 备份 status。现在 guest 全局加载一个小兼容层
    (/opt/dsh/android/liblinkfix.so):link() 被内核拒绝时退回复制文件,git、curl、
    python3、openssh-server、sudo 等都能正常安装
  • adduser / groupadd 报 lock file already used (nlink: 1):这些工具用 link() 建锁,
    再检查链接数判断锁是否被占;复制不会让链接数增加,兼容层据此如实回报
  • 安装软件包时 dpkg 把文件属主改成 root 不再以 EPERM 失败(沙箱内本来就是"root"的约定)

应用:设置 → 安卓沙箱 → 检查更新 → 应用热更新。
也可以把 dsh-hot.zip 放进手机的 Download 目录,重开应用即可。

v1.1.3

Choose a tag to compare

@itiswdwa itiswdwa released this 29 Sep 10:20

dsh-android 1.1.3

Fixed

  • 修复升级后卡在启动画面:清理旧运行环境的工作原先在主线程上做,而且每次启动都会重来一轮,
    而旧树里有一万多个删不掉的残留文件;现在移到后台、只尝试一次,删不干净的目录改名挪开(bbc780e)
  • 修复挂载不生效:源目录读不到时(Android/data、SD 卡、没授予存储权限)会被静默丢弃,
    沙箱里只看到一个空目录;现在设置页直接写明原因(a2ef690)

Added

  • 每条挂载的「测一下」:让沙箱真去列一次目标目录,绑上没有、里面有什么,一眼就有答案(a2ef690)
  • 挂载卡片内的「重启服务以生效」:挂载是启动参数,改了必须重启(a2ef690)

安装:下载本页的 dsh-android.apk,覆盖安装即可;会话、API Key、挂载与设置都会保留。
首次启动需要解包内置运行时(约 2 分钟),之后冷启动约 5 秒。完整说明见 README。