dshbase

插件目录 / Developer / dsh-webview-wrapper

dsh-webview-wrapper

已验证 · 实测可装 no1xsyzy

✓ 持续维护

查看 GitHub ↗ ← 返回插件目录

0Stars
0Forks
0未关闭 issue
—语言
2026-08-22最近推送
跨平台平台

功能简介

贯彻 "一切皆插件" 的 DeepSeek Harness webview 封装。 A DeepSeek Harness webview wrapper in the everything-is-a-plugin spirit.

✅
我们的评价
可用 — 实测通过,早期项目

贯彻 "一切皆插件" 的 DeepSeek Harness webview 封装。 A DeepSeek Harness webview wrapper in the everything-is-a-plugin spirit. 实测能干净安装、正常启动。早期项目,但功能可用。

「已验证」表示我们的自动化 CI 在干净 profile 里实际执行了 dsh plugin add 并启动成功——仅此而已。功能描述与版本兼容性均为作者声明。这不是安全审计,也不代表对第三方代码的背书。

README

dsh-webview-wrapper

English | 中文

A naive native desktop shell for the DeepSeek Harness Web surface. dsh-webview-wrapper is an out-of-tree deepseek-harness plugin that hosts the already-running Web app in an OS-native window through WebviewJS — the platform's own webview engine (WebView2 on Windows, WebKit on macOS, WebKitGTK on Linux), never a bundled browser. No Electron, no fork, no patch to the harness.

In keeping with the everything-is-a-plugin philosophy, the integration is pure composition. The package installs into a profile like any out-of-tree plugin, its bundle patch layer inserts one plugin row, and the plugin mounts itself once the Web composition provides the webServer / webRuntime services. The harness itself stays a stock installation.

Features

  • Native window + system tray for the exact surface dsh web serves.
  • Close-to-tray: closing the window hides it and the harness keeps running (an invisible 1×1 keep-alive window holds the process alive).
  • Tray menu (Show / Quit) and tray double-click.
  • Clean teardown: unloading the plugin — or shutting the profile down — exits the native app through the effect disposer.
  • Invariant companion (dsh-webview-wrapper/invariant) registered with the InvariantRegistry.

Installation

Prerequisites:

  • A stock deepseek-harness installation whose profile mounts the Web bundle (dsh web). The wrapper injects webServer and webRuntime, so the target profile must be Web-based — the shipped web profile is the natural target.
  • The WebviewJS platform requirements: Windows → WebView2 (ships with Windows 11 and current Edge), macOS → built-in WebKit (10.15+), Linux → WebKitGTK 4.1 and libxdo.
  • pnpm (the plugin manager forwards its arguments to pnpm).

Quick start

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

Custom profile

The shipped web profile already lists the Web layers (@deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app) in its dsh.profile.bundles. To use a custom profile, copy it and add only the wrapper:

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

What add does, step by step

  1. dsh plugin initializes the profile on first use, then runs pnpm add in the profile directory.
  2. Because dsh-webview-wrapper declares dsh.bundle.patch in its manifest, the plugin manager automatically appends it to the profile's dsh.profile.bundles layer stack.
  3. On the next boot, the bundle's patch layer (cordis.patch.yml) pins the web-runtime row's browser handoff off (the wrapper owns the window) and inserts the webview plugin row into the composition.
  4. The plugin waits for webServer / webRuntime, then owns the native window lifecycle.

One rule: don't add the in-box bundles

dsh plugin add is only for out-of-tree plugins. The Web bundles (@deepseek-ai/dsh-base, @deepseek-ai/dsh-web-app) are in-box: they load from the harness installation and belong in dsh.profile.bundles — never in the profile's dependencies. adding an in-box bundle makes pnpm materialize the whole harness tree inside the profile's node_modules:

  • pnpm installs it with autoInstallPeers: false, so the tree is missing its peers (e.g. @deepseek-ai/cordis); pnpm peers check inside the profile reports them.
  • At boot the loader resolves plugins from the profile directory, so those copies shadow the installation (the $DSH_HOME/profiles/node_modules junctions) and fail to load — tool calls error.
  • A first symptom along the way: @deepseek-ai/dsh-web-app pulls in the harness's native directory picker, whose koffi dependency has an unapproved build script; pnpm 11 (default strict-dep-builds: true) exits non-zero (ERR_PNPM_IGNORED_BUILDS), dsh plugin skips the dsh.profile.bundles reconcile, and the profile boots without the Web layers.

To get out of that state, drop the in-box bundle from dependencies (keep it in dsh.profile.bundles — it resolves from the installation), run pnpm install in the profile directory to prune the harness tree, and boot again.

Running a local checkout

Build the checkout first, then install from the folder:

pnpm run build
dsh plugin --profile web add file:/absolute/path/to/dsh-webview-wrapper

Usage

  • First boot starts in the tray — no main window is created until you ask for it. Double-click the tray icon or choose Show to open the 1024×768 window hosting http://127.0.0.1:<port> (the live Web surface).
  • Closing the window hides it to the tray; the harness keeps running.
  • Quit in the tray menu exits the application.

How it works

File Role
src/index.ts The plugin: creates the WebviewJS Application, the tray, and the main window; routes custom-menu-click, window-close-requested, and application-close-requested; calls app.exit() on disposal.
cordis.patch.yml The bundle patch layer: pins the web-runtime row's openBrowser off (the webview owns the window) and inserts { id: webview, name: 'dsh-webview-wrapper' } into the composition.
src/invariant.ts The invariant companion, registering the package with the InvariantRegistry.
assets/icon.svg Taskbar / tray icon source, rasterized with sharp.

Lifecycle sketch:

apply(ctx)
├─ readIcon(icon.svg, 16)          # one shared async rasterization
└─ ctx.effect(() =>                 # plugin lifetime == native app lifetime
   ├─ new Application()
   ├─ whenReady() → 1×1 keep-alive window + tray (Show/Quit)
   ├─ tray double-click / Show → createOrShowMainWindow()
   │    └─ BrowserWindow(1024×768) + webview → http://127.0.0.1:<ctx.webServer.port>
   ├─ window-close-requested → hide (close-to-tray)
   └─ disposer → app.exit()

Known limitations and roadmap

The wrapper is deliberately naive; the rough edges below are the roadmap:

  1. No native notifications — nothing in the harness surfaces as an OS notification. Roadmap: WebviewJS Notification.
  2. Generic HTTP transport — the webview loads the Web app over http://127.0.0.1:<port>, the same browser HTTP carrier any tab uses. Roadmap: replace it with WebviewJS IPC (webview.expose() / window.ipc.postMessage) and/or a custom protocol, dropping the loopback-HTTP dependency.
  3. No menu bar — only the tray menu exists. Roadmap: app.setMenu() with File/Edit roles and accelerators.
  4. Console window + tray-only exit — launching through the CLI shows the host console window, and the only exit paths are the tray Quit and profile shutdown. Roadmap: package as a GUI-subsystem executable (the WebviewJS CLI / Node SEA) so no console appears, and add an in-page quit affordance.

Other current rough edges: default fixed 1024×768 window with a hardcoded title (no config surface yet), and the main window is not opened at startup (the app starts in the tray).

Development

git clone https://github.com/no1xsyzy/dsh-webview-wrapper.git
cd dsh-webview-wrapper
pnpm install
pnpm run build      # re-run after every change
dsh plugin --profile web add file:/absolute/path/to/dsh-webview-wrapper

For a private dev profile, copy web first as in Custom profile — add only out-of-tree plugins, never the in-box @deepseek-ai/dsh-web-app.

Notes:

  • The workspace never runs the app. The wrapper is a plugin: it only executes inside a profile composition (it injects webServer / webRuntime), so this checkout has no dev server and no standalone entrypoint — and its dependency chain ships prebuilt platform binaries, so there are no native addon builds either. Use the dsh plugin ... add file:<path> flow to test.
  • lib/ and node_modules are gitignored; lib/ is build output.
  • Name discipline (npm publication). The npm package name must stay identical across package.json name, the plugin name in src/index.ts, the bundle row in cordis.patch.yml, and the invariant registration in src/invariant.ts. The plugin manager resolves bundles and the InvariantRegistry keys registrations by npm name, so renaming means updating all four places.
  • Keep README.md and README.zh.md in sync.

安装

🧩 让 Agent 自动装(推荐)

装一次目录插件,之后本站所有插件都能让 DeepSeek Harness 自动找、自动装:

dsh plugin add dshbase-catalog

然后对 agent 说「帮我装 dsh-webview-wrapper」,它会在目录里找到并自动安装。文档:dshbase-catalog · 已验证场景包。

该插件是 GitHub 源码(未发 npm)——直接从仓库装:

Web profile:

dsh plugin --profile web add github:no1xsyzy/dsh-webview-wrapper

Headless(CLI)profile:

dsh plugin --profile headless add github:no1xsyzy/dsh-webview-wrapper

实测报告

验证通过:从 GitHub 源码完成 L1 安装 + L2 加载 + L3 运行(dsh 0.1.0-rc.6)。

安全:尚未扫描——我们的每日静态扫描将很快覆盖它。

分享徽章

Developer 里更多

浏览全部 7819 个插件 →