1 parent
bb93c6a2b6
commit
d4d1c16252
10 files changed
+178
-40
No files matched your search
@@ -4,7 +4,7 @@
|
||||
|
||||
<h1 align="center">⚔️ DeepSeek Harness cybersecurity red-team tool (dsh-purge)</h1>
|
||||
|
||||
<p align="center"><strong>Version 1.1.79</strong></p>
|
||||
<p align="center"><strong>Version 1.1.80</strong></p>
|
||||
|
||||
<p align="center">
|
||||
<em>DeepSeek Harness jailbreak: every model, swap prompts per model. Default prompt for 小码酱. Please star ⭐ If you build on this, see Attribution required.</em>
|
||||
@@ -57,7 +57,7 @@ The author's personal channel: [t.me/LLM_PoJia](https://t.me/LLM_PoJia). Notes a
|
||||
|
||||
## What this is
|
||||
|
||||
**dsh-purge** is a cybersecurity red-team plugin for the official [DeepSeek Harness](https://www.deepseek.com/harness/) already installed on your machine. **1.1.79** targets **DSH 0.2.1-rc.2** (0.2.0 still works). Official **Web** (`dsh web`) and the official **desktop EXE** are both supported. Install and Apply them separately.
|
||||
**dsh-purge** is a cybersecurity red-team plugin for the official [DeepSeek Harness](https://www.deepseek.com/harness/) already installed on your machine. **1.1.80** targets **DSH 0.2.1-rc.2** (0.2.0 still works). **DSH 0.2.1-rc.3 and newer RCs are not supported.** Official **Web** (`dsh web`) and the official **desktop EXE** are both supported. Install and Apply them separately.
|
||||
|
||||
Harness does more than forward a prompt. It rewrites prompts, approval gates, sandbox policy, and session migration at runtime. Asking only “will the model answer” treats a host-layer block as a model refusal. This plugin separates those two layers on your own install, for controlled evaluation and for seeing which default policy is too tight.
|
||||
|
||||
@@ -131,11 +131,12 @@ This repo is [Apache License 2.0](./LICENSE). Forks and redistributions must kee
|
||||
|
||||
## Supported hosts
|
||||
|
||||
**1.1.79 targets DSH 0.2.1-rc.2.** 0.2.0 still works. Do not apply it to 0.1.x.
|
||||
**1.1.80 targets DSH 0.2.1-rc.2.** 0.2.0 still works. Do not apply it to 0.1.x.
|
||||
|
||||
- **dsh 0.2.1-rc.2** (official desktop / official `dsh web`): use **1.1.79**. Fixes `{{cwd}}` / `[cwd]` crash, patch #40 match, dropped `toolFilter`, host `dsh-tools` resolve, hostFs fd, desktop helper self-kill, `file:` archive update, Ctrl+Enter steer.
|
||||
- **dsh 0.2.1-rc.2** (official desktop / official `dsh web`): use **1.1.80**. Fixes `{{cwd}}` / `[cwd]` crash, patch #40 match, dropped `toolFilter`, host `dsh-tools` resolve, hostFs fd, desktop helper self-kill, `file:` archive update, Ctrl+Enter steer.
|
||||
- **dsh 0.2.0-rc.2**: use **1.1.40** or newer; this line also installs.
|
||||
- **dsh 0.1.7** (incl. rc.1 / rc.2): use **1.1.39** or older — pick the tag on [Releases](https://github.com/YuJunZhiXue/dsh-purge/releases).
|
||||
- **dsh 0.2.1-rc.3 / rc.4 and newer are not supported.** Unmatched patches stay pending or skipped; nothing is rewritten blindly. Stay on **0.2.1-rc.2**.
|
||||
|
||||
Unmatched patches stay pending or skipped; nothing is rewritten blindly.
|
||||
|
||||
@@ -183,9 +184,10 @@ pnpm add https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/mas
|
||||
`pnpm add` and `dsh plugin add` fetch the package; `postinstall` writes `dsh-purge` into `dsh.profile.bundles` and adds a body `insert` in the profile `cordis.patch.yml`. Without that insert the host never loads the plugin and no button appears. pnpm 11/12 skips install scripts (`ERR_PNPM_IGNORED_BUILDS`) unless you allow the build:
|
||||
|
||||
```sh
|
||||
pnpm add --allow-build=dsh-purge https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master
|
||||
# If the package is already in node_modules:
|
||||
pnpm approve-builds dsh-purge
|
||||
pnpm add --allow-build=dsh-purge --allow-build=dsh-purge@https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master
|
||||
# Already installed, warning only — the full specifier is required (name-only leaves "set this to true or false"):
|
||||
pnpm approve-builds dsh-purge@https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master
|
||||
# If bundles / insert are still missing:
|
||||
node node_modules/dsh-purge/scripts/ensure-profile-bundle.mjs
|
||||
```
|
||||
|
||||
@@ -194,7 +196,7 @@ Success: `node_modules/dsh-purge/package.json` exists, `"dsh-purge"` is in that
|
||||
For the desktop client you can also click the button (`dsh://` deep link; it still downloads the same tarball):
|
||||
|
||||
<p align="center">
|
||||
<a href="dsh://plugin/install?id=dsh-purge&name=dsh-purge&version=1.1.79&repo=YuJunZhiXue%2Fdsh-purge&permissions=%E7%B3%BB%E7%BB%9F%E6%8F%90%E7%A4%BA%E8%AF%8D%E6%B3%A8%E5%85%A5%2C%E6%9C%AC%E6%9C%BA%E8%A1%A5%E4%B8%81%2C%E8%AE%BE%E7%BD%AE%E9%A1%B5&downloadUrl=https%3A%2F%2Fcodeload.github.com%2FYuJunZhiXue%2Fdsh-purge%2Ftar.gz%2Frefs%2Fheads%2Fmaster"><strong>Install in desktop client</strong></a>
|
||||
<a href="dsh://plugin/install?id=dsh-purge&name=dsh-purge&version=1.1.80&repo=YuJunZhiXue%2Fdsh-purge&permissions=%E7%B3%BB%E7%BB%9F%E6%8F%90%E7%A4%BA%E8%AF%8D%E6%B3%A8%E5%85%A5%2C%E6%9C%AC%E6%9C%BA%E8%A1%A5%E4%B8%81%2C%E8%AE%BE%E7%BD%AE%E9%A1%B5&downloadUrl=https%3A%2F%2Fcodeload.github.com%2FYuJunZhiXue%2Fdsh-purge%2Ftar.gz%2Frefs%2Fheads%2Fmaster"><strong>Install in desktop client</strong></a>
|
||||
</p>
|
||||
|
||||
### 3. Three more clicks after the command
|
||||
|
||||
+10
-8
@@ -4,7 +4,7 @@
|
||||
|
||||
<h1 align="center">⚔️ DeepSeek Harness 网络安全红队工具(dsh-purge)</h1>
|
||||
|
||||
<p align="center"><strong>Version 1.1.79</strong></p>
|
||||
<p align="center"><strong>Version 1.1.80</strong></p>
|
||||
|
||||
<p align="center">
|
||||
<em>DeepSeek Harness 破甲:让所有模型都能破甲,不同模型可换不同提示词;默认提示词面向国模「小码酱」。Jailbreak for every model — swap prompts per model. 求 Star 收藏 ⭐ 如要二开,请查看署名要求部分</em>
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
## 介绍
|
||||
|
||||
**dsh-purge** 是装在本机官方 [DeepSeek Harness](https://www.deepseek.com/harness/) 上的网络安全红队评测插件。当前 **1.1.79** 已适配 **DSH 0.2.1-rc.2**(0.2.0 仍可用)。官方 **Web**(`dsh web`)和官方 **桌面端**(EXE)都支持,两边分开装、分开应用。
|
||||
**dsh-purge** 是装在本机官方 [DeepSeek Harness](https://www.deepseek.com/harness/) 上的网络安全红队评测插件。当前 **1.1.80** 已适配 **DSH 0.2.1-rc.2**(0.2.0 仍可用)。**不支持 DSH 0.2.1-rc.3 及更新的 rc。** 官方 **Web**(`dsh web`)和官方 **桌面端**(EXE)都支持,两边分开装、分开应用。
|
||||
|
||||
Harness 不只是把问题交给模型。它还会在运行时改提示词、审批门、沙箱和会话格式。只看「模型答不答」,会把宿主拦截误当成模型拒绝。这个插件在你自己的安装里把这两层分开,用来做受控评测,也用来看默认策略该不该收紧。
|
||||
|
||||
@@ -133,11 +133,12 @@ Harness 不只是把问题交给模型。它还会在运行时改提示词、审
|
||||
|
||||
## 适配范围
|
||||
|
||||
**1.1.79 已适配 DSH 0.2.1-rc.2**,0.2.0 仍可用。不要拿它去打 0.1.x。
|
||||
**1.1.80 已适配 DSH 0.2.1-rc.2**,0.2.0 仍可用。不要拿它去打 0.1.x。
|
||||
|
||||
- **dsh 0.2.1-rc.2**(官方桌面 / 官方 `dsh web`):用 **1.1.79**。已修 `{{cwd}}` / `[cwd]` 整轮失败、补丁 #40 命中、`toolFilter` 废弃、`dsh-tools` 解析、hostFs fd、桌面换包自杀、`file:` 归档更新、Ctrl+Enter 插话。
|
||||
- **dsh 0.2.1-rc.2**(官方桌面 / 官方 `dsh web`):用 **1.1.80**。已修 `{{cwd}}` / `[cwd]` 整轮失败、补丁 #40 命中、`toolFilter` 废弃、`dsh-tools` 解析、hostFs fd、桌面换包自杀、`file:` 归档更新、Ctrl+Enter 插话。
|
||||
- **dsh 0.2.0-rc.2**:用 **1.1.40** 及以上;本页这档也能装。
|
||||
- **dsh 0.1.7**(含 rc.1 / rc.2):用 **1.1.39** 及更早 —— 在 [Releases](https://github.com/YuJunZhiXue/dsh-purge/releases) 里选对应标签。
|
||||
- **不支持 dsh 0.2.1-rc.3 / rc.4 及更新。** 宿主对不上时补丁会显示待应用或跳过,不会乱改文件。请退回 **0.2.1-rc.2** 再用本插件。
|
||||
|
||||
对不上的补丁会显示待应用或跳过,不会乱改文件。
|
||||
|
||||
@@ -185,9 +186,10 @@ pnpm add https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/mas
|
||||
`pnpm add` 和 `dsh plugin add` 都会拉包;`postinstall` 再把 `dsh-purge` 写进 `dsh.profile.bundles`,并在用户层 `cordis.patch.yml` 补上本体 `insert`(没有这一行,宿主不加载插件,界面没有按钮)。pnpm 11/12 默认拦安装脚本(`ERR_PNPM_IGNORED_BUILDS`),请带上允许构建,或事后补跑:
|
||||
|
||||
```sh
|
||||
pnpm add --allow-build=dsh-purge https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master
|
||||
# 已经装上但只有警告时:
|
||||
pnpm approve-builds dsh-purge
|
||||
pnpm add --allow-build=dsh-purge --allow-build=dsh-purge@https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master
|
||||
# 已经装上但只有警告时,必须带完整 specifier(只写 dsh-purge 会留下 set this to true or false):
|
||||
pnpm approve-builds dsh-purge@https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master
|
||||
# bundles / insert 还没写上时再补:
|
||||
node node_modules/dsh-purge/scripts/ensure-profile-bundle.mjs
|
||||
```
|
||||
|
||||
@@ -196,7 +198,7 @@ node node_modules/dsh-purge/scripts/ensure-profile-bundle.mjs
|
||||
桌面客户端也可以点按钮(`dsh://` 唤起,下的仍是同一份压缩包):
|
||||
|
||||
<p align="center">
|
||||
<a href="dsh://plugin/install?id=dsh-purge&name=dsh-purge&version=1.1.79&repo=YuJunZhiXue%2Fdsh-purge&permissions=%E7%B3%BB%E7%BB%9F%E6%8F%90%E7%A4%BA%E8%AF%8D%E6%B3%A8%E5%85%A5%2C%E6%9C%AC%E6%9C%BA%E8%A1%A5%E4%B8%81%2C%E8%AE%BE%E7%BD%AE%E9%A1%B5&downloadUrl=https%3A%2F%2Fcodeload.github.com%2FYuJunZhiXue%2Fdsh-purge%2Ftar.gz%2Frefs%2Fheads%2Fmaster"><strong>唤起客户端一键安装</strong></a>
|
||||
<a href="dsh://plugin/install?id=dsh-purge&name=dsh-purge&version=1.1.80&repo=YuJunZhiXue%2Fdsh-purge&permissions=%E7%B3%BB%E7%BB%9F%E6%8F%90%E7%A4%BA%E8%AF%8D%E6%B3%A8%E5%85%A5%2C%E6%9C%AC%E6%9C%BA%E8%A1%A5%E4%B8%81%2C%E8%AE%BE%E7%BD%AE%E9%A1%B5&downloadUrl=https%3A%2F%2Fcodeload.github.com%2FYuJunZhiXue%2Fdsh-purge%2Ftar.gz%2Frefs%2Fheads%2Fmaster"><strong>唤起客户端一键安装</strong></a>
|
||||
</p>
|
||||
|
||||
### 3. 装完还要做这三下
|
||||
|
||||
@@ -904,7 +904,7 @@ window.__ModuleLoader__.load({ id: "dsh-purge", factory: (require) => {
|
||||
.dshp-pill.is-wait{color:var(--dshp-warn);border-color:color-mix(in srgb,var(--dshp-warn) 30%,var(--dshp-line))}
|
||||
.dshp-pill.is-miss{color:var(--dshp-mute)}
|
||||
.dshp-pill.is-bad{color:var(--dshp-bad)}
|
||||
.dshp-btn{appearance:none;font-family:inherit;font-size:16px;line-height:24px;font-weight:600;padding:8px 12px;border-radius:8px;border:1px solid transparent;cursor:pointer;transition:transform 500ms var(--dshp-ease),opacity 300ms var(--dshp-ease)}
|
||||
.dshp-btn{appearance:none;font-family:system-ui,-apple-system,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans SC",sans-serif;font-size:16px;line-height:24px;font-weight:600;padding:8px 12px;border-radius:8px;border:1px solid transparent;cursor:pointer;transition:transform 500ms var(--dshp-ease),opacity 300ms var(--dshp-ease);-webkit-text-fill-color:currentColor;text-indent:0;overflow:visible}
|
||||
.dshp-btn:hover:not(:disabled){transform:translateY(-1px)}
|
||||
.dshp-btn:active:not(:disabled){transform:scale(0.98)}
|
||||
.dshp-btn:disabled{opacity:.45;cursor:not-allowed}
|
||||
@@ -1083,6 +1083,38 @@ body:not([data-ds-dark-theme]) .dshp-auth-ops button.primary{background:var(--ds
|
||||
.dshp-tab-btn:hover{color:var(--dsw-alias-label-primary,currentColor)}
|
||||
.dshp-tab-btn.on{color:var(--dsw-alias-brand-primary,#6dbf8c)}
|
||||
.dshp-tab-btn.on:after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;border-radius:2px;background:var(--dsw-alias-brand-primary,#6dbf8c)}
|
||||
/* 宿主工具条按钮常继承图标字体 / font-size:0 / color:transparent,字在 DOM 里但看不见(#169)。 */
|
||||
.dshp-hero-chip-btn,.dshp-tab-btn,.dshp-launch,.dshp-icon-btn,.dshp-hbtn,.dshp-btn,.dshp-dock-tab,.dshp-dock-head button,.dshp-auth-ops button,.dshp-switch button{
|
||||
font-family:system-ui,-apple-system,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans SC",sans-serif!important;
|
||||
-webkit-text-fill-color:currentColor!important;
|
||||
text-indent:0!important;
|
||||
letter-spacing:normal!important;
|
||||
overflow:visible!important;
|
||||
text-overflow:clip!important;
|
||||
width:auto!important;
|
||||
max-width:none!important;
|
||||
}
|
||||
.dshp-hero-chip-btn{
|
||||
font-size:12.5px!important;
|
||||
line-height:1!important;
|
||||
font-weight:600!important;
|
||||
color:#1a1916!important;
|
||||
-webkit-text-fill-color:#1a1916!important;
|
||||
min-width:max-content!important;
|
||||
height:28px!important;
|
||||
padding:0 12px!important;
|
||||
}
|
||||
.dshp-hero-chip-btn.on{color:#2f6b4f!important;-webkit-text-fill-color:#2f6b4f!important}
|
||||
body[data-ds-dark-theme] .dshp-hero-chip-btn,.dshp-dock[data-theme="dusk"] .dshp-hero-chip-btn{color:#f4f1ea!important;-webkit-text-fill-color:#f4f1ea!important}
|
||||
body[data-ds-dark-theme] .dshp-hero-chip-btn.on,.dshp-dock[data-theme="dusk"] .dshp-hero-chip-btn.on{color:#6dbf8c!important;-webkit-text-fill-color:#6dbf8c!important}
|
||||
.dshp-tab-btn{font-size:13px!important;line-height:16px!important;font-weight:500!important;color:#5c564c!important;-webkit-text-fill-color:#5c564c!important;padding:0 4px 9px!important}
|
||||
.dshp-tab-btn.on{color:#2f6b4f!important;-webkit-text-fill-color:#2f6b4f!important}
|
||||
body[data-ds-dark-theme] .dshp-tab-btn{color:#c9c3b8!important;-webkit-text-fill-color:#c9c3b8!important}
|
||||
body[data-ds-dark-theme] .dshp-tab-btn.on{color:#6dbf8c!important;-webkit-text-fill-color:#6dbf8c!important}
|
||||
.dshp-launch{font-size:13px!important;line-height:1!important;font-weight:600!important;min-width:max-content!important}
|
||||
.dshp-btn{font-size:16px!important;line-height:24px!important;font-weight:600!important}
|
||||
.dshp-btn-primary{color:#fff!important;-webkit-text-fill-color:#fff!important}
|
||||
.dshp-btn-tiny{font-size:14px!important;line-height:20px!important}
|
||||
/* Glass follows the host color. Weight and background opacity are kept separate: the shell is translucent, the text sits on a more solid layer. */
|
||||
.dshp-dock{font-family:inherit;font-size:14px;line-height:1.6;font-weight:500;-webkit-font-smoothing:antialiased;text-shadow:none}
|
||||
.dshp-dock[data-theme="white"],.dshp-dock[data-theme="dusk"]{backdrop-filter:blur(22px) saturate(1.4)!important;-webkit-backdrop-filter:blur(22px) saturate(1.4)!important;color:var(--dshp-ink)!important;border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary,#6d8f78) 34%,transparent)!important;--dshp-glass:blur(18px) saturate(1.35);--dshp-accent:var(--dsw-alias-brand-primary,#3d8f68);--dshp-fill:color-mix(in srgb,var(--dsw-alias-brand-primary,#6dbf8c) 14%,transparent)}
|
||||
@@ -3677,9 +3709,9 @@ body[data-ds-dark-theme] .dshp-rewind-item span{color:var(--dsw-alias-label-tert
|
||||
.rt-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-brand-primary)}
|
||||
.rt-spacer{flex:1}
|
||||
.rt-btn{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:inherit;
|
||||
border-radius:6px;padding:3px 9px;font-size:12px;cursor:pointer;font-family:inherit;white-space:nowrap}
|
||||
border-radius:6px;padding:3px 9px;font-size:12px;cursor:pointer;font-family:system-ui,-apple-system,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;white-space:nowrap;-webkit-text-fill-color:currentColor;overflow:visible}
|
||||
.rt-btn:hover{border-color:var(--dsw-alias-border-l2)}
|
||||
.rt-btn-primary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:#fff}
|
||||
.rt-btn-primary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:#fff;-webkit-text-fill-color:#fff}
|
||||
.rt-btn-primary:hover{opacity:.9}
|
||||
.rt-btn:disabled{opacity:.5;cursor:default}
|
||||
.rt-tabs{display:flex;flex-wrap:wrap;gap:2px;padding:6px 12px 0;border-bottom:1px solid var(--dsw-alias-border-l1)}
|
||||
|
||||
+1
-1
@@ -2530,7 +2530,7 @@ const COMPLETE_PROMPT_WATERFALL_INJECT =
|
||||
"\t\t\t\treturn [...purge, ...tail, base]; // [dsh-purge] complete prompt keeps inject + agent-instructions\n" +
|
||||
"\t\t\t})(completeSection, dshPurgeSections, dshPurgeRest),\n" +
|
||||
"\t\t\tcontexts: runtimeContextSuppressed ? [] : transformed.contexts\n" +
|
||||
"\t\t};";
|
||||
"\t\t};";
|
||||
|
||||
function clearShellNetworkBan(pattern) {
|
||||
return pattern
|
||||
|
||||
+87
-13
@@ -105,24 +105,98 @@ export function ensureProfileBundles(profileDir) {
|
||||
return { ok: true, wrote: true, path: fp };
|
||||
}
|
||||
|
||||
function readPurgeTarball() {
|
||||
try {
|
||||
const pkg = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
||||
return String(pkg?.dsh?.install?.tarball || "").trim();
|
||||
} catch {
|
||||
return "https://codeload.github.com/YuJunZhiXue/dsh-purge/tar.gz/refs/heads/master";
|
||||
}
|
||||
}
|
||||
|
||||
/** pnpm 12 会给 tarball 单独写一行 `dsh-purge@https://...: set this to true or false`。只写包名不够。 */
|
||||
export function purgePnpmBuildSpecs() {
|
||||
const specs = ["dsh-purge"];
|
||||
const tarball = readPurgeTarball();
|
||||
if (tarball) specs.push(`${PURGE_NAME}@${tarball}`);
|
||||
return specs;
|
||||
}
|
||||
|
||||
function isPurgeAllowBuildKey(key) {
|
||||
const name = String(key || "").replace(/^['"]|['"]$/g, "");
|
||||
return name === PURGE_NAME || name.startsWith(`${PURGE_NAME}@`);
|
||||
}
|
||||
|
||||
function parseAllowBuildLine(line) {
|
||||
const m = String(line || "").match(/^[ \t]+(?:"([^"]+)"|'([^']+)'|(\S+?))[ \t]*:[ \t]*(.*?)\s*$/);
|
||||
if (!m) return null;
|
||||
return { key: m[1] || m[2] || m[3], value: String(m[4] || "").trim() };
|
||||
}
|
||||
|
||||
function formatAllowBuildLine(key) {
|
||||
return ` ${key}: true`;
|
||||
}
|
||||
|
||||
/** 把 dsh-purge 以及 `dsh-purge@tarball` 都写成 true,避免装别的插件还报 ERR_PNPM_IGNORED_BUILDS(#168)。 */
|
||||
export function rewritePnpmAllowBuilds(raw) {
|
||||
const wanted = purgePnpmBuildSpecs();
|
||||
const text = String(raw || "").replace(/\r\n/g, "\n");
|
||||
if (!text.trim()) {
|
||||
return `allowBuilds:\n${wanted.map(formatAllowBuildLine).join("\n")}\n`;
|
||||
}
|
||||
const lines = text.split(/\r?\n/);
|
||||
let start = -1;
|
||||
for (let i = 0; i < lines.length; i += 1) {
|
||||
if (/^allowBuilds[ \t]*:/.test(lines[i])) {
|
||||
start = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start < 0) {
|
||||
const prefix = text.endsWith("\n") ? "" : "\n";
|
||||
return `${text}${prefix}\nallowBuilds:\n${wanted.map(formatAllowBuildLine).join("\n")}\n`;
|
||||
}
|
||||
let end = lines.length;
|
||||
const kept = [];
|
||||
const seen = new Set();
|
||||
for (let i = start + 1; i < lines.length; i += 1) {
|
||||
const line = lines[i];
|
||||
if (!line.trim()) {
|
||||
end = i;
|
||||
break;
|
||||
}
|
||||
if (/^\S/.test(line)) {
|
||||
end = i;
|
||||
break;
|
||||
}
|
||||
const parsed = parseAllowBuildLine(line);
|
||||
if (!parsed) {
|
||||
kept.push(line);
|
||||
continue;
|
||||
}
|
||||
if (isPurgeAllowBuildKey(parsed.key)) {
|
||||
kept.push(formatAllowBuildLine(parsed.key));
|
||||
seen.add(parsed.key);
|
||||
continue;
|
||||
}
|
||||
kept.push(line);
|
||||
}
|
||||
for (const key of wanted) {
|
||||
if (!seen.has(key)) kept.push(formatAllowBuildLine(key));
|
||||
}
|
||||
const next = [...lines.slice(0, start + 1), ...kept, ...lines.slice(end)].join("\n");
|
||||
return next.endsWith("\n") ? next : `${next}\n`;
|
||||
}
|
||||
|
||||
/** pnpm 11/12 默认拦 postinstall(ERR_PNPM_IGNORED_BUILDS)。写进 profile 的 allowBuilds,下次 add 能跑脚本。 */
|
||||
export function ensurePnpmAllowBuild(profileDir) {
|
||||
const fp = path.join(profileDir, "pnpm-workspace.yaml");
|
||||
let text = "";
|
||||
try { text = fs.readFileSync(fp, "utf8"); } catch { text = ""; }
|
||||
if (/(^|\n)[ \t]*dsh-purge[ \t]*:[ \t]*true\b/.test(text)) return { ok: true, wrote: false, path: fp };
|
||||
if (!String(text).trim()) {
|
||||
fs.writeFileSync(fp, "allowBuilds:\n dsh-purge: true\n", "utf8");
|
||||
return { ok: true, wrote: true, path: fp };
|
||||
}
|
||||
if (/(^|\n)allowBuilds[ \t]*:/.test(text)) {
|
||||
const next = text.replace(/(^|\n)(allowBuilds[ \t]*:[ \t]*\n)/, "$1$2 dsh-purge: true\n");
|
||||
if (next === text) return { ok: true, wrote: false, path: fp };
|
||||
fs.writeFileSync(fp, next, "utf8");
|
||||
return { ok: true, wrote: true, path: fp };
|
||||
}
|
||||
const prefix = text.endsWith("\n") ? "" : "\n";
|
||||
fs.writeFileSync(fp, `${text}${prefix}\nallowBuilds:\n dsh-purge: true\n`, "utf8");
|
||||
const current = String(text || "").replace(/\r\n/g, "\n");
|
||||
const next = rewritePnpmAllowBuilds(current);
|
||||
if (next === current) return { ok: true, wrote: false, path: fp };
|
||||
fs.writeFileSync(fp, next, "utf8");
|
||||
return { ok: true, wrote: true, path: fp };
|
||||
}
|
||||
|
||||
|
||||
@@ -51,9 +51,9 @@ window.__ModuleLoader__.load({
|
||||
.rt-dot{width:8px;height:8px;border-radius:50%;background:var(--dsw-alias-brand-primary)}
|
||||
.rt-spacer{flex:1}
|
||||
.rt-btn{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:inherit;
|
||||
border-radius:6px;padding:3px 9px;font-size:12px;cursor:pointer;font-family:inherit;white-space:nowrap}
|
||||
border-radius:6px;padding:3px 9px;font-size:12px;cursor:pointer;font-family:system-ui,-apple-system,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;white-space:nowrap;-webkit-text-fill-color:currentColor;overflow:visible}
|
||||
.rt-btn:hover{border-color:var(--dsw-alias-border-l2)}
|
||||
.rt-btn-primary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:#fff}
|
||||
.rt-btn-primary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:#fff;-webkit-text-fill-color:#fff}
|
||||
.rt-btn-primary:hover{opacity:.9}
|
||||
.rt-btn:disabled{opacity:.5;cursor:default}
|
||||
.rt-tabs{display:flex;flex-wrap:wrap;gap:2px;padding:6px 12px 0;border-bottom:1px solid var(--dsw-alias-border-l1)}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { promises as fsp } from "node:fs";
|
||||
import fs, { promises as fsp } from "node:fs";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
|
||||
+11
-3
@@ -73,12 +73,23 @@ function localDataOffset(buf, localOffset) {
|
||||
return localOffset + 30 + nameLen + extraLen;
|
||||
}
|
||||
|
||||
function isZipDirectoryEntry(name) {
|
||||
return /[/\\]$/.test(String(name || ""));
|
||||
}
|
||||
|
||||
export function extractZipBuffer(buf, dest) {
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
const root = path.resolve(dest);
|
||||
const prefix = root.endsWith(path.sep) ? root : root + path.sep;
|
||||
for (const entry of readZipEntries(buf)) {
|
||||
const rel = safeZipName(entry.name);
|
||||
if (!rel) continue;
|
||||
const out = path.resolve(root, rel);
|
||||
if (out !== root && !out.startsWith(prefix)) throw new Error("Invalid zip path");
|
||||
if (isZipDirectoryEntry(entry.name)) {
|
||||
fs.mkdirSync(out, { recursive: true });
|
||||
continue;
|
||||
}
|
||||
if (entry.compSize === 0xffffffff || entry.localOffset === 0xffffffff) {
|
||||
throw new Error("zip64 is not supported");
|
||||
}
|
||||
@@ -90,9 +101,6 @@ export function extractZipBuffer(buf, dest) {
|
||||
if (end > buf.length) throw new Error("Truncated zip data");
|
||||
const compressed = buf.subarray(start, end);
|
||||
const body = entry.method === 0 ? compressed : zlib.inflateRawSync(compressed);
|
||||
const out = path.resolve(root, rel);
|
||||
const prefix = root.endsWith(path.sep) ? root : root + path.sep;
|
||||
if (out !== root && !out.startsWith(prefix)) throw new Error("Invalid zip path");
|
||||
fs.mkdirSync(path.dirname(out), { recursive: true });
|
||||
fs.writeFileSync(out, body);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dsh-purge",
|
||||
"version": "1.1.79",
|
||||
"version": "1.1.80",
|
||||
"description": "DeepSeek Harness 破甲:让所有模型都能破甲,不同模型可换不同提示词;默认提示词面向国模「小码酱」。Jailbreak for every model — swap prompts per model. 求 Star 收藏 ⭐ 如要二开,请查看署名要求部分",
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
# 1.1.80
|
||||
|
||||
## 中文
|
||||
|
||||
- 版本 **1.1.80**。修复 bug,修复稳定性。
|
||||
- **#168**:pnpm 12 的 `allowBuilds` 把 `dsh-purge@codeload...` 也写成 `true`,装别的插件不再留下 `set this to true or false`。
|
||||
- **#169**:芯片 / 应用按钮强制系统字体和实色字,不再被宿主图标字体吃掉。
|
||||
- **#170**:纯 Node 解 zip 时目录条目建目录,不再写成同名空文件导致 EEXIST。
|
||||
- **#172**:`lib/skills.js` 补上 `fs`,#54 软链重叠守卫重新生效。
|
||||
- **#176**:写清 **不支持 DSH 0.2.1-rc.3 及更新的 rc**,请退回 **0.2.1-rc.2**。对不上的补丁待应用或跳过,不乱改文件。
|
||||
|
||||
## English
|
||||
|
||||
- **1.1.80**. Bug fixes and stability.
|
||||
- **#168**: pnpm 12 `allowBuilds` also sets `dsh-purge@codeload...` to `true`, so installing other plugins no longer leaves `set this to true or false`.
|
||||
- **#169**: chip / Apply buttons force a system font and solid text color so the host icon font cannot hide the label.
|
||||
- **#170**: Node zip fallback creates directories for directory entries instead of empty files (no more EEXIST).
|
||||
- **#172**: import `fs` in `lib/skills.js` so the #54 symlink overlap guard works again.
|
||||
- **#176**: **DSH 0.2.1-rc.3 and newer RCs are not supported.** Stay on **0.2.1-rc.2**. Unmatched patches stay pending or skipped.
|
||||
|
||||
# 1.1.79
|
||||
|
||||
## 中文
|
||||
|
||||
Reference in new issue
Block a user