官方主题插件
Official theme plugin
别名:@deepseek-ai/dsh-client-ui-theme、主题服务、Appearance 设置行、ThemeRuntime
DSH 自带的主题插件(`@deepseek-ai/dsh-client-ui-theme`):管亮 / 暗 / 跟随系统三态、宿主在插件加载前注入的调色板引导,以及 `--dsw-*` 设计令牌(静态尺度 + 语义别名)——第三方皮肤最终大多落在它这套令牌上。
一句话
官方主题插件不是一个「皮肤」,而是主题这件事的机制本身:它定义有哪几种主题、把偏好持久化到哪、以及在界面脚本跑起来之前怎么先把颜色定下来。第三方皮肤(插件的、或直接改 patch 层的)最后都是在覆盖它这套令牌。
三态与它存在哪
实现里写得很直接(@deepseek-ai/dsh-client-ui-theme/lib/index.js,实测 0.1.0-rc.6):
| 常量 | 值 |
|---|---|
THEME_PREFERENCES | ["light", "dark", "system"] |
DEFAULT_PREFERENCE | "system" |
THEME_SETTINGS_NAMESPACE | "ui-theme" |
THEME_PREFERENCE_FIELD | "preference" |
所以偏好落在 $DSH_HOME/settings.yaml 的 ui-theme.preference(宿主 settings,不是 profile 的 cordis.patch.yml)。三个词汇要分清:light / dark 是内置主题 id;system 是偏好、不是主题 id——实现里显式抛错 "system" is a preference, not a registrable theme id,它靠 matchMedia('(prefers-color-scheme: dark)') 解析成实际主题;第三方主题是运行期注册的(进程内扩展),注册 = 覆盖同名别名变量,而 README 承认目前不验证一组覆盖是否完整。
最后一条是排错关键:皮肤只覆盖一半令牌不会报错,表现出来就是「有些地方没变」。看到「换了主题但某个面板还是旧颜色」,先怀疑覆盖不全,而不是缓存。
启动前的调色板引导
宿主侧在 HTTP 服务器存在时,会往每个 index 响应里紧接 <body> 起标签注入一段同步脚本(injectBootTheme → bootThemeScript),核心是 document.documentElement.style.colorScheme = dark ? 'dark' : 'light' 与 document.body.toggleAttribute('data-ds-dark-theme', dark)。
三点推论:它是同步的、在界面模块脚本之前执行,所以不会先白屏闪一下再变黑;没有 settings provider 时嵌的是 system,所以「设置没生效」和「设置文件没被读到」在这里表现一样;data-ds-dark-theme 是明暗判定位,排查颜色问题时先看 <body> 上有没有它,比看 CSS 快。
令牌:两段式命名
lib/styles/design-platform.css 是令牌的唯一权威来源,命名分两层(本轮实际读到的例子):
| 层 | 前缀 | 实测例子 |
|---|---|---|
| 静态尺度 | --dsw-static-* | --dsw-static-blue-500、--dsw-static-deepseek-500、--dsw-static-neutral-bluish-950 |
| 语义别名 | --dsw-alias-* | --dsw-alias-bg-base、--dsw-alias-label-primary、--dsw-alias-border-l2、--dsw-alias-scrollbar-bg-l1 |
| 局部特例 | --dsw-specific-* | --dsw-specific-sidebar-fill、--dsw-specific-input-major |
README 里写着设计规则:新增颜色不许直接在别名层造值,必须同时给一个静态尺度层级与一个语义别名。所以市面皮肤(如「丝滑的DSH」里 dsh-myskin 的 patch 块)写的是 --dsw-alias-* / --dsw-specific-* 这类别名——改静态层等于改原料,改别名层才是改意图。patch 层可以带令牌覆盖,这就是「不装插件也能换配色」的路子(机制见 concept/1)。
界面入口
主题在设置界面里有一行:客户端侧注册进 settings.general.item 槽(实现注释称 Appearance row,三个色块对应 Light / Dark / System)。所以位置是「设置 → 通用」里的外观行,不是单独的主题页。
与其它东西的关系
| 关系 | 对象 | 说明 |
|---|---|---|
| 落在 | client/1 官方 Web UI | 它改的就是这个界面的样子 |
| 同层邻居 | asset/1 官方中文界面词条 | 一个管配色、一个管词条,都挂在同一个设置界面里 |
| 层序依据 | concept/1 patch 层与层序 | 「改令牌」这条路的覆盖顺序在这一层 |
| 装在同层的插件 | dsh-loader(npm) | 主题类改动同样受升级断裂影响 |
分区里另外几条(dsh-myskin、dsh-wallpaper-engine、图标包占位)还没有词条,只存在于 data/zones/themes.yml 的卡片上。
未核实 / 未声明
targets只写了[shell, colors]:图标(icons)与壁纸(wallpaper)不在其中——分区文件写了「独立图标包尚未成规模」,壁纸由dsh-wallpaper-engine这类第三方插件承担。editor也未声明:包内确有lib/styles/shiki.css(代码块着色),但我没有核实「换主题会连带改编辑器配色」这条因果。- 没有
dsh plugin add形式的安装命令:它随 bundle 层出厂;install字段写的是落点与偏好位置。 - 第三方主题注册的稳定性:README 说是「进程内扩展、不跨越内置 settings schema」,且移除任一第三方主题都不会覆盖最后一个持久化的内置偏好。上游自述,本轮未复现。
repo/ 许可证:取自该包package.json的repository.url(directory: packages/client/ui-theme)与license: MIT;仓库根 LICENSE 未读取。- 哪些界面:实现是客户端(
platform: web)插件;headless / TUI 形态下有没有主题概念本轮未核实,compat.runtime因此只写web。 - 令牌总数:本轮只列举实际读到的若干条,没有统计完整清单,所以不给「一共多少个令牌」这类数字。
谁引用了这一条
信息表
- category
- appearance.theme
- install
- 内置:随 @deepseek-ai/dsh-web-app 的 bundle 层出厂,没有单独的安装命令;偏好写在 $DSH_HOME/settings.yaml 的 ui-theme.preference
- licenseRefs
- [object Object]
- repo
- deepseek-ai/deepseek-harness
- targets
- shell、colors
- titleEn
- Official theme plugin
- updatedAt
- 2026-10-02
被 3 条词条引用
按标签浏览:设置(2)