Skip to main content
D

dsh-refined

djh2203/dsh-refined

A port of DeepSeek-Refined for DeepSeek Harness (DSH), which injects "Obsidian Border"-style Markdown styling and multi-theme color schemes into the DSH frontend.

Install

dsh plugin --profile web add github:djh2203/dsh-refined

README

dsh-refined

license DeepSeek Obsidian JavaScript

DeepSeek-Refined 的 DeepSeek Harness 移植版

为 DeepSeek Harness(DSH)前端注入 Obsidian Border 风格的 Markdown 美化与多主题配色。

原版是一个 Tampermonkey 用户脚本(见 DeepSeek-Refined),作用于网页版 DeepSeek Chat。本仓库把它移植到 DSH,提供两种安装形态:

形态持久性适用场景
部署级插件(bundle 包,推荐)常驻,后端重启不丢,所有会话生效,一条命令安装自己/团队的部署
动态插件(main.js 粘贴版,实验版)会话级,进程重启后需重装;主题选择存在 Host 进程内存里(重启即丢,且同一 Host 的各浏览器共享)快速体验、无法改部署的场合

动态粘贴版是功能子集:只有 5 套主题、Markdown 美化和头部调色板按钮。行内代码点击复制与手型光标、和壁纸类插件的背景让位、菜单里的共存开关,都只有部署版有。要完整体验请用部署级安装。

不注入脚本、不改动 DSH 源码,纯前端扩展,随时可卸载恢复原样。

功能

功能说明
5 套主题Border(默认)/ Nord / Twilight / GitHub / Atom One,深色/浅色自动跟随系统
设计令牌覆盖通过 theme.overrideTokens() 覆盖 DSH 的 --dsw-alias-* CSS 变量(与网页版同一套变量名),整站配色统一生效
Markdown 美化各级标题左侧彩色圆角竖条;引用块 Border 点阵图案背景 + 品牌色圆角竖条;粗体/斜体/行内代码/KaTeX 公式独立配色
行内代码点击复制(仅部署版)点一下聊天正文里的行内代码即复制其内容,顶部弹出「已复制:…」提示条;代码块、工具输出块、链接与引用芯片不拦截,⌘/Ctrl/Alt+点击不抢,选区压在代码上时让位给原生选择
与壁纸类插件共存(仅部署版)文字色固定归本插件(!important 样式表),底色/描边/品牌色在检测到别的插件画背景时自动让位,壁纸与玻璃效果不被顶掉;菜单里可手动接管
主题切换会话头部右侧调色板按钮,一键切换;选择存在浏览器 localStorage(后端重启也保持)

前置条件

  • DSH(DeepSeek Harness)Web 端;本版本在 0.2.0-rc.2 上实测通过。
  • 安装走 dsh plugin 时需要 pnpm(npm i -g pnpm,一次性);没有 pnpm 就用下面的 install.sh。
  • 不需要任何构建步骤:仓库里的 lib/*.js 就是最终产物。

它动了什么,不做什么

给别人装的东西,先把边界说清楚:

会做的

  • 往页面注入样式(Markdown 美化 + 文字色 !important,正常情况一张 <style>;若头部槽位注册失败改用浮动按钮,会多一张)和一个会话头部按钮;卸载时全部移除,界面恢复原样。
  • 通过 DSH 公开的 theme.overrideTokens() 覆盖 --dsw-alias-* 设计令牌;不改动 DSH 源码,不替换应用根节点。
  • 只在浏览器 localStorage 里写三个键:dsr_theme(主题)、dsr_surface(背景归属)、dsr_foreground(文字归属)。

不会做的

  • 不联网:没有任何网络请求、不上报遥测。
  • 不碰你的文件、终端、会话内容和凭据;Host 侧(lib/index.js)是空实现,不注册任何 tool / prompt / 命令。
  • 不读取别的插件的 DOM 或样式内容去“猜”布局——背景归属判定只读 document.styleSheets 里 --dsw-alias-bg-base 这一个令牌名。

安装方法

方式一:一条命令(推荐,部署级)

npm i -g pnpm                                  # 一次性:dsh plugin 是 pnpm 转发器
dsh plugin --profile web add github:djh2203/dsh-refined
dsh web --port 3080                            # 重启 DSH

无需改任何配置:本包声明了 dsh.bundle,dsh plugin add 安装后会自动把 dsh-refined 加入 profile 的 dsh.profile.bundles,重启即生效。

  • 发布前/本地试装:把 github 地址换成本地路径 → dsh plugin --profile web add file:/绝对路径/dsh-refined
  • profile 名:web 换成你自己的(dsh --profile <名字> ... 用的那个)
  • 验证:Settings → 插件 出现 dsh-refined;任意会话头部右侧出现调色板按钮
  • 更新:dsh plugin --profile web update dsh-refined → 重启
  • 卸载:dsh plugin --profile web remove dsh-refined → 重启

方式二:install.sh(没有 pnpm 的环境)

git clone <本仓库地址> dsh-refined
cd dsh-refined
./install.sh web                  # web 换成 profile 名
dsh web --port 3080               # 重启

脚本把包链接进 ~/.dsh/profiles/web/node_modules/,并在 cordis.patch.yml 追加条目(幂等,可重复执行)。卸载:删除条目与链接后重启。

与方式一二选一:脚本会检测 profile 的 package.json 里是否已有 dsh-refined 依赖,已有就报错退出,避免同一个包被挂两次。macOS 上也安全(不会用 BSD sed -i)。

方式三:动态粘贴(临时体验)

  1. 打开 main.js,全选复制全文(GitHub 仓库页点 Raw 再复制更干净)
  2. 打开你的 DSH Web,新建一个会话
  3. 把全文粘贴到输入框发送,附上一句话:

    请把上面的内容创建为动态 Cordis 插件并运行:HOST 段 → code.host,CLIENT 段 → code.client

  4. 助手定义并运行插件后,聊天里会出现运行卡片,点「允许」授权
  5. 主题立即生效:会话头部右侧出现调色板按钮,可切换 5 套主题

和其它插件共存(壁纸 / 玻璃类)

壁纸类插件(如 dsh-plugin-wallpaper-engine)靠两件事抢戏:往 body 上声明 --dsw-alias-bg-* 画玻璃/透明底,以及用 theme.overrideTokens 改文字色。本插件把令牌拆成两组,各走一条赛道,互不打架:

组令牌归属实现方式
前景(文字)--dsw-alias-label-primary/secondary/tertiary/caption固定归本插件写在自己的 <style> 里带 !important。作者样式表的 !important 优先于 ui-layout presenter 写在 body 上的行内普通声明,所以别的插件后注册令牌层也顶不掉文字色
表面(底色/描边/品牌/代码块)--dsw-alias-bg-*、--dsw-alias-border-*、--dsw-alias-brand-primary、--dsw-alias-markdown-code-block*、--dsw-specific-*可以让位走 theme.overrideTokens 令牌层;一旦发现别的插件在画背景,整层撤掉,别人的背景才看得见

自动判定:扫描 document.styleSheets,只看带 data-plugin 标记的 <style>,跳过 @deepseek-ai/*(内核自带)和本插件自己;表里重声明了 --dsw-alias-bg-base(页面基色)就算「别人在画背景」——壁纸 / 玻璃类插件都会把它改成 transparent 或玻璃色。复检时机:apply 时、apply 后 1.5s、每次 theme/change、每次打开调色板菜单。结论没变时不会反复重注册令牌层。

调色板菜单里可以手动接管这两个判定(都存在 localStorage):

  • 背景:自动 / 我的 / 让出(dsr_surface):点一次切一档。自动 = 上面那条检测;我的 = 无视检测自己画;让出 = 强制不写表面令牌。
  • 文字:跟随其它插件(dsr_foreground):默认关闭(用本插件的文字色)。壁纸太花导致文字看不清时可打开,把文字色交还给壁纸插件。

已知局限:

  • 只认带 data-plugin 标记的第三方样式表。无标注的 <style> 检测不到,手动切「背景:让出」即可。
  • 如果对方把背景写在 theme.overrideTokens 层里而不是样式表里,本插件切换主题时重新注册表面层会盖住它 —— 同样用「背景:让出」解决。
  • 动态粘贴版(main.js)暂未实现这套检测(沙箱里 document 可达,只是没做):它固定自己画背景、固定用自己的文字色,也就没有这两个开关。

更新不到新版?(git 装法的坑)

dsh plugin add github:... 之后,profile 的 pnpm-lock.yaml 会把 dsh-refined 钉死在当时解析到的那个 commit 上(形如 version: git+https://…/dsh-refined.git#<commit>)。仓库之后再有提交,dsh plugin --profile web update dsh-refined 仍可能装回旧 commit —— 表现就是"更新完行为没变"。

按可靠程度排序:

  1. 直接装本地目录(最可靠,改代码即时生效):dsh plugin --profile web add file:/绝对路径/dsh-refined
  2. 先删 lockfile 里那两条解析记录再重装:pnpm-lock.yaml 里搜 dsh-refined@git+…,把 importers 段的 version: 行和 packages:/snapshots: 里对应的两个块删掉,然后 dsh plugin --profile web update dsh-refined(或 pnpm install)——pnpm 会重新解析分支
  3. 先试「重新 add 一次」:dsh plugin --profile web add github:djh2203/dsh-refined(对同一 specifier,pnpm 常常直接复用 lockfile 的解析,所以不保证生效)
  4. 改完务必验证:node -e "console.log(require(process.env.HOME+'/.dsh/profiles/web/node_modules/dsh-refined/package.json').version)"

常见疑问

  • Settings → 插件 页面里没有它? 正常——那是部署级插件的清单。动态粘贴版属于创建它的那个会话,只在聊天里的运行卡片可见。
  • 装上了,但没生效 / 有时有效有时无效? 这是 1.0.0 的一个启动竞态:插件原先用 ctx.get('theme') 自己探测服务,外壳的 theme / slots 服务还没就绪时 apply 直接静默返回,于是主题不生效、按钮也不出现。现在插件对象声明了 inject: ['theme', 'slots'],由 cordis 等两个服务就位后再激活,不再赌加载顺序。升级:dsh plugin --profile web update dsh-refined 后重启。判断是否生效:浏览器控制台会有 [dsh-refined] 已启用:主题 …。
  • 重启 DSH 后没效果了? 动态粘贴版是会话级临时扩展,重启即失,请改用方式一部署级安装。
  • dsh plugin 报 pnpm 找不到? 先 npm i -g pnpm(方式一第一步)。

开发注意

  • 自测:node test/smoke.js(不用浏览器,stub 掉 window/document/theme 真跑 apply);node test/parity.js 检查 main.js 与 lib/client.js 的调色板是否还一致。

  • 点选判定别用「全局有没有选区」:页面别处残留一个选区就会让行内代码永远点不动(selectionCovers() 只在选区压住该 code 时才让位)。

  • 自己注入的 <style> 不要打 data-plugin="<本包名>"。dsh-client-modules 会把工厂产出的样式算成自己的:materialize 后认领所有无标记的 <style>,模块重载时再 style[data-plugin="<包名>"] → remove()。结果就是插件还活着、令牌还在,但整张样式表凭空消失(美化 / 光标 / 文字色 !important 全没)。本插件用 data-plugin="dsh-refined-theme" 绕开,并在 theme/change 与 5 秒轮询里补回被删的标签。

  • 客户端插件对象必须显式声明 inject: ['theme', 'slots']。不要用 ctx.get('theme') 自己探测后就 return——那就是上面那个“时灵时不灵”bug 的成因。

  • 改完 lib/client.js 后要重装(dsh plugin --profile web update dsh-refined)或重启 DSH;浏览器端 bundle 是按 mtime 快照分发的,直接改文件不会自动重载。

与原版的差异

  • 选择器适配:DSH 的 Markdown 容器是 CSS Modules 哈希类名(如 _markdown_1nba0_5),使用 [class*="_markdown_"] 前缀匹配,避免依赖具体哈希值
  • 深色模式钩子相同:DSH 与网页版一样使用 body[data-ds-dark-theme]
  • 持久化:原版用 localStorage;部署版同样用 localStorage(后端重启保持)
  • 行内代码点击复制:原版挂在 document 上做事件委托;部署版同样是 document 捕获阶段委托,但多两层过滤——只在 [class*="_markdown_"] 容器内、排除 pre / .md-code-block / 工具输出块([data-read]、[data-diff]、[data-search]、[data-terminal])、并且点在链接/按钮上时不拦截;有文字选区时让位给原生选择。动态粘贴版暂未实现(动态沙箱里 document 其实是可达的,是没做,不是做不到)
  • 未移植:消息宽度 75% 与表格宽度 70%(DSH 布局为固定列宽 + 表格自适应滚动,强行收窄会破坏版面)

自定义

所有配色集中在 lib/client.js(部署版)与 main.js(动态版)顶部的 THEMES 对象中,两处保持一致即可。字段含义:strong = 粗体、em = 斜体、math = 公式、heading = 标题竖条颜色数组 [h1..h6]、blockquoteDot = 引用块点阵颜色等。新增主题:复制任意一个主题对象改名即可,切换菜单会自动出现。

Related plugins