-
dsh-purge-plus v1.4.1 Stable
released this
2026-10-19 12:29:24 +08:00 | 0 commits to main since this release1.4.1 — 修「装完就用不了」的 cwd 变量崩溃
症状
装完插件、还没点「应用」,每一轮对话都失败:
unknown prompt variable "{{cwd}}" in section "deployment:persona-suffix"; registered variables: provider, model根因
0.2.1 的
dsh-agent-loop只注册两个提示词变量:ctx.systemPrompt.variable("provider", …) ctx.systemPrompt.variable("model", …)cwd在 0.1.x 还有,0.2 拿掉了。而宿主的interpolate()遇到未注册变量不是留空,
是抛异常:if (!Object.hasOwn(variables, name)) { throw new Error(`unknown prompt variable "{{{name}}}" in ${kind} "${input.name}"; …`) }旧版
cordis.patch.yml给system-prompt配了:personaSuffix: Your working directory is {{cwd}}.deployment:persona-suffix是每轮都参与渲染的段,所以这个错在插件一装上就发生,
与是否点过「应用」无关——这就是「基本上下载安装后都有」的原因。修法(三层,逐层收窄)
层 文件 做法 1. 配置 cordis.patch.ymlpersonaSuffix改为""。persona 不再发任何变量;工作目录由宿主 runtime context 提供,persona 里重复一遍没有收益。2. 注册 lib/cwd-variable.js(新)插件在 systemPrompt全局层补一个cwdprovider,取值优先级agent.options.cwd→session.header.cwd→process.cwd()。这样用户自己 preset 里写的{{cwd}}也能解析。宿主已注册同名变量时抛already registered,按成功处理。3. 兜底 lib/identity.js① overlayOfficialIdentity写出的 persona-suffix 改成纯文本;② 旧的Working directory: {{cwd}}.剥离后不再留变量;③sanitizeAssemblySections把任何残留的{{cwd}}降级成{ {cwd} }——变量注册失败时也不会炸整轮。关键取舍:不依赖「宿主会留空未注册变量」。三层里任何一层单独生效都不会崩,
三层齐全时{{cwd}}正常解析出真实路径。验证
npm run test:cwd(test/cwd-variable.mjs,21 项)直接加载宿主真实的
dsh-system-prompt渲染器,逐条断言:- 旧配置在
provider/model两个变量下确实抛错,且报错文本与用户反馈一致(复现) - 当前
cordis.patch.yml的活动配置里没有{{cwd}} overlayOfficialIdentity的产物能渲染通过,输出里没有裸{{cwd}}registerCwdVariable注册后{{cwd}}解析出真实路径(含三条 fallback)- 重复注册不算失败
- 转义后的文本能被宿主渲染(证明兜底不是装饰)
找不到宿主模块时,依赖渲染器的断言会显式
skip,不会假装通过——上一版正是
这种「看起来没问题」的验证方式漏掉了这个 bug。
镜像说明 / Mirror note:
dsh-purge-plus是社区分支(JeffKeeping/dsh-purge-plus),不在已删除的YuJunZhiXue/dsh-purge仓库内,原仓库没有发布过 GitHub Release。本 Release 由镜像仓库wqmll/dsh-purge-plus依据 tag 生成,说明文字取自该分支的CHANGELOG.md。资产按上游 CI 相同方式生成:
dsh-purge-plus-1.4.1.zip是git archive源码包(可直接dsh plugin install离线安装);dsh-purge-plus-1.4.1.tgz是内容等价的 npm 包。Downloads
- 旧配置在
-
dsh-purge-plus v1.4.0 Stable
released this
2026-10-18 23:27:25 +08:00 | 0 commits to main since this release1.4.0 — 借 IG5 的做法加固四处工程细节
参考 Minglink/dsh-infinite-gen-5 的
source/json_output.js、source/attachment_lease.js、审批门与 CAS 修订号模式,挑了四处与本插件能力相符的改进。不搬它的逆向引擎、worker 协议、Ghidra / x64dbg 适配层——那些属于另一类插件。新增:严格 JSON 输出边界(
lib/json-safe.js)宿主会在渲染前校验工具结果。旧实现全程
JSON.stringify,三种情况会出事:情况 旧行为 现在 BigInt(如 64 位地址被算成 BigInt)抛异常 → 整个响应 500 投影阶段报 INVALID_PLUGIN_OUTPUT并指出路径循环引用 抛异常 → 500 同上,带 at定位字段值 undefined静默丢字段 → 界面以为「没数据」 省略该字段但保留 null;不可靠值转成{__invalid,__reason,__at}另外拒绝
-0、NaN、Infinity、Symbol、Function、稀疏数组、带额外属性的数组、accessor、非普通对象(class 实例)。深度上限 64、节点上限 20 万,超限报错而非截断。64 位地址保持字符串精度。sendJson全部改走stringifySafe—— 永不抛,坏字段变成可诊断标记,而不是把 200 变成 500。新增:文件身份与写入守卫(
lib/host-lease.js)改宿主文件之前要先确认「我改的还是我看到的那个文件」。旧实现只比路径字符串,三种情况会被骗:
- 目标被换成符号链接 / 目录联接 → 看到的是另一份文件;
- 同一路径下文件被替换(重装、换版本)→ 路径对、内容不对;
- Windows 路径大小写不敏感,
C:\App与c:\app会被当成两份。
现在写前取一份 identity(真实路径 + size + mtime + 前 64 KiB 的 SHA-256),写完再取一次,不一致报
changed/vanished。另附writeFileAtomic(同目录临时文件 → rename),保留原文件 mode。新增:审批档位与审计流水(
lib/tool-gate.js)purge_apply/purge_revert/purge_uninstall三个破坏性工具以前没有任何「这次调用批没批」的记录。现在:- 审计永远记:
$DSH_HOME/dsh-purge/audit.jsonl,每次调用一行(intent / allow / deny / result),失败也记;审计写不进去绝不影响工具结果。 - 审批可选,
approvalMode两档:audit(默认):只记流水,行为与旧版完全一致,不弹任何东西。enforce:走宿主approval.request,只有明确allowed-once才next()。缺 agent、缺 approval 服务、抛错、未知结果、signal 已 abort —— 一律 deny 不派发,从不缓存上一次批准。
默认不是 enforce 的原因:本插件的主入口是人自己点「应用」,人就是审批者,再弹一次只是多一次点击;而本机策略可能把 approval 一律自动拒绝,强制审批等于把插件锁死。需要更严时(模型自动跑长任务)再切 enforce。
- 新工具
purge_audit:读回审计尾部,让模型在长任务里能自查「上一次 apply 到底批没批、结果如何」。 - 设置页新增「审批与审计」区块:单选档位 + 展开查看流水(
.dshp-audit,等宽、限高滚动)。
新增:状态修订号(
lib/revision.js)设置页每 5 秒轮询
/status,Web 与桌面可能同时开着。旧实现里 apply / revert 无条件执行,后点的会静默覆盖先点的结果。现在状态机有单调递增的
rev:/status带出,动作时带回,不一致返回 409 + 当前 rev + 最后一次动作。客户端收到 409 提示「另一个窗口刚改过状态」并自动重新拉取,而不是留着旧数字让用户重复点击。不持久化——重启后归零是正确语义。修复:
hooksDenyBypass保存时抹掉同文件其他键saveHookDenySettings原来只重建hooksDenyBypass一个键再覆盖整文件。approvalMode住进同一个hooks-deny.json后,切一次 hooks 开关就会把审批档位悄悄重置。改成合并写入(实测:approvalMode与hooksDenyBypass同时保留)。优化:请求体错误分类
readJsonBody原来只抛一句Error,所有异常都压成 500,界面无法区分「内容太大」和「JSON 写错了」。现在按BODY_TOO_LARGE(413)、BODY_INVALID_JSON(400)、BODY_NOT_OBJECT(400)分类,19 处 catch 统一走bodyErrorStatus。新增接口
路由 方法 作用 /dsh-purge/approval-modeGET / POST 读/写审批档位,重启后生效 /dsh-purge/auditGET 读审计尾部( ?limit=1..200,默认 40)/dsh-purge/status新增rev、last_action、approval_mode三个字段。测试
71 项离线断言(json-safe 20 / host-lease 13 / revision 11 / tool-gate 27),不启动宿主、不碰真实工程。
镜像说明 / Mirror note:
dsh-purge-plus是社区分支(JeffKeeping/dsh-purge-plus),不在已删除的YuJunZhiXue/dsh-purge仓库内,原仓库没有发布过 GitHub Release。本 Release 由镜像仓库wqmll/dsh-purge-plus依据 tag 生成,说明文字取自该分支的CHANGELOG.md。资产按上游 CI 相同方式生成:
dsh-purge-plus-1.4.0.zip是git archive源码包(可直接dsh plugin install离线安装);dsh-purge-plus-1.4.0.tgz是内容等价的 npm 包。Downloads