dsh-background
为 DeepSeek Harness(DSH)的 Web / Desktop 界面设置自定义背景图的插件。
DSH 0.2.x 去掉了旧版的「设置 → 通用 → 背景图」。这个插件把它补回来:选一张本地图片作为整个界面的背景,侧边栏、会话列表、内容区等大块表面自动变成半透明,正文对比度仍然够用。右下角常驻一个背景按钮,选择图片、恢复默认、移除背景都在弹出的面板里完成;选择结果写入 $DSH_HOME/dsh-background/,刷新页面或重启应用都不会丢。
插件只在本机 loopback 的同源页面上读写自己的数据,不发起任何外部网络请求。
功能特性
- 整窗背景:任意 JPEG / PNG / WebP 图片都可以作为整个界面的背景,铺满窗口并固定,不随内容滚动。
- 自动半透明:左侧栏、会话列、内容列等大块表面按主题色自动调成半透明,浅色与深色主题分别适配,不需要手动改样式。
- 三步操作:右下角按钮打开面板即可「选择图片」「恢复默认」「移除」,面板内实时预览当前背景,操作结果有文字提示。
- 持久保存:模式与图片保存在
$DSH_HOME/dsh-background/,不依赖浏览器存储,也不受 Desktop 每次启动随机端口的影响。 - 内置默认图:没有自定义图片时使用随包分发的
assets/default.jpg;host 不可用时客户端回退到打包进 bundle 的同一张图。 - 零依赖、无网络:没有运行时依赖,不需要联网,只通过同源 HTTP 路由读写本地文件。
界面效果

右下角的背景按钮打开设置面板,可以预览当前背景并执行三个操作。

使用内置默认背景时,侧边栏与内容区保持半透明,正文仍然清晰。
安装
环境要求
- DSH 0.2.x,使用 Web 或 Desktop 界面(插件面向 web 客户端平台,TUI / headless 不适用)。
- 本地构建需要 Node.js 18 及以上;只在 DSH 里运行插件不需要系统 Node。
1. 克隆仓库
把仓库放到 DSH 的插件目录(默认 %USERPROFILE%\.dsh\plugins,设置了 DSH_HOME 时以它为准):
$dshHome = if ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $env:USERPROFILE '.dsh' }
$pluginDir = Join-Path $dshHome 'plugins\dsh-background'
New-Item -ItemType Directory -Force (Split-Path $pluginDir) | Out-Null
git clone https://github.com/waterc07/dsh-background.git $pluginDir
2. 把插件链接进 profile
选择要启用插件的 profile(desktop 或 web),在它的 node_modules 下建立指向插件目录的链接:
$profileName = 'desktop'
$profileDir = Join-Path $dshHome "profiles\$profileName"
New-Item -ItemType Junction -Path (Join-Path $profileDir 'node_modules\dsh-background') -Target $pluginDir
也可以交给 DSH 的插件命令(内部调用 pnpm)来建立链接:
dsh plugin --profile $profileName add $pluginDir
3. 在 profile 里注册 bundle
编辑 $dshHome\profiles\<profile>\package.json:把插件加入 dependencies,并追加到 dsh.profile.bundles 列表末尾。
{
"dependencies": {
"dsh-background": "link:../../plugins/dsh-background"
},
"dsh": {
"profile": {
"bundles": [
"...",
"dsh-background"
]
}
}
}
bundles 的顺序就是层叠顺序,把插件放在最后即可;通常不需要再改 profile 的 cordis.patch.yml。
4. 重启 DSH
完全退出并重新启动 DeepSeek Harness(或重新执行 dsh --profile desktop)。界面右下角出现背景按钮就说明插件加载成功。首次安装请完整重启,仅刷新页面不足以注册 host 路由。
卸载
删除 profile 的 node_modules\dsh-background 链接,并从 package.json 的 dependencies 与 dsh.profile.bundles 中删掉 dsh-background,重启即可。$dshHome\dsh-background\ 里的数据目录可以在确认不需要后手动删除。
使用说明
- 点击右下角的圆形背景按钮打开面板;再次点击、按 Esc 或点击面板外区域关闭。
- 选择图片:从本地选一张图片,浏览器端会缩放到最长边 2560px 并压成 JPEG(质量从 0.9 逐步降到 0.58,直到不超过大小上限)。
- 恢复默认:删除自定义图片,回到随插件分发的默认背景。
- 移除:完全关闭背景,所有被调成半透明的表面恢复原样。
- 面板中会显示当前背景的预览;操作进行中和完成后都有提示文字。
图片限制:
| 项目 | 限制 |
|---|---|
| 原始文件 | ≤ 40 MB,且必须是 image/* 类型 |
| 缩放 | 最长边 ≤ 2560px,保持比例 |
| 保存格式 | JPEG(不保留透明通道) |
| 存储上限 | 编码后的 data URL ≤ 2,000,000 字符(约 1.5 MB 图片,超出会提示换一张) |
配置与数据
插件没有用户可配置项,数据目录跟随 DSH:
$DSH_HOME/dsh-background/
├─ state.json # {"mode":"default"|"custom"|"off","rev":<毫秒时间戳>}
└─ background.bin # 自定义背景图片的原始字节
$DSH_HOME 未设置时取 %USERPROFILE%\.dsh(Windows)或 ~/.dsh(macOS / Linux)。该目录按 DSH home 共享,不区分 profile。
- 选择图片:写入
background.bin,再写state.json(mode=custom);两次写入都是「临时文件 + rename」的原子替换。 - 恢复默认:删除
background.bin,写state.json(mode=default)。 - 移除:只写
state.json(mode=off),保留background.bin;把state.json删掉后,host 会按background.bin是否存在推断为custom或default。 state.json缺失或损坏时同样按是否存在background.bin推断模式。- 写入文件时设置
0o600权限(POSIX 生效),接口返回的rev用于给图片 URL 加缓存失效参数。
HTTP 路由
host 侧注册以下路由,全部只接受本机 loopback(127.0.0.1 / ::1)且同源的请求,其它来源返回 403;请求体最大 4 MB,错误统一返回 { "error": "..." }。
| 方法 | 路径 | 请求体 | 成功响应 | 说明 |
|---|---|---|---|---|
| GET | /api/dsh-background/state |
— | { "mode": "default"|"custom"|"off", "rev": "..." } |
当前模式与缓存失效版本 |
| GET | /api/dsh-background/image |
— | image/jpeg 字节 |
custom 返回 background.bin,否则返回内置默认图;off 时 404 |
| POST | /api/dsh-background/set |
{ "dataUrl": "data:image/jpeg;base64,..." } |
{ "mode": "custom", "rev": "..." } |
接受 jpeg / png / webp,data URL 最长 2,000,000 字符 |
| POST | /api/dsh-background/remove |
{} |
{ "mode": "off", "rev": "..." } |
关闭背景,保留已保存的图片文件 |
| POST | /api/dsh-background/reset |
{} |
{ "mode": "default", "rev": "..." } |
删除自定义图片,恢复内置默认图 |
400 / 404 / 405 / 413 / 500 等错误也返回 JSON。
实现原理
插件由 host 和 client 两半组成,通过 DSH 的 bundle 机制组合:
- host 半(
src/index.js,构建到lib/index.js):一个 Cordis 插件,声明inject = ['webServer'],在apply(ctx)里通过ctx.effect注册上表 5 条路由。它负责把图片和模式落盘,并在 Web UI 的同源地址上把图片发回浏览器——因为 Desktop / Web shell 每次启动都监听随机 loopback 端口,纯浏览器存储会随 origin 变化而「丢失」。 - client 半(
src/client.js,构建到lib/client.js):以window.__ModuleLoader__.load({ id, factory })形式声明,由package.json的dsh.client.platform = "web"登记。apply(ctx)时注入样式、挂载右下角 UI、读取 host 状态并绘制背景。 - bundle 补丁(
cordis.patch.yml):向 profile 的层叠树插入id: background, name: dsh-background条目。
绘制与半透明处理:
- 给
<body>加data-dsh-wallpaper属性,并把当前图片 URL 写进 CSS 变量--dsh-wallpaper-image;背景由「半透明罩层 +cover固定图片 + 主题底色」三层组成。罩层在浅色主题下是 74% 的主题底色,深色主题(data-ds-dark-theme)下是 55%,用来保证正文对比度。 - CSS 先把
_frame、_sidebarCol、_rightbarCol、_centerCol等大块表面改成半透明;client 还会扫描这些列内面积占比超过 55% 的纯色块,把它们与--dsw-alias-bg-base、--dsw-specific-sidebar-fill、--dsw-alias-bg-layer-1三个主题 token 比对,命中后按 60% / 72% / 78% 的color-mix()替换,并记录到集合里,以便移除背景或卸载时精确还原。 - 用
MutationObserver监听 body 子节点变化与data-ds-dark-theme属性切换,窗口尺寸变化时重算;启动后轮询等待_frame挂载(最多 15 秒)。热重载时先调用上一实例的window.__dshBackgroundDispose再挂载新实例。 - 默认图在构建时以 base64 data URL 内联进 client bundle,host 不可用时回退使用;host 端则直接读取
assets/default.jpg返回。
目录结构
dsh-background/
├─ assets/
│ └─ default.jpg # 内置默认背景图
├─ docs/
│ ├─ panel.png # README 截图:设置面板
│ └─ preview.png # README 截图:默认背景效果
├─ lib/ # 构建产物(入库,DSH 直接加载)
│ ├─ client.js # 由 src/client.js 生成,内联默认图
│ └─ index.js # 由 src/index.js 复制
├─ scripts/
│ └─ build.mjs # 唯一的构建脚本
├─ src/
│ ├─ client.js # 浏览器侧源码
│ └─ index.js # host 侧源码
├─ cordis.patch.yml # bundle 补丁
├─ LICENSE
├─ package.json
└─ README.md
开发与构建
lib/ 是入库的构建产物:DSH 直接加载 lib/index.js 与 lib/client.js,运行时不执行构建,所以改完 src/ 后必须重新构建并提交 lib/。
node scripts/build.mjs
# 或 npm run build
构建做两件事:
- 把
src/client.js里的__DEFAULT_IMAGE__占位符替换成assets/default.jpg的 base64 data URL,写出lib/client.js; - 把
src/index.js原样复制为lib/index.js。
没有打包器、没有运行时依赖、不访问网络。构建会在占位符缺失、默认图 data URL 超过 2,000,000 字符时直接报错退出。要换内置默认背景,替换 assets/default.jpg 后重新构建即可。
调试钩子:页面加载前设置 window.__DSH_BACKGROUND_DEBUG__ = true,客户端实例会挂到 window.__DSH_BACKGROUND__,方便测试;默认不暴露。
已知限制
- 依赖 DSH 内部样式:半透明效果基于 DSH 自己的 CSS 类名(
_frame、_sidebarCol等)和主题变量,属于未公开细节。DSH 升级后如果这些名字变了,背景仍会生效,但大块表面可能不再半透明,需要跟进适配。 - 只做「铺满」:不提供裁剪、焦点选择、模糊或亮度调节;背景固定(
background-attachment: fixed),不随内容滚动。 - 统一转 JPEG:选 PNG / WebP 也会用 canvas 重新编码成 JPEG,透明通道不保留(透明区域会变黑)。
- 大小上限:原图 ≤ 40 MB;编码后的 data URL ≤ 2,000,000 字符(约 1.5 MB 图片),超出时会提示换一张。
- 单份配置:数据按
$DSH_HOME共享,没有多套主题、轮播或按 profile 区分的能力。 - 仅本机可用:路由只允许 loopback 同源访问,把 DSH Web 暴露到局域网 / 公网后,背景相关接口会被拒绝(403)。
兼容性
- 面向 DSH 0.2.x,在 0.2.1-rc.3 上验证;依赖 host 的
webServer服务、bundle 补丁和dsh.client客户端 bundle 机制。未来大版本若调整插件模型或样式结构,可能需要相应更新。 - 仅适用于 Web / Desktop 的 web 客户端;TUI、headless 等不加载浏览器侧 bundle 的场景没有效果。
- 开发与验证环境为 Windows;代码没有平台相关逻辑,但 macOS / Linux 未逐一验证。
许可
MIT © 2026 waterc
assets/default.jpg 是随插件分发的演示用默认背景(机甲大师赛事照片),版权归原权利人所有,不在 MIT 许可范围内;公开分发前请自行确认授权,或替换该文件后重新构建。docs/ 下的两张界面截图用于说明功能。
No comments yet. Be the first to write one.