自动重试可挽回的请求失败,并为旧插件搭建兼容环境
32.2/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add LuoLingP/request-doctor该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · other
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 6 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 72 处,展示前 61 条)
- 发起网络请求client.js:57
const response = await fetch(path, init) - 读取本地文件lib/compat-repair.js:23
return readFileSync(path, 'utf8'); - 读取本地文件lib/install-support.js:29
return existsSync(join(absolute, 'package.json')) ? { kind: 'local', dir: absolute } : { kind: 'remote' }; - 读取本地文件lib/install-support.js:118
if (existsSync(join(dir, STAGING_DIR))) rmSync(join(dir, STAGING_DIR), { recursive: true, force: true }); - 删除本地文件递归lib/install-support.js:118
if (existsSync(join(dir, STAGING_DIR))) rmSync(join(dir, STAGING_DIR), { recursive: true, force: true }); - 写入本地文件lib/install-support.js:139
writeFileSync( - 写入本地文件lib/install-support.js:166
writeFileSync( - 删除本地文件lib/install-support.js:181
rmSync(join(dir, STAGING_DIR), { force: true }); - 读取本地文件lib/install-support.js:190
if (!existsSync(staging)) return false; - 删除本地文件lib/install-support.js:195
rmSync(staging, { force: true }); - 读取本地文件lib/install-support.js:205
return existsSync(join(dir, STAGING_DIR)); - 删除本地文件递归lib/install-bundle.js:62
rmSync(target, { recursive: true, force: true }); - 删除本地文件递归lib/install-bundle.js:69
rmSync(target, { recursive: true, force: true }); - 删除本地文件递归lib/install-bundle.js:103
rmSync(target, { recursive: true, force: true }); - 读取本地文件lib/install-bundle.js:166
if (existsSync(join(destination, 'package.json'))) continue; - 写入本地文件lib/install-bundle.js:194
writeFileSync(path, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8'); - 读取本地文件lib/install-rescue.js:100
return readFileSync(join(profileDir, 'node_modules', ...name.split('/'), 'package.json'), 'utf8') !== ''; - 读取本地文件lib/install-rescue.js:123
manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); - 写入本地文件lib/diagnostics.js:37
writeFileSync(input.statusFile, `${JSON.stringify(snapshot(), null, 2)}\n`, 'utf8'); - 读取本地文件lib/runtime-probe.js:18
if (existsSync(join(candidate, 'package.json'))) return candidate; - 读取本地文件lib/runtime-probe.js:111
if (candidate.includes('app.asar') || existsSync(join(candidate, 'package.json'))) return candidate; - 读取本地文件lib/runtime-probe.js:145
if (candidate.includes('app.asar') || existsSync(candidate)) return candidate; - 读取本地文件lib/version-repair.js:263
manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); - 读取本地文件lib/version-repair.js:281
const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')); - 读取本地文件lib/compat-env.js:32
const value = JSON.parse(readFileSync(path, 'utf8')); - 读取本地文件lib/compat-env.js:50
if (typeof fromRuntime === 'string' && (fromRuntime.includes('app.asar') || existsSync(join(fromRuntime, 'package.json')))) { - 读取本地文件lib/compat-env.js:54
return existsSync(join(candidate, 'package.json')) ? candidate : undefined; - 写入本地文件lib/compat-env.js:68
mkdirSync(input.shimDir, { recursive: true }); - 读取本地文件lib/compat-env.js:71
const realSource = readFileSync(input.realEntry, 'utf8'); - 读取本地文件lib/compat-env.js:76
const hasDefault = parseExportedNames(input.realEntry, (file) => readFileSync(file, 'utf8'))?.includes('default') - 读取本地文件lib/compat-env.js:111
if (readFileSync(path, 'utf8') === content) return false; - 写入本地文件lib/compat-env.js:115
writeFileSync(path, content, 'utf8'); - 删除本地文件递归lib/compat-env.js:159
rmSync(shimDir, { recursive: true, force: true }); - 删除本地文件递归lib/compat-env.js:184
rmSync(destination, { recursive: true, force: true }); - 写入本地文件lib/compat-env.js:193
writeFileSync( - 删除本地文件递归lib/compat-env.js:324
rmSync(join(root, ...stale.split('/')), { recursive: true, force: true }); - 删除本地文件递归lib/compat-env.js:341
rmSync(join(root, ...name.split('/')), { recursive: true, force: true }); - 删除本地文件lib/compat-env.js:350
rmSync(marker, { force: true }); - 删除本地文件lib/compat-env.js:363
if (readdirSync(dir).length === 0) rmdirSync(dir); - 写入本地文件lib/compat-env.js:451
if (!existsSync(backupPath)) copyFileSync(manifestPath, backupPath); - 写入本地文件lib/compat-env.js:462
writeFileSync(temporary, content, 'utf8'); - 写入本地文件lib/compat-env.js:463
renameSync(temporary, path); - 发起网络请求lib/package-fetch.js:23
const response = await fetch(`${REGISTRY}/${encodedName(name)}`, { signal: AbortSignal.timeout(TIMEOUT_MS) }); - 写入本地文件lib/package-fetch.js:139
mkdirSync(dirname(target), { recursive: true }); - 写入本地文件lib/package-fetch.js:140
writeFileSync(target, data); - 发起网络请求lib/package-fetch.js:171
const response = await fetch(url, { signal: AbortSignal.timeout(TIMEOUT_MS) }); - 写入本地文件lib/package-fetch.js:175
mkdirSync(destDir, { recursive: true }); - 读取本地文件lib/stat-cache.js:23
const stat = statSync(path); - 读取本地文件lib/stat-cache.js:45
const manifest = JSON.parse(readFileSync(path, 'utf8')); - 读取本地文件lib/env-verify.js:20
const stat = statSync(path); - 读取本地文件lib/env-verify.js:43
return readFileSync(path, 'utf8'); - 读取本地文件lib/env-verify.js:90
const shimNames = parseExportedNames(shimPath, (source) => readFileSync(source, 'utf8')) ?? []; - 读取本地文件lib/env-verify.js:99
const names = parseExportedNames(path, (file) => readFileSync(file, 'utf8')); - 写入本地文件lib/cache-store.js:12
utimesSync(dir, now, now); - 读取本地文件lib/cache-store.js:25
return statSync(dir).mtimeMs; - 读取本地文件lib/cache-store.js:40
entries = readdirSync(base, { withFileTypes: true }); - 读取本地文件lib/cache-store.js:56
inner = readdirSync(path, { withFileTypes: true }); - 删除本地文件递归lib/cache-store.js:70
rmSync(item.path, { recursive: true, force: true }); - 读取本地文件lib/plugin-discovery.js:97
if (!existsSync(join(nested, ...name.split('/'), 'package.json'))) return false; - 读取本地文件lib/plugin-discovery.js:107
entries = readdirSync(root, { withFileTypes: true }); - 读取本地文件lib/plugin-discovery.js:118
scoped = readdirSync(join(root, entry.name), { withFileTypes: true });
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
一个 DSH 插件:自动修好客户端这边造成的请求失败,并为老版本插件提供兼容
README
由 DeepSeek 最新模型翻译生成dsh-request-doctor · 请求急救员
DSH 插件:自动修好客户端这边造成的请求失败,并让版本对不上的插件能装上、能跑。
它解决什么问题
请求莫名失败
网络抖一下、服务端超时、模型返回空、上下文太长——这些都不是你操作的问题,但默认会让一次对话直接断掉。
插件判断这属于「本机这边能挽回」的失败后自动重试,间隔逐次拉长,不会把对方打得更糟。
不重试:欠费、限流、服务端故障、内容审核拦截、图片超限。这些重试没有意义。
不重放:会改动东西的操作(执行命令、写文件、发消息)。只重放只读的(读文件、搜索、抓网页、看页面)。
版本对不上的插件
DSH 升级后,旧插件可能只认 0.2.1-rc.2,而你现在是 0.2.1-rc.3。默认结果是插件用不了,甚至装不上。
插件不会去关掉这个检查,而是给那个插件搭一个它期望的旧环境,跟 Windows 的「以兼容模式运行」是一个意思——不是忽略问题,是提供它需要的环境。
分两种情况:
当前实现还够用:在插件目录里放一层很薄的转发包,声明旧版本号,调用转到当前实现。不复制代码,开销极小。
当前实现缺了插件要的东西:把插件当初对着写的那份真实旧版本从仓库取回来装进去。跑的是它认识的那份代码,不是一个缺胳膊少腿的替身。
展开完整文档(README 剩余 1 节)
dsh-request-doctor · 请求急救员 DSH 插件:自动修好客户端这边造成的请求失败,并让版本对不上的插件能装上、能跑。 它解决什么问题 请求莫名失败 网络抖一下、服务端超时、模型返回空、上下文太长——这些都不是你操作的问题,但默认会让一次对话直接断掉。 插件判断这属于「本机这边能挽回」的失败后自动重试,间隔逐次拉长,不会把对方打得更糟。 不重试:欠费、限流、服务端故障、内容审核拦截、图片超限。这些重试没有意义。 不重放:会改动东西的操作(执行命令、写文件、发消息)。只重放只读的(读文件、搜索、抓网页、看页面)。 版本对不上的插件 DSH 升级后,旧插件可能只认 0.2.1-rc.2,而你现在是 0.2.1-rc.3。默认结果是插件用不了,甚至装不上。 插件不会去关掉这个检查,而是给那个插件搭一个它期望的旧环境,跟 Windows 的「以兼容模式运行」是一个意思——不是忽略问题,是提供它需要的环境。 分两种情况: 当前实现还够用:在插件目录里放一层很薄的转发包,声明旧版本号,调用转到当前实现。不复制代码,开销极小。 当前实现缺了插件要的东西:把插件当初对着写的那份真实旧版本从仓库取回来装进去。跑的是它认识的那份代码,不是一个缺胳膊少腿的替身。 取回的版本缓存在 profile 下的 .request-doctor-cache/,同一个版本只下载一次。 旧版本里也没有:如实报告不兼容。不伪造、不放占位——放一个「调用时才报错」的假货,只是把崩溃推迟到运行期,那是骗自己。 装不上的插件 分两种情况,命令只有一个: /doctor install <插件目录,或者包名> 本地目录:先把环境备好,再正常安装,管理器的版本检查就会按它自己的规则通过。 注册表里的包(dsh-ssh-ops、@scope/name@1.2.3 这类):管理器的安装路径是「pnpm 装完再检查」。远程包的字节在检查之前就落地了,没法提前改好 manifest,所以它对不兼容的包永远装不上。 这种情况由插件自己把 pnpm 该做的事做一遍:取包、取依赖、对齐声明、建兼容环境、登记为 bundle、重载。装完会打印位置、环境状态、依赖和重载结果。 覆盖范围 扫描的是所有不兼容的插件,不是一个。来源包括:Loader 拒绝的包、已启用但没被拒绝的、已禁用但装着的、安装时环境还欠着的,以及加载失败后不在插件清单里、只能靠扫目录发现的。 建完会核对,不是建完就算 环境建好之后,会逐条确认插件要的每个符号是否真能拿到,再决定算不算修好。 这一条是必要的:垫片少写一个导出,插件在加载那一刻就会崩,而修复流程会以为一切正常。核对通不过就记为未修复,不谎报成功。 检查脚本也接上了核对:垫片存在但内容不对的插件会被重新适配,不会当作已经修好放着。 路由冲突只报告 两个插件可能声明同一个 LLM provider id。插件会提示你,但不会替你停用任何一个——那是你的插件,由你决定。 运行开销 稳态下几乎不耗资源。 - 源码和 manifest 按文件签名缓存,没变就不重解析 - 后台扫描健康时逐步退避到 30 分钟一次 - 内容没变就不写盘,不触发文件监听 - 长会话里那些记账用的结构都有上限 - 定时器全部 unref,不拖住进程退出 安装 仓库根目录就是包本身:没有构建步骤,没有运行时依赖,npm pack 出来 33 个文件,装进去就能用。 从可视化界面安装 打开「插件」页,选安装,填本仓库地址或本地目录。装完立即生效,不用重启。 仓库里带 dsh.bundle.patch,DSH 会据此把插件挂进组合;版本检查对得上,不会出现在「不兼容」列表里。 用命令安装 /doctor install <仓库本地路径或包名> 本地目录和注册表里的包都走这一条。 手动放进 profile 1. 把本仓库内容复制到 <profile>/node_modules/dsh-request-doctor/ 2. 在 <profile>/package.json 的 dependencies 里加上 "dsh-request-doctor": "link:<本目录>" 3. 在 <profile>/cordis.patch.yml 里插入: - insert: - id: request-doctor name: 'dsh-request-doctor' 1. 重启 DSH 装完自检 /doctor 会打印已修复的数量、最近几次修复的记录,以及最近一轮版本审计的结论。任何一项为 0 都正常——没坏东西可修的时候它不动作。 配置 都放在 cordis.patch.yml 的 config 下,全部可选。 | 配置项 | 类型 | 默认 | 说明 | | autoRepair | boolean | true | 总开关 | | autoVersionRepair | boolean | true | 是否自动处理版本不匹配 | | maxRetries | number | 12 | 单步模型请求最多修几次 | | maxToolRetries | number | 2 | 单次工具调用最多重放几次 | | maxVersionRepairs | number | 64 | 单轮扫描最多适配几个插件,0 表示不限 | | maxAuthRetries | number | 2 | 鉴权类失败最多重试几次,额度单独且更小 | | maxRepeatedToolCalls | number | 3 | 同名同参调用超过几次后不再重放 | | initialDelayMs | number | 400 | 首次退避基准 | | maxDelayMs | number | 20000 | 退避上限 | | jitterRatio | number | 0.25 | 退避抖动比例 | | retryableToolPattern | string | 见下 | 允许重放的工具名正则 | | recordRetryEvents | boolean | true | 是否写入会话重试记录 | 默认只读工具白名单: ^(read|read_image|glob|grep|web_fetch|web_search|cordis_inspect_.*|browser_(list_tabs|snapshot|get_text|wait|scroll)|db_(query|preview|describe_table|list_tables))$ 使用 /doctor 查看各类修复计数和最近发生的事。 /doctor install <目录路径或包名> 本地插件先备好环境,再让你正常安装;注册表里的包则直接装上。已经装着的包会就地修复,不会重装一遍。 /doctor allow <包名@版本> 只授权、不安装。给那些想继续在插件面板里点安装的人用:先放行这个版本,再在界面上装,装完声明对齐和兼容环境会自动补上。 插件面板里的「不兼容安装」 打开「插件」,标签栏里会多一个「不兼容安装」。里面列出当前被 DSH 版本检查拒掉的插件,每行一个按钮;顶上还有一个输入框,可以直接填 包名@版本。 点按钮做的事和 /doctor install 一样:先按管理器的规则授权这个版本,再让它自己装,装完声明对齐和兼容环境由后台扫描补上。点完不会立刻变绿,等几秒。 界面是随插件一起加的客户端模块。新装的插件要先刷新一次页面,浏览器才会加载它——插件热替换只覆盖已经载入过的客户端模块。 页面渲染出错时不会留一片空白,而是把那句错显示出来。看到「这个页面渲染出错」就是那条信息本身在告诉你原因。 还原 被适配过的插件目录里有 package.json.request-doctor-original,是改动前的备份。 要恢复原状:删掉插件目录下的 node_modules(如果只有本插件为它建过),用备份覆盖 package.json,再删掉 .request-doctor-compat.json。 兼容环境只包含标记里记下的那些包,删除时也只删那些——插件自带的依赖不会被误删。 已知边界 - 兼容环境只能保证「插件要用的东西还在」。插件内部若有别的假设已经变了,仍可能表现异常,需要作者更新。 - 第三方依赖不在检查范围,那是插件自己的事。 License MIT
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
LuoLingP/request-doctor
自动重试可挽回的请求失败,并为旧插件搭建兼容环境
相关插件 · 其他
模型破甲清洗YuJunZhiXue/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,148已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,266已汉化DSH
70.7
这是你的仓库?认领条目