Back to home@Olympianz

dsh-desktop-packager

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).

Stars
0
Language
JavaScript
Created
Aug 31, 2026
Updated
Aug 31, 2026
GitHub repo

Introduction

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 productNamelogo → 应用图标(.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__.loadsettings.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-configGET返回 { view }(脱敏后的 design/plugins/models/users)
/api/desktop-configPOST{ action, payload } → 应用改动并返回 { view }
/api/desktop-config/catalogGET返回 { plugins, models }(枚举)
/api/desktop-config/logoGET返回 { 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 的模型(留空 = 全部)。
  • 权限设置:新增/删除用户(账号 + 密码),并为每个用户勾选权限 (查看/修改 settingssettings-designsettings-pluginssettings-modelssettings-permissions)。

2. 打包

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

参数默认说明
dshCheckoutDir配置 dshCheckoutDir已构建pnpm run build 完成)的 harness 源码目录
out~/Desktop/DeepSeek-Harness-dist产物输出目录
appName设计方案里的 appName应用显示名(工具参数优先级高于设计方案)
bundleIdcom.deepseek.harnessbundle identifier
version0.1.1版本号
archarm64arm64 / x64
identity空(ad-hoc)Developer ID 签名身份
nodeBin / nodeVersion复用本地 Node / 指定下载版本
skipDmg / keepStagingfalse只出 .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-designsettings-pluginssettings-modelssettings-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.jsapps/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