🎨 dsh-theme
DeepSeek Harness 主题插件 · 30 款即插即用主题 · DSH 原生集成
一个面向 DeepSeek Harness Web 界面的主题包:既是零依赖的 DSH 客户端插件(注册进「设置 → 通用」,与内置「外观」选择器并列),也附带 30 个独立 CSS 文件 可任意方式接入。
每个主题都完整映射 DSH 官方设计令牌(--dsw-alias-* 语义层、--dsw-specific-* 组件层、--shiki-* 代码高亮),并同时提供浅色 / 深色两套变体——深色变体会跟随 DSH 内置的 data-ds-dark-theme 自动切换,无需额外设置。
🤖 你是 AI Agent / 想快速接入?直接看 docs/AGENT.md(Agent 快速接入指南)。
30 款主题目录
打开 preview.html(构建产物,双击即可,无需服务器)可浏览全部 30 款主题的实时预览。
目录结构
dsh-theme/
├── package.json # DSH 插件清单:dsh.client { inject:["slots"], platform:"web", immediately:true }
├── README.md
├── docs/
│ └── AGENT.md # ★ Agent 快速接入指南(安装/API/自定义主题/排障)
├── preview.html # 构建生成:30 主题自包含预览页(file:// 直接打开)
├── src/
│ ├── themes.json # ★ 30 个主题的唯一数据源(16 个语义插槽 × light/dark)
│ └── client.template.js # 客户端插件模板(__THEME_DATA__ 由构建内联;设置页 React 行)
├── scripts/
│ ├── build.mjs # 构建:生成 themes/*.css、manifest、client.js、preview.html(含令牌校验)
│ ├── screenshot.mjs # 开发工具:对运行中的 DSH 界面截图验证主题
│ ├── plugintest.mjs # 开发工具:模拟 DSH loader 对插件做集成测试
│ └── pixelcheck.mjs # 开发工具:PNG 像素校验(截图非空 + 主色命中)
├── themes/ # 构建生成:每主题一个独立 CSS(可直接用)
│ ├── ocean.css
│ ├── ...
│ ├── index.css # 全部 30 个主题合一的样式
│ └── manifest.json # 机器可读目录(含色板 swatch)
├── lib/
│ ├── index.js # ★ 服务端入口(no-op cordis 插件,loader 挂载必需)
│ ├── client.js # ★ 构建生成:自包含 DSH 客户端插件(内联全部主题)
│ └── themes.data.json # 运行时数据
└── shots/ # 开发工具产出的效果截图
快速安装(三选一)
方式 0:一键安装脚本(推荐给普通用户 / Agent)
克隆仓库后直接运行(自动完成构建 + dsh plugin add + loader 条目写入,幂等、带备份):
git clone https://github.com/mux9056-bot/dsh-theme ~/dsh-theme
cd ~/dsh-theme
node scripts/install.mjs # 可选:--profile <名字> 装到其他 profile;--no-build 跳过构建
脚本跑完只需重启 dsh web 并刷新页面。详细说明见 docs/AGENT.md。
通过 Agent 安装(3 分钟)
如果你用 DeepSeek Harness 或其他 AI Agent,把下面这段指令直接复制发给你的 Agent,
它会照着 docs/AGENT.md 自动完成安装、重启与验证:
📋 给 Agent 的安装指令(可直接复制)
请帮我把 dsh-theme 主题插件安装到 DSH web 界面(仓库:https://github.com/mux9056-bot/dsh-theme ):
- clone 仓库到持久路径(如
~/dsh-theme,不要用 /tmp);若无 lib/client.js 先执行 npm run build
- 安装进 web profile:
COREPACK_ENABLE_PROJECT_SPEC=0 dsh plugin --profile web add ~/dsh-theme
(若报 corepack 权限错就用这个前缀重试)
- 必须在
$DSH_HOME/profiles/web/cordis.patch.yml 追加 loader 条目:
- insert: [{ id: theme, name: 'dsh-theme' }] —— 客户端插件没有自动发现,漏掉就不生效
- 重启
dsh web(注意:agent 通常运行在 dsh web 进程内,需用 detach 方式重启并留出收尾时间;或让用户手动重启)
- 验证:
curl -s http://127.0.0.1:3080/ | grep '"id":"dsh-theme"' 命中;
并打开「设置 → 通用」确认出现「主题包 · 30 款」色卡行
- 完成后告诉我,我刷新页面即可使用
Agent 会自行处理所有已知坑(corepack 权限、loader 条目、重启时机、manifest 验证);
遇到异常可直接让它查阅 docs/AGENT.md 的排障清单。手动安装见下节。
快速接入(DSH 原生方案)
⚠️ 重要:DSH 的客户端插件(dsh.client 清单)没有自动发现机制。光把包装进 profile 的
node_modules 还不够 —— 必须同时满足三个条件插件才会出现在 boot manifest 里:
① 依赖装入 profile;② 在 profile 补丁层注册 loader 条目;③ 重启 dsh web。
并且包的 exports 必须提供 . 主入口(lib/index.js),因为 loader 会 import() 整个包。
方式 A:作为 DSH 客户端插件(推荐)
lib/client.js 遵循 DSH 官方客户端插件打包契约(与 @deepseek-ai/dsh-client-ui-theme 同款):
// package.json —— 本项目的 dsh.client 清单
"dsh": { "client": { "inject": ["slots"], "platform": "web", "immediately": true } },
"exports": {
".": { "default": "./lib/index.js" }, // 服务端入口(loader import 必需)
"./client": { "default": "./lib/client.js" } // 浏览器 bundle
}
第 1 步:构建并安装依赖(本地目录即可,无需发布 npm):
npm run build # 生成 lib/client.js 等构建产物
dsh plugin --profile web add /absolute/path/to/dsh-theme
若遇到 corepack 报 EPERM ... package.json(它会试图往项目外层写 packageManager 字段),
加环境变量重试:COREPACK_ENABLE_PROJECT_SPEC=0 dsh plugin --profile web add <path>。
第 2 步:在 profile 补丁层注册 loader 条目($DSH_HOME/profiles/web/cordis.patch.yml):
- insert:
- id: theme
name: 'dsh-theme'
第 3 步:重启 web profile 并刷新页面
dsh web # 重启(或在你原来的终端里 Ctrl+C 后重跑)
刷新后:左下角侧边栏 → ⚙ 设置 → 通用 → 找到「主题包 · 30 款」分区即可换肤。
(也可在浏览器控制台用 window.dshTheme API,见下文。)
方式 B:纯 CSS(零依赖,任何部署都适用)
每款主题是一个自包含的 CSS 文件,选择器基于 body 上的属性:
/* themes/ocean.css 的生效选择器 */
body[data-dsh-theme="ocean"] { /* 浅色令牌 */ }
body[data-dsh-theme="ocean"][data-ds-dark-theme] { /* 深色令牌 */ }
使用只需两步:
// 1. 引入主题 CSS(任一方式:<link>、注入 <style>、构建时合并)
// 2. 给 body 打上属性
document.body.setAttribute("data-dsh-theme", "ocean");
方式 C:完整源码集成
若你在 deepseek-harness 完整源码中开发,可将 src/client.template.js 作为客户端插件包
(仿照 packages/client/ui-theme 布局),npm run build 后产出 lib/client.js 即符合
packages/client/* 的构建产物格式(__ModuleLoader__.load + exports.inject/apply)。
插件功能
window.dshTheme.list() // [{id,name,nameZh,desc,descZh,tags}, ...] 共 30 项
window.dshTheme.get() // {id,name,nameZh} 或 null
window.dshTheme.set("aurora") // 切换主题(无效 id 抛错)
window.dshTheme.cycle() // 轮换到下一个主题
window.dshTheme.reset() // 恢复 DSH 默认外观
window.dshTheme.setMode("light"|"dark"|"system")
window.dshTheme.getMode()
主题机制:语义插槽 → DSH 设计令牌
每个主题在 src/themes.json 中只定义 16 个语义插槽 × 2 种模式,构建时自动展开为 94 个
DSH 真实令牌(全部经过与 DSH 实际 CSS 的差集校验,无拼写错误):
代码高亮:默认使用 DSH 内置 shiki 配色(浅/深各一套,自动适配);个别主题可覆写
(如 terminal 的磷光绿语法色),在 src/themes.json 中加 shiki.light/dark 字段即可。
自定义 / 新增主题
- 在
src/themes.json 的 themes 数组里追加一个对象(id 唯一、小写字母/数字/连字符):
{
"id": "mytheme",
"name": "My Theme", "nameZh": "我的主题",
"desc": "…", "descZh": "…",
"tags": ["light", "blue"],
"light": { "bg": "#f5f8fc", "surface": "#ffffff", "surfaceAlt": "#e9f0f8", "text": "#12283f",
"text2": "#4a637c", "text3": "#7c93a8", "border": "rgba(18,40,63,0.10)",
"accent": "#1d6fb8", "accentText": "#ffffff", "accentHover": "#175a94",
"code": "#eaf2fa", "codeBanner": "#e1ecf6", "sidebar": "#eaf2f9",
"warn": "#b45309", "error": "#dc2626", "success": "#15803d" },
"dark": { /* 同结构,深色插槽 */ }
}
npm run build —— 自动产出该主题的 themes/<id>.css、更新 manifest、重打 lib/client.js,
并执行令牌名校验(每个变量名都必须存在于 DSH 真实令牌集,防止拼错)。
开发与验证
npm run build # 全量构建 + 令牌校验
npm run verify # 仅校验(令牌名 ∈ 内置 DSH 令牌集、花括号配平)
npm run verify:live # ★ 校验时对比「运行中的 DSH」真实 CSS(DSH 升级后用它复检令牌漂移)
node scripts/plugintest.mjs # 对运行中的 DSH (http://127.0.0.1:3080) 做插件集成测试
node scripts/screenshot.mjs ocean light shots/ocean-light.png # 截图验证某主题
node scripts/pixelcheck.mjs shots/ocean-light.png eef5fb # 像素级校验主色
verify:live 会抓取运行中 DSH 的样式资源并提取全部 --dsw-* / --shiki-* 令牌,把 30 个主题
以及设置行的 UI 令牌一并与真实令牌集比对 —— 这是 DSH 升级后最可靠的适配自检。
(DSH_LIVE_URL 环境变量可指定别的实例地址。)
集成测试会模拟 DSH loader 的真实加载路径:__ModuleLoader__.load 注册 → __DSH_MODULES__.materialize(id)
→ apply(ctx),并断言:30 个色块、主题切换后 computed style 命中插槽色、深浅色切换、轮换/重置、
刷新后持久化恢复。
开源 / 发布
- npm 发布:包名
dsh-theme 在 npm 上未被占用,可 npm publish;用户随后只需
dsh plugin --profile web add dsh-theme + loader 条目 + 重启(见上)。
- ⚠️ 旧包
dsh-theme-pack@1.0.0(已存在于 npm)是早期版本:缺少服务端入口(exports["."] /
lib/index.js),装进 DSH 会报 ERR_PACKAGE_PATH_NOT_EXPORTED,不要用它;请用本仓库的新包名。
- 发布前检查清单:
npm run verify:live 通过 → npm run build → npm pack 确认产物包含
lib/、themes/、scripts/、docs/。
已知限制与说明
- 设置页集成:主题入口在「设置 → 通用 → 主题包」,与内置「外观」选择器并列;没有页面级浮动控件
(DSH 理念:插件应注册进宿主 UI 槽位,而不是独立悬浮组件)。
- 模式切换:行内「浅色/深色」会直接设置
body[data-ds-dark-theme](persist 到 localStorage),
此时 DSH 内置「外观」设置页的显示可能与实际不一致;点「自动」即可恢复跟随内置设置。
- loader 条目是硬性要求:DSH 的
client-modules 只扫描 loader entries(补丁层里的行),
不会自动发现 node_modules 里的 dsh.client 包;漏掉 cordis.patch.yml 的 insert 会导致插件不进
boot manifest。参见 docs/AGENT.md 的排障章节。
- 服务端入口必需:loader 会
import() 插件包,因此 exports["."] 与 lib/index.js 缺一不可;
漏掉会报 ERR_PACKAGE_PATH_NOT_EXPORTED 或 ERR_MODULE_NOT_FOUND。
- 样式隔离:设置行样式与当前主题 CSS 分属两个
<style> 元素,任何主题切换/清空都不会破坏行样式;
深色模式下色卡预览条跟随 body[data-ds-dark-theme] 切换为对应深色 swatch。
- 主题标识:主题通过
body[data-dsh-theme="<id>"] 生效,与 DSH 内置外观(浅/深)正交,二者可自由组合。
- 兼容性:令牌名取自 DSH
0.1.0-rc.6 的 Web 产物;DSH 升级后请用 npm run verify:live 复检。
- 依赖平台 seed:设置行用
react + slots 服务(DSH 平台 seed,inject: ["slots"]),
需要 DSH 版本提供这两个 seed(0.1.0-rc.6 起包含);缺失时插件优雅降级(仅保留 window.dshTheme API)。
License
Apache License 2.0