npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-aug-remote

v2.5.0

Published

一个插件、两种角色:主服务端把 DeepSeek Harness 变成手机能安全访问的 PWA(移动端界面、配对码网关、Web Push),并把选定会话共享给已配对的桌面端;子客户端在另一台 DSH 桌面端的侧边栏里远程使用这些会话。One DSH plugin, two roles: the host turns DeepSeek Harness into a phone-reachable PWA (mobile UI, pairing-code gateway behind your own rev

Readme

这是 KyoMio/dsh-zen-remote 的个人 fork:在它基础上加了远程产物下载、Office 预览中继、客户端本地文件物化上传和 500 MiB 上传上限。它不是官方插件,也不代表上游立场。请从本仓库的 Release 安装;改动与维护说明见 NOTICE 与 FORK.md。

| 会话列表主屏 | 会话页 | 会话信息卡 | | --- | --- | --- | | 会话列表主屏 | 会话页 | 会话信息卡 |

| composer 权限 sheet | 公网设备看到的配对页 | | --- | --- | | composer 权限 sheet | 配对页 |

截图为 390×844 手机视口、浅色主题;深浅主题均适配。配对页由网关绘制,按 DSH 官方风格、跟随系统浅色 / 深色。


一个插件、两种角色

同一个包、同一行插件。跑哪一半由 DSH「插件」页设置区块里的 role 决定:

| | 主服务端(role: host,默认) | 子客户端(role: client) | | --- | --- | --- | | 机器 | 跑会话的那台 | 另一台装了 DSH 桌面端的电脑 | | 加载什么 | 手机界面、网关(子进程)、Web 推送、会话共享、中继服务端 | 中继客户端 + 侧边栏与会话页的远程部件 | | 不加载什么 | — | 不起网关、不注册推送、手机界面不生效——不和主服务端抢端口 |

已配对的桌面应用端只看得到服务端开启了远程的会话,在本地工作区后面按「服务端名 · 工作区名」分组。服务端的工作区只有其中至少一个会话开启了远程才会出现——没动过的工作区不会显示成空分组;已经显示过的分组里会话全部关闭远程后,空分组会留到刷新页面为止。子客户端本地的会话完全不受影响。


远程连接

适合什么场景:一台电脑常开、跑会话(主服务端),另一台电脑的 DSH 桌面端(子客户端)远程查看、接着干活——历史、实时进度、发消息、审批、终端都能用,所有执行都发生在主服务端。手机、平板走的是另一条路:浏览器经网关访问主服务端(Web 应用端),见配置公网访问。

怎么用,四步:

  1. 配对:主服务端设置页生成「桌面应用端」配对码,子客户端设置页填服务端地址和配对码。逐步说明见下面的设置页配置引导。

  2. 开启远程:远程按会话逐个开。主服务端在会话的「…」菜单里点「开启远程」(也可以用标题行的地球图标、设置页的共享列表,见会话共享)。

    主服务端在会话的「…」菜单里开启远程

  3. 在子客户端使用:侧边栏本地工作区后面出现「服务端设备名称 · 工作区名」分组,点开就像本地会话一样用;标题行的地球图标显示连接状态(在线 / 离线 / 版本有差异)。服务端上没有开启远程会话的工作区不会出现。

    子客户端侧边栏里的「书房 · Desktop」分组,标题行是远程连接状态图标

  4. 关闭与恢复:服务端关闭远程、会话闲置休眠(默认 48 小时无动静)、或在子客户端自己关闭时,正打开的会话页会显示「远程已关闭」横幅并禁用输入,切到别的会话后它从列表里隐藏;重新开启远程后自动回来。断线期间页面保持原样,连上后自动续上。

    远程被关闭后,会话页输入框上方的「远程已关闭」横幅

手机上也能开关:用手机(Web 应用端)访问主服务端时,会话页的信息卡片里有一行「远程访问」,显示是否已开启、剩余闲置时间,点开关即可开启或关闭。

能做什么、不能做什么,见功能和已知限制;已配对的桌面应用端被视为可信设备,信任边界见安全模型。

以上截图中,红框圈出的是本插件加入 DSH 界面的部分;会话标题为演示用,对话内容已模糊处理。


安装

界面安装(桌面端 App 与 Web 端都适用;桌面端是 2.0 主服务端的实际形态):左侧「插件」页 →「添加插件」→ 输入 dsh-aug-remote → 装完点「立即启用」,然后重启桌面端 App(Web 端重启 dsh web)。

Web 服务命令行(无头机器上跑 dsh web 的主服务端,手机访问也指向这里):

dsh plugin --profile web add dsh-aug-remote
# 然后重启 dsh web

开着 HMR 升级插件: 先 remove 再 install(dsh plugin --profile <name> remove dsh-aug-remote 后再 add dsh-aug-remote,或在「插件」页先卸载再添加);直接在运行中的旧版上覆盖安装不会被干净地接管。

DSH 0.2.1-alpha.3 起: dsh --profile <name> --from-default-profile <模板> 会用模板新副本覆盖已有的自定义 profile,删掉其中的 dependencies(包括 dsh-aug-remote)和用户 cordis.patch.yml。执行前先备份 ~/.dsh/profiles/<name>(如 cp -a ~/.dsh/profiles/<name> ~/.dsh/profiles/<name>.bak-$(date +%Y%m%d%H%M%S)),之后重新装插件。~/.dsh/*.json 里的配对/共享状态在 profile 之外,不受影响。

dsh plugin 必须用 --profile 指明装进哪个 profile,不带会直接报错。桌面端的 desktop profile 由 App 独占管理,命令行会拒绝 --profile desktop,所以桌面端只能用上面的界面安装。

手工改 profile(本地开发、link: 装法):把依赖写进 profile 的 package.json(桌面端在 ~/.dsh/profiles/desktop,Web 端在 ~/.dsh/profiles/web),装完重启:

// ~/.dsh/profiles/desktop/package.json
{
  "dependencies": {
    "dsh-aug-remote": "^2.5.0"        // 本地开发换成 "link:/path/to/dsh-aug-remote"
  }
}
cd ~/.dsh/profiles/desktop && pnpm install
# 然后重启 DSH 桌面端 App(Web 端重启 dsh web)

pnpm install 只装包、不启用。还要到「插件」页打开它的开关,或者自己把 "dsh-aug-remote" 追加到同一个文件 dsh.profile.bundles 数组的末尾(数组里原有的项别动)。界面安装和 dsh plugin 会自动写这一项,手工装法要自己补。

无论哪种装法,组合层都只有一行。2.0.0 起挂载层只剩 dsh-aug-remote 一行,主入口按角色自己加载网关与推送子插件。不要再把旧的 dsh-aug-remote-gateway / dsh-aug-remote-push 两行加回来:loader 会警告后跳过;真挂两行网关就是两个网关进程抢 3088 端口。

把 cordis.patch.yml.example 抄进 profile 的 cordis.patch.yml、换成绝对路径即可——同样只有一行,附带的 config: 示例列了可写的行配置。用界面或 dsh plugin 正常安装的不需要它。

卸载:在「插件」页打开 dsh-aug-remote,点「卸载」并确认;Web 服务也可以用命令行 dsh plugin --profile web remove dsh-aug-remote;手工装的从 profile 的 dependencies 和 dsh.profile.bundles 里删掉它。之后重启;要清掉配对与共享状态再删 ~/.dsh/lan-gate-state.json、~/.dsh/lan-gate.config.json、~/.dsh/aug-remote-shares.json 与 ~/.dsh/aug-remote-server.json(服务端 id;删了之后已配对的子客户端会把它当成一台新服务端)。


从 1.x 升级

一次性的事实,按踩到的概率排序:

  • 三行合并为一行。 profile 补丁里残留的 dsh-aug-remote-gateway / dsh-aug-remote-push 旧行会被 loader 警告后跳过。原来写在那两行上的 config: 不再生效——搬到 dsh-aug-remote 行,或者直接在插件设置页里改。
  • 1.0 时代在 profile 补丁里手工 insert 过 dsh-aug-remote/dsh-push.mjs 那一行的,需要删掉——主入口现在按角色自动加载推送子插件,残留的那一行会让推送加载两次。
  • ~/.dsh/lan-gate.config.json 继续生效。 无需迁移,它的值会显示在设置页里。每个字段的优先级:环境变量 > 插件行设置 > lan-gate.config.json > 内置默认值。插件从不改写、也从不删除这个文件。
  • 已配对设备自动归为 Web 应用端,继续照常用,不需要重新配对。
  • 管理页搬家了。 /lan-gate/admin 现在只剩一段指向插件设置页的说明(对非本机直连的请求仍然 403)。配对码、设备管理、测试推送、会话共享全部在 DSH「插件」页的 dsh-aug-remote 设置区块里。
  • 什么配置都不动的话,插件按主服务端起来,网关、推送、手机界面的行为与 1.1.x 完全一致。

配置公网访问(主服务端)

装完在本机 127.0.0.1:3080 就能用手机界面。要从外面访问:给自己的网关配一个终结 TLS 的反代,用 403 自检确认,再配对设备。nginx / Caddy / Cloudflare Tunnel / Lucky 的完整配置见 docs/remote-access.md,简版:

  1. 网关只监听 127.0.0.1:3088,由反代(nginx、Caddy、Cloudflare Tunnel、Lucky)终结 HTTPS 并转发。自检:用手机流量(别连家里 Wi-Fi)访问 https://你的域名/lan-gate/admin,正确结果是 403。能看到说明页就代表反代没带 X-Forwarded-* 头、公网请求被当成了本机用户——先修转发头再往下走。
  2. 在服务端这台机器打开 DSH「插件」页,展开 dsh-aug-remote 设置区块,先选要配的设备角色,再点生成 8 位配对码(10 分钟有效、只能用一次)。
  3. 手机打开你的 HTTPS 域名,在配对页输入配对码。配对成功即进入 DSH,身份存在长期 Cookie 里。浏览器菜单「添加到主屏幕」装成 App,同意通知权限,agent 干完活推到锁屏。

配对设备

配对码生成时绑定设备角色,兑换时校验角色——拿错通道用码会被明确拒绝,码不被消耗,也不计入错码锁定。

| | Web 应用端 | 桌面应用端 | | --- | --- | --- | | 形态 | 手机、平板及各类浏览器,经网关访问 | 装了 DSH 桌面端、aug-remote 设为子客户端角色的计算机 | | 可见范围 | 服务端全部会话 | 仅服务端已开启远程的会话(服务端强制) | | 配对方式 | 浏览器打开网关地址,在配对页输入配对码 | 在子客户端的插件设置页填服务端地址和配对码 |

桌面应用端配对,逐步:

  1. 在服务端的插件设置区块选「桌面应用端」,生成配对码。
  2. 在另一台电脑的 DSH 桌面端里打开插件设置区块,角色切到子客户端,填入服务端地址和配对码。
  3. 地址必须 https://,内网地址才允许 http——局域网段(192.168.x、10.x、172.16–31.x)、Tailscale/CGNAT(100.64.x)、回环、localhost / *.local、IPv6 ::1 / fc00::/7 / fe80::/10。公网地址走明文 http 会被拒绝,设备令牌不会明文过公网。
  4. 配对成功后令牌存在插件行里(密钥字段),客户端自动连接。设置区块显示连接状态——已连接 / 离线 / 版本有差异 / 令牌已吊销——并可以解配。

服务端的设置区块可以改设备名、改设备角色(set-role)、单独或全部吊销。吊销立即生效:连接与推送订阅一并失效。桌面应用端够不到任何管理路由——网关只把它的请求转进中继前缀。

设备名称:设置页「角色」卡片里的「设备名称」字段(配置项 serverName)两种角色共用:主服务端上它是其他设备侧边栏分组标题里的名字(默认取电脑名);子客户端上它是配对时注册到服务端的名字。名字双向自动同步:服务端改自己的名字,子客户端分组标题约 15 秒内跟随;子客户端保存新名字,服务端设备列表跟着更新;服务端在设备列表里给子客户端改名,子客户端约 30 秒内跟随。子客户端只在主动保存设置时推送自己的名字,其余时候以服务端记录为准;离线时改的名字如果进程在推送前退出,下次启动以服务端记录为准。名字 1–40 个字符。


会话共享

远程按会话逐个开启,有四个入口:

  1. 侧边栏会话行的「…」菜单里的「开启远程 / 关闭远程」;
  2. 会话页标题行的远程图标(点击开关、带二次确认;悬停显示剩余闲置时间;图标带小圆点表示此刻有桌面应用端在看);
  3. 插件设置区块的「已开启远程的会话」列表,含一键全部关闭;
  4. 手机(Web 应用端)会话页信息卡片里的「远程访问」开关。

闲置休眠:开启远程的会话在 48 小时(可配,idleHours)内没有任何会话动静——回合开始或结束、发消息、审批或提问得到回答,不分服务端还是子客户端——就自动关闭远程。运行中的回合、等待审批/回答的会话永远不会被扫掉;只开窗口「看着」不算活跃。剩余时间悬停标题行图标可见,设置区块里逐条列出。

新建会话:autoShareNewSessions 打开时,服务端新建的会话自动开启远程;经中继新建的会话(子客户端远程分组里点的)一律自动开启,这条入口的安全性正建立在此之上。子智能体会话与分叉会话自动跟随父会话,不用逐个开启。

「关闭远程」意味着什么:未开启远程的会话,其列表、历史、实时进度、审批/提问事件,全部在中继处拒绝或过滤——不只是界面上藏起来。@ 引用候选只列已共享会话;发消息、改写排队消息、斜杠命令里内嵌的会话引用指向未共享会话时,整个调用被拒绝。

关闭远程后在子客户端的表现:服务端关闭某个会话的远程(或它闲置休眠)时,该会话直接从子客户端的侧边栏列表里隐藏——按「已归档」处理,在 DSH 里打开「显示已归档」筛选还能看到它。唯一的例外是此刻正打开着的会话页:页面停在原处,composer 上方出现「远程已关闭」横幅并注明原因(服务端关闭 / 闲置休眠 / 已在本机关闭),输入禁用;切到别的会话后它也随之隐藏。服务端重新开启远程(或重新共享)后,会话回到原工作区,打开着的页面自动恢复——横幅消失、输入恢复可用。

断线与恢复:服务端(或链路)断线期间,已打开的远程会话页保持原状——横幅提示离线、输入禁用;连接恢复后自动续上:会话流与任务列表类面板自动重新拉取最新快照,不用手动刷新。例外是文件树变更与终端面板,断线后需要重新打开。


配置

设置页配置引导

在哪打开:DSH 左侧点「插件」→ 插件列表里点 dsh-aug-remote → 在「包含的组件」里再点一次 dsh-aug-remote,下面就是设置区块。

通用操作:字段右上角出现「已覆盖」表示这个值保存在插件设置里(覆盖了配置文件或默认值),点「重置」恢复成下一层的值;改完点卡片底部的「保存」。需要重载的字段会有提示,保存后插件自己重载,不用重启 App。

主服务端

  1. 「运行角色」选「主服务端」,「设备名称」填一个好认的名字(比如「书房」)——子客户端侧边栏的分组标题、手机上都显示它。保存。

    主服务端设置页:角色卡片里的运行角色与设备名称

  2. 「网关与反代」:只在本机和手机经反代访问时保持默认即可,公网访问见配置公网访问。要让局域网里的子客户端直连网关,把「监听地址」改成 0.0.0.0(必须包含本机回环,设置页靠回环地址管理网关)。

  3. 「配对」:选「Web 应用端」(手机、浏览器)或「桌面应用端」(另一台 DSH 桌面端),点「生成配对码」,10 分钟内在对方那里输入。「设备」列表里可以改名、改设备角色、吊销。

    生成配对码与设备列表

  4. 「远程共享」:闲置休眠时长、是否自动共享新会话。卡片下方的「已开启远程的会话」列出当前开着远程的会话、剩余闲置时间、是否有设备正在查看,可以逐个或全部关闭。

    已开启远程的会话列表

  5. 「推送」:推送内容摘要、回合结束推送等,按需开启,说明见通知什么时候会响。

子客户端

  1. 「运行角色」选「子客户端」,保存——插件自动重载,设置页换成子客户端的内容。

  2. 「设备名称」填这台电脑的名字(比如「客厅」),配对时它会登记到服务端的设备列表里。保存。

  3. 「连接服务端」:填服务端的网关地址(局域网例如 http://192.168.1.10:3088,公网必须 https://)和服务端生成的「桌面应用端」配对码,点「配对」。

  4. 「连接状态」显示「已连接到『服务端设备名称』」就完成了,侧边栏随即出现服务端的分组。「诊断」区列出请求拦截器状态和最近的远程调用失败,排障先看这里。

    子客户端设置页:角色、设备名称、连接服务端与连接状态

截图中的地址、配对码为演示值。

字段参考

全部在 DSH「插件」页 → dsh-aug-remote 设置区块里改。每个字段按此顺序取第一个合法值:环境变量 > 插件行设置 > ~/.dsh/lan-gate.config.json > 默认值;某层的值类型/范围/枚举不合法时该层视为未设置。改完需要重启网关/推送的字段(role、port、host、targetPort、rateLimit、trustedProxies、vapidSubject、lang 与推送各字段),插件会自己重载插件行——不用手动重启 App;其余字段立即生效。

插件行字段(与 src/config.ts 一致):

| 字段 | 默认 | 说明 | | --- | --- | --- | | role | host | host 跑网关 + 推送 + 共享;client 连接服务端。不是精确的 client 就按 host 处理 | | port | 3088 | 网关端口;被占用自动往上试(最多 +20) | | host | 127.0.0.1 | 网关监听地址;反代不在本机时才需要放开 | | targetPort | (自动) | 本机 DSH Web UI 端口。留空即可:网关自动发现宿主实际监听端口(桌面端构建的端口可配置) | | rateLimit | 120 | 未配对请求的每分钟上限(按真实客户端 IP) | | trustedProxies | 空 | 逗号分隔 IP;反代不在本机时必填 | | vapidSubject | mailto:admin@localhost | 推送联系人。iOS 必须改成真实邮箱或 https 网址,否则 Apple 拒发 | | lang | auto | 网关页面、推送开关卡片与通知文案的语言。auto 跟随浏览器的 Accept-Language(认不出就用中文),zh/en 写死 | | pushTurnEnd | 关 | 「回合结束」也推一条。默认不推——回合结束不代表需要你。等授权/等回答的通知不受影响,永远推 | | pushEvents | agent/turn-stopping | 「回合结束」算哪些事件,逗号分隔;只在 pushTurnEnd 开时有意义 | | pushDebounceMs | 15000 | 两条自动推送的最小间隔;等授权/等回答的通知不受压制 | | pushSummary | 关 | 通知带上本回合的最终回复(只取正文,不含思考过程;截 120 字)和提问原文 | | pushTool | 开 | 设 false 关掉模型可调用的 push_notify 工具 | | serverName | 电脑名 | 设备名称(≤ 40 字),两种角色共用:主服务端是子客户端分组标题里的显示名;子客户端是配对时注册的名字;与服务端双向自动同步 | | idleHours | 48 | 远程会话的闲置休眠时长(小时),范围 (0, 8760] | | autoShareNewSessions | 关 | 服务端新建的会话自动开启远程 | | pluginBridgeConsent | {} | 插件桥的整机数据同意表:插件名 → 布尔。设置页「插件桥」小节管理,一般不用手改;表里未登记插件的残留键不清理 |

| serverUrl(子客户端) | 空 | 服务端网关地址,按上文规则校验 | | deviceToken(子客户端) | 空 | 配对拿到的设备令牌;密钥字段,处处打码 | | turnFoldDesktop | 关 | 回合过程折叠在任意宽度生效(默认仅手机宽度) | | keyboardLiftRatio / keyboardLiftMaxPx / keyboardSafetyPadPx | 0.42 / 400 / 15 | 软键盘抬升校准,给浏览器拿不到键盘高度的环境用(见已知问题一节) | | maxUploadBytes | 20 MB | 附件上传上限 |

旧的环境变量继续可用且优先级最高:LAN_GATE_PORT、LAN_GATE_HOST、LAN_GATE_TARGET_PORT、LAN_GATE_RATE_LIMIT、LAN_GATE_TRUSTED_PROXIES、LAN_GATE_VAPID_SUBJECT、LAN_GATE_LANG、DSH_PUSH_TURN_END、DSH_PUSH_EVENTS、DSH_PUSH_DEBOUNCE_MS、DSH_PUSH_SUMMARY、DSH_PUSH_TOOL、DSH_PUSH_LANG(通知文案覆盖;不设时由 lang 决定)、DSH_PUSH_APPROVAL_GRACE_MS(「等授权」推送前的等待窗口,给更快的自动审批插件让路;默认 5000;它与仅文件层的 pushApprovalGraceMs 键不在设置面板里)。LAN_GATE_RELAY_SECRET 不可外部指定:插件每次加载现生成、自己交给网关。

上传上限、键盘校准、回合折叠这几个旋钮与 1.x 行为一致——只是从「插件行 YAML」搬到了「设置页」(手写插件行 YAML 也照样有效)。


通知什么时候会响

默认只在真正需要你的时候响,分两条互不依赖的线。

一、系统自己判断的(恒开,且不受最小间隔压制)

| 情况 | 通知 | | --- | --- | | 某个工具在等你授权 | 「DSH 等你授权」,带工具名 | | 模型调用 ask_user_question 在等你回答 | 「DSH 等你回答」 |

这两类不看会话层级——子代理自己卡在授权上,照样喊你,因为等的还是你。也不受最小间隔压制:「有操作等你点头」是最不能被吞掉的一条。2.0 起桌面端 App 里跑的会话同样覆盖:钩子挂在服务端侧,会话在哪跑都一样。

有机器答复者时的时机:审批事件的顺序是「先记 asked → 问答复者 → 记 decided」,所以推送并不是一见到 asked 就发,而是等 DSH_PUSH_APPROVAL_GRACE_MS(默认 5 秒)——这段时间内被答复掉的就不推。换了更慢的模型答复者就把这个值调大(实测平均 2.4 秒)。策略自动放行的授权不会打扰你。

二、模型自己决定的

push_notify 工具,模型在这些时候该调:你明确要求做完通知、需要你介入才能继续、出现你大概率想立刻知道的意外。不该调的场景同样写在工具描述里,同一段文字还作为会话上下文注入,两处共用同一个常量、不会各改各的。

默认不会响的:普通跑完一轮不推(想要旧行为设 pushTurnEnd 或 DSH_PUSH_TURN_END=1);子代理跑完永远不推,无论上面那个开关。

通知里写什么:默认只有标题。开 pushSummary 才带这一轮的最终回复——只取正文,不含思考过程;这一轮没说话就退回「最后执行了 xx 工具」。推送 payload 是 aes128gcm 端到端加密的。


功能

主服务端(手机访问,1.x 的延续)

  • 会话列表主屏 + 独立会话页两级页面栈,横向推入推出
  • 主屏插件入口 chips,按已装插件自动出现,显隐可自定义
  • composer 重排:控件图标化,权限/模型菜单变成底部 sheet
  • 会话信息卡:六格统计 + 导出日志 / 重命名 / Fork / 归档;分享图一键导出 PNG 长图;2.0 起多一行「远程访问」开关
  • 回合过程折叠、左缘右滑返回、安卓返回手势接管、手机本地附件上传
  • 配对码换长期设备令牌,认令牌不认 IP,可随时吊销
  • 真 PWA + 真 Web Push(VAPID + aes128gcm),默认只在等授权/等回答时响

主服务端(2.0 新增)

  • 会话共享:四个开关入口(含手机信息卡片)、闲置休眠、新建自动共享、子会话跟随
  • 以上全部在 DSH 跑桌面端 App 时同样成立:网关自动转发到桌面端后台的实际端口,桌面端会话的等授权/等回答照推手机

桌面应用端(2.0 新增)

  • 侧边栏远程分组(「服务端名 · 工作区名」),远程会话与本地会话同等使用:完整历史、实时进度、发消息、取消、排队调整、审批与提问应答、模型选择、文件树、改动列表与改动摘要 / diff、目标、斜杠命令、预设切换、子智能体提问/中断、附件与 @ 引用、开在服务端的终端
  • 远程会话里的产物文件可下载到本机(2.2.6):产出台卡片与文档预览头各一个「下载到本机」,经中继按窗口读取服务端文件字节后由浏览器落盘(任何大小的文件都走分段读取,不占满内存);Word/Excel/PPT 预览改由服务端 LibreOffice 出 PDF(officeToPdf/* 已登记进中继白名单),不再报「此功能暂不支持远程会话」
  • 远程会话可附加非图片文件:上传请求由子客户端在本机后台接住、经中继流式转到服务端会话;上限 500 MiB 是中继自定的(本机上传无此限),超限在子客户端本地即提示;慢速链路受客户端侧 15 分钟上传预算约束(宿主 HTTP 服务的 5 分钟请求期限才是实际上限:500 MiB 约需 14 Mbps 持续带宽)。拖拽进输入框的文件在远程会话里也走这条上传(桌面壳的 host-path 桥会被收敛,不再插成客户端本地路径);@ 里手打/粘贴(或拖拽插入)的客户端绝对路径在发送前自动物化到服务端的 ~/.dsh/tmp/prompt-attachments/<会话>/,并把消息里的路径原地改写为服务端绝对路径(模型用普通读文件工具去读;服务端已有同名路径则原样保留;旧服务端没有这条路由时退回附件回执;确实送不出去的文件会在消息里带一条明确的失败说明,不再静默变成不可读文本)
  • 远程会话里的模型下拉框显示服务端的模型目录(分组名「服务端名 · 分组名」),本机会话只显示本机模型;中继离线时保留上次拉到的服务端分组;视觉路由等本机设置里不会出现服务端分组。已知边界:服务端新建且未发过消息的会话,下拉框按本机默认模型显示
  • 远程分组里新建的会话跑在服务端对应工作区、自动开启远程;远程会话可改名、归档、置顶、分叉,也可从子客户端关闭其远程(带确认)
  • 远程会话标题行连接图标(在线 / 离线 / 版本有差异);会话被休眠或服务端关闭时显示「远程已关闭」及原因;服务端离线时分组变灰、输入禁用,后台自动退避重连
  • 审批/提问先到先得:服务端自己的界面先答了,子客户端自动同步成「已处理」

两端(2.1 新增)

  • 插件桥:其他插件登记一份桥接声明后,它的面板数据在远程会话里取自主服务端——子客户端本机把声明命中的 GET 请求改道到服务端,服务端以本机回环执行、流式交回,本机数据绝不混入远程会话。两端插件名、确切版本与声明一致才算已桥接;整机数据另需主服务端主人在设置页逐插件同意。接入指南见插件桥

深度说明:界面 · 公网接入 + 中继协议


版本容错

三层,从严到宽:

  1. 中继协议版本必须一致——实际操作上,两端 aug-remote 需为相同版本。服务端若还是 1.x,它的网关不认子客户端的 Bearer 令牌,请求会撞上通用配对墙,子客户端报「令牌已失效(或服务端 aug-remote 低于 2.0.0)」。DSH 版本可以不同。
  2. DSH 接口指纹决定其余:两端各自对中继会用到的几组远程接口生成规范化指纹,握手时比对。全部一致即完全兼容,版本号不同也无关;有差异照常连接,远程分组标注「(版本有差异)」,设置页诊断区列出差异组,只有受影响的面板降级。
  3. 运行时降级:某次转发调用因参数或结果校验失败,只有那个面板显示「与服务端版本不兼容」并记入诊断区,其余功能继续可用。

安全模型

一台已配对设备被信任到什么程度,明说:

  • 已配对的桌面应用端被视为可信设备。 远程会话里的终端是以服务端用户身份运行的 shell,不受智能体沙箱与审批限制。文件预览接口(workspaceFiles/read 等)不限制在会话目录内——服务端进程读得到的文件都读得到。已配对设备可以在服务端任意工作区新建会话(不受「开启远程」限制;新建的会话自动开启远程)。
  • 「只有开启远程的会话可见」约束的是会话数据:未开启远程的会话,其列表、历史、实时进度、审批/提问事件都被中继拒绝或过滤;@ 引用候选只列已共享会话;发消息、改写排队消息、斜杠命令里内嵌的 dsh-session: 会话引用一旦指向未开启远程的会话,整个调用被服务端拒绝。它不是围住整台机器的沙箱。
  • 管理操作只在服务端本机:生成配对码、改角色、吊销只能在跑服务端那台机器的设置页做——经网关进来的请求可以查看状态,但变更动作被拒——唯一例外是开关会话的远程:Web 应用端(手机)可以开关,手机信息卡片里的「远程访问」开关就走这条;桌面应用端根本够不到管理路由。

已知限制

  • 同时开多个 DSH 窗口(包括用浏览器打开桌面端的后台页面)时,子客户端对「当前打开的是哪个会话」可能判断不准:关闭远程的会话隐藏时机可能不对,极端情况下正打开着的会话会被当成后台会话、被踢回首页。
  • 换到另一台服务端后再换回原来那台,或服务端删除某工作区后又以同一 id 重建:相关远程分组要重载页面才会再出现(DSH 侧边栏对移除过的工作区 id,在页面生命周期内不再接受)。
  • 远程会话里「导出会话」已禁用(菜单项隐藏,后台对虚拟会话 id 一律拒绝);改动面板的摘要与 diff 可以看(经中继转发),但「打开 / 在访达中显示 / 在应用中打开」这类会在服务端机器上弹窗的入口在远程会话里隐藏(交付物卡片同理)。
  • @ 引用候选由宿主先截前 50 条再按共享过滤:服务端会话很多时,已共享会话可能不出现在候选列表里(不影响引用检查本身——直接写出的引用仍会被逐条校验)。
  • 第三方插件自己的接口要经插件桥才能在远程会话里工作:协作插件自行登记,第三方插件靠内置适配器。都没接的插件,其面板在远程会话里降级或隐藏(插件的工具跑在服务端,不受影响)。
  • 装了 dsh-better-sidebar 时,远程会话里它有两档处理:0.25.0、0.26.0、0.26.1、0.28.0-alpha.0 与 0.28.0 五版由内置适配器桥接——面板读写的是主服务端的数据(整机数据,需在主服务端设置页逐插件同意,见安全边界);其他版本维持隐藏——那些版本的面板读写的是子客户端本机的文件,且因为它接管了宿主的「文件」标签,未桥接的远程会话里侧栏文件 tab 显示「未桥接」说明占位;聊天或交付物里的文件链接在远程会话里会打开一个空的右栏。
  • 两端 aug-remote 需为相同版本(中继协议版本一致);DSH 版本可以不同,接口指纹有差异时远程分组标注「(版本有差异)」。

已知问题

iOS 26.x 独立 PWA 视口缩水:加到主屏后视口底部会少掉一条状态栏高度,普通 Safari 标签页正常。这是 iOS 系统缺陷,缺掉的区域在文档之外,CSS 够不着;本插件做了三层缓解(浅色 manifest 背景 + 安全区补偿 + 强制重排),能减轻但不保证复原。彻底恢复只能整个 App 退出重开。

个别环境软键盘对浏览器完全不可见,输入框抬升靠估算兜底:部分组合里系统不把键盘高度告知页面(visualViewport、VirtualKeyboard API 一并失效,均已实测排除)。插件聚焦后探测约 1.2 秒,判定「键盘不可见」就按估计高度抬升输入框。抬升高度差得明显的话,在设置页里调 keyboardLiftRatio / keyboardLiftMaxPx / keyboardSafetyPadPx。正常环境完全不走这条路径。

经反代访问时设置页打不开(插件配置列表空白、模型卡片报「settings are unavailable in this browser」):DSH 官方设计是设置类 RPC 只对回环连接开放,远程浏览器的设置镜像初始即 unavailable。绕法:回跑 DSH 的那台机器用本机浏览器改。经网关打开的插件设置页同样受此限制。与本插件无关。


权限与数据

  • 网络:网关只监听本机(默认 127.0.0.1:3088),对外暴露完全由你的反代/隧道决定;推送经浏览器推送服务商中转(aes128gcm 端到端加密);桌面应用端与主服务端之间的中继也走这条网关,授权在服务端逐请求复核。插件自身不向任何第三方上报数据。
  • 文件:附件上传只写入当前会话工作目录下的 .dsh-uploads/;配对状态在 ~/.dsh/lan-gate-state.json,配置在 ~/.dsh/lan-gate.config.json,共享表在 ~/.dsh/aug-remote-shares.json,服务端 id 在 ~/.dsh/aug-remote-server.json。
  • 凭据:不收集、不存储任何账号密码;设备身份是本插件自己签发的随机令牌(Web 应用端为 HttpOnly Cookie,桌面应用端为密钥字段),外加一枚每次加载现生成的中继共享密钥,不出这台机器对。

排障:运行日志在 ~/.dsh/logs/web.log(网关与推送的行带 [dsh-aug-remote-*] 前缀;桌面端构建打到 App 控制台)。安全问题请走 GitHub Security Advisories 私下报告,不要公开提 issue。


已适配的第三方插件

移动端 UI 对下列插件做了专门适配。所有适配都锚定对应插件自己的 DOM 标记;插件桥另算一类——插件自己登记声明即可(见插件桥),不依赖本表: 没装该插件时规则不生效,装了未列出的插件也不会被误伤。

| 插件 | 移动端适配内容 | 实测版本 | | --- | --- | --- | | dsh-better-sidebar | 0.19+:它的全部 tab 都在 DSH 0.1.5 官方右侧栏里、手机上宿主自己切全屏(避让刘海与底部指示条)——会话页头部留入口按钮,左缘回退手势收它,文件树里点 @ 引用后自动收起。≤ 0.18(自绘右栏,只在 DSH < 0.1.5 上):手机全宽抽屉并避让刘海安全区、底部居中的关闭按钮。插件桥:0.25.0、0.26.0、0.26.1、0.28.0-alpha.0 与 0.28.0 五版由 aug-remote 的内置适配器桥接——远程会话里它的文件 / git / 任务面板读写的是主服务端的数据(整机数据,需在主服务端设置页逐插件同意;等于让桌面应用端读写服务端整盘并执行 git 写操作,见安全边界);其他版本不桥接,远程会话维持「隐藏本机界面」的原有处理 | 0.19.1(老版规则 0.15.0;适配器 0.25.0, 0.26.0, 0.26.1, 0.28.0-alpha.0, 0.28.0) | | @nanmicoder/dsh-agent-teams | AgentTeams 活动浮层挪到会话头部下方(原位置压住头部按钮)、会话列表页自动隐藏;子代理会话头部保留可点的父会话标题,一键切回主会话 | 0.1.9 | | @ychris12138/dsh-usage-stats | 用量与余额入口收进主屏 chips 行 | 0.2.9 | | @opendsh/dsh-plugin-scheduled-tasks | 定时任务入口收进主屏 chips 行 | 0.2.3 | | dsh-at-file | @文件引用,配合附件上传的 @ 路径引用使用;它和本插件的附件 chip 读同一份草稿 token,手机端隐藏它 .dsh-uploads/ 下那几行以免同一个文件被画两遍(缩略图 + 文件名),其余 @ 引用不动 | 0.6.7 | | @ace-zone/dsh-market | 插件市场弹窗顶栏在手机上放不下,关闭的 × 被挤出面板外(触屏没有 Esc,等于关不掉);隐藏标语 / 版本号 / 官网链接三个装饰位,标题改成省略号收缩,语言切换和 × 保留并加大点按面积 | 0.1.66 | | dsh-vision-toolkit | 图像 Q&A/OCR,配合手机端附件上传使用 | — | | dsh-web-ui 全家桶 | 沿用上游 dsh-web-mobile 的兼容规则(文件树 / 预览浮层限宽居中等) | — |

混合版本——桥接与否逐端判定:桥不桥看服务端装的 better-sidebar 版本(在适配器版本表里 + 主人同意);界面发什么请求看子客户端自己的版本(UI 在本机加载);两端 aug-remote 不同版则适配器摘要比对失败、退隐藏档:

(旧 aug-remote + 服务端 BS 0.25 + 客户端 BS 0.25 即当前已发布版的现状,照常桥接。)

| 两端 aug-remote | 服务端 BS | 客户端 BS | 结果 | | --- | --- | --- | --- | | 新(含 0.26 适配) | 0.26 | 0.26 | 全量桥接,新功能全可用 | | 新 | 0.25 | 0.25 | 照常桥接,行为与旧版一致 | | 新 | 0.25 | 0.26 | 桥接;0.26 新方法与 /sidebar/write 被 0.25 服务端 404、ws/sidechat 被拒后走 15s 轮询——单功能降级,核心侧聊通,不误路由不写本机 | | 新 | 0.26 | 0.25 | 桥接;UI 不发新请求,等同 0.25 体验 | | 旧(≤ 2.2.1) | 0.26 | 任意 | 不在适配器版本表 → 未桥接隐藏档 | | 旧 | 0.25 | 0.26 | 按 0.25 桥接;新方法被适配器以 adapter-method-unknown 拒绝,/sidebar/write 带虚拟 id 落本机插件报错(不写文件)——单功能降级 | | 一新一旧 | 任意 | 任意 | 核心远程会话可用,适配器摘要不同 → 桥接比对失败 → 隐藏档,直到两端同版 |

各项适配的技术细节(锚点选择器、断点、取舍记录)见界面文档的「兼容插件」一节。


上游致谢

本插件的界面层衍生自 mexiaosqwq/dsh-web-mobile,通道层衍生自 zylzyqzz/dsh-mobile-pwa(其自身衍生自 Bernardxu123/dsh-mobile-gate),均为 MIT,原始版权行保留在 LICENSE。

License

MIT