packages/dsh-remote-web-ui
zhu1090093659/dsh-web手机/PC 远程操控 dsh web 工作区:扫码配对、令牌门控通道、SSE 实时同步,提供移动端与完整桌面 GUI 两种远程形态。
基于 dsh-mobile-gate 的完整移动端 PWA:安全远程访问网关 + 可安装到主屏(manifest + service worker)+ 离线可用 + 触屏手势(下拉刷新/边缘返弹/捏合缩放字体)+ agent 完成推送 + 触屏优先布局,桌面零影响。
把 DeepSeek Harness(DSH)变成手机上的完整 PWA:安全远程访问你的自建 DSH + 一键「添加到主屏」成独立 App + 离线可用 + 触屏手势 + 任务完成通知。
基于 MIT 的 dsh-mobile-gate(安全网关基座)做差异化增强。
当前版本 `0.3.0` —— 对齐 DSH 官方 `0.2.x`(engines.dsh: ">=0.2.0 <0.3.0")。
📍 生态定位:社区现有移动端方案都停留在「窄屏 CSS 微调」,本项目做的是移动端 PWA 一站式完整方案。
模块 · 说明 📡 安全远程访问 · 独立子进程网关,首次访问本机审批(审批绑 IP、令牌绑浏览器,同一出口 IP 下的手机和电脑可同时在线)+ 可选访问密码 + 每 IP 限流。DSH 主服务仍只监听本机回环,/api 信任栅栏不受影响 📱 真 PWA · manifest.json + service worker:手机浏览器「添加到主屏」后全屏独立窗口运行,带图标/启动屏/主题色 🧩 可安装 · 主屏图标、standalone 显示、apple-touch-icon、maskable 图标 🌐 离线可用 · service worker:静态壳缓存优先、API 网络优先、导航离线回退页 👆 触屏手势 · 下拉刷新、边缘右滑返回、捏合缩放字体(可重置) 🔔 任务完成通知 · 真正的 Web Push(RFC 8291 aes128gcm 加密 + RFC 8292 VAPID 鉴权),切到别的 App 也能收到 📐 触屏布局 · 44px 触摸目标、safe-area 适配、全屏弹窗、紧凑排版、代码横向滚动——桌面零影响 🌐 Bot 浏览器 · 一条命令给 Bot 装上真实 Chrome(Chrome for Testing + playwright-core + 代理 shim + profile patch + 自检),截图直接出现在对话里,遇到登录/支付/验证码可人机接力。详见 docs/browser.md 🔒 桌面不受影响 · 所有规则都以 html[data-lan-device="phone"] 或以排除 data-lan-device="desktop" 的 @media 为根 🎯 0.2 版 DOM 对齐 · 移动端 CSS 全部改用 DSH 0.2 的 slot 词表(main.conversation / conversation.view / conversation.chat.flow / conversation.input.model / conversation.composer.dock …),0.1 时代已失效的选择器全部移除
手机 ──> 网关 (独立 Node 子进程 · 0.0.0.0:3088)
├─ 未批准 -> 「等待本机批准」页面(轮询 /lan-gate/admin)
├─ 已批准+令牌Cookie -> 反向代理到 DSH Web UI (本机地址:端口)(每个浏览器各领一枚令牌)
│ └─ HTML 注入:manifest link + PWA bootstrap + 触屏CSS + randomUUID polyfill
├─ /pwa/* -> 直接提供 manifest / sw.js / app.css / 图标 / offline.html
├─ /pwa/push/* -> 订阅 / 发送(真实加密推送)
└─ 超限 -> 429 限流页
电脑 127.0.0.1:3088/lan-gate/admin -> 批准/拒绝/撤销设备、选择访问方式(手机/电脑/自动)/api 信任栅栏完好。webStartup 服务读出本次启动真实的 host/port(dsh web --port 0 / --host 都照样工作),再显式传给子进程。npm add @zylzyqzz/dsbot@0.3.0
dsh plugin --profile web add @zylzyqzz/dsbot已声明 dsh.bundle manifest,安装后自动激活配置层,无需手写 patch。包:https://www.npmjs.com/package/@zylzyqzz/dsbot
git clone https://github.com/zylzyqzz/dsbot.git
cd dsbot
dsh plugin --profile web add ./dsbot源码安装需要给 pnpm 放行构建脚本(见官方 publish 文档的 allowBuilds 说明)。本包是纯 JS、无构建步骤,npm 预构建包不需要任何授权。参考 cordis.patch.yml.example,把绝对路径替换进你的 profile patch。
变量 · 默认 · 说明 LAN_GATE_PORT · 3088 · 网关监听端口 LAN_GATE_HOST · 0.0.0.0 · 网关监听地址 LAN_GATE_TARGET_HOST · 127.0.0.1 · 本机 DSH Web UI 地址(插件会自动填 webStartup.host,此变量优先) LAN_GATE_TARGET_PORT · 3080 · 本机 DSH Web UI 端口(插件会自动填 webStartup.port,此变量优先) LAN_GATE_RATE_LIMIT · 120 · 每 IP 每分钟请求上限 LAN_GATE_PASSWORD · 空 · 访问密码。设了之后打开网关先要输密码,密码只存在服务器上,浏览器拿到的是 HMAC 派生的会话 cookie LAN_GATE_TRUSTED_HOSTS · 空 · 对外服务地址白名单,逗号分隔(如 203.0.113.10,app.example)。DSH 0.2 的 Host/Origin 栅栏按浏览器看到的 Host 校验,网关原样透传 Host,所以这里必须声明对外地址;不带端口的条目匹配任意端口 LAN_GATE_REWRITE_HOST · 空 · 设为 1 时把 Host 改写成回环地址(仅老版本 DSH 需要) LAN_GATE_DSH_TOKEN · 自动 · DSH 进程 launch token,插件从 ctx.connection 自动读取并交给网关 LAN_GATE_PUBLIC_URL · 空 · 仅用于生成 token 化 URL 时的基准地址 LAN_GATE_VAPID_PUBLICKEY · 自动生成 · Web Push VAPID 公钥(base64url) LAN_GATE_VAPID_PRIVATEKEY · 自动生成 · Web Push VAPID 私钥(base64url PKCS#8) LAN_GATE_VAPID_SUBJECT · mailto:dsbot@localhost · VAPID 联系方式
VAPID 密钥对未提供时会自动生成一次并保存到 ~/.dsh/lan-gate-vapid.json(权限 600),重启不失效。DSH 0.2 起,浏览器要拿一个签名 session cookie 才能用 Web UI,而这个 cookie 的首次签发需要一个进程 launch token(每次重启都会变)。本插件的做法:
ctx.connection.authenticatedUrl() 读出本次启动的 launch token,交给网关子进程;前提是 DSH 侧要信任对外地址:把 LAN_GATE_TRUSTED_HOSTS 设成对外的 host 或 host:port(bundle 的 connection 行会自动把它并进 --trusted-host 列表),或直接在启动参数里加 --trusted-host 。
[dsbot] listening on 0.0.0.0:3088 -> : (pwa=on)。http://:3088 → 出现「等待本机批准」。http://127.0.0.1:3088/lan-gate/admin → 批准该设备并选「手机」。ds-bot 有 12 个浏览器工具,但不自带浏览器,启动参数还是写死的、没有代理配置项。这条命令把缺的部分一次补齐:
# 在你的 DSH 服务器上
node scripts/setup-browser.mjs --proxy http://127.0.0.1:7890
# 装完重启
sudo systemctl restart dsh-web它会:下载 Chrome for Testing → 装系统库(Ubuntu 24.04 的 libasound2t64 改名已处理)→ 装 playwright-core → 装代理 shim → 真开一个网页验证 → 把 - id: bot 写进 profile patch(先备份)。
装完 Bot 就多出 browser_open / browser_snapshot / browser_click / browser_screenshot / browser_handoff 等 12 个工具, 其中 browser_screenshot 的截图直接进对话,不是一行工具日志。
node scripts/setup-browser.mjs --verify-only # 随时自检
node scripts/setup-browser.mjs --print-config # 只打印 YAML
sudo node scripts/xray-split-route.mjs # 代理分流:国内直连,其余走代理为什么需要 shim、代理怎么选、排错表 → docs/browser.md
DSH 0.2 在智能体工作期间会渲染 [data-chat-running]。注入脚本用 MutationObserver 盯着它: 一旦从「有」变成「没有」,说明这一轮跑完了 —— 此时
Notification(页面在前台时最直接);/pwa/push/send,网关按订阅加密后推给其他设备。0.2 版移除了旧的宿主侧dsh-push.mjs插件:它依赖 DSH 0.1 的conversation/http服务接口,在 0.2 已不存在。判定逻辑改到浏览器侧,反而更准(DSH 自己的 DOM 就是事实来源),也不再占用宿主进程。
npm test # 起 mock 上游,验证 /pwa 资产、HTML 注入、状态上报、Web Push 加解密回环路径 · 作用 lan-gate.mjs · Cordis 插件入口:解析目标地址 + spawn 网关子进程 + 生命周期管理 lib/lan-gate-server.cjs · 网关本体:零依赖单文件(HTTP 代理 + 审批 + 令牌 + 限流 + PWA 注入) lib/web-push.cjs · 真 Web Push:VAPID 密钥对 + ES256 JWT + ECDH/HKDF 派生 + AES-128-GCM 加密 pwa/manifest.json · PWA 安装清单 pwa/sw.js · service worker(离线缓存 + 推送通知 + 订阅轮换) pwa/inject.js · 注入页引导:注册 SW + 加载手势 + 通知订阅 + 任务完成判定 pwa/touch-gestures.js · 下拉刷新 / 边缘返弹 / 捏合缩放 pwa/app.css · 移动触屏布局(data-lan-device 前缀,桌面零影响) pwa/offline.html · 离线回退页 pwa/icons/ · SVG 源 + 192/512 PNG + maskable 图标 cordis.patch.yml / .example · 插件 bundle 挂载层 scripts/setup-browser.mjs · Bot 浏览器一键安装:Chrome + 系统库 + playwright-core + shim + 自检 + profile patch scripts/verify-browser.mjs · 浏览器自检(真开一个网页,输出 JSON 报告) scripts/pw-proxy-shim.mjs · Playwright 代理 shim:注入 --proxy-server 与去自动化标志,不改 ds-bot 源码 scripts/xray-split-route.mjs · xray 分流修复:国内直连 / 其余走代理,带 xray -test 与自动回滚 docs/browser.md · Bot 浏览器原理、配置、排错 test/gateway.test.cjs · 网关冒烟测试 test/browser-setup.test.cjs · 安装器 / shim / 分流规则的纯函数测试
lan-gate.mjs 只负责 spawn + 生命周期,永不 import 它的服务代码进 DSH 进程。ctx.subprocess 会先洗掉子进程环境里的凭据和 DSH_* 事实,再叠加调用方给的 env。所以 LAN_GATE_*、DSH_HOME、VAPID 密钥必须在 spawn 请求里显式给出。html[data-lan-device="phone"] 或排除 desktop 的 @media(max-width:820px),桌面必须永不受影响。[data-slot=...] / [data-*] / ARIA 而非 hash 类名,避免前端构建后失效。DSH 改 slot 名时移动端样式会静默失效 —— 升级 DSH 后记得回上游 packages/client 重新核一遍 slot 词表。lib/lan-gate-server.cjs 里的注入脚本字符串,历史上有「双引号套双引号」bug,注意字面量转义。lib/web-push.cjs 的 encryptPayload + buildVapidAuthorization。dsh-mobile-gate(MIT)——安全网关基座。安装插件 = 在你的机器上运行第三方代码,权限与你本人相同。收录/发布不等于安全审查。请:只在你自己的服务器上跑、别放密钥到不熟悉的环境、定期审计 `lib/lan-gate-server.cjs` 的变更。远程访问务必走审批 + 令牌,别把网关端口裸奔到公网。
MIT。网关 lib/lan-gate-server.cjs 基于 dsh-mobile-gate 扩展,保留原 MIT 版权与许可,详见 LICENSE。