dsh-theme-palette
DeepSeek Harness 的五套配色(黑白、暖砂、靛蓝、苔绿、自定义三色),明暗两模式各自用 OKLCH 重算整条色阶,并按配色求解文字与承载面的对比度;附配置导入导出短码与高对比档。
安装
dsh plugin --profile web add dsh-theme-palette
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-theme-palette
[English](README.md) · [中文](README-zh.md) · [日本語](README-ja.md) · [Español](README-es.md) · [Português](README-pt.md) · [हिन्दी](README-hi.md)
Theme palette for DeepSeek Harness (web & desktop): 4 preset palettes + custom × light/dark, two independent axes.
Static render of the settings page at the real panel width (564 px content).
Dark · Custom palette · High contrast
 ·  · 
Compatibility
Surface · Status
DSH desktop / web client · 0.2.x
Node.js · 22.19.0+ (on the 22.x line) or 24.0.0+
Changes to host source · none
The engines field of the package is ^22.19.0 || >=24.0.0 — the row above is the same requirement in prose.
The plugin only stacks colour tokens through ctx.theme.overrideTokens; it does not register a theme, patch the host, or touch the appearance preference.
What it does
- 4 presets + custom — Mono, Warm sand, Indigo, Moss (each adapting to light and dark independently), plus a custom palette derived from three colours;
- the whole ramp is recomputed, not swapped: OKLCH rebuild → role-based chroma → sRGB gamut clamp → contrast solved on real surfaces;
- host colour tokens: 179 for tinted palettes plus 13 plugin-owned tokens, 19 for mono (1080 setting combinations fully scanned); all 66 colour tokens the built CSS actually consumes resolve to the plugin — body, secondary, tertiary, captions, links, sidebars, cards, user bubble, primary button, scrollbars, switches, Markdown headings/bold, code blocks, and now error/success/warning states and the +/− rows of the file diff (the red/green/amber scales join the rebuild for the first time: temperature only, hue rotation capped at 8°, so the semantics never drift);
- adjustable: text tint (3), sidebar depth (3), Markdown emphasis, scrollbars, switch colour;
- custom palette (pick surface / text / accent — the text hue joins the derivation, and a clearly dark or light surface becomes that mode's canvas lightness; the engine keeps its contrast guarantees), config export/import via a
dshs1.code, high-contrast mode, and 4 UI languages; - self-healing: if the host drops the override layer, the palette is re-applied; after repeated failures auto-restore pauses and the settings page offers a re-enable button;
- contrast promises: body text is promised 12:1 in light and 10:1 in dark (15:1 in high contrast), secondary ≥ 6.2 in light / 8.0 in dark (HC 9 / 9.6), tertiary ≥ 4.85 in light / 6.4 in dark (HC 7 / 7.6), links ≥ 4.95 in light / 4.62 in dark (HC 7; the light floors carry a colour-vision headroom; dark links also clear an APCA Lc ≥ 60 gate, 75 in HC) — measured on the surfaces the text actually lands on (the dark side needs more, because a WCAG ratio overstates readability on a dark background);
- the promised surfaces are light 00/60 and dark 950/875; dark 800 (module surface) and 850 (sub-surface) do not back body text — the report counts them apart as "out of policy" (neither pass nor fail);
- UI in 简体中文 / 繁體中文 / English / 日本語 (follows the host language, can be pinned).
Install
# from npm cd ~/.dsh/profiles/desktop pnpm add dsh-theme-palette
To pin a version, use pnpm add dsh-theme-palette@<version> — [CHANGELOG.md](CHANGELOG.md) marks the sections that were never published to npm, so you do not pin one of those.
From a GitHub Release tarball: pick the asset on the releases page and install it with pnpm add <path-to-tgz>.
Then restart the GUI — a running process keeps the old module. Open it from avatar → Settings → Color theme.
Configuration
Item · Options
Palette · Mono · Warm sand · Indigo · Moss (thumbnails follow light/dark)
Strength · Quiet / Standard / Strong — how much body text follows the palette
Panel surfaces · Sidebar (Lighter / Same / Deeper). The right panel is never tinted — it is a full-height transparent overlay, so painting it would cover the conversation (the setting was removed in 1.9.10)
More options · Language, Markdown emphasis, scrollbars, switches/checks
Every choice applies immediately and is stored in localStorage. Light/dark stays under the host’s Appearance control.
Palette engine
OKLCH(L, C, hue) ──► gamut clamp (binary search on C) ──► sRGB hex
▲
└── role chroma × intensity, then contrast solve on {canvas, card, sidebar, overlay}
- semantic aliases keep
var(--dsw-static-neutral-bluish-NN)chains, so anything following a token follows the palette; - light surfaces use steps 00–300, dark surfaces 800–950;
- semantic colours (1.13.5): the host's red/green/amber scales keep their host lightness and only get a temperature harmonisation toward the palette hue (
harmonizeSemantic: hue rotation capped at 8°, chroma scaled to 88–92%) — error stays red, success stays green, warning stays amber, just in the palette's warm/cool key; an achromatic custom palette (pure black/white/grey) is left untouched; - the coverage claim is testable:
tools/check-host-contract.mjsextracts every colour token the built CSS actually consumes and requires each one to be either declared by the plugin or to end itsvar()chain in a declared token — 1.13.4 and earlier fail this with 30 leaks (red/green/amber, danger hover, diff rows), 1.13.5 reports zero; - text floors are enforced at build time: body ≥ 12:1 in light and ≥ 10:1 in dark (high contrast: 15:1), secondary ≥ 6.2 in light / 8.0 in dark (HC 9 / 9.6), tertiary ≥ 4.85 in light / 6.4 in dark (HC 7 / 7.6), link ≥ 4.95 in light / 4.62 in dark (HC 7), link APCA Lc ≥ 60 in dark (HC 75); sidebar and bubble text follow
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:32,最后更新 2026-10-30