Skip to main content
I

dsh-native-launcher

ingleav626-art/dsh-native-launcher

Windows desktop launcher for the DSH Web UI: desktop shortcut, silent start, system tray with open/full-exit (stop service, close app window, quit tray), PWA app window with focus-instead-of-relaunch, install prompt, and task-completion notifications.

Install

dsh plugin --profile web add github:ingleav626-art/dsh-native-launcher

README

dsh-native-launcher

以"零额外安装"为设计原则:仅凭一个官方插件与 Windows 原生机制,让 DeepSeek Harness Web UI 获得桌面 App 式的一键启动体验。

设计理念

不额外安装任何东西。以官方 DeepSeek Harness 为中心,通过官方支持的插件机制,尝试拼出类似桌面端的体验。

  • 零额外安装:不引入 Electron / Python / WebView2 等任何重型桌面端或运行时——只有官方 dsh 插件 + Windows 自带机制(wscript / powershell / cmd / NotifyIcon / AppsFolder)。装进 profile 即用,卸载即干净。
  • 以官方为中心:不魔改、不替换官方 Web UI,一切围绕官方版本做加法;插件本身也只是标准 dsh bundle patch,官方升级后依然兼容。
  • 轻量体验优先:适合想获得"桌面 App"般手感、又不想额外下载软件的人——装一个插件,换来快捷方式、托盘、独立应用窗口。
  • 原生能力借用:浏览器本身就是最好的"桌面壳"——PWA 安装、--app 独立窗口、系统应用注册,这些官方浏览器能力直接借用,不为小众需求自造轮子;同时也为"想深度适配浏览器生态"的用户保留了路径(安装为应用后任务栏/开始菜单/可固定全部由系统管理)。

一句话:用最小的插件代价,换取最接近原生的桌面体验;不装软件,只用官方的东西。

安装

平台:仅支持 Windows(Windows 10/11,x64)。macOS / Linux 请勿安装本插件。

前置要求:dsh plugin 命令依赖 pnpm。若提示 pnpm is not recognized,先安装:

npm install -g pnpm

(或启用 Node 自带的 corepack:corepack enable pnpm

# 方式一:npm
npm install -g dsh-native-launcher
dsh plugin --profile web add dsh-native-launcher

# 方式二:源码安装
git clone https://github.com/ingleav626-art/dsh-native-launcher
dsh plugin --profile web add <path-to-repo>
# 重启 dsh web 后生效

安装后重启:桌面出现快捷方式,右下角托盘出现图标。双击快捷方式即用。

安装为应用(推荐,一次性):普通标签页打开 http://127.0.0.1:3080 → 视觉中心出现安装提示框 → 点「安装」→ 弹出浏览器安装提示 → 确认。装完后:

  • 快捷方式自动打开已安装的应用(独立窗口、任务栏独立图标、可固定)
  • 若点安装无反应(浏览器安装抑制期),用 Edge 菜单 ⋯ → 更多工具 → 应用 → 将此站点安装为应用

特性

  • 桌面快捷方式:安装即生成(默认名 DSH WebUI,官方 DSH 图标),双击即用;幂等——已存在则跳过,指向错误/图标变更自动重建,设置页可强制重建
  • 静默启动:wscript 隐藏窗口,无 cmd 黑窗、无闪屏
  • HTTP 就绪探测:实例已在运行(HTTP 200)→ 直接打开连上;未运行 → 才启动(不会 EADDRINUSE 失败;对 0.0.0.0 / 127.0.0.1 / [::] 监听形态免疫;TCP 通但服务未就绪时不会误判)
  • 已安装应用优先打开:若 Edge/Chrome 已把站点安装为 PWA 应用,快捷方式直接打开已安装的应用窗口(独立任务栏、无地址栏、官方图标);未安装时按 openMode 回退(--app 独立窗口 / --new-window / 默认)
  • 聚焦唤起不重复弹窗:应用已在运行时(无论快捷方式还是托盘),通过 Win32 API(按 PID + 窗口标题双匹配,绕过前台锁)聚焦现有窗口,绝不新开实例;冷启动失败也会自动换路径回退,不再"点了没反应"
  • 冷启动自愈:浏览器完全未运行时(首进程可能吞掉 --app-id/--app 参数),每次启动都会验证浏览器进程是否真的起来——没起来自动换下一条路径,最终回退默认方式打开,不再"点了没反应"
  • 系统托盘:NotifyIcon 托盘菜单(打开 WebUI / 退出 WebUI),单实例互斥,无论从快捷方式还是终端直接启动 dsh 都会出现;"退出 WebUI"=停止 DSH 服务 + 关闭浏览器应用窗口 + 关闭托盘,一次彻底退出;重启 dsh 自动换新托盘(版本标记 + 进程探测)
  • 可靠通知(托盘原生 Toast 为主):任务完成 / 出错 / 被中止 / 被阻塞 / 达 Token 上限——托盘直发 Windows 原生 Toast(有声、进通知中心),不依赖浏览器通知权限;浏览器通知仅作兜底(不双弹);Toast 失败降级 BalloonTip + 提示音,原因写 tray-notify.log页面关闭时 host 自动补发(2s 确认窗口);等待批准 / 回答 / 计划审阅也会通知(pendingInteraction 检测)
  • 关闭语义(桌面 App 行为):关闭所有页面窗口后,无任务则优雅退出服务(官方 appExit,含持久化 flush);有任务则驻留到完成再退出;20s 防抖 + 2s 二次确认防误杀
  • 安装引导:站点可安装时自动弹出白底安装模态框(含安装按钮与浏览器限制兜底提示),可一键唤出 Edge/Chrome 原生安装流程
  • 官方图标:应用 / 快捷方式 / 托盘 / favicon 全部使用 DeepSeek Harness 官方图标(favicon.svg 原版渲染)
  • 增强设置页:设置侧边栏新增 "WebUI 启动器" section(查看配置 / 重建快捷方式)+ 独立"通知"设置 section(完成原因开关、关键词规则、等待确认开关、测试按钮)
  • 零依赖:仅 node builtins + Windows 自带工具

下一步实现(规划中)

  • 功能可自定义化:设置页升级为完整配置 UI(托盘开关 / 自动打开 / 打开方式 / 端口等全部可调、可持久化),不再需要改配置文件
  • 模块化可裁剪:通知 / 关闭语义等可选模块带独立开关——甚至可以裁剪成纯启动器(只保留快捷方式 + 托盘 + 打开/退出,不加载通知等无关代码)
  • 一键卸载:卸载命令自动清理桌面快捷方式、托盘进程、生成物目录(目前需手动三步清理)
  • 多浏览器适配:Chrome / Firefox 的 PWA 安装引导差异化处理

常见问题

Q:任务完成了但没收到通知? A:通知主通道是托盘原生通知(不依赖浏览器权限)。若托盘也没弹:先确认托盘图标在(重启 dsh 会自动拉起/换新托盘),再看 ~/.dsh-webui-launcher/tray-notify.log 是否有失败原因。另注意 Windows 会静默屏蔽短时间内的连续通知(同 tag 几秒内重复时尤其明显)——设置页"发送测试通知"请间隔几秒再点。

Q:关掉窗口后服务退出了,但我不想让它退? A:把配置 closeToExit 改为 false——关窗后服务常驻(手动用托盘"退出 WebUI"才退出)。

Q:任务还在跑,我关了窗口,任务会丢吗? A:不会。有任务在跑时服务会驻留,任务跑完(且仍无窗口)才自动退出;任务完成还会弹托盘通知。

Q:改了端口,启动打开的还是旧页面? A:改 port 后已安装的旧 PWA 仍指向旧端口,启动会自动回退 --app 模式(功能可用);清理旧应用请到 edge://apps 手动卸载。

Q:卸载重装了浏览器应用(PWA),通知没了? A:托盘通知不受影响;浏览器兜底通知需要在通知设置页重新点一次"请求权限"。

Q:托盘图标不见了? A:重启 dsh 会自动重新拉起(含旧托盘自动换新);仍不行就任务管理器结束残留的 PowerShell 托盘进程(含 pwsh)再重启。

Q:一个任务会收到两条通知(托盘+浏览器)? A:不会。托盘是主通道,浏览器通知只在其未送达时兜底(3 秒确认),正常情况下只弹一条。

Q:双击快捷方式只有命令行窗口,WebUI 没打开? A:快捷方式通过 dsh --profile web 启动服务,依赖 PATH 中的全局 dsh 命令。若你平时用 npx @deepseek-ai/dsh web 运行(dsh 未全局安装),dsh 命令不存在会导致启动失败。v0.2.1 起会自动回退 npx 启动并在窗口显示提示;建议执行 npm install -g @deepseek-ai/dsh 全局安装以获得秒开体验。若仍失败,请提供 %USERPROFILE%\.dsh-webui-launcher\ 下的日志(新建 issue 时模板会引导提供)。

卸载

dsh plugin --profile web remove dsh-native-launcher   # 1. 移除插件(profile 依赖 + bundle)

然后手动清理生成物(插件只负责生成,不负责回收):

Remove-Item "$env:USERPROFILE\.dsh-webui-launcher" -Recurse -Force   # 2. 启动脚本/托盘/图标/日志
Remove-Item "$env:USERPROFILE\Desktop\DSH WebUI.lnk"                 # 3. 桌面快捷方式
  • 托盘进程:右键托盘 → 退出托盘(若还在运行)
  • 已安装的 PWA(若装过):Edge 打开 edge://apps → DSH WebUI → 卸载
  • 最后重启 dsh

版本状态

v0.2.1(当前)—— 启动可靠性修复

v0.2.1 修复

  • launch.cmd 分支结构:诊断日志文本中的括号/箭头破坏 cmd 的 if/else 解析,导致"已运行/未运行"分支同时执行(前端拉起的同时又启动新实例、端口冲突)——已修复并实测验证
  • HTTP 就绪探测:启动探测从 TCP 改为 HTTP(返回 200 才算"已运行"),消除托盘退出后立即双击时的误判
  • 启动命令兜底dsh 不在 PATH(npx 方式使用)时自动回退 npx --yes @deepseek-ai/dsh,并在窗口显示明确提示,不再静默失败
  • 托盘拉起可靠性:spawn 参数修复 + 存活验证自动重试(最多 3 次),根治"托盘 spawn 后立即退出"
  • 环境自诊断日志:启动时自动记录 node / dsh 命令可用性 / 端口 / 托盘进程 / 快捷方式目标(PowerShell 5.1 兼容)——问题反馈无需反复追问,看日志即可定位
  • auto-open 去重:页面已在用时不再重复打开浏览器
  • close-to-exit 门槛:仅快捷方式(启动器)拉起时生效;命令行 / npx 启动为常驻服务

v0.2(桌面化体验完整闭环)

v0.1 基础(桌面化外壳)

  • 桌面快捷方式(官方图标)+ 静默启动(无黑窗)
  • TCP 端口探测:已运行则直连,未运行才启动(不重复启动)
  • 已安装 PWA 应用优先打开:装过应用的直接打开应用窗口,未安装自动回退浏览器
  • 应用窗口聚焦唤起:应用已在运行时,快捷方式 / 托盘只聚焦现有窗口,绝不重复弹新实例
  • 多代 Edge 兼容:同时支持新版 PWA 宿主进程 pwahelper.exe 与旧版 msedge.exe --app-id;窗口检测按 app_id + 端口 URL(任意 host) 双锚点,域名 / 应用名 / 标题均可变
  • 系统托盘(打开 WebUI / 退出 WebUI,"退出"=停服务 + 关应用窗口 + 退托盘,一次彻底退出)
  • 安装引导模态框(白底,一键唤出浏览器原生安装流程)
  • 设置页增强 section(查看配置 / 重建快捷方式)+ 独立"通知"设置 section
  • 官方 DSH 图标全入口统一

v0.2 新增(可靠性 + 关闭语义)

  • 托盘原生 Toast 通知主通道:通知决策完成后由托盘(PowerShell)直发 Windows 原生 Toast(有声、进通知中心)——不再依赖浏览器通知权限,绕开浏览器通知的不可靠转发;浏览器通知降级为兜底(仅当托盘未消费时补发,不双弹);Toast 失败自动降级 BalloonTip + 提示音,失败原因记录到 tray-notify.log
  • 等待确认通知:任务进入等待批准 / 等待回答 / 计划审阅状态时通知(dsh-notification v0.1.2 的 pendingInteraction 检测,设置页可开关)
  • 关闭语义(桌面应用行为):所有页面窗口关闭后(pagehide + fetch keepalive 上报),host 检查任务——无任务则走官方 appExit 优雅退出(持久化 flush);有任务则驻留到完成,任务完成且仍无窗口时自动退出;20s 防抖 + 2s 二次确认避免刷新/闪断/重开竞态误杀,多窗口全部关闭才算
  • 页面关闭通知兜底:任务完成时若页面已关(client 决策不可达),host 在 2 秒确认窗口后直接补写托盘通知(全量、无规则过滤)——"关了页面也不会漏提醒"
  • 托盘自更新:tray.ps1 版本标记 + apply 进程探测(覆盖 powershell.exe / pwsh.exe)——重启 dsh 时旧托盘自动换新,不再"托盘还是旧逻辑"
  • 强杀残留清理:托盘启动时清空未消费的通知文件——大退后重启不再补弹"上次任务结束"

安装为应用后自动获得(浏览器原生能力,无需本插件代码):任务栏独立图标、无地址栏独立窗口、开始菜单条目、可固定任务栏、应用级关闭——与桌面 App 一致的窗口体验。

v0.1

  • 桌面快捷方式、静默启动、TCP 端口探测、系统托盘(打开/停止/退出)
  • PWA 应用窗口优先、安装引导、设置页增强、任务完成通知(dsh-notification 集成)

工作原理

桌面快捷方式(DSH WebUI.lnk)
    │ wscript.exe launcher.vbs(隐藏窗口,无黑窗)
    ▼
launch.cmd HTTP 就绪探测 (127.0.0.1:<port>)
    ├─ 已运行(HTTP 200) → 拉起托盘 → open-webui.ps1(打开已装应用/浏览器,不重复启动)
    └─ 未运行 → 拉起托盘 → set DSH_LAUNCHER=1 && dsh --profile web(静默启动;dsh 不在 PATH 时自动回退 npx --yes @deepseek-ai/dsh)
                                │
                                ▼
                         插件 apply(任意启动方式都会执行)
                                ├─ 拉起系统托盘(Mutex 单实例 + 版本自更新)
                                ├─ 注册 PWA 路由(manifest + 官方图标)
                                ├─ 注册设置页 "WebUI 启动器" section
                                ├─ 注册通知/关闭语义(见下)
                                └─ 检测 DSH_LAUNCHER=1 → loader.await() 就绪
                                   → webServer.port 就绪 → 打开 WebUI

open-webui.ps1 打开链路(多路探测,命中一个即启动)

优先级方式说明
0已运行检测 → 聚焦现有窗口按 app_id / 端口 URL(任意 host)匹配 pwahelper/msedge 进程;已在运行则 Win32 聚焦,绝不新开
0--app-id=<app_id>host 启动时扫描 Edge 已安装应用(Manifest Resources + Preferences 按站点 URL 匹配),部署自适应;冷启动后验证进程是否真的出现
0bAppsFolder(explorer shell:AppsFolder\<AUMID>Windows 已注册应用列表,按站点 host 前缀 + 名称匹配
1-2PWA 快捷方式扫描开始菜单 / 任务栏 / 桌面(浏览器 exe + --app-id 特征),避免自我递归
3Chromium Web Applications 目录旧结构 internal manifest 匹配
4--app / --new-window / 默认未安装应用时的浏览器回退

通知链路(可靠主通道)

回合结束(agent 实时窗口判定,防重放)
   ├─ client(页面开着):规则过滤 → 上报 host → 写 tray-notify.json
   │      └─ 3s 后查 tray-acked:托盘已消费 → 浏览器不弹;未消费 → 浏览器兜底
   └─ host 兜底(2s 确认窗口):无客户端在线才补写(页面全关场景)
          └─ 托盘 Timer 1.5s 轮询 → PowerShell 原生 Toast(AUMID 注册)
             ├─ 成功 → 删除队列文件
             └─ 失败 → 记 tray-notify.log + BalloonTip + 提示音

等待批准 / 回答 / 计划审阅(pendingInteraction)走同一通道。

关闭语义(桌面 App 行为)

页面加载 → online 登记(per-tab clientId)
页面关闭/刷新 → pagehide + fetch keepalive → offline 上报
   → 全部客户端离线 → 20s 防抖(刷新/重连可取消)
   → 任务空闲 → 2s 二次确认 → appExit(0) 官方优雅退出(持久化 flush)
   → 任务在跑 → 驻留;任务完成且仍无客户端 → 自动退出

配置

cordis.patch.yml(或 profile 的 patch 层覆盖):

- id: native-launcher
  config:
    # 快捷方式双击后执行的启动命令(cmd 中运行,依赖 PATH 里的 dsh;dsh 缺失时自动回退 npx --yes @deepseek-ai/dsh)
    launchCommand: dsh --profile web
    # 是否自动打开浏览器(仅快捷方式启动且带 DSH_LAUNCHER=1 时)
    autoOpen: true
    # 快捷方式名称(不含扩展名)
    shortcutName: DSH WebUI
    # 快捷方式已存在时是否强制覆盖
    force: false
    # 端口探测端口(需与 webserver 端口一致)
    port: 3080
    # 是否启用系统托盘
    tray: true
    # 打开方式:app(--app 独立窗口,默认)| new-window(独立窗口)| default(浏览器默认行为)
    openMode: app
    # 关闭语义(桌面应用行为):所有页面窗口关闭后,无任务则优雅退出服务;有任务则驻留到完成
    closeToExit: true

生成物(用户目录 ~/.dsh-webui-launcher/):

文件作用
launcher.vbswscript 入口:隐藏窗口调起 cmd
launch.cmdHTTP 就绪探测 + 启动/直连 + 拉起托盘(dsh 缺失时自动 npx 回退)
open-webui.ps1多路探测打开已安装应用 / 浏览器(已运行→聚焦,未运行→启动)
tray.ps1NotifyIcon 托盘(单实例 Mutex;打开 / 退出 WebUI;Toast 通知轮询;版本标记)
tray-version.txt托盘脚本版本标记(apply 用它做托盘自更新)
tray-notify.json通知队列文件(host 写 → 托盘轮询弹 Toast → 消费删除)
dsh-webui.ico快捷方式 / 托盘图标(官方 DSH 图标)
native-launcher.log插件运行日志(启动/快捷方式/托盘/通知/关闭语义诊断,含环境快照)
launch.log快捷方式启动分支日志(每次双击的探测结果与走向,排查用)
tray-exit.log托盘退出原因记录(mutex 冲突 / 正常退出,排查用)
tray-notify.log托盘 Toast 失败原因 / tick 错误(排查用)
pwa-scan.logPWA 应用扫描诊断日志(每次启动重写,排查用)

与同类方案对比

方案形态亮点短板
dsh-native-launcher(本插件)标准 dsh 插件 + Windows 自带机制轻量(零重型依赖)、托盘、已装应用优先打开、可靠通知、关窗自动退出、安装引导、设置页、端口直连、静默启动、官方图标仅 Windows
jenokagong/dsh-webui-launcher纯 bat控制台可最小化恢复、快速启动(~2s)关窗=停服务、无托盘、无端口直连
LvienOeria 插件dsh 插件幂等 state hash、配置 .bak 备份、坏配置大声报错不支持 Windows,无托盘/快捷方式
zhanweipan 启动器Electron一键部署、版本管理、多实例、日志面板重型桌面端,与轻量定位相悖
Hllojjh 托盘Python 托盘单实例互斥、只停自己进程树、外部占用识别、二次确认依赖 Python 运行时
Ruler4396 启动器WebView2服务驻留三模式、关窗即停依赖 WebView2 运行时

差异化:同为 dsh 插件的方案里,LvienOeria 不支持 Windows、jenokagong 无托盘,而重型桌面端(Electron/WebView2/Python)都要求额外安装运行时——与"不额外安装任何东西"的理念相悖。本插件是"纯 Windows 原生 + 纯插件"的最小代价路线:桌面"应用窗口"走浏览器原生 PWA 机制——用户安装 PWA 后快捷方式直接打开已安装应用(任务栏独立、官方图标、可固定),而非自造浏览器壳——同样是"任务栏独立应用",成本比 Electron/WebView2 低一个数量级,且零运行时依赖。

致谢

  • 构建于 DeepSeek Harness 插件生态之上(MIT License, Copyright (c) 2026 DeepSeek)——"以最小破坏性利用原生插件生态实现桌面级体验"的设计理念,依赖其 Cordis 插件机制与官方 API
  • 任务通知功能完整集成自dsh-notification(MIT License, Copyright (c) 2026 DeepSeek)——host 投影(lib/notification-host.js)与 client 完成检测/设置(lib/notification-client.js)为其原样构建产物(v0.1.2 同步:含等待确认通知),通过本插件包内模块挂载(含 Settings > 通知 设置页)本插件将其浏览器通知升级为托盘通知更可靠。
  • 图标使用官方 DeepSeek Harness 品牌图标(源自 dsh web 的 favicon.svg),仅用于非商业开源插件场景

许可证

MIT

Related plugins