Skip to content

Repository files navigation

DSH 悬浮框壳子(dsh-shell)

一个"只承载官方 DSH Web UI"的悬浮窗壳子:Electron 无边框置顶窗口(一窗一框),渲染层 React + shadcn/ui + Tailwind CSS;内容区 iframe 内嵌官方 DeepSeek Harness Web UI,通过 ?focus=<data-slot 路径> 聚焦到任意插槽——消息流、输入区、会话列表、详情面板,或任意第三方插件注册的插槽。

多窗口同连一个 dsh 实例,经官方 events.mux 广播实现数据同步显示:在一个窗口选择会话、输入内容、发送消息,其他窗口同步呈现。

只兼容官方 DSH Web UI:第三方 UI 必须基于官方插槽系统(@deepseek-ai/dsh-client-ui-slots)扩展,随官方界面照常渲染;不兼容任意第三方页面——内容源白名单在构造层拒绝一切非官方形态的 URL。

特性

能力 说明
🪟 悬浮窗 无边框、置顶(alwaysOnTop)、标题栏拖拽、边缘缩放、最小化/还原、关闭
🎯 插槽聚焦 ?focus=<data-slot 路径> 只显示目标插槽;预置 6 项 + 自定义路径输入
🔒 内容源白名单 iframe src 唯一经 lib/frameUrl.ts 构造——只允许「目标 origin 根路径 + focus 参数」,第三方页面一律拒绝
🔗 目标连接管理 默认 http://127.0.0.1:3081,UI 可改并记忆(localStorage),storage 事件跨窗口同步
📡 多窗口数据同步 所有窗口同连一个 dsh 实例,共享服务端会话状态 + events.mux 广播,一个窗口操作、全部窗口同步显示
🧩 第三方 UI 兼容 基于官方插槽注册的 DSH UI 插件在聚焦视图内照常渲染

兼容性(重要)

  • 只兼容官方 DSH Web UI(deepseek-ai/deepseek-harness 的 web 客户端,含 @deepseek-ai/dsh-client-app-shell 装配与 @deepseek-ai/dsh-client-ui-slots 插槽注册表)
  • 聚焦效果依赖目标 dsh 已挂载 @dsh-focus/focus-plugin?focus= 的 CSS 聚焦由官方页面内的插件实现,壳子只构造 URL);未挂载时 ?focus= 无聚焦效果,页面完整正常显示
  • 版本基线:@deepseek-ai/dsh@0.1.0-rc.6;壳子只依赖 URL 参数协议与 data-slot 语义,不锚定官方编译产物类名
  • 目标 dsh 默认回环地址(127.0.0.1);跨机器部署需在 dsh 侧配置 trustedHosts

原理

┌──────────────────────── Electron 主进程 ────────────────────────┐
│  window-manager:无边框置顶悬浮窗创建/最小化/关闭/多窗口         │
│  ipc:window:minimize / window:close / window:create            │
└───────────────▲───────────────────────────────┬─────────────────┘
        IPC invoke(preload contextBridge)      │ ?slot= URL 参数
┌───────────────┴───────────────────────────────▼─────────────────┐
│                     渲染层(React + shadcn/ui)                  │
│  TitleBar / SlotPicker / SettingsDialog / DSHFrame              │
│  lib/frameUrl:白名单 src 唯一构造入口                           │
│  store/config:目标地址 localStorage + 跨窗口 storage 同步        │
└───────────────┬─────────────────────────────────────────────────┘
                │ iframe src = <target>/?focus=<slot>
┌───────────────▼─────────────────────────────────────────────────┐
│          官方 DSH Web UI(同源 iframe,数据完全一致)            │
│  插槽树 sidebar | conversation | details + 第三方注册插槽        │
└─────────────────────────────────────────────────────────────────┘
  • 数据同步:所有窗口连同一个 dsh 进程,会话状态只存在 host 侧一份;每次变更经 /api/events.mux/api/events.host 下行 WebSocket 广播给所有连接的窗口;同源浏览器状态(localStorage,如会话选择)跨窗口共享。?focus= 只是纯 CSS 显示裁剪,数据流不变——"显示不同插槽,数据完全同步"。
  • 白名单边界:壳子只约束 iframe 的初始 src(导航层);iframe 文档内部的 /api、WebSocket 请求同源于 DSH host,不受壳子约束。

快速开始

前置条件

  1. 已启动一个 dsh 实例(默认 http://127.0.0.1:3081
  2. 目标实例已挂载 @dsh-focus/focus-plugin(聚焦效果依赖;未挂载也可运行,页面正常显示)
npm install        # 安装依赖
npm run dev        # 启动悬浮窗(默认聚焦 conversation.session 消息流)

生产构建与打包:

npm run build      # electron-vite 构建(out/)
npm run package    # electron-builder 打包(dist/:portable + NSIS 安装包)

Windows 注意:若 shell 环境注入了 ELECTRON_RUN_AS_NODE=1,先执行 Remove-Item Env:ELECTRON_RUN_AS_NODEnpm run dev(否则 Electron 会被当纯 Node 运行)。

使用

操作 说明
拖动标题栏 移动悬浮窗
拖窗口边缘/角落 缩放
最小化 / 关闭 窗口控制按钮(右上)
+ 新建悬浮框 打开第二个悬浮窗(一窗一框,可再选插槽)
插槽下拉 预置插槽:消息流 / 输入区 / 对话区 / 会话列表 / 详情面板 / 消息全宽
自定义路径… 输入任意 data-slot 路径(含第三方插件注册的插槽);未知路径按官方 no-op 语义完整显示
设置按钮 修改目标 DSH 地址(默认 http://127.0.0.1:3081,白名单校验,非法地址拒绝并提示)
连接失败 窗口内显示错误占位 + 重试 / 修改地址入口

配置持久化于渲染层 localStorage(key dsh-shell.target),同源多窗口自动同步。

开发

npm run typecheck  # tsc --noEmit(main/preload/renderer 双 tsconfig)
npm run test       # vitest 单测(白名单/插槽/配置持久化,21 用例)
npm run dev        # electron-vite dev(渲染层 HMR + 主进程热重载)

结构(electron-vite 三段构建):

src/
├── shared/ipc-channels.ts   # IPC 契约(通道名 + WindowApi 类型)
├── main/                    # 主进程:窗口管理 / IPC / 生命周期
├── preload/                 # contextBridge 暴露最小 window.api
└── renderer/src/
    ├── components/          # 壳子 UI(含 shadcn ui 原语)
    ├── lib/                 # 业务纯函数:frameUrl 白名单 / slots 插槽
    └── store/               # 数据存取:config / ipc / windowParams

已知限制与演进方向

  • 窗口位置/大小不记忆、无托盘常驻、无一键拉起 dsh、每窗口共享同一目标地址、无透明圆角窗——均为 v1 边界,演进项见 .intentflow/floating-frame/later-on.md
  • iframe 加载判定用 onLoad 启发式 + 15s 超时;跨源限制下无法读取官方页面内部状态

相关项目

  • dsh-focus — 本壳子的聚焦引擎:?focus=<插槽路径> 纯 CSS 聚焦插件(需挂载到目标 dsh 实例)
  • deepseek-ai/deepseek-harness — 官方 DeepSeek Harness(本壳子唯一兼容的 Web UI)

License

MIT

About

中文:Electron 无边框置顶悬浮窗壳子,内嵌官方 DSH Web UI 并以 ?focus= 插槽聚焦,多窗口同连一个 dsh 实例实现数据同步 English:Frameless floating shell for the official DeepSeek Harness web UI — embeds DSH UI via iframe with ?focus= slot focusing; multi-window state sync over one dsh instance

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages