DeepSeek Harness 智能皮肤轮换 —— 随机 / 顺序 / 加权 /…
30.8/100
综合分
1
GitHub 星标
245
npm 周下载
—/5
用户评分
数据截至 2026/10/12 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-skin-rotationnpm 源 · dsh-skin-rotation 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · market
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 24 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-skin-rotation @ 1.0.2
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 03:22:15
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件
查看扫描证据(共 42 处,展示前 27 条)
- 读取本地文件lib/index.js:161
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')); - 读取本地文件lib/index.js:177
const own = JSON.parse(readFileSync(join(dirname(manifestPath), 'package.json'), 'utf8')); - 读取本地文件lib/index.js:189
return existsSync(candidate) ? located(candidate) : null; - 读取本地文件lib/index.js:192
return existsSync(candidate) ? located(candidate) : null; - 读取本地文件lib/index.js:231
const value = JSON.parse(readFileSync(join(profileDir, 'compatibility.json'), 'utf8')); - 读取本地文件lib/index.js:249
const value = JSON.parse(readFileSync(manifest, 'utf8')).version; - 写入本地文件lib/index.js:445
mkdirSync(dirname(original.path), { recursive: true }); - 读取本地文件lib/state.js:210
return migrateState(JSON.parse(readFileSync(join(profileDir, STATE_FILE), 'utf8'))); - 写入本地文件lib/state.js:281
mkdirSync(dirname(path), { recursive: true }); - 写入本地文件lib/state.js:286
writeFileSync(fd, text, 'utf8'); - 写入本地文件lib/state.js:290
renameSync(temporary, path); - 读取本地文件lib/state.js:293
if (existsSync(temporary)) rmSync(temporary, { force: true }); - 删除本地文件lib/state.js:293
if (existsSync(temporary)) rmSync(temporary, { force: true }); - 读取本地文件lib/state.js:355
parsed = JSON.parse(readFileSync(join(profileDir, HISTORY_FILE), 'utf8')); - 读取本地文件lib/patch.js:183
for (const name of readdirSync(directory)) { - 删除本地文件lib/patch.js:187
if (Date.now() - statSync(path).mtimeMs > maxAgeMs) rmSync(path, { force: true }); - 读取本地文件lib/patch.js:187
if (Date.now() - statSync(path).mtimeMs > maxAgeMs) rmSync(path, { force: true }); - 删除本地文件lib/patch.js:189
rmSync(path, { force: true }); - 写入本地文件lib/patch.js:206
mkdirSync(txDir, { recursive: true }); - 写入本地文件lib/patch.js:219
writeFileSync(journalPath, JSON.stringify(journal, null, 2), 'utf8'); - 删除本地文件lib/patch.js:225
rmSync(journalPath, { force: true }); - 读取本地文件lib/patch.js:235
return JSON.parse(readFileSync(journalPath, 'utf8')); - 读取本地文件lib/patch.js:244
const files = readdirSync(directory).filter((name) => name.endsWith(TX_SUFFIX)); - 读取本地文件lib/patch.js:247
.map((name) => ({ name, mtimeMs: statSync(join(directory, name)).mtimeMs })) - 读取本地文件lib/patch.js:269
const current = existsSync(originals[index].path) ? readFileSync(originals[index].path, 'utf8') : ''; - 写入本地文件lib/patch.js:290
writeFileSync(entry.path, original.source, 'utf8'); - 删除本地文件lib/patch.js:292
rmSync(entry.path, { force: true });
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 启动随机换肤
- 设置内开关控制
DeepSeek Harness 随机换肤:每次启动随机用一个已安装皮肤,开关在「设置 -> 皮肤」里。
最近更新
在 GitHub 查看全部 →v2.0.12026-10-11
修复 2.0.0 引入的回归:桌面应用里设置卡片的每次改动都因 cross-site-request-rejected 失败,读取却一直正常。
· 问题出在哪
2.0.0 要求 POST 必须带可验证的 Origin。桌面外壳发写请求时不带 Origin 头——宿主自己的 /api 防护恰好允许这种情况,而带了 Origin 就必须与 Host 一致——于是插件拒绝了宿主早已接受的请求。卡片显示的状态永远改不了。
· 修复方式
现在守卫只拒绝浏览器自己标记为跨站的请求(Sec-Fetch-Site: cross-site,页面脚本无法伪造),并把 localhost / 127.0.0.1 / [::1] 视为同一台机器。这正是皮肤管理器用的规则,也是宿主防护早已执行的规则。
拒绝记录现在写进状态载荷的 lastRejection(原因、方法、是否带 Origin),下次再出源问题,发一个请求就能定位,不用再复现一轮。
· 已验证
· 对真实 DSH 宿主:不带 Origin 的 POST 现在返回 200(2.0.0 里返回 403);Origin 与 Host 匹配、localhost 别名两种情况都返回 200;Sec-Fetch-Site: cross-site 和外来 Origin 仍返回 403。
· 本地 62 项测试,CI 上 Node 20/22/24 全部通过,外加打包 tarball 的任务。
完整细节见 CHANGELOG.md。
v2.0.02026-10-11
从随机抽取到轮换系统:策略、真实池、历史记录,以及崩溃安全的配置写入。你现有的偏好会自动迁移。
· 安装
dsh plugin --profile web add
· 新增
· 策略 —— 随机、顺序、加权和固定,启动、路由和测试共用同一引擎。顺序模式在重启后从正确位置继续;加权模式接受任意非负有限权重,把 0 视为「不参与抽取」。
· 池 —— 每个皮肤都报告为兼容 / 排除 / 不兼容 / 不可用。排除皮肤永远不等于卸载。
· 近期重复控制 —— 避开最近 2 或 3 次成功轮换。只是偏好,绝不拦截。
· 历史记录 —— 有上限,独立文件,ISO 8601 格式,记录触发方式、模式、结果、失败阶段和原因。
· 恢复上一个 —— 回到池中最近一次成功的皮肤。
· 崩溃安全写入 —— 日志让中断的轮换在下次启动时完成或回滚,并拒绝覆盖它无法解释的补丁。
· 状态 schemaVersion + 迁移,以及轮换预设(保存 / 应用 / 删除)。
· tools/verify-package.mjs —— 打包、解包、从隔离目录加载,拒绝仅仓库文件和开发者绝对路径;由 CI 运行。
· 修复
· 每次保存都会丢失排除项(Set 既未规范化也未序列化)。
· 顺序模式下,当前皮肤离开候选列表时会跳过一个皮肤。
· 恢复可能回滚一个并非它写入的手工编辑补丁。
· 验证
· 本地和 CI 中 Node 20/22/24 上共 59 项测试,外加一个包 tarball 任务。
· 真实主机端到端:启动轮换、set-mode / set-weight / set-excluded / save-preset / use-preset / rotate-now / restore-previous / reset-defaults、同源强制(403)和无效输入(400)。
· v1 偏好文件迁移到 v2,启动守卫保持完好。
完整细节见 CHANGELOG.md。
v1.0.22026-10-06
DeepSeek Harness 随机皮肤轮换。无需构建步骤即可安装:dsh plugin --profile web add。亮点:每次启动挑一个不同的已安装皮肤,绝不连续两次相同;Settings → Skins 里有开关,还有「立即换一个」操作;只挑运行中的宿主真正会加载的皮肤(对齐 DSH 的插件准入检查,并遵循 compatibility.json 的授权);重写两个补丁层里共享的 dsh-skin 托管块,保留每一行外部内容和注释;每个宿主进程只轮换一次:热重载不重抽,重启才重抽;29 项测试,含一项针对 node-semver 的差分 SemVer 测试。完整列表见 CHANGELOG.md。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。
README
由 DeepSeek 最新模型翻译生成dsh-skin-rotation
DeepSeek Harness 智能皮肤轮换 —— 随机 / 顺序 / 加权 / 固定四种策略,可筛选候选池、可查轮换历史、配置写入崩溃安全。纯本地运行,不需要额外 AI API。
它做什么
你装了四个皮肤,四个都喜欢,但每次只用其中一个。
dsh-skin-rotation 会在每次启动 DeepSeek Harness 时按你选的轮换策略启用一个皮肤,控制项都在「设置 → 皮肤」页里:
| 策略 | 行为 |
| random 随机 | 每次启动换一个,可选避开最近 2 / 3 次用过的 |
| sequential 顺序 | 按你的顺序依次轮换,重启后从正确位置继续 |
| weighted 加权 | 按权重比例抽取(权重不必凑成 100) |
| fixed 固定 | 始终使用指定皮肤,不做自动切换 |
它同时是可解释、可恢复的:哪些皮肤在候选池里、其余为什么被排除、什么时候换过什么、上一次成功的皮肤是哪一只(一键恢复)。
展开完整文档(README 剩余 1 节)
dsh-skin-rotation
DeepSeek Harness 智能皮肤轮换 —— 随机 / 顺序 / 加权 / 固定四种策略,可筛选候选池、可查轮换历史、配置写入崩溃安全。纯本地运行,不需要额外 AI API。
它做什么
你装了四个皮肤,四个都喜欢,但每次只用其中一个。
dsh-skin-rotation 会在每次启动 DeepSeek Harness 时按你选的轮换策略启用一个皮肤,控制项都在「设置 → 皮肤」页里:
| 策略 | 行为 |
| random 随机 | 每次启动换一个,可选避开最近 2 / 3 次用过的 |
| sequential 顺序 | 按你的顺序依次轮换,重启后从正确位置继续 |
| weighted 加权 | 按权重比例抽取(权重不必凑成 100) |
| fixed 固定 | 始终使用指定皮肤,不做自动切换 |
它同时是可解释、可恢复的:哪些皮肤在候选池里、其余为什么被排除、什么时候换过什么、上一次成功的皮肤是哪一只(一键恢复)。
第 1 次启动 → 深海女仆工坊 第 2 次启动 → 虎鲸链路 第 3 次启动 → 鲸鱼娘昼夜工坊
不只是"随便抽一个"
- 真正的候选池:每个已安装皮肤都会被标为 compatible(参与)/ excluded(你排除的)/ incompatible(宿主不兼容)/ unavailable(读不到)。排除 ≠ 卸载,插件绝不碰你已安装的文件。
- 只抽宿主真能加载的皮肤:DSH 会拒绝 @deepseek-ai/dsh peer 范围不含当前运行时的插件行(补丁写着启用、但行根本不启动),naive 的随机可能抽到"死皮肤"导致一个皮肤都没有。本插件复刻了这道准入判定,并读取 profile 的 compatibility.json 放行记录。
- 可读的轮换历史:时间、从哪只到哪只、触发原因(startup / manual / restore)、策略、结果。失败会如实记为失败,且不会进入"最近使用"集合。
- 恢复上一皮肤:一键回到最近一次成功、且当前仍在候选池里的皮肤。
- 崩溃安全的配置写入:轮换要改两层补丁文件,事务日志保证被中断的写入在下次启动时要么补完、要么回滚;对于"变了但不是它改的"文件,它拒绝覆盖并给出诊断。
- 带版本的状态文件:schemaVersion + 向前迁移,升级不丢偏好。
安装
从 GitHub 一行装:
dsh plugin --profile web add github:luoyuejun9/dsh-skin-rotation
从 npm 装:
dsh plugin --profile web add dsh-skin-rotation
或者用 最新 Release 上的预构建 tarball——不需要构建,也不会触发 allowBuilds 授权:
dsh plugin --profile web add https://github.com/luoyuejun9/dsh-skin-rotation/releases/latest/download/dsh-skin-rotation.tgz
重启一次,然后打开「设置 → 皮肤」,轮换卡片就在这个页面底部。
装进桌面端而不是 web profile?把 --profile web 换成 --profile desktop 即可,两边都能用。
设置卡片
设置 → 皮肤 ├── 已安装皮肤 ← 皮肤管理器自己的页面 └── 🎲 皮肤轮换 ← 本插件
├── [开关] 启动时自动轮换 轮换模式:[随机 ▾] 近期不重复:[避开最近 2 个 ▾]
├── 当前皮肤:虎鲸链路 · 候选池 2 个 ├── ☑ 虎鲸链路 · 权重 [3] ├── ☐ 深海女仆工坊 (已排除) ├── ☐ 不兼容皮肤 (不兼容,已排除)
├── [立即换一个] [恢复上一皮肤] [重新读取]
├── 最近轮换 │ 2026-10-11 21:04 · 启动 · 官方默认 → 虎鲸链路 · 成功 └── ▸ 高级设置 (权重说明、恢复默认配置)
| 控件 | 作用 |
| 启动时自动轮换 | 关闭后启动不改动皮肤;「立即换一个」仍然可用。 |
| 轮换模式 | random / sequential / weighted / fixed。fixed 下你指定皮肤,不再自动切换。 |
| 近期不重复 | 优先避开最近 2 / 3 次成功轮换用过的皮肤。这只是偏好、不是阻塞:当候选池里全是"最近用过"的,它照样会选一个并如实说明。 |
| 皮肤勾选框 | 是否参与轮换。取消勾选 = 排除,不是卸载;不兼容的皮肤不可被勾选。 |
| 权重 | 仅 weighted 模式显示;填 0 表示不参与抽取,留空表示默认权重 1。 |
| 恢复上一皮肤 | 回到最近一次成功且仍在候选池中的皮肤,并在历史里记为一次 restore。 |
在皮肤管理器里手动切换皮肤依然有效——直到下次启动,这正是这个插件的意义。
工作原理
flowchart LR
A[宿主启动] --> B{轮换开启?}
B -- 否 --> Z[保持当前皮肤]
B -- 是 --> C[发现已安装皮肤]
C --> D[排除宿主会拒绝的皮肤]
D --> E[随机抽一个,且不与上次相同]
E --> F[改写 profile patch + home patch 里的dsh-skin managed 区段]
F --> G[DSH 的 HMR 监听器重新组合插件树]
G --> H[页面打开时已经是抽中的皮肤]
- 轮换是宿主侧的决定,一次启动只做一次。 进程级 boot key 保证插件被热重载时不会重复抽签,真正重启才会重抽;浏览器刷新不会重掷骰子。
- 它改的是补丁层,不是皮肤。 插件改写的是皮肤管理器自己也在用的那段 # --- dsh-skin managed --- 互斥区段,profile patch 与优先级更高的 home patch 一起改。区段之外的一切——手写行、注释、DSH 自己追加的设置行——原样保留,写入走临时文件 + rename 的原子替换。
- 只抽宿主真能加载的皮肤。 DSH 会拒绝那些 @deepseek-ai/dsh peer 范围不含当前运行时的插件行:补丁里写着 disabled: false,行却根本不会启动,结果是一个皮肤都没有。本插件用自己的语义化版本求值器复刻了这道准入判定,并读取 profile 的 compatibility.json 放行记录,因此随机结果不会落到死皮肤上。
- 浏览器半区只有一张卡片。 它监听 DOM,往皮肤管理器页面根节点追加一个容器,把卡片渲染进去;不注册自己的设置页、不留全局状态,卸载时清掉自己创建的 observer、定时器和样式。
- 不碰皮肤文件、skin.json,也不接管管理器自己的状态。
写入的文件
| 路径 | 内容 |
| <profile>/cordis.patch.yml | 共用 dsh-skin managed 互斥区段 |
| <DSH_HOME>/cordis.patch.yml | 同一区段——优先级更高,必须一起改 |
| <profile>/.dsh-skin-rotation.json | 本插件自己的偏好:开关、上次抽中的皮肤、启动标识、客户端回报 |
HTTP 接口:GET/POST /api/dsh/skin-rotation,仅同源,跨站请求直接拒绝。
环境要求
- DeepSeek Harness web profile,>=0.2.0-rc.2 <0.3.0-0(声明在 engines.dsh)。
- 至少装两个皮肤轮换才有意义。皮肤的判定沿用生态约定:包内带合法 skin.json(id、package、bodyAttr、wiring.id)。
- 卡片挂在皮肤管理器的皮肤页(settings.section id dsh-skins)里;没有管理器时轮换依然工作,只是改用路由开关。
- 不依赖任何 @deepseek-ai/* 运行时包:无需解析、无需构建、安装时不执行任何脚本。
- Windows 与 POSIX 都适用:写入用临时文件 + rename,恢复日志是纯 JSON。
- 已被 dsh.so 独立收录:安全审计通过(低风险),安装验证 L5(已在 dsh 0.2.0-rc.2 上实机跑通)。
开发
node --test # 29 个用例
npm pack --pack-destination dist # 打包发布用的 tarball
| 测试 | 覆盖内容 |
| test/host.test.mjs | 区段改写(含区段外记录保留)、真实 profile 的发现、随机规则、启动一次性、双层写入与回滚、路由防护 |
| test/client-card.test.mjs | 整棵卡片渲染树,通过桩模块加载器 + 桩 React 驱动,不需要浏览器 |
| test/semver-oracle.test.mjs | 与真实 node-semver 的差分验证,覆盖生成的组合矩阵(本机没装时自动跳过) |
| tools/e2e-rotation.sh | 在独立 DSH_HOME 下真实启动宿主多次,断言抽中的皮肤就是浏览器实际拿到的那个 |
端到端脚本是里面最有意思的一个:它不验证插件「自认为」做了什么,而是去取浏览器实际收到的 boot graph,确认里面只有一个皮肤模块。
FAQ
会和皮肤管理器打架吗? 不会。两边用同一套规则写同一段区段;本插件只在启动时轮换,之后完全不插手。
浏览器刷新会重抽吗? 不会——每个宿主进程只抽一次,否则每次刷新都换皮肤。
只装了一个皮肤呢? 轮换等于不换,区段照样会被规范化。
能一直用我现在这个皮肤吗? 关掉开关即可,启动不再改动皮肤,手动切换也不受影响。
项目边界
本插件只管在你已安装的皮肤之间轮换:候选池、策略、历史记录与配置写入的可靠性。它刻意不做皮肤的安装、下载、卸载和预览,也不取代皮肤管理器或插件市场——那些已经有成熟项目,本插件与它们并存。
路线图
- 轮换方案(Presets)已支持保存与一键切换;可视化的方案编辑器暂不在计划内。
- 状态文件里保留了随机种子(seed)字段,用于可复现的运行;暂未在 UI 暴露。
- 会话级主题(不同会话用不同皮肤)未实现:DSH 当前没有公开、稳定的会话级主题切换接口,因此它留在路线图里,而不是用不可靠的 DOM 手段假装做到。
License
MIT © luoyuejun9预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
luoyuejun9/dsh-skin-rotation
DeepSeek Harness 智能皮肤轮换 —— 随机 / 顺序 / 加权 /…
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,225未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,370已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13941 个插件含 PR 收录与…
★ 355已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7
这是你的仓库?认领条目