DSH HUB
首页插件商店插件包社区排行榜资源发布指南
插件源码
返回插件目录

fellow99 /

fellow99/deepseek-harness-desktop

仅 Topic 仓库

An Electron-based desktop wrapper for deepseek-harness.

★ 1 Stars0 Forks0 IssuesN/A 社区评分0 已确认安装
查看 GitHub
README来源: main@86cf4556

中文 | English


DeepSeek Harness Desktop

An Electron-based desktop wrapper for deepseek-harness, providing deep desktop integration.

Status: ✅ Scaffold and dsh consumption complete — the main process runs runProfile('desktop') to host the dsh Host, and the renderer loads the dsh Web UI same-origin (tray/notification MVP capabilities pending). See docs/000-产品概念设计.md for details.


What is this

DeepSeek Harness (dsh) is an open-source agent harness by DeepSeek AI, built on an "everything is a plugin" architecture; its native entry is dsh web (a browser Web UI).

This project wraps the dsh Web UI in a native desktop shell with Electron, adding desktop capabilities such as tray and notifications while fully reusing the dsh frontend — making the agent harness run like a first-class desktop app. It is not a thin "wrap dsh web pointing at localhost" shell, but a first-class desktop application built on dsh's existing architecture.

Core design

dsh has completed its Host/Client split, and its webserver serves both the SPA dist and /api. The desktop shell therefore uses an in-process Host + webserver + localhost same-origin data plane:

┌─ Electron main process (Node.js, also hosts dsh Host)──────────────┐
│  runProfile('desktop', ['--port','0']) → { ctx, shutdown }          │
│    ├─ webserver   ← bound to 127.0.0.1:<free port>, serves dist+/api│
│    ├─ apiProxy    ← RPC gateway                                     │
│    └─ connection  ← already registered /api + WebSocket on webserver│
│  once ready: loadURL(`http://127.0.0.1:${ctx.webServer.port}/`)     │
│  ┌─ Tray / Notification: subscribe to ctx session/event             │
│  └─ Frameless window controls: thin IPC (min/max/close)             │
└───────────────▲────────────────────────────────────────────────────┘
                │ contextBridge: window.dsh (thin IPC, window controls)│
┌───────────────┴────────────────────────────────────────────────────┐
│ Renderer: loadURL('http://127.0.0.1:<port>/')  ← same-origin        │
│   standard dsh Web UI (WebApiClient: fetch /api + WS event stream)  │
└─────────────────────────────────────────────────────────────────────┘

Key point: the renderer loads localhost same-origin — zero CORS, zero auth, zero custom protocol, zero IPC carrier — reusing dsh's existing WebApiClient (HTTP uplink + WebSocket downlink), zero upstream changes.

Planned MVP features

  • ✅ System tray (quit / restore)
  • ✅ Native notifications
  • ✅ Frameless window / custom title bar
  • ✅ Clipboard image paste

(Deferred: global shortcut, launch at login, multiple windows; native file picker reuses dsh's standard frontend directory browser)

Target platforms & distribution

  • Platforms: Windows + Linux (macOS later)
  • Distribution: local packaging for personal use (Electron Forge make); no auto-update, code signing, or store distribution yet

Tech stack

  • Electron + Electron Forge (scaffolding & packaging)
  • deepseek-harness (a sibling directory of this project, not a submodule, referenced as ../deepseek-harness; consumed via local source reference)
  • TypeScript

Development

Integration approach

  • Source reference: dsh lives in a sibling directory (../deepseek-harness, not a submodule); we consume its build artifacts.
  • Host integration: src/main/host.ts dynamically imports dsh's runProfile (apps/cli build artifact), hosting the dsh Host in the main process (webserver bound to 127.0.0.1:<free port>), returning a { ctx, shutdown, port, url } handle.
  • Same-origin data plane: the renderer does loadURL(http://127.0.0.1:<port>/) to load the dsh Web UI same-origin, reusing WebApiClient (HTTP uplink + WebSocket downlink) — zero CORS, zero auth, zero new carrier.
  • desktop profile: profiles/desktop/ (dsh.profile.bundles = [dsh-base, dsh-web-app], with cordis.patch.yml overriding web-runtime.printUrl: false), copied to $DSH_HOME/profiles/desktop at runtime.

Build process (with patches)

dsh depends on Node internal APIs (HMR, native directory dialog) that are unavailable under Electron, so two patches must be applied before building. One command does it all (idempotent — --reverse --check detects already-applied and skips):

npm run build:dsh   # ① git apply both patches under patches/ → ② pnpm install (if node_modules missing) → ③ build:lib:host + build:lib:client + build:web
Patch Purpose
patches/dsh-disable-hmr.patch Adds a DSH_DISABLE_HMR switch to runProfile, skipping watch-only HMR (HMR depends on --expose-internals)
patches/dsh-disable-native-picker.patch Forces directory-picker to use browse under Electron (the native dialog worker fails because it spawns electron.exe)

Electron compatibility root cause: dsh's loader obtains the Node internal ESM loader via the node-addon-require-builtin native module, which fails under Electron because Electron's V8 lacks the GetAlignedPointerFromEmbedderData symbol; in development the loader falls back to default ESM import, resolved by host.ts's ensureWorkspaceLinks linking workspace packages into dsh's root node_modules.

Start / package

npm install
npm start          # Development: Vite build + launch Electron, main process hosts dsh Host and loads its Web UI
npm run package    # Package: prepackage auto-collects (pnpm deploy materializes dsh artifacts into dsh-dist/, extraResource copies into resources/dsh-dist)

The packaged output out/DeepSeek Harness Desktop-win32-x64/ already includes dsh (lib + node_modules + web dist + profile); the exe runs dsh directly.

Directory structure

This project and deepseek-harness (dsh) live in sibling directories (not a submodule), integrated via source reference:

(sibling directories)
├── deepseek-harness-desktop/      # This project (Electron desktop shell)
│   ├── docs/                      # Product concept design
│   ├── specs/                     # Spec documents (as-built; see specs/README.md for index)
│   ├── patches/                   # dsh upstream patches (git apply, auto-applied by build:dsh)
│   │   ├── dsh-disable-hmr.patch
│   │   └── dsh-disable-native-picker.patch
│   ├── scripts/                   # Build scripts
│   │   ├── build-dsh.mjs          # apply patches + install deps + build dsh artifacts
│   │   └── collect-dsh.mjs        # collect dsh artifacts into dsh-dist/ (pnpm deploy + materialize)
│   ├── profiles/desktop/          # Custom desktop profile (dsh.profile.bundles + cordis.patch.yml)
│   ├── src/
│   │   ├── main/                  # Electron main process (= dsh Host host)
│   │   │   ├── index.ts           # single-instance lock → start host → create window → tray/notification/lifecycle
│   │   │   ├── host.ts            # runProfile('desktop') → { ctx, shutdown }; readiness determination
│   │   │   ├── windows.ts         # BrowserWindow, loadURL(localhost), frameless/security
│   │   │   ├── tray.ts            # system tray (quit/restore)
│   │   │   ├── notifications.ts   # subscribe to ctx session/event → native notifications
│   │   │   └── lifecycle.ts       # NO_PROXY/CA, crash handling
│   │   ├── preload/index.ts       # contextBridge: window.dsh (thin IPC)
│   │   └── renderer/renderer.ts   # minimal renderer entry (fallback loading page)
│   ├── forge.config.ts            # Electron Forge config (extraResource copies into resources/dsh-dist)
│   ├── vite.*.config.ts           # Vite configs (main/preload/renderer)
│   ├── index.html                 # renderer entry (Forge Vite convention: at project root)
│   └── resources/                 # app icon, tray icon
│
└── deepseek-harness/              # The wrapped host (dsh, source reference, not a submodule)
    ├── apps/                      # cli (dsh bin, profile-boot), web (Web frontend, build:web produces dist)
    ├── packages/                  # host / client / core / session workspace packages
    ├── vendor/                    # vendored cordis framework packages (cordis / loader / hmr / ...)
    └── native/                    # landlock-run native module (Linux sandbox, cut in MVP)

Related docs

  • docs/000-产品概念设计.md — product concept design (architecture, data flow, module breakdown, open questions)
  • specs/README.md — spec document index (project-level and module-level specs)
  • AGENTS.md — AI agent working conventions

References

  • deepseek-harness (sibling directory ../deepseek-harness) — the wrapped host; its docs/ directory contains full architecture docs
  • opencode (desktop shell reference: packages/desktop/) — a similar "wrap an agent harness with Electron" use case

License

MIT © 2026 fellow99

—/ 5

暂无评分

需要先验证清单

Commit 86cf4556cbc5

社区评论

还没有评论,来写第一条。

DSH HUB

社区维护的 DSH 插件索引。不是 GitHub 或 DeepSeek AI 的官方产品。

社区资源API关于