- Home
- Plugins
- Integrations & Remote
- dsh-console-plugin
dsh-console-plugin
chenjun25/dsh-console-plugin
Pair a phone with this computer's DSH instance by QR code or a six-digit code, then drive it remotely — send instructions, view images, answer approvals — from the panel, with public-tunnel support for pairing across networks.
Install
dsh plugin --profile web add github:chenjun25/dsh-console-pluginREADME
DSH控制台面板(dsh-console)
在 DSH 里加一块配对面板:手机扫一下二维码(或输 6 位码)就连上这台电脑的 DSH, 之后在手机 App 里收发会话、看历史、传文件。手机不在同一个网络时走公网隧道。
全部能力都在本机跑(局域网服务 + DSH 自己的会话服务),局域网内使用不依赖任何云端。
配套 App:鸿蒙「DSH控制台」
本插件是电脑这一侧,手机端要装鸿蒙 App 「DSH控制台」 配合使用。 App 只在应用商店下载,本仓不提供安装包。
能干的事
| 能力 | 说明 |
|---|---|
| 扫码配对 | 面板出二维码,手机 App「扫一扫」直接连上。二维码里是一次性票据,5 分钟过期、兑换即焚,长期访问码不进二维码 |
| 6 位码配对 | 面板出 6 位数字,App 里输进去就行,手机自己找同一网络里的电脑,不用填 IP。码 15 分钟有效,用掉即作废 |
| 异地配对 | DSH 装在云服务器 / 手机和电脑不在同一 WiFi 时,打开「异地配对」开关,面板给出 6 位异地配对码,App 输进去也能连 |
| 公网访问 | 开通公网访问服务后,手机在蜂窝网也能连回这台电脑(隧道由插件自己拉,不用另装东西) |
| 状态灯 | 顶部主卡两盏:手机连没连、这台电脑的 DSH 会话服务通不通,互不干扰 |
| 升级卡 | 面板里直接显示 npm 上的最新版号,能一键升级 / 回滚 |
| 网页聊天 | DSH 侧栏底部多一个「网页聊天」入口,把网页版对话放进右侧栏,和会话并排 |
安装
方式 A · 一条命令装(推荐)
dsh plugin --profile web add dsh-console-plugin
--profile 后面写你自己的 profile 名(默认是 web)。这个参数不能省,省掉会直接报
required option '--profile <name>' not specified。
刚发的版本有时会装到上一个,那是 pnpm 的「最小发布龄」供应链策略在拦新包,等一会儿再装, 或者指定版本号 / 关掉这条策略:
dsh plugin --profile web add dsh-console-plugin@latest --config.minimumReleaseAge=0
方式 B · 插件页安装
DSH 侧栏 → 插件 → 「添加插件」→ 选 dsh-console-plugin-<版本>.tgz。
方式 C · 写进 profile(开发用)
profile 的 package.json 里:
"dependencies": { "dsh-console-plugin": "link:<你的插件目录绝对路径>" }
再把 "dsh-console-plugin" 加进该文件的 dsh.profile.bundles 数组,然后跑一次 pnpm install。
⚠️ 不要在 profile 的
cordis.patch.yml里再写一遍insert。 loader 行放在包自己的cordis.patch.yml里(包里已经带了)。 profile 那个文件只放 id 定向的配置覆盖 —— 重复 insert 会让插件加载两次。
配置项(一般不用动)
写在 profile 的 cordis.patch.yml 里,按 id 定向覆盖:
- id: dsh-console
config:
port: 8899 # 局域网服务端口
name: "我的电脑" # 面板上显示的节点名,默认取系统主机名
allowShiftPort: false # 端口被占用时要不要自动往后顺延
面板上有什么
挂在 设置 → 导航列表 → DSH控制台,也挂在插件页的配置区,侧栏底部还有两个入口。
┌──────────────────────────────────────────────────────────────┐
│ [DFY] DSH控制台 ● 手机 · 刚刚活跃 ● DSH 正常 │
│ DeepSeek Harness · 我的电脑 │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ 扫码连接 [ 刷新二维码 ] [ 展开 ] │
│ ┌──────────┐ │
│ │ 二维码 │ ← 折叠区,点「展开」才显示 │
│ └──────────┘ │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ 6 位配对码 │
│ ╔═══════════════╗ │
│ ║ 627681 ║ ← 方框包住,15 分钟倒计时 │
│ ╚═══════════════╝ [ 换一个新码 ] │
│ 有效 12:34,用掉即作废 │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ 异地配对 [ 开关 ] │
│ 默认只允许同一局域网内配对。DSH 部署在云服务器 / 异地时打开。│
│ ── 打开后才出现 ── │
│ 异地配对码 ****** 👁 剩余 09:12 [ 换一个码 ] │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ 插件升级 当前版本 x.y.z [ 检测更新 ] [ 升级 ] [ 回滚 ] │
└──────────────────────────────────────────────────────────────┘
┌───────────────────────────┬──────────────────────────────────┐
│ 局域网直连 ● 已连接 │ 公网访问 ○ 未开通服务 │
└───────────────────────────┴──────────────────────────────────┘
两盏灯是两回事,别混:
- 手机 · 刚刚活跃 / 手机 · 未连接 —— App 在前台时每 60 秒有心跳;切后台/锁屏后心跳停。 只要最近 10 分钟内来过请求就算连着。未连接标灰,不算错误(可能只是还没配对)。
- DSH 正常 / 连不上 DSH:… —— 这台电脑进程内能不能拿到会话服务,跟手机通不通完全无关。 手机连不上时先看这盏:它红了是电脑的问题;它绿而手机灯灰,才是网络/配对的问题。
配色全部走主题变量(--dsw-alias-*),深色 / 浅色主题都跟着走。
侧栏两个入口:
- 底栏「DSH控制台」—— 打开上面这块面板。真有新版本时图标上会带一个「可更新」小徽标。
- 底栏「网页聊天」—— 在右侧栏开一个网页聊天标签页,内容就是 chat.deepseek.com。 只在 DSH 桌面端可用(需要宿主提供 webview 通道);加载失败会显示「重新加载」按钮。
怎么配对
同一个网络(最常见)
手机 App → 电脑节点 → 二选一:
| 方式 | 操作 |
|---|---|
| 扫一扫 | 对着面板二维码点「扫一扫」,扫完直接连上 |
| 输 6 位码 | 把面板上那 6 位数字输进去,手机自动找同一网络里的电脑,不用填 IP |
不在同一个网络
前提:先开通公网访问服务。
- 面板上打开「异地配对」开关(默认关,安全闸门)
- 下面会冒出一张「异地配对码」卡,6 位数字,15 分钟自动换一个
- 手机 App 输这个码就能连上
开关打开期间,任何拿到你公网地址的人都能尝试配对 —— 票据 5 分钟一次性、 异地码 15 分钟作废、公网来源输错 20 次锁 15 分钟。配好之后建议把它关掉。
公网访问与隧道
- 公网访问靠 frpc 这个独立可执行文件。需要时插件自动下载到
~/.dsh/frp(Windows 下是frpc.exe),下载后先对 size、再对 sha256,任何一项不符一律不落盘。 - 下载失败(没网 / 取不到清单 / 校验不过)时,「公网访问」卡下面会直接显示原因。
也可以自己把 frpc 丢进
~/.dsh/frp手动解决 —— 用户手放的 frpc 永远优先,插件不会覆盖。 - 没开通公网访问服务的用户完全不受影响:不下载、不启动,面板上也不会多出东西。
端口
局域网服务默认 8899。6 位码那条路手机侧只探 8899,所以:
- 端口被占时插件直接启动失败并打出该怎么办的日志,不偷偷挪(偷偷挪会让手机扫不到这台电脑)。
- 确实要换端口,配
"port": 8900,并且让手机端同步改。 "allowShiftPort": true才会恢复「占用就往后顺延 20 个端口」的行为,一般不需要。
接口
局域网路由(手机连这个)
前缀无、端口 8899,请求带 ?token=<访问码> 或 x-dsh-console-token 头。
| 路径 | 方法 | 要访问码 | 作用 |
|---|---|---|---|
/qr | GET | 否 | 二维码 PNG |
/claim | POST | 否 | 6 位码 / 异地配对码换访问码。错码 403、格式错 400、超限 429,成功即核销 |
/pair/ticket | POST | 否 | 一次性票据换访问码(body {"ticket":"pt_…"})。票 5 分钟过期、用一次即焚 |
/newcode | GET | 否 | 换一张新码 |
/info | GET | 是 | 节点信息(设备表 / 隧道 / 公网候选 / 会员状态摘要) |
/sessions | GET | 是 | 读 DSH 会话列表 |
/attachment | GET | 是 | 取附件 |
/cmd | POST | 是 | 下指令(会话收发、切模型、文件浏览、插件清单、队列、升级…) |
/cloud/status /cloud/bind /cloud/redeem | GET/POST | — | 公网短 ID 与兑换码续期 |
/mp/api/* /mp/pair/accept | — | — | 手机端专用通道(RPC + WebSocket 复用) |
错误一律 {ok:false, error:"…"},不抛异常。公网配对失败时额外带一个 reason 字段
(remote-pair-off 开关没开 / need-vip 会员没开 / code-mismatch 码不对过期 /
too-many 尝试过多 / bad-format 格式错),方便 App 给不同提示。
面板数据路由(DSH 客户端半边读这个)
前缀 /api/dsh-console,走 DSH 自己的 connection.fetch.register,
带 DSH 的浏览器认证层,所以裸 curl 会 401 —— 这是对的,不是 bug。
| 路径 | 方法 | 作用 |
|---|---|---|
/api/dsh-console/state | GET | 二维码、6 位码、异地配对状态、连线状态、升级状态 |
/api/dsh-console/newcode | POST | 换一张新码 |
/api/dsh-console/sessions | GET | 会话列表(App / 排查用) |
/api/dsh-console/cmd | POST | 下指令(App / 排查用) |
面板自己只读前两条,后两条留给手机端和排查。
二维码里装的是什么
dsh-console://pair?b=http://192.168.x.x:8899&k=pt_<32位hex>&n=<节点名>&i=dsh-console&c=<公网候选>&v=<每次不同>
b局域网地址(云服务器部署时会变成云内网地址,这时要用异地配对码)k一次性配对票据,不是长期访问码c公网候选地址(逗号分隔),手机断 WiFi 时靠它兜底v每次都不同,只为让二维码刷新时真的重画
安全说明
- 二维码和 6 位码都在这台电脑的屏幕上,看得到就等于能配对 —— 别在共享场合开面板
- 没有网页版配对页:
/、/pair、/web、/pet一律 403,配对只走手机 App - 二维码里是一次性票据,截屏也没用(5 分钟过期、用一次即焚)
- 6 位码 / 异地配对码都是一次性的:换成访问码立刻作废
/sessions、/cmd、/attachment这些能操控 DSH 的路由必须带访问码- 访问码每次进程重启会变,二维码和 6 位码里都带着它,所以自动跟着更新
- 公网来源(带转发头)默认只能走带访问码的路由,且要会员有效;免鉴权的配对页默认一律拒绝
- 同一个网络里拿到访问码的人可以操控这台电脑,访问码别外传
自测
node test/selftest.mjs
不需要装进 DSH 就能跑。 需要源码仓里的 test/ 目录(npm 包里只带 lib/,不带测试脚本)。
验 10 组:载荷格式、6 位码一次性、二维码真能出图、/claim 通路、
配对页已彻底删除、安全边界(401/403)、端口被占时必须报错而不是偷偷换、
客户端半边契约、宿主半边契约(必须 connection.fetch.register + sessionController.prompt)、
包清单(files 里的文件都得存在)。
自测自己占 18777 和 18888,不碰 8899,所以插件正常跑着也能跑自测。
文件结构
dsh-console-plugin/
├─ package.json 插件清单(dsh.client.inject / peerDeps / files)
├─ cordis.patch.yml bundle patch(insert → lib/index.js)
├─ lib/
│ ├─ index.js 宿主半边:读 sessionController + 起局域网服务 + 注册 Fetch 路由
│ ├─ client.js 客户端半边:面板 UI、侧栏入口、网页聊天页、中英文案
│ ├─ lan-server.mjs 局域网 HTTP 服务:配对码、票据、业务路由、公网闸
│ ├─ tunnel.mjs 隧道生命周期(frpc 的启停)
│ ├─ frpc-bootstrap.mjs frpc 自动下载 + sha256 校验
│ ├─ cloud-link.mjs 云链路:短 ID、会员状态快照
│ ├─ dsh-console-cloud.mjs 版号检测 + 一键升级 / 回滚
│ ├─ mp-*.mjs 手机端:协议契约 / RPC 分发 / 路由 / 长连接 / 附件
│ ├─ attachments.mjs 附件登记表
│ └─ websocket.js 最小 WebSocket 实现
├─ test/ 自测
└─ README.md 就是本文件
MIT License · 作者 CJ
Related plugins
dsh-web (dsh-ssh)
zhu1090093659/dsh-web
dsh-web (dsh-remote-web-ui)
zhu1090093659/dsh-web
dsh-web-ui (dsh-ssh)
zhu1090093659/dsh-web-ui
dsh-web-ui (dsh-remote-web-ui)
zhu1090093659/dsh-web-ui