🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

主题工坊 tuibe/dsh-deepseek-theme-studio

DeepSeek Harness
tuibe28 天前有提交已提供中文文档扫描:含敏感能力

调校毛玻璃与流体特效,定制界面视觉风格

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/7 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add tuibe/dsh-deepseek-theme-studio
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · vision
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 28 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件发起外部网络请求
查看扫描证据(共 10 处,展示前 10 条)
  • 读取本地文件
    lib/index.js:82
    text = readFileSync(statePath(), 'utf8')
  • 写入本地文件
    lib/index.js:102
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    lib/index.js:105
    writeFileSync(tmp, body, { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    lib/index.js:107
    renameSync(tmp, file)
  • 写入本地文件
    lib/index.js:111
    writeFileSync(file, body, { encoding: 'utf8', mode: 0o600 })
  • 读取本地文件
    lib/index.js:383
    if (!existsSync(statePath())) writeState({})
  • 发起网络请求
    lib/client.js:1073
    const response = await fetch(API_PATH, {
  • 发起网络请求
    lib/client.js:1123
    const response = await fetch(API_PATH, { method: 'GET', headers: { accept: 'application/json' } })
  • 发起网络请求
    lib/client.js:1165
    const response = await fetch(API_PATH, {
  • 发起网络请求
    lib/client.js:1229
    if (hostAvailable) void fetch(API_PATH, {
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 调校毛玻璃特效
  • 定制流体视觉效果
  • 百项参数可调

README

由 DeepSeek 最新模型翻译生成
dsh-deepseek-theme-studio DeepSeek 官网视觉语言的 DSH Web 客户端主题插件:毛玻璃 / 液化(流体)/ 量子化(Q1–Q4)三类效果,全部参数可调、可持久化、可程序化调用。 - 宿主实测版本:0.2.0-rc.2 - 目标 profile:web($env:USERPROFILE\.dsh\profiles\web) - 安装后外观与 DSH 原生完全一致,直到你在设置里显式启用效果。 - 复用与许可台账见 REUSE.md,第三方许可见 LICENSES/。 1. 交付物 | 路径 | 说明 | | package.json | manifest(dsh.bundle.patch / dsh.client / exports)| | cordis.patch.yml | loader 条目(dsh.bundle.patch 指向它)| | lib/index.js | 宿主半(Node):JSON 参数文件 + 围栏 HTTP 路由 + 热加载 | | lib/client.js | 浏览器 bundle(scripts/build.mjs 由 src/ 生成,勿手改)| | src/* | 可读源码(参数表、存储、各效果引擎、设置行、程序化 API)|
展开完整文档(README 剩余 1 节)
dsh-deepseek-theme-studio

DeepSeek 官网视觉语言的 DSH Web 客户端主题插件:毛玻璃 / 液化(流体)/ 量子化(Q1–Q4)三类效果,全部参数可调、可持久化、可程序化调用。

- 宿主实测版本:0.2.0-rc.2
- 目标 profile:web($env:USERPROFILE\.dsh\profiles\web)
- 安装后外观与 DSH 原生完全一致,直到你在设置里显式启用效果。
- 复用与许可台账见 REUSE.md,第三方许可见 LICENSES/。

1. 交付物

| 路径 | 说明 |
| package.json | manifest(dsh.bundle.patch / dsh.client / exports)|
| cordis.patch.yml | loader 条目(dsh.bundle.patch 指向它)|
| lib/index.js | 宿主半(Node):JSON 参数文件 + 围栏 HTTP 路由 + 热加载 |
| lib/client.js | 浏览器 bundle(scripts/build.mjs 由 src/ 生成,勿手改)|
| src/* | 可读源码(参数表、存储、各效果引擎、设置行、程序化 API)|
| scripts/build.mjs | 零依赖构建(--check 做陈旧检查)|
| scripts/smoke-factory.mjs | 在 Node 里跑一遍 bundle 工厂,抓语法/导出错误 |
| scripts/verify-tokens.mjs | 令牌漂移自检(失败非零退出)|
| scripts/png-diff.mjs | 纯 Node PNG 双图差异报告(含 --dump-region diff)|
| REUSE.md | 复用与许可台账(Phase 0 闸门产物:逐行来源与许可判定)|
| ACCEPTANCE.md | 9 项验收的实测证据 |
| icon.svg, LICENSE, LICENSES/ | 图标 / 许可证 / 第三方声明 |

2. 安装 / 升级 / 卸载 / 还原

dsh 不在 PATH 上,下面用绝对路径调用。

本仓库克隆到哪,就填哪 $repo = "$env:USERPROFILE\src\dsh-deepseek-theme-studio" $dsh = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd"

2.1 安装(本地路径)

$env:COREPACK_ENABLE_PROJECT_SPEC = "0" # 见 §6 坑 1 & $dsh plugin --profile web add $repo

换成别的 profile 只改 --profile 的值,其余完全一样:

| profile | 你在哪用它 | 命令 |
| desktop | 桌面版 DSH(托盘常驻的那个,Web GUI 通常绑定随机端口)| & $dsh plugin --profile desktop add $repo |
| web | dsh --profile web 起的纯 Web 实例 | & $dsh plugin --profile web add $repo |

两者是独立的两份 profile(各自有自己的 package.json / node_modules / 设置),装一个不影响另一个;想两边都有就各装一次。重启也只重启你要用的那个。

桌面版重启:完全退出 DeepSeek Harness(含托盘图标)再打开。这份 profile 没有 patchReload: live,所以热更新不适用于"新增插件"这种改动。

预期输出(本次实测):

dependencies:
+ dsh-deepseek-theme-studio link:$repo
Done in 3s using pnpm v11.7.0

安装做三件事,缺一不可:

1. profiles/web/package.json → dependencies 增加 "dsh-deepseek-theme-studio": "link:$repo";
2. 同文件 dsh.profile.bundles 追加 "dsh-deepseek-theme-studio";
3. profiles/web/node_modules/dsh-deepseek-theme-studio 建 Junction 指向源码目录。

loader 条目由本包自己的 cordis.patch.yml 提供(dsh.bundle.patch 机制),因此不需要手改 profiles/web/cordis.patch.yml。本包内容:

- insert:
- id: deepseek-theme-studio
name: 'dsh-deepseek-theme-studio'

2.2 生效:重启 profile

客户端插件没有自动发现机制 —— 只把包装进 node_modules 不会生效,必须重启 profile 让 boot manifest 重新组合。
重启前可先跑 node scripts/preflight-profile.mjs 体检(见 §7)。

web profile:

停掉当前实例后: $exe = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\DeepSeek Harness.exe" $bin = "$env:LOCALAPPDATA\Programs\DeepSeek Harness\resources\app.asar\dsh\node_modules\@deepseek-ai\dsh\lib\bin.js" $env:ELECTRON_RUN_AS_NODE = "1" Remove-Item Env:DSH_PROFILE, Env:DSH_PROFILE_DIR, Env:DSH_SHELL -ErrorAction SilentlyContinue & $exe --expose-internals $bin --profile web --port 19399 --no-open 输出形如: dsh web: http://127.0.0.1:19399/?token=<TOKEN>

然后浏览器打开该 URL 并 Ctrl+Shift+R 硬刷新。

为什么必须清那几个环境变量:dsh.cmd 走的是 desktop host CLI(manageDesktopProfile: true),会强行注入 --profile desktop,于是 --profile web 变成「profile 指定了两次」而报错;且 DSH_PROFILE_DIR 会把 profile 目录钉死在 desktop。直连内层 bin.js 并清掉这三个变量即可。

desktop profile: 完全退出 DeepSeek Harness(含托盘图标)再打开即可 —— 桌面版由它自己拉起,不需要手敲命令。重启后到设置 → 通用 看那一行在不在;不在就按 §6 坑 2 逐条查,或先跑 node scripts/preflight-profile.mjs --profile desktop。

2.3 升级

本地 link 安装:改完 src/ 后 node scripts/build.mjs(或用 pnpm run build),再重启 profile 即可;不需要重新 add。npm 安装:& $dsh plugin --profile web add dsh-deepseek-theme-studio@<新版本> 后重启。

2.4 卸载

& $dsh plugin --profile web remove dsh-deepseek-theme-studio

实测会把 dependencies 与 dsh.profile.bundles 中的条目一并移除(刷新页面不够,必须重启 profile)。
node_modules 下可能残留一个失效 Junction,可手动删除:

Remove-Item "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-deepseek-theme-studio" -Force -Recurse

2.5 还原原生外观(不卸载)

设置 → 通用 → DeepSeek 官网主题工作台 → 点 一键还原原生;或:

window.dshThemeStudio.reset()

还原后本插件不写任何令牌、不挂任何 canvas、不设 data-dts 根属性,只剩设置行本身(关掉设置即不可见)。

3. 三条控制通道

3.1 设置页 UI

注册进宿主自己的 settings.general.item 槽位(order: 20,紧随内置「外观」行 order: 10 与字号行 order: 11), 不是独立悬浮面板。分组折叠、每组控件由参数表自动生成。

3.2 程序化 API

同一个对象挂两处:window.dshThemeStudio 与 ctx.provide('themeStudio', api)。

| 方法 | 签名 | 说明 |
| list() | () => ParamInfo[] | 每个参数的 key / 标签 / 分组 / 类型 / 范围 / 步长 / 默认值 / 当前值 |
| get(key) | (string) => any | 取一个参数(未知 key 抛错)|
| getAll() | () => object | 取全部当前值 |
| set(key, value) | (string, any) => any | 设一个参数,按参数表强制类型与范围 |
| setMany(patch) | (object) => object | 批量设置 |
| reset() | () => object | 还原原生 |
| exportPreset() | () => string | 导出 JSON(含 $schema)|
| importPreset(text\|object) | (any) => {applied, unknown} | 导入 |
| presets() / applyPreset(id) | | 内置预设:native / official-dark / official-light |
| subscribe(fn) | (fn) => () => void | 订阅变更 |
| selfCheck() / formatSelfCheck() | | 令牌 + DOM 钩子漂移报告 |
| diagnostics() / diagnosticsText() | | 全量诊断(含每个效果的运行状态)|

window.dshThemeStudio.applyPreset('official-dark')
window.dshThemeStudio.set('glass.blur', 32)
window.dshThemeStudio.formatSelfCheck()

3.3 JSON 参数文件(可手工编辑 + 热加载)

// $env:USERPROFILE\.dsh\theme-studio.json
{
"appearance.mode": "dark",
"appearance.backgroundMode": "fluid",
"glass.enabled": true,
"glass.blur": 24,
"quantum.q1Spacing": 90,
"quantum.q2Levels": 6
}

- 文件名/路径:$DSH_HOME/theme-studio.json(默认 $env:USERPROFILE\.dsh\theme-studio.json),原子写(tmp+rename)。
- HTTP 接口(前缀路由,带 loopback + 同源信任围栏):
- GET /deepseek-theme-studio/api → { ok, value, fileError, revision, path }
- POST /deepseek-theme-studio/api { "method": "get" }
- POST /deepseek-theme-studio/api { "method": "set", "patch": { "glass.blur": 30 } }(浅合并,null 删键)
- POST /deepseek-theme-studio/api { "method": "replace", "value": { ... } }
- 客户端每 3 秒(页面可见时)检查一次 revision,文件被手工改动即热加载;fileError 会在设置行显示, 不会被当成空配置静默吞掉。
- 文件必须是 UTF-8 无 BOM 的 JSON 对象;带 BOM 会被容忍,语法错误会被报告。

安全说明:该路由只做 DNS-rebinding / 跨站防护(Host 必须是 loopback 或 webRuntime.trustedHosts,且 sec-fetch-site 不是 cross-site),不是鉴权。本机任意进程都能读写,与生态内同类插件的取舍一致。

4. 参数完整说明

持久化 key = 参数名本身(JSON 文件里的键;localStorage 里加前缀 dsh-deepseek-theme-studio:)。
「默认」列是安装后的初始值 —— 全部等于"什么都不做"。

4.1 外观模式 / 背景

| 设置项 | 键 | 控件 | 范围 / 步长 | 默认 |
| 外观模式 | appearance.mode | 三态 | system/light/dark | system |
| 背景模式 | appearance.backgroundMode | 分段 | solid/gradient/fluid | solid |
| 底色 | appearance.bgColor | 取色器 + 文本 | HEX(空 = 跟随宿主)| "" |
| 强调色 | appearance.accentColor | 取色器 + 文本 | HEX(空 = 跟随宿主)| "" |
| 流体调色板 1–5 | appearance.palette1..5 | 取色器 ×5 | HEX | #000000/#1a3870/#204a7e/#eed8aa/#000000 |
| 装饰层不透明度 | appearance.opacity | 滑杆 | 0–100%,步长 1% | 60% |
| 渐变角度 | appearance.gradientAngle | 滑杆 | 0–360°,步长 1 | 180 |

4.2 液化(流体)

| 设置项 | 键 | 范围 / 步长 | 默认 |
| 启用流体背景 | fluid.enabled | 开关 | 关 |
| 流速 | fluid.speed | 0–2×,步长 0.05 | 0.28 |
| 噪声波长(形状宽窄)| fluid.scale | 0.2–4,步长 0.01 | 1.77 |
| 指针扰动半径 | fluid.radius | 0–300 px,步长 1 | 140 |
| 域扭曲强度 | fluid.distort | 0–6,步长 0.05 | 2.2 |
| 卷曲强度 | fluid.swirl | 0–3,步长 0.05 | 0.8 |
| 颗粒噪点 | fluid.grain | 0–0.05,步长 0.001 | 0.005 |
| 指针光晕 | fluid.glow | 0–0.6,步长 0.01 | 0.13 |
| 暗角 | fluid.vignette | 0–1,步长 0.01 | 0.38 |
| 流体柔化模糊 | fluid.blur | 0–24 px,步长 1 | 0 |
| 指针流场扰动 | fluid.flowmap | 开关 | 开 |

4.3 毛玻璃

| 设置项 | 键 | 范围 / 步长 | 默认 |
| 启用毛玻璃 | glass.enabled | 开关 | 关 |
| 模糊半径 | glass.blur | 0–40 px,步长 1 | 24 |
| 深色 tint / 浓度 | glass.tintDark / glass.tintDarkAlpha | HEX / 0–1 步长 0.01 | #000000 / 0.20 |
| 浅色 tint / 浓度 | glass.tintLight / glass.tintLightAlpha | HEX / 0–1 步长 0.01 | #ffffff / 0.55 |
| 描边透明度 | glass.borderAlpha | 0–1,步长 0.01 | 0.08 |
| 饱和度 | glass.saturation | 0–2×,步长 0.05 | 1 |
| 四个白名单槽位 | glass.slot.composer / .bubble / .sidebar / .sessionlog | 开关 | 前三开、第四关 |
| 槽位选择器(可改) | glass.slot.<名>.selector | 文本 | 见 §4.3.1 |

4.3.1 白名单默认选择器与漂移说明

| 槽位 | 默认选择器 | 0.2.0-rc.2 实测命中 |
| 输入卡 | [data-composer-card] | 1 |
| 用户消息气泡 | [class="_userStack"] [class="_bubble"] | 有消息时命中 |
| 侧栏按钮 | [class="_newSession"] | 3 |
| 会话日志控件 | [data-slot="settings.general.item"] [role="switch"] | 仅设置页打开时命中 |

任务书里的第四项"会话日志按钮"在 0.2.0-rc.2 不存在为按钮:该版本把 session log 做成设置页 General 区的一行(@deepseek-ai/dsh-client-ui-settings-session-log),行内是 Switch 原语;dsh-unknown-theme 针对的 .nL4_yW_sessionLogButton 在本版宿主中查无此类(已抽取全部 51 个宿主 client bundle 的 class-map 佐证)。
因此默认指向真实控件,且随时可在设置里改选择器。
同屏 backdrop-filter 元素硬上限 6(GLASS_MAX_TARGETS),超出者被标记跳过;会形成 containing block 而困住 position: fixed 浮层的祖先(_frame、_sidebarCol、[data-slot] 列、 role=dialog/menu 等)永不加滤镜。

4.4 量子化

| 编号 | 设置项 | 键 | 范围 / 步长 | 默认 |
| Q1 | 空间量子化(点阵)| quantum.q1Enabled | 开关 | 关 |
| Q1 | 栅格间距 | quantum.q1Spacing | 24–160 px,步长 1 | 90 |
| Q1 | 斥力半径 | quantum.q1Radius | 0–300 px,步长 1 | 140 |
| Q1 | 弹簧回弹 / 阻尼 | quantum.q1Spring / quantum.q1Damping | 0.005–0.3 / 0.5–0.99 | 0.05 / 0.85 |
| Q1 | 网格线 / 节点不透明度 | quantum.q1LineOpacity / quantum.q1PointOpacity | 0–0.6 | 0.08 / 0.08 |
| Q1 | 命中节点半径 | quantum.q1ActivePoint | 1–8 px,步长 0.1 | 2.2 |
| Q1 | 点阵颜色 | quantum.q1Color | HEX | #ffffff |
| Q2 | 颜色量子化 | quantum.q2Enabled | 开关 | 关 |
| Q2 | 色阶数 | quantum.q2Levels | 2–16 阶,步长 1 | 6 |
| Q2 | Bayer 抖动强度 | quantum.q2Dither | 0–1,步长 0.05 | 1 |
| Q3 | 形态量子化(粒子)| quantum.q3Enabled | 开关 | 关 |
| Q3 | 粒子总数 | quantum.q3Count | 200–6000,步长 50 | 1400 |
| Q3 | 成形时间 | quantum.q3Assemble | 300–4000 ms,步长 50 | 1200 |
| Q3 | 打散后回正时间 | quantum.q3Scatter | 4–60 s,步长 1 | 22 |
| Q3 | 粒子半径 / 颜色 | quantum.q3Size / quantum.q3Color | 0.5–4 px / HEX | 1.4 / #ffffff |
| Q3 | 指针斥力半径 | quantum.q3Repel | 0–120 px,步长 1 | 19 |
| Q3 | 装饰图形 | quantum.q3Shape | whale/ring/wave | whale |
| Q4 | 状态量子化 | quantum.q4Enabled | 开关 | 关 |
| Q4 | 档位数 | quantum.q4Steps | 2–16 档,步长 1 | 8 |
| Q4 | 量化对象 | quantum.q4Target | pointer/ambient/scroll | pointer |

4.5 聚光灯 / 动画

| 设置项 | 键 | 范围 / 步长 | 默认 |
| 标题聚光灯 | spotlight.enabled | 开关 | 关 |
| 光斑直径 / 颜色 | spotlight.size / spotlight.color | 16–200 px / HEX | 64 / #ffffff |
| 触发元素选择器 | spotlight.selector | 文本 | 见下 |
| 动画总开关 | motion.enabled | 开关 | 开 |
| 统一时长 | motion.duration | 80–400 ms,步长 10 | 160 |
| 缓动曲线 | motion.easing | 4 条(均无过冲)| cubic-bezier(0.2, 0, 0, 1) |

聚光灯默认触发选择器:[data-conversation-header] h1, [data-conversation-header] h2, [class*="_headline"]
(只在标题文字/图标上触发,容器空白区不触发)。

5. 已知取舍(明说,不静默)

1. motion.duration 只作用于本插件自己的表面(效果层、玻璃过渡、设置行)。宿主组件动画不受影响 ——任务 §3.4 禁止大段全局覆盖宿主样式,两者冲突时以此为准。
2. appearance.opacity 允许 0–100%(任务 §3.2 的范围要求),但内置预设与默认值都不超过 60% (任务 §2.1 的简洁预算);超过 60% 时设置行会给出提示。
3. 单元数据里 dsh.compatibility.dshReleases 宿主不读取(app.asar 全量 grep 无消费点);字段按要求照写,实际兼容性由 dsh.bundle.patch / dsh.client / exports 三条契约保证。
4. 鲸鱼轮廓是 DeepSeek 品牌资产,不属于本包 MIT 授权范围;quantum.q3Shape 可切换为 ring/wave 或直接关闭 Q3。

6. 排障(含三个已知坑)

坑 1:corepack EPERM ... package.json

Error: EPERM: operation not permitted, open '...\profiles\web\package.json.lock'

先设环境变量再重试:

$env:COREPACK_ENABLE_PROJECT_SPEC = "0"

若仍失败:确认目标 profile 没有被另一个 dsh 实例占用(关闭正在运行的 web 实例),并把整个命令放在同一个 shell 会话里执行。

坑 2:插件装了但页面上什么都没有

按顺序查这四件事:

1. profile 里有没有 bundle 条目 —— profiles/web/package.json 的 dsh.profile.bundles 必须含 dsh-deepseek-theme-studio;只有 node_modules 里有个包是不够的(客户端插件没有自动发现)。
2. 重启过 profile 没有 —— 刷新页面不够,boot manifest 在 profile 启动时组合。
3. boot manifest 里有没有你的条目 —— 浏览器控制台执行:
window.__DSH_BOOT__.entries.find(e => e.id === 'dsh-deepseek-theme-studio')

有条目但页面报 1 entry did not activate → 打开控制台看 [theme-studio] 前缀的错误。
4. bundle 的 id 是否等于包名 —— window.__ModuleLoader__.load({ id }) 的 id 必须是包名(dsh-deepseek-theme-studio),否则报 loaded without registering "<包名>" via __ModuleLoader__.load。

坑 3:重启时机

- 改了 cordis.patch.yml / package.json / lib/index.js → 必须重启 profile。
- 只改了 lib/client.js(由 src/ 构建)→ 刷新页面即可,宿主按内容版本号重新拉取 bundle;必要时 Ctrl+Shift+R 硬刷新。
- 改完源码记得 node scripts/build.mjs,否则跑的还是旧 bundle:node scripts/build.mjs --check 会告诉你是否陈旧。

其他常见问题

| 症状 | 原因 / 处理 |
| 设置行里显示"参数文件解析失败" | theme-studio.json 不是合法 JSON(常见:编辑器写了 BOM、尾逗号)。修好后 3 秒内自动恢复 |
| 设置行显示"未连接参数文件" | 宿主半没挂载(webServer 服务不可用)或 URL 前缀被改。此时仍可用,只是仅存 localStorage |
| 重启后参数"丢了" | 桌面端每次启动换端口 → localStorage 按 origin 隔离;正是为此把 JSON 文件做成权威来源。检查 $DSH_HOME/theme-studio.json |
| 流体效果变成静态渐变 | 当前环境没有 WebGL2(控制台会有 [theme-studio] WebGL2 unavailable 警告)。这是设计好的降级,不会白屏 |
| 粒子/网格在小窗口不见了 | 视口宽度 < 768 px 时刻意关闭(任务 §4.2),属预期 |
| dsh plugin 命令报"profile 指定了两次" | 你用的是 dsh.cmd(desktop host CLI,会强行注入 --profile desktop)。见 §2.2 直连 bin.js 的做法 |

7. 自检与验证脚本

cd $repo
node scripts/preflight-profile.mjs # 重启前体检:loader 到底会不会收这个包(全部 profile)
node scripts/preflight-profile.mjs --profile desktop
node scripts/build.mjs --check # bundle 是否与 src 同步(非零退出 = 陈旧)
node scripts/smoke-factory.mjs # 在 Node 里跑 bundle 工厂,抓语法/导出错误
node scripts/verify-tokens.mjs # 令牌漂移自检(默认扫已解包的宿主树)
node scripts/verify-tokens.mjs --live http://127.0.0.1:19399 # 对运行实例复检
node scripts/png-diff.mjs a.png b.png --json out.json --dump-region diff

preflight-profile.mjs 复刻了宿主 @deepseek-ai/dsh-client-modules 在 profile 启动时做的每一项检查(bundles 条目 / 包可解析 / dsh.client.platform / exports["./client"] 与文件存在 / exports["."] 与服务端入口存在 / 补丁层含 insert 且 name 指向本包),这样配置错误在重启之前就能发现,而不是重启后对着一个空白设置页猜。

运行时自检(浏览器):

window.dshThemeStudio.formatSelfCheck()

verify-tokens.mjs 刻意比参考实现更严格:抓不到宿主 CSS 或运行实例时非零退出,不会像 mux9056-bot/dsh-theme 的 verify:live 那样在抓取失败后仍然打印"校验通过"。

发布(维护者)

发布不需要任何 token、不需要验证码。npm 侧的凭据是通过 trusted publishing(OIDC) 建立的: .github/workflows/publish.yml 用一次性的、限定到本工作流的 OIDC 令牌换发布权,所以没有长期凭据可泄露、也没有东西需要轮换。

流程就三步:

1. 改版本号(构建会把版本号注入 lib/client.js,所以必须重新构建)
node -e "const f='package.json',p=require('./'+f);p.version='0.1.2';require('fs').writeFileSync(f,JSON.stringify(p,null,2)+'\n')"
node scripts/build.mjs

2. 提交
git add -A; git commit -m "Release 0.1.2"

3. 打附注 tag 并推送(工作流由 tag 触发)
git tag -a v0.1.2 -m "v0.1.2"
git push origin main; git push origin v0.1.2

然后工作流会自动:校验 bundle 与 src/ 同步 → 工厂冒烟测试 → 校验 tag 与 package.json 版本一致 → 发布并生成 SLSA provenance。
两个容易踩的坑(都实际踩过):

- 必须重新构建再提交。 scripts/build.mjs 会把版本号写进 bundle(头部注释和 createPluginBody({ version })),只改 package.json 不动 bundle 会导致工作流第一步就失败 —— 这是门禁在起作用,不是 bug。
- 必须用附注 tag(git tag -a),且显式推送 tag。 轻量 tag 配 git push --follow-tags 不会被推上去,工作流根本不会触发。

首次发布为什么更麻烦

新包没有包设置页,所以配不了 trusted publisher —— 得先有一次带 2FA 的发布把包建出来。当时用的是 npm stage publish + 网页批准(分阶段发布对尚未存在的包会先发一个 0.0.0-stage 占位版本)。
包一旦存在,就可以用下面这条命令配置 trusted publisher:

npm trust github <package> --file publish.yml --repository <owner>/<repo> --allow-publish -y

这条命令需要交互式 2FA:它会在浏览器里打开验证页(用安全密钥也行),必须在真实终端里跑 ——管道或后台任务里没有 TTY,npm 会直接抛 EOTP 而不打开浏览器。

配置好后用 npm trust list <package> 查看(同样需要 2FA)。
预览分享卡片长什么样 ↓tuibe/dsh-deepseek-theme-studio
分享 · DeepSeek Harness Hub
tuibe/dsh-deepseek-theme-studio

调校毛玻璃与流体特效,定制界面视觉风格

这是你的仓库?认领条目

回到顶部