DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Olympianz /

Olympianz/dsh-desktop-packager

Verified

Package a built DeepSeek Harness checkout into a distributable macOS desktop app (.app + .dmg) with a standalone Node runtime and an Electron shell, customized through a Web Settings section (logo/VI theme, bundled plugins, bundled models, users & permissions).

★ 0 Stars0 Forks1 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@e51f2899

dsh-desktop-packager

把 DeepSeek Harness 封装成一个可分发的 macOS 桌面应用(.app + .dmg)的 DSH 插件,并在 dsh web 的 Settings 里新增一个 「桌面打包」菜单,通过 4 个配置模块定制化生成 dmg。

能力

  • 注册工具 dsh_package_desktop:把一个已构建的 deepseek-harness checkout 封装成 .app + .dmg,并按「桌面打包」配置定制化生成。
  • Settings 菜单「桌面打包」(浏览器半侧,settings.section),含 4 个 Tab:
    1. 设计方案 — 显示当前 logo、应用名、VI 方案(主题色 / 背景色),可更换 logo 或整体 VI。
    2. 插件设置 — 从已安装插件中勾选「打包进桌面 app」的插件。
    3. 模型设置 — 从已支持的模型中勾选「打包进桌面 app」的模型。
    4. 权限设置 — 配置桌面 app 的用户(账号 + 密码)与权限(查看/修改 settings 各页)。
  • 打包定制化落地:
    • appName → Electron productName;logo → 应用图标(.icns/.png/.svg);
    • themeColor / backgroundColor → 注入 DSH web 主题变量 (--dsw-alias-brand-primary / --dsw-alias-bg-base)与窗口背景色;
    • selectedPlugins / selectedModels → 写入 app 的 DSH_HOME/desktop-config.json, 供 app 内的运行时插件做插件/模型过滤;
    • users → 打包进 Contents/Resources/desktop.json,由 Electron 主进程实现 登录门(账号 + 密码,加盐 scrypt 校验)并注入当前用户权限。

架构

一个 dual-face bundle(Host 原生 TS + 手写浏览器 client bundle):

半侧 入口 形态 说明
Host(入口) src/index.ts 原生 TS(dsh plugin add 直接加载) 提供 desktopConfig 服务 + 注册 dsh_package_desktop 工具 + 注册 HTTP 路由
Host(服务) src/desktop-config.ts 原生 TS 持久化 + 插件/模型枚举 + 用户管理(scrypt 加盐哈希)+ HTTP 路由
Client(浏览器) client.js 手写 bundle(window.__ModuleLoader__.load) settings.section「桌面打包」4 Tab,fetch 同源调 HTTP 路由
打包驱动 packaging/build-macos.mjs 独立 .mjs 定制化生成 .app/.dmg
桌面壳 packaging/electron/* 独立 .js 登录门 + 主题注入 + 拉起 dsh web

配置状态存于单个 JSON 文件(默认 ~/.dsh/desktop-packager/config.json),由 Host 服务、 打包工具与 build-macos.mjs 共享。

浏览器 ↔ Host 桥接(同源 HTTP)

浏览器半侧不依赖 Typert/Remote,直接用同源 fetch 访问 Host 半侧在 webServer 上 注册的 JSON 路由:

路由 方法 作用
/api/desktop-config GET 返回 { view }(脱敏后的 design/plugins/models/users)
/api/desktop-config POST { action, payload } → 应用改动并返回 { view }
/api/desktop-config/catalog GET 返回 { plugins, models }(枚举)
/api/desktop-config/logo GET 返回 { ok, dataUrl? }(logo 预览)

安装

dsh plugin --profile web add /path/to/dsh-desktop-packager

或在 dsh web 会话里让助手调用 dsh_master_install(需 DSH-master)。

本包已在当前机器以符号链接方式装进 ~/.dsh/profiles/web/node_modules/dsh-desktop-packager, 指向源码目录;改动源码后重启 dsh web 即生效。

使用

1. 在 Settings 里配置

打开 dsh web → 左下角 Settings → 「桌面打包」,分别配置:

  • 设计方案:填 logo 绝对路径(.png/.svg/.icns)、应用名、主题色、背景色,点「保存」。
  • 插件设置:勾选要打进桌面 app 的插件(留空 = 全部)。
  • 模型设置:勾选要打进桌面 app 的模型(留空 = 全部)。
  • 权限设置:新增/删除用户(账号 + 密码),并为每个用户勾选权限 (查看/修改 settings、settings-design、settings-plugins、settings-models、 settings-permissions)。

2. 打包

对助手说「帮我用 dsh_package_desktop 打包我的 deepseek-harness」,助手会调用该工具。 核心参数:

参数 默认 说明
dshCheckoutDir 配置 dshCheckoutDir 已构建(pnpm run build 完成)的 harness 源码目录
out ~/Desktop/DeepSeek-Harness-dist 产物输出目录
appName 设计方案里的 appName 应用显示名(工具参数优先级高于设计方案)
bundleId com.deepseek.harness bundle identifier
version 0.1.1 版本号
arch arm64 arm64 / x64
identity 空(ad-hoc) Developer ID 签名身份
nodeBin / nodeVersion 空 复用本地 Node / 指定下载版本
skipDmg / keepStaging false 只出 .app / 保留中间目录

打包时工具把 configPath 传给 build-macos.mjs,后者读取同一份 JSON 并应用 logo / 主题色 / 插件 / 模型 / 用户权限定制。

配置项(cordis.yml)

- id: dsh-desktop-packager
  name: dsh-desktop-packager
  config:
    dshCheckoutDir: /absolute/path/to/deepseek-harness
    out: ~/Desktop/DeepSeek-Harness-dist
    appName: DeepSeek Harness
    bundleId: com.deepseek.harness
    version: 0.1.1
    arch: arm64            # arm64 | x64
    identity: ""           # Developer ID Application: …
    nodeBin: ""            # 复用本地 node 二进制
    nodeVersion: ""
    nodeDistBase: https://nodejs.org/dist
    electronMirror: ""     # 国内镜像加速
    electronBuilderBinariesMirror: ""
    skipDmg: false
    keepStaging: false
    configPath: ~/.dsh/desktop-packager/config.json   # 定制化状态文件

定制化状态文件(configPath)

{
  "design": {
    "appName": "DeepSeek Harness",
    "logoPath": "/absolute/path/to/logo.svg",
    "themeColor": "#4D6BFE",
    "backgroundColor": "#0f1115"
  },
  "selectedPlugins": ["@deepseek-ai/dsh-web-app"],
  "selectedModels": [{ "provider": "deepseek", "model": "deepseek-chat" }],
  "users": [
    { "username": "admin", "passwordHash": "$scrypt$<salt>$<hash>", "permissions": ["settings:view", "settings:edit"] }
  ]
}

密码只保存加盐 scrypt 哈希,绝不落明文。

权限模型

权限键为 <section>:<action>:settings(面板整体)、settings-design、 settings-plugins、settings-models、settings-permissions,每个都有 :view 与 :edit。 打包后桌面 app 的登录门校验账号密码后,把该用户权限通过 DSH_DESKTOP_USER / DSH_DESKTOP_PERMISSIONS 环境变量与 DSH_HOME/desktop-config.json 注入运行时,由 app 内的运行时插件据此对设置页做 可见性 / 可编辑控制。

前置条件(打包机)

  • macOS(默认 arm64 / Apple Silicon)。
  • Node.js ≥ 22.19(跑打包脚本用)。
  • 网络(下载 Node 运行时 / Electron / electron-builder),或提供 nodeBin 复用本地 Node。
  • 一个已构建的 deepseek-harness checkout:apps/cli/lib/bin.js 与 apps/web/dist 必须存在。

目录结构

dsh-desktop-packager/
├── src/
│   ├── index.ts              # Host 入口:desktopConfig 服务 + 打包工具 + HTTP 路由
│   ├── config.ts             # 部署配置 schema(含 configPath)
│   ├── desktop-config.ts     # 定制化状态模型 + 服务(持久化/枚举/用户/哈希/HTTP)
│   └── packager.ts           # 子进程 runner(跑 build-macos.mjs)
├── client.js                 # 浏览器半侧 bundle(settings.section「桌面打包」4 Tab)
├── packaging/
│   ├── build-macos.mjs       # 打包驱动(应用 logo/名称/主题/配置)
│   └── electron/
│       ├── main.js           # 登录门 + 主题注入 + 拉起 dsh web
│       ├── preload.js        # 登录窗 contextBridge
│       └── entitlements.mac.plist
├── package.json              # dual-face manifest(dsh.bundle + dsh.client)
├── cordis.patch.yml
└── tsconfig.json

签名与公证(分发建议)

默认 ad-hoc 签名:本机可正常打开,发给别人时 Gatekeeper 会提示「无法验证开发者」。 彻底免除拦截需 Developer ID 签名 + 公证,详见 packaging/README.md。

—/ 5

No ratings yet

Verified DSH bundle

Commit e51f2899a2aa

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout