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

插件故障隔离 lanbaolu/dsh-fail-soft

DeepSeek Harnessv0.1.17
lanbaolu53 天前有提交已提供中文文档扫描:含敏感能力

自动隔离坏插件,让服务照常启动并可一键恢复

36.7/100
综合分
8
GitHub 星标
221
npm 周下载
—/5
用户评分

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add @lanbaolu/dsh-fail-soft
npm 源 · @lanbaolu/dsh-fail-soft 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · platform
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
数据截至 2026/11/01·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/03·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 53 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包@lanbaolu/dsh-fail-soft @ 0.1.17
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 00:49:01

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 81 处,展示前 40 条)
  • 读取本地文件
    lib/heal.js:54
    hashes = readdirSync(npxRoot)
  • 读取本地文件
    lib/heal.js:61
    if (!existsSync(pkg)) continue
  • 读取本地文件
    lib/heal.js:64
    version = JSON.parse(readFileSync(pkg, 'utf8')).version
  • 读取本地文件
    lib/heal.js:67
    try { mtime = statSync(join(npxRoot, hash)).mtimeMs } catch { }
  • 读取本地文件
    lib/heal.js:90
    if (existsSync(join(cand, '@deepseek-ai', 'dsh-app-boot', 'package.json'))) return cand
  • 读取本地文件
    lib/heal.js:94
    if (existsSync(join(cand, '@deepseek-ai', 'dsh-app-boot', 'package.json'))) return cand
  • 写入本地文件
    lib/heal.js:263
    mkdirSync(dirname(target), { recursive: true })
  • 写入本地文件
    lib/heal.js:264
    copyFileSync(file, target)
  • 写入本地文件
    lib/heal.js:297
    copyFileSync(matched.set.appPatched, appBoot)
  • 写入本地文件
    lib/heal.js:304
    copyFileSync(set.appPatched, appBoot)
  • 写入本地文件
    lib/heal.js:321
    copyFileSync(matched.set.pbPatched, pb)
  • 写入本地文件
    lib/heal.js:326
    copyFileSync(set.pbPatched, pb)
  • 执行外部命令来自配置/变量
    lib/heal.js:496
    execFileSync(process.execPath, ['--check', tmp], { stdio: 'pipe' })
  • 删除本地文件
    lib/heal.js:500
    try { unlinkSync(tmp) } catch { }
  • 读取本地文件
    lib/mount-core.js:35
    if (!existsSync(patchFile)) return null
  • 读取本地文件
    lib/mount-core.js:39
    writeFileSync(bak, readFileSync(patchFile, 'utf8'))
  • 写入本地文件
    lib/mount-core.js:39
    writeFileSync(bak, readFileSync(patchFile, 'utf8'))
  • 读取本地文件
    lib/mount-core.js:52
    const backups = readdirSync(profileDir).filter((f) => f.startsWith(prefix)).sort()
  • 删除本地文件
    lib/mount-core.js:55
    rmSync(join(profileDir, old), { force: true })
  • 读取本地文件
    lib/mount-core.js:215
    body = existsSync(patchFile) ? readFileSync(patchFile, 'utf8') : ''
  • 读取本地文件
    lib/mount-core.js:215
    body = existsSync(patchFile) ? readFileSync(patchFile, 'utf8') : ''
  • 写入本地文件
    lib/mount-core.js:240
    writeFileSync(patchFile, mergePatchBlock(body, block))
  • 读取本地文件
    lib/patch-ops.js:24
    if (!existsSync(file)) return { file, entries: [] }
  • 读取本地文件
    lib/patch-ops.js:27
    lines = readFileSync(file, 'utf8').split('\n')
  • 读取本地文件
    lib/patch-ops.js:77
    const lines = readFileSync(file, 'utf8').split('\n')
  • 写入本地文件
    lib/patch-ops.js:94
    writeFileSync(file, kept.join('\n').replace(/ {3,}/g, '\n\n').trimEnd() + '\n')
  • 读取本地文件
    lib/patch-ops.js:104
    body = existsSync(file) ? readFileSync(file, 'utf8') : ''
  • 读取本地文件
    lib/patch-ops.js:104
    body = existsSync(file) ? readFileSync(file, 'utf8') : ''
  • 写入本地文件
    lib/patch-ops.js:119
    writeFileSync(file, mergePatchBlock(body, block))
  • 读取本地文件
    lib/patch-ops.js:143
    const lines = readFileSync(file, 'utf8').split('\n')
  • 写入本地文件
    lib/patch-ops.js:158
    writeFileSync(file, lines.join('\n').replace(/ {3,}/g, '\n\n').trimEnd() + '\n')
  • 发起网络请求
    lib/client.js:74
    const res = await fetch("/api/fail-soft/status");
  • 发起网络请求
    lib/client.js:88
    const result = await (await fetch("/api/fail-soft/set-enabled", {
  • 读取本地文件
    scripts/failsoft-web.mjs:125
    if (!existsSync(join(profileDir(), 'package.json'))) {
  • 执行外部命令来自配置/变量
    scripts/failsoft-web.mjs:142
    const child = spawn(cmd, cmdArgs, { stdio: ['inherit', 'inherit', 'pipe'] })
  • 读取本地文件
    lib/context-utils.js:48
    const data = JSON.parse(readFileSync(failSoftSwitchFile(), 'utf8'))
  • 写入本地文件
    lib/context-utils.js:60
    writeFileSync(file, JSON.stringify({ enabled: !!enabled }, null, 2) + '\n')
  • 读取本地文件
    lib/context-utils.js:82
    existing = JSON.parse(readFileSync(file, 'utf8'))
  • 写入本地文件
    lib/context-utils.js:89
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    lib/context-utils.js:90
    writeFileSync(file, JSON.stringify({ enabled: true }, null, 2) + '\n')
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-app-boot@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 自动隔离坏插件
  • 服务照常启动
  • 一键恢复

⛔ 已停止更新(2026-09-12):坏插件隔离等保底能力已内置于 DSH Desktop → 请直接使用 https://github.com/dataelement/dsh-desktop

README

由 DeepSeek 最新模型翻译生成
@lanbaolu/dsh-fail-soft ⛔ 本项目已停止更新与维护(2026-09-12) 本插件提供的全部保底能力(坏插件自动隔离、安全模式启动、插件故障恢复/一键修复)已内置于 DeepSeek Harness 官方桌面版 DSH Desktop (v0.8.1 起的「更清晰的插件故障恢复」/安全模式隔离)。 请直接下载使用 DSH Desktop:https://github.com/dataelement/dsh-desktop,无需再安装本插件或内核补丁。 相应处置: - GitHub Releases 全部移除(下载渠道已关闭); - npm 包 @lanbaolu/dsh-fail-soft 已停止发布新版本,已安装用户请卸载并改用 DSH Desktop; - 本仓库已归档(read-only),以下文档仅作历史参考,安装命令均已失效。 插件错误自动隔离:坏插件被禁用、其余插件照常启动,提供隔离管理与恢复 UI。 解决的问题 DSH 的插件装配是 fail-loud:bundle 里任何一个插件加载/激活失败,整个 dsh web 服务就起不来(进程退出,GUI 打不开)。装一个坏插件 = 服务瘫痪, 且报错是一长串内部堆栈。
展开完整文档(README 剩余 1 节)
@lanbaolu/dsh-fail-soft

⛔ 本项目已停止更新与维护(2026-09-12)

本插件提供的全部保底能力(坏插件自动隔离、安全模式启动、插件故障恢复/一键修复)已内置于 DeepSeek Harness 官方桌面版 DSH Desktop (v0.8.1 起的「更清晰的插件故障恢复」/安全模式隔离)。
请直接下载使用 DSH Desktop:https://github.com/dataelement/dsh-desktop,无需再安装本插件或内核补丁。

相应处置:
- GitHub Releases 全部移除(下载渠道已关闭);
- npm 包 @lanbaolu/dsh-fail-soft 已停止发布新版本,已安装用户请卸载并改用 DSH Desktop;
- 本仓库已归档(read-only),以下文档仅作历史参考,安装命令均已失效。

插件错误自动隔离:坏插件被禁用、其余插件照常启动,提供隔离管理与恢复 UI。

解决的问题

DSH 的插件装配是 fail-loud:bundle 里任何一个插件加载/激活失败,整个
dsh web 服务就起不来(进程退出,GUI 打不开)。装一个坏插件 = 服务瘫痪,
且报错是一长串内部堆栈。

本插件让服务在坏插件面前照常启动:坏插件被自动隔离(写 disabled patch),其余插件正常装配;隔离列表可查、可一键恢复(工具 + UI 面板)。

组成

| 部分 | 文件 | 作用 |
| 挂载兜底 | lib/mount.js | 被 DSH 内核(DSH_FAIL_SOFT=1 时)在 include 树挂载前动态加载:坏插件 → 隔离 → 剔除重试 |
| 运行期服务 | lib/index.js | failSoft 服务 + fail_soft_ 工具 + /api/fail-soft/ HTTP API |
| 上下文工具 | lib/context-utils.js | profileDirOf / 持久化开关读写(零 DSH 依赖) |
| UI 面板 | lib/client.js | 设置面板「Fail-soft 隔离」区域:状态 + 一键开关 |
| 第 2 层进程兜底 | scripts/failsoft-web.mjs(bin:dsh-failsoft-web) | 进程外启动包装器:内核补丁失效/未装配时仍能自己解析崩溃、自己写隔离、退避重拉 |

前置条件(一次性)

内核需要"fail-soft 委托插槽"补丁(极小,只做发现与委托,逻辑全在本插件)。

- npm 安装用户(0.0.9+):不需要手动打补丁。npm 包自带 backup/ 补丁模板,插件每次启动时 heal 会自动检测;若内核是官方原版会自动打上补丁,首次安装后请重启一次 dsh 让挂载兜底生效。
- 本地开发:也可用 node patch-apply.mjs(见工作目录 防止插件错误挂不起服务/, sha256 校验,DSH 更新后重打)。

不装内核补丁时:本插件的运行期服务/UI 仍可用(查隔离、手动隔离、恢复),但挂载期自动隔离不生效(崩溃发生在任何插件加载之前,纯插件无法拦截)。

跟随 DSH 官方更新(内核补丁自愈)

DSH 官方升级 = npx 重新拉包到新的 ~/.npm/_npx// 目录,内核补丁会被覆盖丢失。本插件每次启动时自动运行 内核补丁自愈(lib/heal.js):

- 动态定位实际运行的 DSH 安装(不硬编码 npx hash:从当前进程 argv 推断; 0.1.17 起支持 Desktop App——dsh 内核跑在 Electron 主进程、argv 无内核路径时改从 process.resourcesPath → app.asar.unpacked 定位);
- 检测补丁状态:ok(已打)/ needs-apply(丢失,npx 重装同版本)/ needs-adaptation(官方改了代码结构);
- 自动重打:仅当目标与"已知原始版"一致时安全重打(含 profile-boot-.js 文件名 hash 变化的情况);
- 官方改动结构时报告 needs-adaptation 并提示更新 backup/ 模板,绝不破坏新版代码。

补丁健康状态可通过 fail_soft_status 工具、/api/fail-soft/status(patch 字段)、 UI 面板(🧩 行)查看。命令行重打:node patch-apply.mjs(与插件共用同一套 heal 逻辑)。

版本适配:当官方大幅重构挂载链路、自愈报告 needs-adaptation 时,需要更新 backup/ 里的 orig/patched 模板(抓官方新版 → 重打 → 存模板),通常一个版本一次。

安装(装入 profile)

⚠️ 命名必须与包名完全一致:本插件的包名是 @lanbaolu/dsh-fail-soft(带 scope)。
profile 的 dependencies key、bundles 条目、node_modules 链接、以及 cordis.patch.yml 的 insert name 必须全部使用这个完整包名。
不要因为仓库/目录名是 dsh-fail-soft 或 tgz 文件名是 lanbaolu-dsh-fail-soft-.tgz 就注册成裸名 dsh-fail-soft ——那样 DSH 会按 @lanbaolu/dsh-fail-soft 找模块而找不到,启动直接 ERR_MODULE_NOT_FOUND 崩溃(2026-08-19 事故根因)。

推荐使用 DSH 官方安装(自动按包名注册):
dsh plugin --profile web add @lanbaolu/dsh-fail-soft@0.1.17

⚠️ 请带上版本号:pnpm 11 有供应链冷却期(minimumReleaseAge)与元数据缓存,刚发布的版本用不带版本号的 add 可能解析到旧版;显式 @版本号 一定拿到指定版本(本行版本号随每次发布同步,见下方当前状态)。

手动装(务必保留完整包名,以 web profile 为例) ~/.dsh/profiles/web/package.json:
"dependencies": { "@lanbaolu/dsh-fail-soft": "link:" }
"dsh": { "profile": { "bundles": [ ..., "@lanbaolu/dsh-fail-soft" ] } }
2. 建 junction:node_modules/@lanbaolu/dsh-fail-soft → 本目录
3. 构建时已 link 运行时依赖(@deepseek-ai/dsh-app-boot、@deepseek-ai/dsh-tools 进本插件的 node_modules),无需额外安装。

启用 fail-soft

方式一:持久化开关(推荐,终端 / App 通用)

插件 0.0.8+ 提供持久化开关,App 启动(不加载 shell 环境变量)也能用:内核补丁启动时读取 ~/.dsh/fail-soft.json,无需手动设置任何环境变量。

0.1.14 起首次安装自动启用:开关文件不存在时,插件激活即写入 enabled: true(装防崩溃插件本身即启用同意),下次重启生效;已存在的开关文件一律尊重(含显式 false)。装完后无需任何手动开启步骤。

⚠️ 唯一例外:若安装时服务已经因坏插件起不来,插件没有机会激活写开关——先用环境变量进一次安全模式,隔离坏插件后即恢复:
DSH_FAIL_SOFT=1 npx @deepseek-ai/dsh web(App 用户可手动创建
~/.dsh/fail-soft.json,内容 {"enabled": true})。

- UI(0.0.10+):DSH 设置面板 → 「Fail-soft 隔离」区域,一键开关(0.1.15 起面板注册改走官方 slots.inject 契约:设置 slot 声明未就位时等待而非报错——修复部分安装上“装完即 slot 'settings.section' is not declared”崩溃的反馈;即便注册失败也只降级为无面板,核心隔离能力照常);
- 工具:fail_soft_set_enabled(true) / fail_soft_set_enabled(false)
- API:POST /api/fail-soft/set-enabled,body { "enabled": true }
- 效果:写入 ~/.dsh/fail-soft.json,重启 dsh 后生效; fail_soft_status 的 switchEnabled / enabled 字段反映当前开关状态。

方式二:环境变量(原有)

DSH_FAIL_SOFT=1 npx @deepseek-ai/dsh web # 临时
echo 'export DSH_FAIL_SOFT=1' >> ~/.zshrc # 永久(仅终端启动生效)

DSH_FAIL_SOFT 取值:1|true|yes|on。可用 DSH_FAIL_SOFT_MODULE 覆盖内核加载的挂载模块(默认按包名解析本插件)。环境变量与持久化开关二者任一开启即生效。

使用

- 自动隔离:坏插件激活失败 → 诊断打印 + 写
- id: \n disabled: true(带 # quarantined by @lanbaolu/dsh-fail-soft 注释)到 profile 的 cordis.patch.yml → 剔除重试挂载 → 服务照常起。
写入经 mergePatchBlock 合并(0.1.2 起):patch 是空数组 [](DSH 默认无补丁形态)时用条目块替换而非追加,产出始终是单个合法 YAML 数组——隔离器自己不会再写坏 patch。
0.1.14 起分类隔离:只隔离“真坏插件”。瞬态环境错误(EADDRINUSE 端口被占等)与官方核心组件(@deepseek-ai/)失败不写持久隔离,改为抛回原始错误 fail-loud——避免把端口冲突误判成坏插件、把官方 webserver 永久隔离导致“服务活着但 GUI 消失”。
- 工具(模型可直接调用):fail_soft_status / fail_soft_list / fail_soft_restore / fail_soft_quarantine / fail_soft_repair。
- HTTP API:GET /api/fail-soft/status、GET /api/fail-soft/list、 POST /api/fail-soft/restore {id}、POST /api/fail-soft/quarantine {id,name,reason}、 POST /api/fail-soft/repair。
- 修复引擎(0.1.8+):fail_soft_repair 一键修复——补丁丢失自动重打;官方改结构自动回滚到官方原版(挂载兜底不生效但服务能起)并给适配指引;同时去重 profile patch 里重复的 entry id(集成 dsh-fix / dev_fix_patch 能力)。
- UI 面板:web 会话侧栏 conversation.view 显示隔离列表与恢复按钮。
- 恢复:修复插件后删除 patch 文件里对应条目(或用 restore 工具/UI)。

第 2 层:进程级兜底(v0.1.16+)

场景:内核补丁被官方大改回滚、或 fail-soft 插件自身没起来(Desktop App 内嵌内核不在 heal 扫描范围)时,挂载兜底(第 1 层)兜不住。第 2 层把兜底搬到进程外:外层进程与一切插件解耦,捕获 dsh 崩溃输出 → 解析坏插件 → 自己写隔离 → 带退避重拉。不依赖内核补丁,也不依赖插件被装配。

拉起 dsh web(进程外兜底,退出码透传) dsh-failsoft-web 透传参数给 dsh web / 指定 profile / 指定 dsh 入口 dsh-failsoft-web -- --port 3080 dsh-failsoft-web --dsh /Applications/DSH\ Desktop.app/.../dsh/lib/bin.js
DSH_PROFILE=desktop dsh-failsoft-web --dsh # 桌面场景
调参 dsh-failsoft-web --max-restarts 3 --backoff-ms 2000

行为:dsh 正常退出(0) 透传退出;崩溃 + 解析出可隔离插件 → 写 disabled patch 后自动重拉;崩溃 + 无可隔离对象 → 跑 doctor 诊断,最多再给一次机会。

已知边界

- 只兜"插件加载/激活失败"。profile 的 cordis.patch.yml 用户手写坏(YAML 语法错):fail-soft 下会给出诊断并自动从写前备份恢复(0.1.6 起,写前备份 .bak. + 解析失败自动恢复);非 fail-soft 仍 fail-loud,但会提示如何恢复。本插件自己的隔离写入由 mergePatchBlock 保证合法(0.1.2 起,空数组 [] 替换而非追加)。
- 每轮最多隔离一批失败插件并重试,5 轮后放弃(服务以降级树启动,不崩)。
- 挂载期自动隔离需要内核补丁 + DSH_FAIL_SOFT=1(崩溃在插件加载前)。
- 运行期工具/API 采用延迟注册:bundle 装配可能早于 tools/webServer 服务就绪,插件会监听服务注册事件自动补注册;因此重启后 fail_soft_ 工具和 /api/fail-soft/* 会随服务就绪自动出现,不需要手动热重载。

开发者

构建 / 发布(TP 自动上传 + preflight 门禁)/ 回归测试等维护流程见 RELEASE.md。
预览分享卡片长什么样 ↓lanbaolu/dsh-fail-soft
分享 · DeepSeek Harness Hub
lanbaolu/dsh-fail-soft

自动隔离坏插件,让服务照常启动并可一键恢复

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部