dsh-mobile

61Stars4Forks0Issues0Watchers

Bring DeepSeek Harness to mobile browsers and Android apps, securely access your computer's sessions and workspaces via home or office LAN, with support for on-demand mobile interface customization and extending computer capabilities.

Language
TypeScript
License
Apache-2.0
Branch
main
androiddeepseek-harnessdsh-pluginlanmobilewebview

Install

$ dsh plugin --profile web add github:saya-ch/dsh-mobile

Run the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial

一句话定位

把电脑上的 DeepSeek Harness 带到手机浏览器或 Android App,通过受保护的局域网继续用同一份会话、工作区、消息和工具;不修改 DSH 源码,不暴露公网通道。

核心能力

  • 在手机上继续电脑端工作:同一份会话、工作区、消息和工具实时同步,电脑只跑 DSH 这一个前端,手机只是另一个客户端
  • 三种设备配对方式:扫码、配对链接、一次性密钥,配对成功后会持久化设备信任,后续打开 App 不再要求重新输入
  • 自动局域网发现与适配:监听 DNS-SD/mDNS 与周期性 UDP 公告(默认 3 秒间隔),切换 Wi-Fi、热点或 IP 后通常自动恢复
  • 独立 HTTPS 与证书固定:自签名 CA 只在下发 Android App 时绑定指纹;手机浏览器首次需手动信任该证书
  • 会话级别回环代理与设备/会话授权:设备 token 只保存 SHA-256 摘要,配对/会话/活跃请求上限可调,配对设备和电脑端 DSH 完全等权
  • 对话驱动的手机端定制:在 DSH 会话里 /mobile <需求> 由 agent 直接改 $DSH_HOME/mobile-access/ 下的 mobile.cssmobile.js 或扩展目录,几秒后手机端自动生效
  • 移动扩展(Extensions)机制:在本机额外目录里写 host.mjs(电脑端 Node.js 权限)+ mobile.js/css(手机端脚本),手机端通过 api.host.invoke() / api.host.fetch() 调用电脑能力(读写文件、执行命令等)

技术实现

  • 语言: TypeScript(编出 ESM .mjs,并出一份 mobile-layout.js 的 Client 端浏览器 bundle);配套 Android App 是 Kotlin WebView 薄壳
  • 关键依赖: @deepseek-ai/cordis(Cordis 宿主容器)、@deepseek-ai/schemastery(配置与扩展清单 Schema)、bonjour-service(mDNS / DNS-SD 服务发布)、qrcode(生成配对二维码 SVG)、selfsigned(自签发 CA 与服务端证书)
  • 架构模式: 三层分面 — Host face(src/plugin.ts 注册 Cordis 插件,挂载 WebServer 的 /mobile-access/... 回环管理路由以及 /api/mobile-access/... 已配对外 HTTPS 网关;依赖 webServer + commands) + Client face(src/client.ts + src/mobile-layout.ts,DSH web profile 启动时按 platform=web 立即注入,替换 desktop layout module 指向移动版) + Android App(同一 HTTPS URL,App 内 WebView 接 dshMobile Bridge 暴露文件选择、相机扫描、分享、剪贴板、通知等受控原生能力)
  • 入口文件: src/plugin.ts:39name='dsh-mobile'inject=['webServer','commands']apply(ctx, config);配合 src/index.ts 暴露所有子模块(含 MobileAccessGatewayAccessControllerMobileAccessServiceassertSupportedDshVersionparseGatewayConfig 等);Client 端入口 src/mobile-layout.tssrc/client.ts

适用场景

需要在家里沙发上、Wi-Fi 切换到手机热点时、或出差到酒店/办公局域网里继续使用电脑端 DeepSeek Harness,并希望在同一份会话和工作区里推进任务时安装使用。常见搭配是:电脑常驻 DSH Web,手机扫码配对一次后随时打开 Android App 或浏览器访问,配对设备可以执行工具、读写工作区文件、调用电脑侧本地脚本完成自动化。

前置依赖与兼容性

依赖最低版本说明
DSH Host(@deepseek-ai/dsh-host-webserver0.1.0-rc.5 / 0.1.0-rc.6 / 0.1.0-rc.7启动时 assertSupportedDshVersion 强制校验该范围,未通过会直接拒绝;不通过则不会变通启动
@deepseek-ai/dsh-commands0.1.0-rc.60.1.0-rc.7提供 /mobile <需求> 对话命令,依赖其 ctx.commands.register
@deepseek-ai/dsh-llm0.1.0-rc.60.1.0-rc.7/mobile 调用 agent.steer 需要其 createUserMessageboundContextSummary
React^18.2.0仅为 Client face 的 peer(用于 createElement 渲染桥接 UI)
Node.js^22.19.0>=24.0.0package.json:66 的 engines 字段
平台(宿主机)macOS / Windows / Linux跨平台,依赖 selfsigned/bonjour-service/qrcode 均为纯 JS,无原生模块;setup 在 Windows 上会额外通过 PowerShell 加两条仅限 LocalSubnet 的入站防火墙规则
Android AppAndroid(Kotlin WebView)唯一受支持的手机原生 App;通过 GitHub Release 取得 APK;配对使用 App 内固定的 CA 与 Android Keystore 加密的设备 token

安装方式

dsh plugin --profile web add github:saya-ch/dsh-mobile

安装后必须运行 dsh plugin --profile web exec dsh-mobile setup 完成首次的自签名 CA + 局域网选择;之后重启 DSH,在左下角“移动访问”卡片即可生成密钥/二维码。

配置项

配置类型说明默认值
setupFile隐藏字段setup 命令写入的受管配置文件绝对路径;用于自动跟随网卡cordis.patch.yml 中默认 $DSH_HOME/mobile-access/setup.json
listenHost / listenPort字符串 / 端口号LAN 监听地址;纯数字端口;与 publicOrigin 互斥127.0.0.1 / 3443
upstreamOrigin字符串回环代理要桥接到的 DSH Web 监听源,必须是带端口的回环 HTTPhttp://127.0.0.1:3080
publicOrigin / publicAuthorities字符串数组设备端要使用的对外 HTTPS 主机名集合;非回环监听必须显式给出无(设了 publicOrigin 则禁用 listenPort/publicAuthorities
allowedCidrsCIDR 数组允许直连的客户端网段;非回环监听必须给出回环监听默认 127.0.0.0/8, ::1/128
stateFile路径设备注册表持久化文件(仅存 token digest 与吊销时间戳)必填
controlFile隐藏字段DSH 插件卡片的开/关状态文件$DSH_HOME/mobile-access/control.json
customCssFile / customScriptFile路径手机端可选的自定义 mobile.css / mobile.js,存改就生效默认位于 $DSH_HOME/mobile-access/
mobileLayoutFile隐藏字段Host face 注入手机端的 browser bundle默认 ./mobile-layout.js
instanceIdSHA-256局域网发现/绑定 CA 用的稳定安装标识;非认证机密默认为 stateFile 路径的 SHA-256
pairingCaFile路径给 Android 安装器下发并绑定指纹的 CA 证书绝对路径;必须是 instanceId 对应的自签 CA受管 setup 自动写入
initiallyEnabled布尔控制首启时插件开关(由插件卡片持久化覆盖)false
tls子对象服务端 TLS 来源:mode: 'provided'(自备 cert/key,可选中间 CA)或 mode: 'disabled'(仅回环监听)受管 setup 自动签
pairingTtlMs / deviceTtlMs / sessionTtlMs毫秒配对码、设备 token、会话的有效期120000 / 90 天 / 8 小时
maxDevices / maxSessions / maxConnections / maxActiveRequests / maxWebSockets整数并发与持久化资源上限32 / 64 / 64 / 32 / 16
maxBodyBytes / upstreamTimeoutMs字节 / 毫秒单次回环代理请求体上限 / 上游回环代理超时160 MiB / 30000
rateLimitWindowMs / maxPairingAttempts / maxRateLimitKeys整数限流窗口、配对失败上限、限流键表上限60000 / 8 / 256

说明:上表的 stateFilecontrolFilesetupFilecustomCssFilecustomScriptFilemobileLayoutFilepairingCaFile 这些“隐藏字段”默认在 Schema 中标记为 hidden,普通用户无需手动写;插件市场安装 + dsh-mobile setup 一条命令会生成默认值。如需调整,主要是改 cordis.patch.yml 里的 mobile-access 行的 config: 子键,或用 setup --address <IP> --port <port>setupFile 重定向。

常见问题

Q: 安装后界面里没看到“移动访问”卡片怎么办?

A: 首先确认已运行 dsh plugin --profile web exec dsh-mobile setup 写入 $DSH_HOME/mobile-access/setup.json,并已重启 DSH;如果还是没显示,检查 DSH Host 版本是否在白名单 0.1.0-rc.5/rc.6/rc.7 内;不兼容时插件会直接抛错而不是带病启动,启动日志中会出现 unsupported DeepSeek Harness version ...

Q: 用手机浏览器第一次访问被提示证书不受信任怎么办?

A: 这是预期行为。LAN 网关使用自签 HTTPS,需要在手机浏览器里手动信任这套设备证书,或改用 Android App(App 内私有 trust store 自动接受该 CA,且不会写入系统信任区)。

Q: 自动发现没找到我的电脑,配对二维码扫不出来怎么办?

A: 先在电脑端用 dsh plugin --profile web exec dsh-mobile setup --address 192.168.x.x 显式绑定 IP;如果多网卡地址不在同一网段,也可以指向 https://IP:端口 手动连接;Windows 上 setup 默认会添加只对 LocalSubnet 开放的入站防火墙规则,被防火墙拦截时可重审。

Q: 设备凭据丢了、或者借给别人用过的手机,怎么撤销?

A: 配对设备拥有电脑端 DSH 的全部操作权限,必须当完全可信设备对待。丢失/转手时应在电脑端插件卡片里删除该设备(删除会立即使其失效),必要时用 dsh plugin --profile web exec dsh-mobile purge --yes 清空 $DSH_HOME/mobile-access/ 全部数据并轮换所有 token。

Q: mobile.css / mobile.js 改完没生效?

A: 手机端在 5 秒内会拉取一次保存后的版本,请确认文件确实写到了 $DSH_HOME/mobile-access/ 下,而非被系统重定向到只读/隔离位置;另外 mobile.js 必须用 window.dshMobile.register(({ root }) => { ... }) 形式挂载到 root,否则插件运行时不会调用。

Q: 为什么我的电脑装的是其他版本 DSH,插件报错不让启动?

A: 见 src/compatibility.ts — 插件强制限定已验证的 3 个 DSH 版本,未通过会立刻失败,这是为了避免在桌面页面或 layout 契约已变更的情况下硬撑成“勉强能用”。升级 DSH Host 后请同时升级 dsh-mobile。

Q: 同一个网络里有多台电脑怎么区分?

A: 每台电脑自动派一个 stable instanceId(来自 stateFile 路径的 SHA-256),Android App 扫码或局域网扫描后用这个 ID 匹配同一台电脑,不会把多台电脑的同名实例串起来;也可以在“移动访问”卡片里看到当前分配的 instanceId

Q: 卸载 dsh-mobile 后会留下数据吗?

A: 会。仅 remove 时退出进程,不动 $DSH_HOME/mobile-access/(证书、设备注册表、控制状态、自定义文件、扩展都在这里);要彻底清掉证书、设备和自定义文件,先 dsh plugin --profile web exec dsh-mobile purge --yes,再 remove。Windows 上 purge 会同步移除 setup 时添加的两条防火墙规则。

上手难度

进阶 — 安装 + setup 命令本身就两条,但要安全使用需要理解“配对设备完全可信、不应放在公网、丢失必撤销”的安全模型;要发挥 /mobile 定制和扩展能力则需要熟悉 $DSH_HOME/mobile-access/ 目录约定和 host.mjs 的本地用户权限边界;遇到多网卡/防火墙场景需要会看 setup --address 显式绑定。

已知问题与限制

  • Alpha 阶段:仅维护最新的 prerelease;早期 alpha 不接收安全修复(SECURITY.md:5-7
  • iOS 客户端未发布:仅 Android App 在 Release 范围内;iOS 仍是本地实验,不进入构建与 Release(README.md:24apps/mobile/README.zh-CN.md:7
  • 移动网关必须放宽 CSP:DSH 上游 HTML 自带 inline JS、用 new Function 复活 Schemastery 回调、动态样式,因此网关 CSP 当前包含 script-src 'self' 'unsafe-inline' 'unsafe-eval'style-src 'self' 'unsafe-inline';其余指令仍按 HTTPS-only 收严,但脚本注入风险未被零化(SECURITY.md:30-32),依赖上游 DSH 引入 nonce / 稳定 hash / 外部引导资源后才能收紧
  • 强制 DSH 版本白名单:src/compatibility.ts:2-6 只放 0.1.0-rc.5/rc.6/rc.7,其它版本启动即失败;升级 DSH 后需同时升级 dsh-mobile
  • 依赖 0.0.0.0 内网监听时必须显式给出 publicAuthorities:不能用回环默认值;并且一旦设了 publicOrigin,TLS 必须保留为 mode: 'provided',不能禁用(src/config.ts:211238-240
  • 自签 CA 必须在 LAN 内单独下发给 Android:Android App 只信任自己 instanceId 指纹绑定过的 CA,不调用 Android 系统信任区;浏览器需要手动信任(SECURITY.md:19-22
  • 设备注册表用临时文件原子重命名写入,文件大小上限 1 MiB、设备上限默认 32(src/storage.ts:89,302);不可绕过 JsonDeviceStore 直写多个实例
  • mobile-accesssetup 后必须能写入 $DSH_HOME/mobile-access/;只读文件系统/不可写 HOME 会让 setup 抛错;多 profile 并存时各自独立的 stateFilecontrolFile 路径由 cordis.patch.yml 注入