DeepSeek Harness Web GUI 的自定义背景插件:图片 / 动图 / 视频 / 内置极光渐变,磨砂玻璃质感,配浮动控制面板
30.7/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查未通过:仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add liuliyisui/dsh-background该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-settings@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 自定义界面背景
- 支持图片动图视频
- 内置极光渐变
README
由 DeepSeek 最新模型翻译生成dsh-background v3
自定义 DeepSeek Harness Web GUI 背景的客户端插件:在界面背后画一层壁纸(图片 / 动图 / 视频)或内置极光渐变,配合毛玻璃界面与一个浮动控制面板,设置持久化在宿主端($DSH_HOME/settings.yaml 的 background: 段)。
功能
- 壁纸:选择本地图片、GIF/WebP 动图或视频(mp4/webm/ogv/mov),选中即上传即生效;支持填充方式与九宫格位置预览。
- 媒体库:上传的媒体持久化到 $DSH_HOME/skin-aurora-media/,面板里可列出、选用、删除;上传按内容寻址,同一文件重复上传不会产生副本。
- 画面调节:遮蔽(变暗)、淡化(融入主题底色)、模糊、透明度。
- 毛玻璃:输入框与侧边栏高斯模糊,模糊半径独立可调。
- 极光渐变:没有壁纸时的默认背景,深浅两套配色。
- 实时生效:面板里改完立刻应用,无需刷新页面。
- 持久化:通过宿主 settings 服务读写(background 命名空间 + schemastery 校验)。
- 零 React 依赖:控制面板是纯 DOM 实现。
使用
1. 重启 dsh web(插件注册需要重启生效),刷新浏览器。
2. 点击右下角 🎛 打开「背景定制」面板。
3. 勾选「启用自定义背景」,选壁纸、调参数。
展开完整文档(README 剩余 1 节)
dsh-background v3
自定义 DeepSeek Harness Web GUI 背景的客户端插件:在界面背后画一层壁纸(图片 / 动图 / 视频)或内置极光渐变,配合毛玻璃界面与一个浮动控制面板,设置持久化在宿主端($DSH_HOME/settings.yaml 的 background: 段)。
功能
- 壁纸:选择本地图片、GIF/WebP 动图或视频(mp4/webm/ogv/mov),选中即上传即生效;支持填充方式与九宫格位置预览。
- 媒体库:上传的媒体持久化到 $DSH_HOME/skin-aurora-media/,面板里可列出、选用、删除;上传按内容寻址,同一文件重复上传不会产生副本。
- 画面调节:遮蔽(变暗)、淡化(融入主题底色)、模糊、透明度。
- 毛玻璃:输入框与侧边栏高斯模糊,模糊半径独立可调。
- 极光渐变:没有壁纸时的默认背景,深浅两套配色。
- 实时生效:面板里改完立刻应用,无需刷新页面。
- 持久化:通过宿主 settings 服务读写(background 命名空间 + schemastery 校验)。
- 零 React 依赖:控制面板是纯 DOM 实现。
使用
1. 重启 dsh web(插件注册需要重启生效),刷新浏览器。
2. 点击右下角 🎛 打开「背景定制」面板。
3. 勾选「启用自定义背景」,选壁纸、调参数。
4. 「恢复默认」一次性清除该命名空间的所有自定义设置。
架构
| 文件 | 职责 |
| lib/index.js | 宿主半部:注册 background settings 命名空间,把媒体路由挂到 webServer |
| lib/media.js | 宿主半部:媒体库路由(流式上传 / 列表 / Range 服务 / 删除),不依赖任何 @deepseek-ai 包 |
| lib/client.js | 浏览器半部:背景层、主题 token 通道、毛玻璃、浮动控制面板 |
| test/media.test.mjs | 媒体路由测试,跑在纯 Node http server 上,不需要 DSH 运行时 |
| tools/ | 开发工具:CDP 探针(probe-gui.mjs)与 GUI token 发现(web-token.mjs) |
浏览器 bundle 以 module-loader 格式(window.__ModuleLoader__.load({id, factory}))由宿主经 /plugins/dsh-background/client.js 提供。
v3 相对 v2 的关键改动
v3 是一次重写,不是叠加。以下每条都对应一个在线上 DOM 或代码里实测确认的缺陷。
1. 背景层原本根本不可见
不透明的 pI_x6G_frame / pI_x6G_root 消费 --dsw-alias-bg-base,且以 position: relative 在绘制顺序上排在 z-index: -1 的背景层之后。v2 只在「设置了壁纸图片」时才把这个 token 打薄,所以纯渐变状态下极光渐变从来没显示过(实测:token 改成 transparent 后 frame 立即透明,改成 rgba(21,21,23,0.25) 即得到「淡化 0.25」)。
v3 把「打薄 token」作为固定的第一步,并让 fade 直接由它实现。
2. 同一个 token 有两个写入方
v2 同时用 标签(!important)和 theme.overrideTokens() 写 --dsw-alias-bg-base,并且颜色功能与图片功能各写一套。v3 只有 overrideTokens() 一个写入方;颜色功能整体砍掉后,这个冲突从根上消失。
3. 毛玻璃其实只糊了侧边栏
v2 的毛玻璃 CSS 挂在 [data-phase="active"] 下,而 [class="inputBar"] 在真实 DOM 里匹配 0 个元素(真实输入框是 DIV.uV2eYG_input)。所以「输入框毛玻璃」从未生效。
(更正:早期探测说 [data-phase="active"] 也匹配 0 个元素——那是在空会话 hero 状态下测的;活跃会话里它是存在的。第 14 条记录了真正的原因。)
v3 删掉了 v2 里「把 dialog 内所有后代背景强制透明」那条会削掉按钮底色的规则。
14. 玻璃加在了错误的层上(主人报的「输入框没有毛玻璃」)
修完第 3 条之后,玻璃的目标选成了 [class="composerSeat"] [contenteditable]——里层那个可编辑元素。但真正可见的输入框是它外面的卡片:
[data-composer-card] → background: rgb(44,44,46) 不透明;圆角 22px
└─ [data-composer-input] contenteditable → 玻璃加在这里
backdrop-filter 只能模糊它背后的内容,而背后正是那张不透明卡片自己的颜色——所以玻璃永远看不出来。空会话的 hero 与活跃会话用的是同一套卡片,因此两种状态都没生效。
Now the glass is applied to [data-composer-card], and [data-composer-input] is kept transparent (no longer stacking a second layer of surface). These data-composer- are the app's own stable hooks, far more reliable than class names with build hashes.
tools/verify-v3.mjs pins it down with 5 assertions: the card must have a 26px backdrop-filter, the card background must be semi-transparent, and the inner editable must be fully transparent.
15. The glass's own fill must override the background (the "black band in the middle of the input box")
After changing the card to real glass, the user saw a blurry dark band in the middle of the card. The cause is not a CSS mistake, but the inevitable result of glass + wallpaper: backdrop-filter samples everything behind the card, and when the wallpaper is tiled with cover, the input box happens to sit right on the darkest region at the very bottom of the image—blurred by 14px into a dark blob, showing through the 34% background color.
The reason the input box in the reference image looks clean is that behind it is a smooth gradient. So the fix is to let the card's own fill take the lead: a near-solid base color (dark rgba(20,24,36,0.88)), a 1px thin border, plus a very faint vertical gradient, keeping the blur and saturation to maintain the glass texture.
How to actually test it: tools/probe-composer.mjs uses CDP's Page.captureScreenshot with clip to take a 2x zoomed-in close-up of the input box; a full-window screenshot can't reveal this kind of detail. It also outputs a row-by-row brightness profile, used to distinguish "a semi-transparent card sampling a non-uniform background" from "something is actually drawn there"—in the early days, guessing between these two by eye wasted many rounds.
16. That gradient you added yourself is the "input box black band"
To achieve the layering of the reference image, item 15 once added a linear-gradient(180deg, rgba(255,255,255,0.05), rgba(0,0,0,0.10)) to the card. On such a dark panel, that -10% black is read by the eye as a horizontal band.
The row-by-row brightness profile is decisive: before the fix it slid monotonically from 44 → 35 (max difference 9.0); after removing the gradient it was basically flat at 33 → 33 (max difference 4.8, almost entirely the contribution of the placeholder text itself). Keep the panel flat; don't add decorative gradients.
17. In glass mode the sidebar is washed into a dull gray slab
Glass mode gave sidebarCol the rgba(20,28,50,0.55) dark gradient carried over from v2; it stacked on top of the 30% dimming, crushing the wallpaper to death, turning the sidebar into a stuffy gray slab that completely clashes with the bright, transparent main text area next to it.
Now in glass mode sidebarCol stays transparent: the frosting is delegated to a dedicated blur layer, and the sidebar and main text share the same dimming layer (item 13).
4. Uploads read the file into memory and silently corrupt binary data
v2 used Buffer.concat on the entire request body (up to 512MB), then used a greedy regex /Content-Type:...\r\n\r\n([\s\S]?)\r\n--/ to find file boundaries in a latin1 string.
Tested on the same valid multipart data of 98,332 bytes, v2 only added 10 bytes—any image or video containing \r\n-- internally would be truncated at the first \r\n--.
v3 switches to streaming: the Transform parses the part header only once, then falls back to a fixed delimiter length before passing it on, so even boundaries split across TCP segments won't be misjudged as data; pipeline provides true backpressure.
5. Every slider move writes to disk
In v2, four sliders bound input events directly to scope.set(), so dragging a slider once meant dozens of writes to settings.yaml. v3 switches to optimistic local preview + 200ms debounce, and commits to disk in a single batch via scope.mutate() (one drag = one write).
6. The write storm of "restore defaults"
v2 iterated over 16 fields writing them one by one, with default values written in a nested triple. v3 clears the entire section with a single atomic operation:
scope.mutate([{ op: "unset", path: [] }])
7. Frosted-glass blur hijacked by the wallpaper blur
v2 used GLASS_CSS(Math.max(8, Number(v.blur) || 14)) to reuse the wallpaper's blur value; setting the wallpaper to 60 would also blur the UI to 60. v3 adds an independent glassBlur field.
8. Images stuffed into localStorage
v2 stored image data URLs in localStorage (5MB quota, settings not portable), while also unsetting the image field in settings. v3 directly uses media-library URLs for lookup, and all localStorage-related code is deleted.
9. Removing unused features
Light/dark background colors (color / colorDark) and the separate dark image (imageDark) have been removed from the schema—the panel never wrote them anyway. Image position changed from a hand-typed CSS value to a nine-grid preset dropdown.
10. The second item of the native dropdown is unreadable
When is expanded, Chromium uses its own light-colored popup background, while the option text inherits the panel's light label color (--dsw-alias-label-primary). Under a dark theme that means white text on a white background—the second item of every dropdown (like "Video") is unreadable.
Now each option's foreground/background is explicitly pinned, and each select's color-scheme follows the theme (refreshed on theme events in sync()).
11. "Wallpaper URL" manual input box removed
壁纸只可能由上传产生,它的地址没有任何手工输入的场景。该行改为只读的「当前壁纸」显示;「选择本地图片 / 视频」变成 选中即上传、即生效,不再需要单独的上传按钮;重新选择走媒体库,另有「清除壁纸」。schema 里 media 字段保留(它仍是壁纸的存储位置)。
12. 状态行误报「命名空间不可用」
插件启动时 settings 镜像还处于 loading,v3 早期版本把它当成 unavailable,而且那句状态只赋值一次、之后再没更新——于是「settings 命名空间不可用」会一直挂在面板上,而背景其实正常渲染。现在只有真正 unavailable 才报错,loading 期间保留既有视图,等首个 ready 快照再落「就绪」。
13. 侧边栏的淡化程度必须和壁纸一致
毛玻璃关闭时,侧边栏的 --dsw-specific-sidebar-fill 原本被设成 纯 transparent,于是它露出原样壁纸,而正文区显示的是淡化后的那一层。两者不一致的直接后果:侧边栏看起来比正文「更透」,文字压在花哨画面上严重掉对比度。
现在侧边栏拿到的是 和画布完全相同的 wash(同一个 fade 算出的同一个值),一个滑块同时管住两处;关掉「侧边栏与壁纸同步淡化」则恢复主题原色、完全不透。
tools/verify-v3.mjs 里有一条断言直接钉住这个不变量:--dsw-specific-sidebar-fill 必须与 --dsw-alias-bg-base 逐字相同。
18. 解药是模糊半径,不是不透明度
第 15 条的收尾走了一段弯路:为了压掉输入框里的暗块,把卡片底色一路加到 0.88——暗块没了,但面板变成一块 实心板,玻璃也彻底看不见了。
两条路都试过之后才看清这是个两难:玻璃之所以「看得见」,就是因为它透出背后的东西;而壁纸在输入框后面正好压着最暗的一块。
真正的解法是加大卡片自身的 backdrop-filter 模糊半径:把背后那张高对比插画糊成一片柔和色场,玻璃透出的是颜色而不是形状——这正是参考图的观感。最终形态是「中等底色 + 模糊下限」:
| 形态 | 逐行亮度极差 |
| 0.34 底色(暗块透出) | 局部成块 |
| 0.88 + 装饰渐变 | 9.0(单调下满 = 一条带) |
| 0.88 平色(实心板) | 4.8 |
| 0.52 底色 + blur 28px | 2.9 |
断言也改成防退化:卡片必须有 blur(≥ 16px),且底色必须落在 0.3~0.85 的通透区间——既不能薄到露出暗块,也不能厚成实心板。
19. 「玻璃要多透」是审美,把它交给滑块
第 15~18 条来回改了四轮(0.34 → 0.72 → 0.88 → 0.52),每一轮都是我在猜主人想要多透。这种审美选择不该由实现者猜,所以现在它是一组参数:
- 毛玻璃模糊(px,0~40):卡片与侧栏共用;卡片有 16px 下限,低于它背后的壁纸会露出硬形状而不是化成色场。
- 玻璃不透明度(0.2 很透 ~ 0.95 近实心):一个旋钮同时驱动输入框和侧栏,两者永远一致——不会出现「输入框透了但侧栏还闷着」。
侧栏的玻璃也随之回来了:玻璃模式下给 sidebarCol 刷的是 主题自己的底色按该不透明度的半透明版本。既不是全透明那种发闷的灰板,也不是 v2 那套硬编码的深蓝渐变(rgba(20,28,50,0.55),它会把壁纸压死、让侧栏变成一块外来板)。
默认 glassOpacity: 0.45。tools/verify-v3.mjs 新增两条断言:滑块必须存在,且把它设成 0.8 后 卡片与侧栏的 alpha 必须同时变成 0.8。
可读性:主题与壁纸的明暗搭配
这是背景类插件的固有代价:把 --dsw-alias-bg-base 打薄之后,正文直接坐在壁纸上,文字对比度就由壁纸的明暗决定。tools/legibility.mjs 能量出真实数字(重建「壁纸 → 遮罩 → 淡化 wash」的合成背景,再按 WCAG 公式计算对比度)。
实测同一张浅色壁纸(平均亮度 0.763,fade: 0.25):
| 主题 | 通过 ≥ 4.5:1 | 不合格 | 严重 /client.js&rev= 提供且带 cache-control: immutable,指纹随文件内容变化——这是判断「改动没生效」还是「这个窗口还跑着旧 bundle」的唯一可靠依据。为了看清它,曾经排查了好几轮。
- 不做迁移:settings.yaml 里残留的 color / colorDark / image / imageDark 会被 schema 直接忽略。
- 面板真正写过的字段(enabled / blur / overlay / fade / opacity / size / glass / sidebar / mediaType / muted / gradient)名称与含义保持不变。
安装位置
只有两个真实位置(实测确认):
- 源码:F:\DeepSeek Harness\dsh-background\
- 运行副本(实际被加载的):%DSH_HOME%\profiles\web\node_modules\dsh-background
- profile 依赖登记:%DSH_HOME%\profiles\web\package.json 的 dsh.profile.bundles
注意:%DSH_HOME%\vendor\DeepSeekHarness 是一个指向 F:\DeepSeek Harness 的 Junction,不是独立副本——往它里面复制等于复制到源码自己身上(会把 sharing violation)。profile 里 file: 依赖写的是这条 junction 路径,所以源码即 vendor。
改动生效顺序:改源码 → 复制到运行副本 → 重启 dsh web。
开发与验证
媒体路由测试:纯 Node http server,38 项,不碰正在运行的服务
node test/media.test.mjs
探测线上 GUI:背景层是否可见、玻璃选择器是否命中、面板几何、真实类名
node tools/probe-gui.mjs baseline # 截图写到 tools/shots/
端到端面板验证:驱动真实面板,13 项(上传 / 批量写入 / 独立玻璃模糊 / 侧边栏淡化一致 / 一次性 reset)
node tools/verify-v3.mjs --url http://127.0.0.1:3080
可读性量测:重建合成背景,按 WCAG 算每个文字元素的对比度(最差在前)
node tools/legibility.mjs --url http://127.0.0.1:3080
tools/web-token.mjs 从 Electron 的 main.log 取回当前 dsh web 的访问 token(1.1.5-rc.1 起裸地址返回 401),并回源校验一次,所以重启后不用手动更新。tools/cdp.mjs 是零依赖的 CDP 客户端(用 Node 内置 WebSocket,不需要 puppeteer)。
验证时怎么避免影响正在使用的 GUI
dsh web 进程同时承载着正在进行的会话,直接重启会把自己这一轮对话掐断。做法是起一个隔离实例:独立 DSH_HOME(只把 profiles 用 junction 复用),换端口跑,验证完删掉。注意隔离目录里会有一份 .credentials.yaml 副本,清理时必须先删 junction 再递归删除,否则会顺着链接删进真实 profile。
已知部署说明
1. 重启生效:插件行为 bundle 需要重启 dsh web 后才会被 dsh-client-modules 扫描进 window.__DSH_BOOT__。
2. settings 命名空间白名单:若网关(@deepseek-ai/dsh-host-apiproxy)仍只暴露 WEB_SETTINGS_NAMESPACES 中的命名空间,需要把 background 加进该数组;升级 @deepseek-ai/dsh 后若被覆盖需重新加回。
3. 客户端半部改动后刷新浏览器即可;宿主半部(lib/index.js / lib/media.js)改动需要重启服务。
20. 「背景定制」面板本身也要磨砂
主人要的一直是面板自己有毛玻璃(我前几轮误当成消息输入框,白改了好几回)。面板原先是不透明的 var(--dsw-alias-bg-layer-2),现在跟随时钟设置:开启毛玻璃时面板变成半透明 + backdrop-filter,底色用 color-mix 从主题色派生(深浅主题自动跟随)。
面板的浓度固定 78%、🎨 按钮 88%——它们装着大量小字和控件,可读性优先;它们不跟随「玻璃不透明度」滑块(那个管输入框和侧栏)。
断言:面板必须有 blur(),且解析出的 alpha ≥ 0.6。注意 color-mix 序列化成 color(srgb r g b / a) 而不是 rgba()。
21. 官方「设置」弹窗也要磨砂
v3 在这里只写了 backdrop-filter、没有把底色变半透明——在原先不透明的面板上等于什么都没做。这就是「设置为什么没有毛玻璃」的答案。
从打包应用的归档里读出的真实 CSS:
| 选择器 | 背景 |
| .wCInkW_panel(role="dialog") | var(--dsw-alias-bg-layer-2) ← 唯一画底色的节点 |
| .wCInkW_nav / .wCInkW_content | 无(纯布局) |
| .wCInkW_mask | var(--dsw-alias-bg-mask-1) |
所以只要给 [role="dialog"] 一个半透明底色就能整块磨砂,不需要碰它的后代(v2 那种 [role="dialog"] * { background: transparent } 会把按钮和列表自己的底色剥掉)。现在的做法:
[data-dsh-glass] [role="dialog"] {
backdrop-filter: blur(14px) saturate(150%);
background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 80%, transparent) !important;
}
底色从面板自己用的那个 token 派生,深浅主题和将来换主题都会自动跟随;浓度固定 80%,因为这个面上全是小字和控件。
打包版(app.asar)怎么读源码
新版桌面端把整个内核装进 app.asar,Windows 无法当目录遍历,而且它的 GUI 地址每次启动随机、token 不落盘(直接请求是 401,日志里也查不到),所以 CDP 探针用不了。改走两条路:
- tools/asar-read.mjs:零依赖自行解析 asar 归档(pickle 头 + JSON 目录 + 拼接的文件体),可以 --list 列目录或抽取单个文件。两个坑:JSON 目录从偏移 16 开始(长度字段在 12),而且 asar 把 size/offset 存成字符串,拼接会得到一个天文数字的读取位置。
- test/glass-css.test.mjs:把 lib/client.js 里的 glassCss() 抽出来求值,断言每个磨砂面既有 blur() 又有半透明底色。这类「加了模糊却看不见」的 bug 在本插件里出现过三次(消息输入框、侧栏、官方设置弹窗),静态测试是唯一不依赖实时 GUI 的守门人——顺带它也会在 CSS 注释里误写反引号截断模板字符串时直接报错。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
liuliyisui/dsh-background
DeepSeek Harness Web GUI 的自定义背景插件:图片 / 动图 / 视频 / 内置极光渐变,磨砂玻璃质感,配浮动控制面板
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,362已汉化DSH
71.4
终端编码代理esengine/DeepSeek-Reasonix
· 指南 · ACP · 扩展开发 · 规格 · 官方网站 · Discord · QQ
★ 36,076已汉化DSH
71.2
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 151,814已汉化DSH
71.1
这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。