編集者注

no1xsyzy/dsh-webview-wrapper

A DeepSeek Harness webview wrapper in the everything-is-a-plugin spirit.

これは DeepSeek Harness(DSH)プラグインです。当サイトは GitHub README、インストール情報、メンテナンス状況、公開セキュリティシグナルをまとめています。

dsh-webview-wrapper

English | 中文

为 DeepSeek Harness 的 Web 界面提供一个朴素的(naive)原生桌面外壳。dsh-webview-wrapperdeepseek-harness 的树外插件:它通过 WebviewJS 把正在运行的 Web 应用装进一个操作系统原生窗口——使用平台自带的 webview 引擎(Windows 为 WebView2,macOS 为 WebKit,Linux 为 WebKitGTK),绝不打包浏览器内核。没有 Electron、没有 fork、不打 harness 的补丁。

贯彻「一切皆插件」的思路,本包只做纯组合:像普通树外插件一样装进某个 profile,bundle 的 patch 层插入一个插件行,插件在 Web 组合提供 webServer / webRuntime 服务后就位,并接管原生窗口的生命周期。harness 本体始终保持原装。

特性

  • dsh web 提供的界面套上原生窗口 + 系统托盘。
  • 关闭即收进托盘:关窗只隐藏窗口,harness 继续运行(一个不可见的 1×1 keep-alive 窗口托住进程)。
  • 托盘菜单(Show / Quit)与托盘双击。
  • 干净退出:插件卸载(或 profile 关闭)时通过 effect 的 disposer 调用 app.exit()
  • 带 invariant 伴生插件(dsh-webview-wrapper/invariant),向 InvariantRegistry 注册。

安装

前置条件:

  • 一份原装 deepseek-harness,其 profile 装配了 Web 组合包(dsh web)。本插件注入 webServerwebRuntime,目标 profile 必须是 Web 形态——随附的 web profile 就是天然目标。
  • WebviewJS 的平台要求:Windows → WebView2(Windows 11 与新版 Edge 自带),macOS → 内置 WebKit(10.15+),Linux → WebKitGTK 4.1 与 libxdo
  • pnpm(插件管理器会把参数转发给 pnpm)。

快速开始

dsh plugin --profile web add dsh-webview-wrapper
dsh --profile web

自定义 profile

随附的 web profile 已经在 dsh.profile.bundles 里列好了 Web 层(@deepseek-ai/dsh-base@deepseek-ai/dsh-web-app)。想用自定义 profile,就从 web 复制一份,再只加 wrapper:

cp -r ~/.dsh/profiles/web ~/.dsh/profiles/ww
dsh plugin --profile ww add dsh-webview-wrapper
dsh --profile ww

add 逐步做了什么

  1. 首次使用时 dsh plugin 会先初始化 profile,然后在 profile 目录里执行 pnpm add
  2. 由于 dsh-webview-wrapper 的 manifest 声明了 dsh.bundle.patch,插件管理器会自动把它追加进 profile 的 dsh.profile.bundles 层栈。
  3. 下次启动时,bundle 的 patch 层(cordis.patch.yml)向组合里插入 webview 插件行。
  4. 插件等待 webServer / webRuntime 服务就绪后,接管原生窗口的生命周期。

一条规则:不要 add 内置 bundle

dsh plugin add 只用于树外插件。Web 组合包(@deepseek-ai/dsh-base@deepseek-ai/dsh-web-app)是内置 bundle:它们从 harness 安装目录加载、只应出现在 dsh.profile.bundles 里——绝不能进 profile 的 dependencies。把内置 bundle 加进依赖,pnpm 就会把整棵 harness 树装进 profile 的 node_modules

  • pnpm 以 autoInstallPeers: false 安装,这棵树缺 peer(如 @deepseek-ai/cordis);在 profile 目录里跑 pnpm peers check 能看到。
  • 启动时 loader 从 profile 目录解析插件,这些副本遮蔽了安装目录($DSH_HOME/profiles/node_modules 的 junction),加载失败——工具调用就会报错。
  • 中途还会先撞上一个症状:@deepseek-ai/dsh-web-app 会带入 harness 的本地目录选择器,其依赖 koffi 带构建脚本且未获批准;pnpm 11(默认 strict-dep-builds: true)于是非零退出(ERR_PNPM_IGNORED_BUILDS),dsh plugin 跳过 dsh.profile.bundles 回填,profile 启动时没有 Web 层。

要脱离这种状态:把内置 bundle 从 dependencies 里删掉(dsh.profile.bundles 里保留——它会从安装目录解析),然后在 profile 目录执行 pnpm install 清掉整棵 harness 树,再启动。

运行本地检出

先构建,再从目录安装:

pnpm run build
dsh plugin --profile web add file:/绝对/路径/dsh-webview-wrapper

使用

  • 首次启动只进托盘——在主动要求之前不会创建主窗口。双击托盘图标或选 Show,打开承载 http://127.0.0.1:<port>(即当前 Web 界面)的 1024×768 窗口。
  • 关闭窗口=收进托盘,harness 继续运行。
  • 托盘菜单里的 Quit 退出应用。

工作原理

文件职责
src/index.ts插件本体:创建 WebviewJS Application、托盘与主窗口;路由 custom-menu-clickwindow-close-requestedapplication-close-requested;卸载时调用 app.exit()
cordis.patch.ymlbundle 的 patch 层:向组合插入 { id: webview, name: 'dsh-webview-wrapper' }
src/invariant.tsinvariant 伴生插件,向 InvariantRegistry 注册本包。
assets/icon.svg任务栏 / 托盘图标源文件,用 sharp 栅格化。

生命周期示意:

apply(ctx)
├─ readIcon(icon.svg, 16)          # 一次共享的异步栅格化
└─ ctx.effect(() =>                 # 插件生命周期 == 原生应用生命周期
   ├─ new Application()
   ├─ whenReady() → 1×1 keep-alive 窗口 + 托盘(Show/Quit)
   ├─ 托盘双击 / Show → createOrShowMainWindow()
   │    └─ BrowserWindow(1024×768) + webview → http://127.0.0.1:<ctx.webServer.port>
   ├─ window-close-requested → hide(关闭即收托盘)
   └─ disposer → app.exit()

已知短板与路线图

外壳刻意保持朴素,以下粗糙之处即路线图:

  1. 没有原生通知——harness 里发生的事不会变成系统通知。路线:接入 WebviewJS Notification
  2. 通用 HTTP 传输——webview 通过 http://127.0.0.1:<port> 加载 Web 应用,和浏览器标签页走同一条 HTTP 通道。路线:改用 WebviewJS IPC(webview.expose() / window.ipc.postMessage)和自定义协议,去掉对 loopback HTTP 的依赖。
  3. 没有菜单栏——只有托盘菜单。路线:app.setMenu(),配上 File/Edit 角色与快捷键。
  4. 黑窗 + 只能靠托盘退出——经由 CLI 启动会带出一个控制台黑窗,退出路径只有托盘 Quit 与 profile 关闭。路线:打包成 GUI 子系统可执行文件(WebviewJS CLI / Node SEA)让黑窗消失,并在页面内提供退出入口。

其它现状:单窗口、启动时固定 1024×768、标题写死(暂无配置面);启动时不打开主窗口(应用先驻留托盘)。

开发

git clone https://github.com/no1xsyzy/dsh-webview-wrapper.git
cd dsh-webview-wrapper
pnpm install
pnpm run build      # 每次修改后都需要运行这行
cp -r ~/.dsh/profiles/web ~/.dsh/profiles/ww-dev
dsh plugin --profile ww-dev add file:/绝对/路径/dsh-webview-wrapper

私人开发 profile 请按自定义 profile的方式复制 web——只 add 树外插件,绝不加内置的 @deepseek-ai/dsh-web-app

注意事项:

  • 本工作区从不直接运行应用。 pnpm-workspace.yaml 刻意禁掉了 WebviewJS 原生插件构建(koffilibwebview-nodejs);wrapper 要组合进 profile 才能跑,不能在工作区里直接执行。测试请走 dsh plugin ... add file:<路径> 流程。
  • lib/node_modules 已在 .gitignore 中;lib/ 是构建产物。
  • 命名纪律(npm 发布)。 npm 包名必须与 package.jsonnamesrc/index.ts 的插件名、cordis.patch.yml 的 bundle 行、src/invariant.ts 的注册名保持一致。插件管理器按包名解析 bundle,InvariantRegistry 按 npm 包名登记注册——改名需要四处同步。
  • 保持 README.mdREADME.zh.md 同步。
REPOSITORY SIGNALS

セキュリティとインストールエビデンス

このスコアは公開リポジトリメタデータと当サイトに登録されたインストールエビデンスのみに基づくもので、コードセキュリティ監査とは異なります。

出所の追跡可能性

公開プラグインカタログから取得し、公開 GitHub リポジトリにリンクしています。

ライセンス

リポジトリは MIT ライセンスを宣言しています。

メンテナンス活動

過去180日以内にコードの更新があります。

インストールエビデンス

再現可能な正確なインストールメタデータはまだ登録されていません。リポジトリの説明に従って手動で確認してください。

インストールライフサイクルスクリプト

確認したパッケージメタデータにインストールライフサイクルスクリプトは宣言されていません。