dsh-pip
v0.1.1
Published
Detach the DeepSeek Harness Web GUI into a Document Picture-in-Picture window: a floating button moves the whole app into an always-on-top window and back
Maintainers
Readme
dsh-pip
为什么做这个
DSH 的 Web 界面活在一个浏览器标签页里——想同时写代码又盯着 Agent,就得在编辑器和标签页之间来回切窗口。dsh-pip 用 Document Picture-in-Picture 把整个应用(不是截图)搬进一个系统级置顶窗口:
- 一条命令安装。 包自带组合补丁(
dsh.bundle.patch):dsh plugin add自动完成插件行挂载,不用手改任何文件。 - 零配置。 装完重启
dsh web,界面右下角多一个「独立窗口」悬浮按钮,点它就完事。 - 窗口默认和浏览器一样大。 独立窗口按当前标签页视口尺寸打开;想固定大小,两个数字就能覆盖。
- 整个应用都在。 按钮点击后,
#root连同样式、主题一起被搬进新窗口——不是投屏、不是截图,是应用本体,交互照常。 - 不支持的浏览器零打扰。 Safari / Firefox 没有 Document PiP API,脚本直接 no-op,连按钮都不会出现。
dsh-pip 与 DeepSeek Harness Desktop 怎么选
这两个项目解决的是同一工作流里的不同层级。dsh-pip 面向已经在使用 dsh web、只想让界面常驻编辑器旁边的用户;DeepSeek Harness Desktop 则是完整的 Electron 桌面发行版,同时接管桌面应用和本地 Harness 服务的生命周期。
| | dsh-pip | DeepSeek Harness Desktop |
|---|---|---|
| 核心定位 | 把现有 Web UI 分离成始终置顶的伴随窗口 | 把 Harness 打包成独立桌面应用 |
| 安装方式 | 一条 dsh plugin 命令 | 下载并安装桌面端构建 |
| 现有环境 | 需要可用的 dsh web profile 和 Chromium 116+ | 自带运行环境,不用手动配置 Node.js 或从命令行启动 |
| Harness 服务 | 复用现有服务和配置,不负责启动或管理 | 自动启动并管理本地 Harness 服务 |
| 窗口体验 | 一键分离 / 返回的 Document PiP 窗口,始终悬浮在编辑器上方 | Electron 桌面窗口、系统托盘和桌面界面适配 |
| 官方界面与插件 | 原样搬动当前官方 Web UI,并通过 DSH 插件机制安装 | 在桌面发行版内保留官方本地 Web UI 和插件能力 |
| 远程访问与 Channels | 不提供,只增强本机窗口体验 | 仓库宣称支持 iOS / Android 手机远控,以及微信、飞书、Discord、WhatsApp Channels |
| 插件发现 | 使用标准 DSH 插件命令,不提供市场 | 插件市场以及把 Desktop 作为 DSH 插件交付仍在规划中,尚未发布 |
| 平台范围 | 支持 Document PiP 的 Chrome / Edge | macOS、Windows 桌面构建 |
如果你已经把 Harness 跑起来了,只想用最小改动获得悬浮窗口,选 dsh-pip:原来的运行方式、浏览器、profile 和升级链路都不变。如果你想要免配 Node.js、无需命令行启动,并由桌面应用统一管理 Harness,选 Desktop。
快速开始
dsh plugin --profile web add dsh-pip重启 dsh web——完成,零配置:
- 插件的 bundle 补丁自动挂载插件行并把浏览器脚本注入每个页面——纯增量、不碰核心行;
- 打开 Web 界面,右下角出现「独立窗口」按钮,点击即分离;
- 关闭独立窗口(或点窗口里的「返回标签页」),应用回到原标签页,按钮恢复。
工作原理
点击按钮时,浏览器脚本在点击的瞬时激活期内调用 documentPictureInPicture.requestWindow(),把原页面的样式表和主题属性复制进新窗口,把应用根节点(#root)整体迁入,并隐藏原页面按钮。窗口的 pagehide 事件——由浏览器自带的「回到标签页」控件或脚本自己的「返回标签页」按钮触发——把根节点搬回去、恢复按钮。
| 一半 | 位置 | 职责 |
|---|---|---|
| 宿主插件 | src/index.ts | 注册 /pip/client.js 路由,把浏览器脚本 + 配置注入每个 index 响应 |
| 浏览器脚本 | src/client.js | 画悬浮按钮,把应用(#root)搬进 / 搬出画中画窗口 |
配置项
全部可选,默认即可用。在 profile 的 ~/.dsh/profiles/web/cordis.patch.yml 里覆盖:
| 字段 | 默认值 | 含义 |
|---|---|---|
| enabled | true | 挂载插件;false(或行上 disabled: true)关闭 |
| width | 省略 | 独立窗口宽度(CSS px);省略 = 跟随浏览器视口宽度 |
| height | 省略 | 独立窗口高度(CSS px);省略 = 跟随浏览器视口高度 |
- id: pip
config:
enabled: true
width: 1280 # 想固定尺寸就写数字
height: 800
requestWindow的宽高是建议值,Chromium 会把窗口限制在屏幕可用范围内,最大化浏览器时实际尺寸可能略小。
环境要求
- Chromium 116+(Chrome、Edge)。Safari / Firefox 不支持 Document Picture-in-Picture API,脚本 no-op,不出现按钮。
webServer服务——webprofile 已通过@deepseek-ai/dsh-host-webserverbundle 提供。
安装与生命周期
安装
dsh plugin --profile web add dsh-pip开发时装未发布的本地检出:
dsh plugin --profile web add file:/path/to/dsh-pip禁用 / 恢复
- id: pip
disabled: true改回 false 即恢复。
升级
dsh plugin --profile web update dsh-pip卸载
dsh plugin --profile web remove dsh-pip同时移除依赖与 bundle 层,不残留任何文件。
已知限制
- 仅 Chromium —— Safari / Firefox 永远不会出现按钮。
- Portal 浮层留在标签页 —— 应用通过
createPortal(..., document.body)渲染菜单、弹窗、toast 和悬浮卡;分离期间这些元素仍指向原标签页的 body,要等应用回去才可见。独立窗口适合阅读 / 稳态浏览,不适合在里面开菜单。 - window 级监听不跟走 —— 全局
window/document监听器(快捷键、滚动跟踪)仍在原标签页触发;只有迁移根节点上的 React 管理事件跟随窗口。
开发
npm install
npm run typecheck # tsc --noEmit
npm run build # tsc → lib/ + copy src/client.js → lib/client.jsnpm publish 前的 prepack 会自动重新构建,发布的 tarball 始终携带最新的 lib/。
