dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
把本机的 DeepSeek Harness 装进口袋。
在手机上继续会话、盯住流式输出、回答问题与审批、下载产物。
轻量界面为小屏重写;需要完整桌面能力时,一键直通宿主 Web GUI。
Pocket Access 是 DeepSeek Harness 的移动端伴侣插件。插件列表与侧栏的显示名为 随身访问;包名为
@restregular/dsh-pocket。English — A mobile companion for DeepSeek Harness. It serves a purpose-built phone UI and can reverse-proxy the full desktop GUI, with live sessions, prompts, tool approvals, file downloads, LAN/tunnel access, one-tap keep-awake, and one-tap restart or shutdown of DSH.
DeepSeek Harness 的 Web GUI 为桌面设计。Pocket 不要求你在手机上重新适应一套缩水界面,也不要求插件作者为移动端再写一遍 UI;它提供两条互补的路径:
ws;二维码编码器随包内嵌,不需要前端构建链。| 类别 | 能力 |
|---|---|
| 会话 | 按桌面工作区顺序分组、折叠、搜索、新建、置顶、重命名、归档/取消归档、复制 Session ID |
| 实时对话 | WebSocket 流式输出、历史快照分批到达、思考过程折叠、工具调用参数与结果、token 用量 |
| 远程控制 | 发送 / 排队 / 插话、停止回合、模型与思考等级、权限预设、/技能 引用 |
| 人机交互 | 阻塞式提问直接作答、工具审批「允许一次 / 拒绝」、跨会话提醒、手机回答后撤回桌面弹窗 |
| 文件与媒体 | 工作区文件树、文本/图片预览、@路径 引用、文件下载到手机、最多 4 张图片消息与本地压缩 |
| 外观与体验 | 跟随系统 / 浅色 / 深色、历史截断设置、回到底部、PWA 主屏幕图标 |
| 宿主能力 | 账户余额、保持电脑常亮、一键重启/关闭 DSH、桌面 Pocket 面板、扫码连接、令牌轮换 |
| 远程访问 | 局域网、Cloudflare、localtunnel、localhost.run、自有服务器 SSH、自定义隧道、固定 publicUrl |
Pocket 的核心差异是:手机界面不是桌面界面的降级版,而是一个可切换的完整方案。
| 轻量界面(默认) | 桌面直通 | |
|---|---|---|
| 首屏 | 为小屏重写的会话列表与聊天流,加载快 | 完整的桌面 bundle(含全部插件) |
| 插件 UI | 重写核心会话、文件、审批流程 | 插件面板、设置、终端、市场原样复用 |
| 适合 | 日常查看、回复、审批、下载产物 | 需要桌面专属功能或第三方插件界面 |
| 代价 | 新插件不会自动出现在轻量页 | 首屏更大;触摸交互不如原生移动页顺手 |
| 切换 | 手机设置 →「界面」;或桌面 Pocket 面板 →「设置 → 手机端界面」 | 同上,也可访问 GET /__pocket/surface?to=desktop |
桌面直通不是简单的 iframe:Pocket 把宿主 Web GUI 整页反向代理给手机,并处理两层认证——手机仍先过 Pocket 令牌/Cookie,Pocket 再用进程启动令牌换取绑定回环 authority 的 GUI Cookie。隧道地址变化不影响使用。
![]() 会话列表 · 工作区分组、搜索、置顶与归档 |
![]() 实时对话 · 流式输出、思考过程、工具卡片与 Markdown 表格 |
![]() 文件下载 · 预览底部、文件树每行都能直接保存到手机 |
![]() 界面切换 · 轻量界面与桌面直通,按场景选择 |
截图使用演示会话、演示余额与演示地址;二维码和令牌均为示例,真实值以你本机面板显示为准。
@restregular/dsh-pocket,或使用本地目录安装。装好后建议把手机页面「添加到主屏幕」;iOS 使用 180/192 PNG 图标,避免 SVG 在主屏幕上显示空白。
一条命令从 npm 安装(Web profile):
dsh plugin --profile web add @restregular/dsh-pocket
也可以在 Plugin Manager →「安装 Bundle」里安装(或调用 plugin_manager 的 install_bundle),包名:
@restregular/dsh-pocket
也可以安装本目录(Plugin Manager →「本地目录安装」):
D:\DeepseekHarnessProjects\dsh-pocket
本包以
link:方式安装到 profile 时,pnpm 不会替被链接的目录安装它自己的可选依赖。若要让 Windows x64 自动带上 cloudflared,请先在本目录执行一次pnpm install(只影响本目录的node_modules)。从 npm 正式安装时这一步由包管理器自动完成。
也可以手动复制面板里的「本机 / 局域网 / 公网」地址。
链接里带有访问令牌,等同于本机 DSH 的钥匙。 不要发到公开群聊或截图分享。令牌泄露时,在面板点「轮换令牌」;旧链接会立即失效。
| 方式 | 适合 | 说明 |
|---|---|---|
cloudflared(推荐) | 大多数场景 | Quick Tunnel 无需账号,没有浏览器拦截页。Windows x64 会通过可选依赖 agentroam-cloudflared-win32-x64 使用经过校验的官方二进制;其他平台把 cloudflared 放进 PATH,或设置 cloudflaredPath。 |
localtunnel | 已有 lt 命令 | 浏览器首次访问会经过 localtunnel 的 511 提示页,需要输入本机公网 IP 作为 tunnel password。 |
localhost.run | 出站 22 端口可用 | 通过 ssh -R 建立隧道,不需要额外客户端。 |
ssh | 有自有服务器 | 不要求服务器开启 GatewayPorts,也不改 sshd;见下一节。 |
custom | 已有 frp / rathole 等 | 任何能在 stdout/stderr 打印公网 URL 的命令都行,%PORT% 会替换成本地端口。 |
publicUrl | 已有反向代理/固定域名 | 直接使用固定地址,不再起隧道进程。 |
auto 会按 cloudflared → localtunnel → localhost.run 的顺序尝试;失败原因会显示在面板的「隧道输出」里。
部分网络(例如只返回 AAAA 记录的 DNS)可能让
*.trycloudflare.com在电脑本机解析失败,但手机走自己的 DNS 通常正常。若手机也打不开,改用局域网地址或切换隧道方式。
tunnel: ssh 只要求服务器能免密 SSH 登录并装有 Node.js:
-R 127.0.0.1:sshRemotePort:127.0.0.1:<本地端口>。sshExposeHost:sshExposePort,转发到 127.0.0.1:sshRemotePort。sshPublicUrl;未设置时访问 http://<sshHost>[:sshExposePort]。tunnel: ssh
sshHost: 203.0.113.10
sshUser: root
sshKeyPath: ~/.ssh/id_ed25519
sshPort: 22
sshRemotePort: 8790
sshExposePort: 80
# 可选:有域名/HTTPS 反代时填写
# sshPublicUrl: https://pocket.example.com
也可以完全不动 YAML:桌面 Pocket 面板的「公网入口」选「自有服务器」,填 IP/域名,点「切换」。切换会重启隧道并更新二维码;再选「Cloudflared(默认)」即可切回。
要求:sshExposePort 在服务器防火墙和云安全组中放行。
sshRemotePort只在服务器回环上使用,不对外暴露。如果服务器上还留着上一条 SSH 会话没释放的半开连接(本机崩溃、休眠或换网络后很常见),sshd会报remote port forwarding failed for listen port 8790;插件会先等 1 秒用原端口重试,仍冲突就自动换一个 20000–60000 的随机回环端口,不必手动清理服务器,面板日志里会注明「被占用,改用 …」。只有连随机端口也失败时才会报错。
直接监听公网 80 时是 HTTP,令牌和会话内容会以明文经过网络。生产使用建议让
sshExposeHost: 127.0.0.1,在服务器上用 Nginx/Caddy 做 HTTPS 反代,并把sshPublicUrl指到 HTTPS 地址。
状态文件保存访问令牌、创建时间、面板选中的局域网 IP、公网入口和「保持电脑常亮」开关:$DSH_HOME/pocket/state.json(默认 ~/.dsh/pocket/state.json)。端口、隧道地址每次启动重新协商。
workspaceController 的工作区顺序和会话归属分组;工作区可折叠/展开并记住状态;标题右侧的 + 直接在对应目录新建会话;空会话(点过新建但没发消息)不显示;顶部按钮切换是否显示已归档会话;支持搜索会话、工作区和目录。Enter 发送、Shift+Enter 换行;运行中显示停止按钮;发送时跟随桌面的 ui-conversation.busyEnter 选择排队或插话。/技能 引用。@路径 引用插入输入框(含空格的路径自动写成 @"...",目录带尾斜杠)。user-questions/request 与 approval/request waterfall;前台阻塞提问可直接作答,工具审批可选择「允许一次 / 拒绝」。手机切到任意会话时,WebSocket 会补发该会话仍在等待的提问/审批;手机作答后桌面端残留的弹窗会同步撤掉。continued 提问仍从投影显示。手机离线时自动回落到桌面 answerer。SetThreadExecutionState,macOS 用 caffeinate,Linux 用 systemd-inhibit;选择持久化,DSH 退出即释放。桌面端和 dsh web 的页面本来就是同一份渲染代码(@deepseek-ai/dsh-web-frontend + 宿主注入的插件 client bundle)。打开桌面直通后:
Host/Origin,所以隧道地址怎么变都不影响。workspaceRegistry.create() 落库,再刷新页面显示新工作区。GET /__pocket/surface?to=desktop|mobile。代价:首屏是完整的桌面 bundle(含所有插件),比轻量页大一个量级,弱网首次打开更慢;终端、拖拽、右键菜单等桌面交互在触摸屏上体验一般;插件自己写的 fixed 浮层可能仍会挡住内容;Electron 专属能力(例如「在文件管理器中打开」)在浏览器里会降级。
dsh web 这类命令行运行方式不支持从 Pocket 重启,界面会自动隐藏入口。
状态概览、公网入口、局域网 IP、双二维码与安全设置集中在一处
X-Pocket-Token 请求头三种携带方式。面板可一键轮换,旧令牌立即失效。/dsh-pocket 路由只接受回环请求,不对局域网/公网开放。realpath 二次校验。下载不会把 Pocket 变成任意文件读取器。插件行 id 为 dsh-pocket,默认配置见 cordis.patch.yml。
| 字段 | 默认 | 说明 |
|---|---|---|
port | 8790 | 移动端监听端口;被占用时自动向后找 10 个端口。0 表示随机端口。 |
lan | false(本仓库 patch 里为 true) | 是否绑定 0.0.0.0 允许局域网访问;关掉时只绑 127.0.0.1,但隧道仍可用。 |
tunnel | auto | auto / cloudflared / localtunnel / localhost.run / ssh / custom / off。 |
autoStart | true | Host 启动后是否自动拉起隧道。 |
publicUrl | 无 | 已有反向代理或固定域名时直接使用它,不再起隧道进程。 |
cloudflaredPath | 无 | 指定 cloudflared 可执行文件;留空时优先用随包二进制,其次 PATH。 |
customCommand | 无 | tunnel: custom 时执行;%PORT% 会被替换成本地端口,输出里第一个公网 URL 视为就绪。 |
sshHost | 无 | 自有服务器地址;设置后可将 tunnel 设为 ssh。 |
sshUser | root | SSH 用户名;请使用免密公钥登录。 |
sshPort | 22 | SSH 端口。 |
sshKeyPath | 无 | SSH 私钥路径;支持 ~/...。 |
sshRemotePort | 8790 | SSH 在服务器 127.0.0.1 上绑定的反向转发端口;被旧会话占用时会在原端口重试并自动改用随机回环端口。 |
sshExposePort | 80 | 服务器上 Node TCP 代理监听的公网端口;需在防火墙/安全组放行。 |
sshExposeHost | 0.0.0.0 | 服务器 TCP 代理绑定地址;若用 Nginx/Caddy 反代可设为 127.0.0.1。 |
sshPublicUrl | 无 | 自有域名/HTTPS 入口;设置后二维码使用它,而不是 http://<sshHost>:<sshExposePort>。 |
token | 自动生成 | 固定访问令牌;留空时使用 ~/.dsh/pocket/state.json 里持久化的令牌。 |
keepAwake | false | 启动后自动保持电脑不休眠;也可以随时在桌面面板或手机顶栏开关,面板上的选择优先。 |
keepAwakeDisplay | true | 常亮时是否同时阻止屏幕关闭;设 false 只阻止系统睡眠(Windows/macOS)。 |
surface | mobile | 手机端默认界面。mobile 是 Pocket 自带轻量页;desktop 直接把桌面 Web GUI 整页反代给手机。面板里的选择优先并持久化。 |
mobileLayout | true | 桌面直通时是否注入窄屏适配样式与抽屉脚本。可在面板「设置 → 窄屏适配」里随时关闭。 |
移动服务(默认 8790)除 /healthz 外都需要令牌。需要自动化或调试时再展开:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | / | 移动页面(无令牌时显示解锁页)。 |
| GET | /api/balance | 当前账户余额与赠金;?force=1 绕过 60 秒缓存。未登录/API Key 模式返回 available: false。 |
| GET | /api/display | 当前手机端显示/截断设置(三个开关 + limit 字符数)。 |
| POST | /api/display | 更新显示/截断设置,{ "truncateTools", "truncateAssistant", "truncateReasoning", "limit" };未传字段保持不变,长度限制在 500–50000。 |
| GET | /api/sessions | 会话列表,同时返回 workspaces / unassigned / archived / pinned 分组和 pending(等待回答的提问/审批摘要)。 |
| POST | /api/sessions | 新建会话,{ "cwd": "..." }。 |
| POST | /api/keep-awake | { "enabled": true | false },打开/关闭宿主的「保持电脑常亮」,返回最新 awake 状态。 |
| POST | /api/restart | 一键重启整个桌面 DSH;响应先返回 { "ok": true, "restarting": true },约 1.5 秒后进程重启。仅 Electron 桌面版可用,dsh web 返回 500 与原因。 |
| POST | /api/shutdown | 一键关闭整个桌面 DSH(不再自动拉起);响应先返回 { "ok": true, "shuttingDown": true },约 1.5 秒后进程退出。仅 Electron 桌面版可用。 |
| GET | /api/sessions/:id | 标题、目录、运行状态。 |
| POST | /api/sessions/:id/pin | { "pinned": true | false },置顶/取消置顶。 |
| POST | /api/sessions/:id/archive | { "stopActivity": true } 可先停止仍在跑的工作;被拒绝时返回 409 与 code: "workspace/session-active"。 |
| POST | /api/sessions/:id/unarchive | 取消归档。 |
| POST | /api/sessions/:id/rename | { "title": "..." },钉住会话标题。 |
| WS | /ws/session/:id?token=... | 会话流:hello、snapshot-meta / snapshot-batch / snapshot-end、frame;以及 question-request / approval-request / interaction-closed 前台交互。 |
| WS | /ws/events?token=... | 首页全局事件流:连接时补发 interactions,之后推送 interaction-pending / interaction-update / interaction-resolved。 |
| GET | /api/sessions/:id/follow | SSE 版本,保留给 curl/调试;部分隧道会缓冲 SSE 响应。 |
| GET | /api/sessions/:id/page?throughSeq=&beforeSeq= | 历史翻页。 |
| POST | /api/sessions/:id/prompt | { "text": "...", "mode": "auto" | "queue" | "steer", "images": [{ "mediaType", "data", "name" }] };图片请求体上限 32 MB。 |
| POST | /api/sessions/:id/cancel | 停止当前回合。 |
| GET | /api/sessions/:id/controls | 模型目录/当前选择、权限目录/当前预设、用户可见技能。 |
| POST | /api/sessions/:id/model | { "provider", "model", "reasoningEffort" }。 |
| POST | /api/sessions/:id/permissions | { "preset": "..." }。 |
| GET | /api/sessions/:id/questions | userQuestions 投影的 active/settled 提问。 |
| POST | /api/sessions/:id/questions/:callId/answer | { "answers": [{ "id", "selected", "custom" }] },回答 continued 提问。 |
| POST | /api/sessions/:id/interactions/:requestId/answer | 回答前台阻塞提问(answers)或审批(outcome: "allowed-once" | "rejected")。 |
| GET | /api/sessions/:id/attachments/:attachmentId | 读取会话图片附件;加 ?download=1 时以附件形式下载。 |
| GET | /api/sessions/:id/file?path=preview/x.png | 读取会话工作区内的图片,供 Markdown 相对路径图片使用。 |
| GET | /api/sessions/:id/download?path=dist/app.zip | 下载会话工作区文件;只允许 cwd 子树。 |
| GET | /api/sessions/:id/files?path=src | 列出会话工作区里的一层目录。 |
| GET | /api/sessions/:id/text?path=src/app.js | 文本预览(最多 400 KB);图片返回 image: true,二进制返回 binary: true。 |
| GET | /api/workspace/files?root=...&path= | 首页工作区文件树;root 必须是已登记的工作区。 |
| GET | /api/workspace/text?root=...&path= | 首页工作区文件预览。 |
| GET | /api/workspace/download?root=...&path= | 首页工作区文件下载。 |
| GET | /workspace/file?root=...&path= | 首页文件树里的图片预览。 |
| GET | /__pocket/download?session=...&path=... | 手机端通用下载入口;桌面直通的预览/文件列表按钮走这里。 |
| GET | /__pocket/surface | 当前界面模式:{ surface: "mobile" | "desktop", desktopAvailable }。 |
| POST | /__pocket/surface | { "surface": "mobile" | "desktop" },切换并持久化。 |
| GET | /__pocket/surface?to=mobile|desktop | 切换后 303 回首页,供无脚本场景使用。 |
| GET | /__pocket/fs?path= | 手机目录选择器:列出本机某个目录的子目录。 |
| POST | /__pocket/workspace | { "path": "D:\\projects\\app" },验证目录后新建工作区。 |
桌面面板路由只接受回环请求:GET /dsh-pocket?op=status;POST /dsh-pocket 支持 tunnel-start、tunnel-stop、tunnel-restart、switch-tunnel、rotate-token、set-lan、keep-awake、set-display、set-surface、set-mobile-layout、restart(只重启 Pocket 移动服务)、restart-dsh(重启整个 DSH)、shutdown-dsh(关闭整个 DSH)。
模型工具 pocket_share 会把当前手机入口地址交给模型,方便用户直接要链接。
origin: subagent)不单独展示。powershell.exe,缺失时回退 pwsh.exe);Linux 需要 systemd-inhibit。node --check lib\index.js
node --check lib\server.js
node --check lib\tunnel.js
node --check lib\awake.js
node --check web\app.js
node --check client\client.js
pnpm install # 拉取 ws,以及 Windows x64 的可选 cloudflared 二进制
lib/index.js 负责配置、生命周期与桌面面板路由;lib/server.js 是移动 HTTP/WS 服务;lib/tunnel.js 管理隧道子进程;lib/awake.js 与 lib/awake-win.ps1 负责保持电脑常亮。web/(原生 ESM,无构建)。client/client.js,注册 sidebar.panellist 与 main 两个 slot。手机浏览器
│ Pocket 令牌 / HttpOnly Cookie
▼
PocketServer(默认 127.0.0.1:8790)
├─ 轻量页 /api/* + /ws/* ────→ DSH Host 服务
│ sessionController / workspaceController / sessionQuery …
└─ 桌面直通:整页反代 ───────→ dsh web GUI(回环地址)
▲
└─ 仅 Pocket 进程持有 GUI Cookie
公网/局域网入口:cloudflared · localtunnel · localhost.run · SSH 反向转发 · 自定义命令
Pocket 不复制 DSH 的会话数据:轻量页通过宿主服务读取快照与事件;桌面直通则只做代理。两条路径共享同一份令牌、文件访问边界和 Host 状态。
Cloudflare Quick Tunnel 会缓冲小的 SSE 响应:手机打开会话时历史快照迟迟不落地,直到用户发送一条消息把缓冲区推过阈值,历史才突然出现。把历史拆成 snapshot-meta / snapshot-batch / snapshot-end 并改走 WebSocket 后,快照和实时帧都能立即到达;/api/sessions/:id/follow 的 SSE 版本仍保留给 curl 调试。
宿主会把多个 Client 插件拼进同一个 <script> 批次。各插件 bundle 的顶层 const 共享全局词法作用域——本插件最初在顶层声明了 const MODULE_ID,与 @restregular/dsh-skill-center 撞名,导致整条 web boot 报 Identifier 'MODULE_ID' has already been declared。现在整个 client/client.js 包在 IIFE 里;新增 Client 插件时也应该这样做。
node --check 和 pnpm install。MIT。随包内嵌的二维码编码器与 cloudflared 二进制的许可见 THIRD_PARTY_NOTICES.md。