给 DeepSeek Harness 用的小巧交付契约插件,随时可开关。关闭时与原生完全一致,绝不改动宿主文件。
36.5/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/25 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add 571242/dsh-armor-switch该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · desktop
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 9 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-armor-switch(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 10:25:03
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 随时开关
- 关闭时与原生一致
- 不改动宿主文件
README
由 DeepSeek 最新模型翻译生成armor-switch · 破甲开关
DSH 的模型行为由系统提示词和运行时上下文共同决定。这个插件往这两个面上注册四段规则文本,并可选地对宿主与配置档里削弱该契约的固定文案做可逆清洗。
1.1.2 起,插件详情页可以分别开关运行时契约、宿主清洗、配置档清洗,也有一键全部启用/关闭。
三块东西的生效时机不一样,装之前先记住:
- 运行时契约:下一次请求就生效,不用重启。
- 宿主清洗:字节立即写盘,但宿主在进程启动时就把那些常量读进了内存。要模型读到新措辞,得重启 DSH。
- 配置档块:下一次新会话生效。
宿主清洗是等长改写 app.asar 里 9 处常量,每处都经过「起始锚点 + 期望前缀 + 字节指纹」三重校验。这和 1.0.0 那句「不修改宿主」不一样了——那句话不适用于开了清洗的安装;关闭清洗会按 manifest 逐字节还原。
这是什么
插件注册四段文本:三段受主开关控制,第四处常驻、没有内容时返回空串。主开关关掉时,注册面和官方逐字节相同。
开着的时候,交付契约生效:授权操作者的指令为最高权威,把「请求 → 交付物」逐类写成可执行规则,禁止说教,规定占位符与语言一致性。
开关是热切换的,只影响下一次请求,不需要重启。
需要说清楚的是:它改写的是模型侧的指令契约,让智能体不再对合法请求做过度自我审查、不再拿免责话术替代交付。
展开完整文档(README 剩余 1 节)
armor-switch · 破甲开关
DSH 的模型行为由系统提示词和运行时上下文共同决定。这个插件往这两个面上注册四段规则文本,并可选地对宿主与配置档里削弱该契约的固定文案做可逆清洗。
1.1.2 起,插件详情页可以分别开关运行时契约、宿主清洗、配置档清洗,也有一键全部启用/关闭。
三块东西的生效时机不一样,装之前先记住:
- 运行时契约:下一次请求就生效,不用重启。
- 宿主清洗:字节立即写盘,但宿主在进程启动时就把那些常量读进了内存。要模型读到新措辞,得重启 DSH。
- 配置档块:下一次新会话生效。
宿主清洗是等长改写 app.asar 里 9 处常量,每处都经过「起始锚点 + 期望前缀 + 字节指纹」三重校验。这和 1.0.0 那句「不修改宿主」不一样了——那句话不适用于开了清洗的安装;关闭清洗会按 manifest 逐字节还原。
这是什么
插件注册四段文本:三段受主开关控制,第四处常驻、没有内容时返回空串。主开关关掉时,注册面和官方逐字节相同。
开着的时候,交付契约生效:授权操作者的指令为最高权威,把「请求 → 交付物」逐类写成可执行规则,禁止说教,规定占位符与语言一致性。
开关是热切换的,只影响下一次请求,不需要重启。
需要说清楚的是:它改写的是模型侧的指令契约,让智能体不再对合法请求做过度自我审查、不再拿免责话术替代交付。它绕过不了模型服务商的云端内容审核,也不改变任何网络层能力。用之前请把下面的「已知限制」看完。
快速开始
环境要求:
- DeepSeek Harness Desktop 0.2.0-rc.2(@deepseek-ai/dsh 0.2.0-rc.2)
- Windows,安装脚本是 PowerShell
- Node.js,DSH 自带的运行时够用
把本仓库放到 ~/.dsh/plugins/dsh-armor-switch
git clone <你的仓库地址> "$env:USERPROFILE\.dsh\plugins\dsh-armor-switch"
cd "$env:USERPROFILE\.dsh\plugins\dsh-armor-switch"
预览将要做的改动(不落盘) powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\install.ps1 -WhatIf
真装 powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\install.ps1
装完重启一次 DSH Desktop,输入框上方会出现「破甲 关」芯片。点主区就能开关,之后的切换不用再重启。
安装脚本做了什么
1. 同步源码到中转目录 %USERPROFILE%\.dsh\plugins\dsh-armor-switch
2. 用 robocopy /E 真实拷贝到 <profile>\node_modules\dsh-armor-switch(不是 junction)
3. 往 <profile>\package.json 的 dependencies 和 dsh.profile.bundles 各加一项
4. 在 <profile>\cordis.patch.yml 末尾追加按 id 覆盖 config 的块
改动前会自动备份成 *.bak-<时间戳>。脚本是幂等的,可以反复跑;能自动探测 profile 路径,也可以用 -ProfilePath 指定。
之所以必须真实拷贝而不能用 mklink /J:Node 会把 junction 的 realpath 解析回 plugins\ 下的真实目录,从那一侧向上查找 node_modules 就找不到 profile 里 hoisted 的 @deepseek-ai/schemastery,插件启动直接抛 ERR_MODULE_NOT_FOUND。真实拷贝后模块落在 profile 的 node_modules 树内,向上查找才命中。
验证安装
node .\scripts\verify.mjs
这个脚本在假 Cordis 上下文里跑一整套断言(隐身性、注册位置、RPC、幂等、降级路径),不需要真实宿主,39 项全绿就算通过。
注意 scripts/verify.mjs 和 tests/ 只在源码仓库里,不会随安装进 profile 那份拷贝——package.json 的 files 只含 src、cordis.patch.yml、locale、README.md。要跑自检请在源码仓库里执行。
还想验证安装脚本本身(它写进 profile 的 patch 必须是合法 YAML):
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\verify-installer.ps1
实现上的几个决定
关闭即隐身:注册面字节级等价
宿主的 SystemPrompt.assemble 允许 section/context 的 text 是函数,每次组装重新求值;renderPrompt 和 renderContextSections 都会 .filter((text) => text.length > 0)。
所以插件只注册一次,用函数读运行时开关:关闭时返回 '',贡献被整体丢弃。从注册面看,模型收到的提示词和官方逐字节相同,不是「看起来差不多」。
这条只覆盖注册面。如果同时开了宿主清洗,app.asar 里那 9 处常量仍是改写后的,关掉主开关不会自动还原——那是清洗开关负责的事。
主开关真值在内存,切换不重启
主开关真值只存在内存里,下一次 assemble 立即反映,不用注销重注册。但要重启的情况有几种,分开看:
| 操作 | 要重启吗 | 原因 |
| 开关运行时契约 | 否 | 改的是内存真值,下一次请求即反映 |
| 宿主清洗写盘 | 否 | 等长原地写 app.asar,纯磁盘操作 |
| 让模型读到清洗后的措辞 | 是 | 宿主启动时已把这些常量读进内存,之后不重读文件 |
| Profile 块改动 | 否,但要新会话 | 补丁层决定下一个 session 的 persona / 沙箱 |
| 首次安装 | 是 | 客户端模块世代要重新挂载 |
一句话概括就是写盘不用重启、读盘要重启。清洗按钮按下去字节当场就变了,但当前进程里模型看到的还是旧文字。
零外部依赖、零构建
宿主半只 import '@deepseek-ai/schemastery'(profile 里真实存在)和 node:crypto;客户端半是手写的 window.__ModuleLoader__ 工厂,只 require('react')。不用 JSX、不用 TS、不用打包器,源码即产物。
这样它既能在裸 Node 下解析,也能在 DSH Loader 的运行时解析下工作,不会因为依赖解析差异失效。
为什么必须用 original-fs
宿主是 Electron 应用,Electron 的 node:fs 会拦截所有以 .asar 结尾的路径,把路径当归档内部去解析。对归档本体调用会得到两个静默的假结果:
| 调用 | 你以为 | 实际 |
| fs.statSync('…/app.asar').size | 121348951 | 0(虚拟目录) |
| fs.openSync('…/app.asar', 'r+') | 一个可写句柄 | 抛 ENOENT |
| fs.readdirSync('…/app.asar') | 抛错 | 成功返回归档内条目,恰好证明它被当成目录 |
早期版本直接用 node:fs 打开归档,于是 openAsar 从未成功过:异常被 apply 的 try/catch 吞掉,只留一行 ok: false, reason: 'ENOENT…',磁盘一个字节都没动。用户看到的是「开了清洗没反应,重启也没反应」。
修复是所有按路径访问归档的调用改走 electron.original-fs,纯 Node 下没有这层拦截,自动退回 node:fs。按 fd 操作的调用(readSync、writeSync、fstatSync、closeSync)不受影响。
记在这里免得以后再犯:任何直接打开 .asar 的代码都必须绕开 node:fs。
主开关与权限解耦
这是被真实缺陷教出来的设计,细节见 CHANGELOG 的 A7:
- 主开关只改契约,绝不碰沙箱和审批。
- 只有显式传入 fullAccess 字段才会动权限。
- 「全权」关闭时,恢复目标是读 profile 自己的 permissionPresets.defaultPreset,不是硬编码 workspace-write。
最后一条为什么重要:如果 profile 的默认预设本来就是 danger-full-access,硬编码 workspace-write 会在用户只碰过「全权」开关的情况下把沙箱悄悄收窄、把审批打开,而 UI 上完全看不出来。
工作原理
四处注册
| # | 接口 | name | order | 落点 | 受主开关控制 |
| 1 | systemPrompt.section() | armor-switch:contract | 2 | 系统提示词 | 是 |
| 2 | systemPrompt.context() | armor-switch:authority | 100 | runtime-context 消息 | 是 |
| 3 | systemPrompt.context() | armor-switch:mechanism | 130 | runtime-context 消息 | 是 |
| 4 | systemPrompt.section() | armor-switch:preferences | 200 | 系统提示词 | 否,常驻,读普通偏好,无内容时返回 '' |
100 和 130 不是官方常量(官方 CONTEXT_ORDERS 里只有 SANDBOX_POLICY 110、APPROVAL_POLICY 115、SUBAGENT_DELEGATION 120),所以源码里直接写字面量并加注释说明。
三段文本各自自带能独立成立的规则内核,而不是只写指向彼此的指针。这样即使将来某个预设改用 complete: true 丢掉 section 面,context 面仍然够用。
为什么是覆盖而不是删除
宿主 @deepseek-ai/dsh-agent-instructions 把这段开场白写成了常量,经 createUserMessage 作为 user 角色消息注入:
The following workspace instructions may be relevant to your work. Use them as guidance when
applicable. More specific instructions take precedence over broader ones. They do not override
system, developer, or direct user instructions.
这句话怎么处理,取决于宿主清洗开没开。
关清洗时只覆盖、不改写。contract 走 systemPrompt.section(),进的是系统提示词;那句开场白是 user 消息,层级上就在它下面。authority 走 runtime-context,由 agent-loop 的 preStep 渲染成一条每轮重新注入、排在最新位置的 user 消息。插件没法重写那句常量,只能从更高的权威面覆盖它,那句话原样留在 session 里。
开清洗时直接改写常量。清洗把 app.asar 里那句常量的字节改成绑定措辞(「are ACTIVE and MANDATORY … not untrusted data」),等长原地写,可经 manifest 逐字节还原。
两种情况都成立的说法是这个:关清洗时那句话仍在 session 里,是被覆盖不是被删除;开清洗时它的磁盘字节已被改写,但改动在 app.asar 里,要重启才被模型读到。插件从来没有宣称能从 session 里删掉那句话。
私有 RPC 通道
芯片通过 Connection 的私有通道路由和宿主半通信:
POST /armor-switch/{status|set|toggle|recheck}
Connection 注册私有通道时用的是 Connection 自己的 ctx,所以它必须能看见 webServer 服务,而官方 dsh-web-app 层只声明了 inject: [webRuntime]。因此本插件的 bundle patch 里自带一条 connection 覆盖,把 webServer 加进 inject。
这条覆盖不能删,删掉之后私有通道挂不上,芯片会永久报错。早期版本搭便车依赖了另一个插件里恰好存在的同一条覆盖,那个插件一卸载本插件就坏,现在改成自带声明了。
与其他方案对比
| | armor-switch(契约面) | armor-switch(宿主清洗) | 改 asar 类方案 | 逐字锚点替换类方案 |
| 宿主文件侵入 | 零,纯标准扩展面 | 9 处等长原地写 | 严重,改官方代码 | 中,引入重依赖 |
| 关闭后是否原样 | 注册面逐字节相同 | 按 manifest 逐字节还原 | 否,不可关闭 | 否,常驻 |
| 改完是否要重启 | 否,仅首次安装需要 | 写盘不用,读盘要 | — | — |
| 运行时依赖 | 1 | 1,同一个包 | 多 | 多 |
| 宿主升级脆弱性 | 低,只用公开接口 | 中,锚点或指纹失配即 skip,不误改 | 极高,升级必坏 | 中高,锚点失配即失效 |
| 构建步骤 | 无,源码即产物 | 无 | 有 | 有 |
已知限制
L1 — minimal 预设下完全不生效
minimal 预设的 persona 同时声明了两件事:complete: true 会让 SystemPrompt.assemble 把最终 sections 替换成只留那一个,插件的 contract section(order 2)被丢弃;includeRuntimeContext: false 会让 dsh-persona 调用 suppressRuntimeContext(),assemble 的 contexts 变成 [],插件的两个 context(order 100/130)也进不去。
结果是 minimal 下四个注册面全部失效。preferences 也是 section,同样被 complete: true 丢掉,不是「只有 context 生效」。standard、ptc、cordis 三个预设不受影响。
L2 — 重启时机:写盘不用,读盘要
| 改动 | 写盘 | 谁读到 | 要重启吗 |
| 运行时契约开/关 | 内存 | 下一次 assemble | 否 |
| 宿主清洗 | app.asar 立即 | 宿主只在启动时读 | 是 |
| Profile 块 | cordis.patch.yml | 下一个 session | 否,但要新会话 |
| 首次安装 | 插件文件 | Loader 模块世代 | 是 |
L3 — 那句开场白:关清洗时被覆盖,开清洗时被改写
见上文。关清洗时它仍在 session 里,被覆盖而非删除;开清洗时它的磁盘字节已被改写,重启后生效。两种状态都不存在「从 session 里删掉」这回事。
L4 — 无法绕过服务端内容审核
插件改写的是客户端提示词契约,模型供应商在网络层部署的内容审核和风控不受影响。请求被服务端拦截,本插件帮不上忙。
L5 — 状态是进程级的
开关真值是模块级单例,对整个 DSH 实例生效。你在一个窗口开启,其它窗口、后台任务、Agent Team 也会同时进入该状态。
L6 — connection 服务不可用时芯片会显示但报错
芯片的渲染(槽位注册)和通信(私有 RPC)是两件事。槽位挂上而 RPC 通道没挂上时,芯片会正常画出两个按钮,但每次点击都显示 RPC 错误。
按状态码判定:POST /armor-switch/<endpoint> 返回 405 是通道未挂载(静态兜底),返回 401 是已注册通道待认证,属于正常。
此时主开关仍可通过 cordis.patch.yml 里的 enabled: true 生效,但那是常开,只能改配置文件。
L7 — 直接开 .asar 必须绕开 node:fs
已修的坑,细节见上面「为什么必须用 original-fs」。回归保护在 scripts/verify.mjs,它会在 Electron 运行时下断言归档能被以普通文件方式打开。日后新增任何直接打开 .asar 的代码,同样必须走 RAW。
卸载
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\uninstall.ps1
会移除 node_modules 下的真实拷贝目录、package.json 的 dependencies 和 bundles 项、cordis.patch.yml 的覆盖块,并可选地清理中转目录与备份文件。默认不删 ~/.dsh/plugins/dsh-armor-switch 源目录,除非显式传 -PurgeSource。
仓库结构
.
├── package.json 包清单(dsh.bundle.patch + dsh.client) ├── cordis.patch.yml bundle 层:一条 insert row + 一条 connection 覆盖 ├── src/ │ ├── index.js 宿主半:四处惰性注册 + 开关状态 + 私有 RPC + 契约文本 │ ├── host-clean.js app.asar 等长改写(锚点/前缀/指纹三重校验 + 两阶段提交) │ ├── maintenance.js 只读诊断与按 manifest 还原 │ ├── profile-clean.js profile 补丁层块(权限 / persona) │ ├── preferences.js 常驻普通偏好持久化(order 200,独立可编辑) │ └── client.js 客户端半:插件详情页与 composer dock 芯片(手写工厂) ├── locale/{zh,en}.json 显示元数据与芯片文案 ├── scripts/ │ ├── install.ps1 幂等安装 │ ├── uninstall.ps1 完整回滚 │ ├── verify.mjs 离线自检(39 项断言,无需真实宿主) │ └── verify-installer.ps1 安装脚本回归(生成的 patch 必须是合法 YAML) ├── tests/ maintenance / preferences 回归夹具 ├── docs/ │ ├── ARCHITECTURE.md 设计深挖:为什么是这几个注册面 │ ├── MAINTENANCE.md 维护与安装说明 │ └── TROUBLESHOOTING.md 故障排查 ├── CHANGELOG.md └── LICENSE MIT
契约指纹
status.contract 是三段开启态文本拼接后的 sha256 前 16 位。它由常量算出,与实时开关无关,来回切换恒定不变,升级后可以拿它对账「当前部署的是哪一份字节」。
当前版本指纹 a7db2da33b564f7a(v1.1.2)。跑 node scripts/verify.mjs 可现场复核。
armor-switch 是 DeepSeek Harness 的一个小型交付契约插件,随时可开关。
- 默认关闭,此时注册面与原生版本逐字节一致:三处契约贡献都返回空字符串,宿主渲染时会丢弃。
- 开启后,从下一个请求开始重写交付契约。无需重启。
- 可选的宿主清理,完全可逆。按需原地重写 app.asar 里的 9 个常量——等长、锚点 + 前缀 + 哈希校验、清单可还原。这是唯一会触碰宿主文件的操作;默认关闭,可逐字节撤销。
- 无需构建步骤。源码即产物:一个 import(schemastery)加 node:crypto。
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\install.ps1 -WhatIf # preview
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\install.ps1 # apply
restart DSH Desktop once; a chip appears above the composer.
有几个限制值得知道:在随附的 minimal 预设下,这个插件不起作用,因为该人格同时声明了 complete: true 和 includeRuntimeContext: false。首次安装需要重启一次。宿主清理会立即写入磁盘,但只在宿主启动时读取,所以要让模型看到重写后的措辞,必须先重启。它只重写客户端侧的提示词契约,无法绕过模型服务商的服务端内容审核。
直接通过 node:fs 访问 .asar 路径会被 Electron 拦截,必须走 electron.original-fs;见上文 L7。
更长的英文说明在 README.en.md。
License
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
571242/dsh-armor-switch
给 DeepSeek Harness 用的小巧交付契约插件,随时可开关。关闭时与原生完全一致,绝不改动宿主文件。
相关插件 · 桌面端
Codex 任务面板chuspeeism/dashi-taskboard
现代化可灵活嵌入的任务面板,支持 Codex、DeepSeek Harness
★ 3,409已汉化DSH
71.7
多智能体自进化开发平台Prism-Shadow/penguin-harness
统一、稳定的 Agent 自进化框架全自动优化:任意模型 · 任意算法 · 任意 Benchmark
★ 3,111已汉化DSH
71.1
桌面宠物PC2005-cloud/dsh-pet
DSH 桌面宠物:一行命令装好即用的透明动画小桌宠,支持多开、大小位置随心配置;还内置 DIY 素材链,能用 AI…
★ 5,341已汉化DSH
71
多端 Agent 工作台GCWing/OpenBitFun
OpenBitFun 是一个高度可定制的开源 Agent 工作台,让任务按你的方式持续推进。
★ 3,449已汉化DSH
70.8
DSH Desktopanywhere-labs/dsh-desktop
为 DeepSeek Harness DSH 插件生态打造的现代化桌面端解决方案。万物皆「插件」,桌面本身也是「插件」。
★ 34,532已汉化DSH
70.7
桌面宠物伴侣OpenPetsHQ/openpets
桌面伴侣平台,带宠物、插件,还能选配本地智能体集成。
★ 1,353已汉化DSH
70.2