dsh-concurrency-guard
Concurrency guard and monitor for DeepSeek Harness: FIFO queue when concurrent model requests reach the limit, per-day persisted stats with error-kind classification, and interruption detection for abandoned streams.
Install
dsh plugin --profile web add dsh-concurrency-guard
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-concurrency-guard

DSH(DeepSeek Harness)并发请求监控与门闩插件。已发布 npm:npm i dsh-concurrency-guard。
挂钩 DSH 唯一的模型请求总线 llm/stream 瀑布,统计全部在途模型请求(主会话、
进程内子代理、workflow 派生代理、会话标题、压缩、以及任何调用 ctx.llm.stream 的
插件),并在并发到达上限后对后续请求 FIFO 排队——**从根上防止并发超限被供应商/
中继锁号**(如 429 / 风控封禁)。
自带 WebUI 实时面板(会话视图「并发监控」页签)、HTTP JSON 端点、落盘状态文件
与 concurrency_status 工具。
效果预览
⚠️ v1.5.4 起面板 UI 已全面重构(废弃原 6 页签,改为「盯盘区 + 视图区」一屏看全布局)。
下方截图仍为重构前版本,尚未更新——请以实际界面为准。截图待补。
会话视图「并发监控」页签(v1.5.4 新布局):顶栏状态 → 指标条(7 项)→ 并发水位 + 在途请求表 → 视图区(会话并发 / 会话活跃 / 异常 / 历史)。
首屏即可看全盯盘信息,无需滚动(实测三件套 + 导航合计 173px,滚动容器 334px;重构前为 2148px 需滚 3 屏以上)。
特性
- 🔎 口径完整:挂在
llm/stream瀑布(所有模型调用的唯一入口),不存在旁路;
每条请求带 provider/model、sessionId、用途(对话/压缩/标题),可精确归属。
- 🏷️ 来源分类:在途/历史请求按来源标记——主会话 / 子代理 / 插件 / 压缩 / 标题
(agent loop 标记 + sessionId 形状判别,面板有「来源」列与分类概览)。
- 👥 会话活跃:按会话聚合在途/排队/最近开始/近 60s 完成数——模型请求间隙
(跑工具等)在途为 0 时,也能一眼看出"某个会话还在不在推进"(面板「会话活跃」表)。
- 🚦 FIFO 门闩:默认
mode=queue, maxConcurrency=5——并发满员后新请求排队,
并发永不超限;排队中被取消立即出队;排队超时 fail-open 强制放行(宁可
瞬时超限也不卡死请求)。
- 🎯 会话级并发控制(v1.5.0+):给在线活跃会话实时设置并发数——面板新页签
「会话并发」/ POST /api/concurrency-guard/sessions / ctx.concurrencyGuard.setSessionLimit()
/ 工具 concurrency_session_set 四通道热改,无需重启,随 state.json 持久化。
- 按顶层会话聚合:请求的 sessionId 经
header.parentSession父链解析归并到
根会话(rootId)——限「对话 A」= 主循环 + 其全部子代理 + 压缩/标题共用同一把
会话锁;子代理解析不到根时降级按原始 id 生效(面板标注)。
- 会话标识:每行显示「标题(session/title 事件)+ 短会话 id + 工作区目录」
三行标识(sessionQuery.readTitleSnapshots 后台刷新,缺失降级),一眼认出是哪个会话。
- 两道门:请求需同时通过 会话门(可选)→ 全局门,固定获取顺序无死锁;
会话满员时即使全局有空位也按该会话自己的 FIFO 队列排队。
cap=0= 暂停该会话(全部排队,排队超时仍 fail-open 兜底,不会永久卡死);
降低上限不打断在途请求,只影响后续准入;clear 清除后排队请求自动放行回全局门。
- 辅助请求(压缩/标题)默认豁免会话门(
sessionExemptAuxiliary,只过全局门),
避免书签性请求被会话限流拖死;monitor 模式与 sessionLimitsEnabled=false 时
会话门整体跳过(限额保留但惰性生效)。
- 🧹 历史自动清理:最近完成记录双保险——条数上限(
history,默认 30)+
时间 TTL(historyTtlMs,默认 1h,超龄自动清理);面板「🗑 清历史」一键清空。
- 📈 持久化统计:按天汇总(请求/完成/异常/中断/取消/门闩/fail-open)+ 异常分类聚合
(限流/超时/网络/中断/鉴权/上游/其他)+ 异常明细三报表(tab 切换 + 今日/全部范围):
① 分类汇总——按 分类×错误 分组(一眼看清"哪种错误最多",分类内按次数降序);② 汇总——按
会话×错误 分组(次数 + 最近出现,URL/时间戳差异自动归一化);③ 明细——每次错误一条
(按时间倒序、最新在前,最近 200 条滚动窗口);每条含错误码/HTTP status/供应商 requestId/Retry-After +
最近会话/模型/供应商与各会话出现次数;「今日」范围显示当天发生的异常(从逐条事件窗口按天过滤聚合),
「全部」显示全历史累计;随状态文件落盘,重启不丢——面板「今日统计」「每日历史」与「异常明细」跨进程连续累计。
异常识别覆盖 DSH 的失败语义:请求错误既可能是抛异常,也可能以
finish chunk(reason.kind=error)正常流出不抛异常——两者均计入异常(v1.3.3 修复,
异常明细聚类 v1.3.4、会话上下文 v1.3.5、协议内字段 v1.3.8、逐条事件明细 v1.3.9)。
- 🚨 回合中断检测:消费端提前弃流(流式输出被掐断在中间)、进程被杀/fiber 重建的
遗留在途、以及"长时间无输出"的僵死流——三路兜底统一记为中断(独立计数 + 面板
「中断」列 + 启动日志告警),不再把这类事故悄悄算进"完成"。
- 🖥️ WebUI 面板(v1.5.4 重构):一屏看全布局——顶栏状态 + 指标条(活跃/排队/已放行/取消/
fail-open/告警/中断)+ 并发水位与在途表 + 视图区(会话并发/会话活跃/异常/历史,按需切换);
可一键热切「排队节制 ⇄ 仅监控」、调整并发上限、暂停轮询、清空历史、重置统计。
重构要点:首屏无需滚动(实测盯盘三件套+导航 173px / 容器 334px,重构前 2148px);
字号收敛为 5 档、行高统一 29px、表格数字 tabular-nums 对齐;弹窗补齐
role="dialog"/aria-modal/焦点进入与归还/Escape 关闭;对比度 0 失败(最低 4.23:1)。
- ⚙️ 配置友好:面板内置配置面板(并发上限/告警阈值/排队超时/历史条数/TTL/停滞判死
直接数字编辑,保存即生效);接入 Settings → Plugins → Plugin configuration 可视化编辑;
配置持久化——运行时改的配置随 state.json 落盘,重启保留(v1.4.0 修复此前"重启丢配置")。
- 📦 零构建链、零依赖:纯 node 内建 + cordis API 实现,手写
__ModuleLoader__
client bundle,无需 npm install / tsdown / tsc;设置页经动态 import 接入
@deepseek-ai/dsh-settings(可选 peer,缺失时自动降级跳过,不影响其余功能)。
- 🛡️ fail-safe:监听器任何异常一律回退原链路;消费端弃流由周期清扫兜底释放并发位。
安装
DSH 的插件装在 profile 里:每个 profile 是一个独立的 npm 项目目录
(默认 ~/.dsh/profiles/<profile名>,本机示例 C:\Users\pc\.dsh\profiles\web),
装进哪个 profile,哪个 WebUI/会话就用上它。
方式 1:dsh 官方 CLI(推荐,已发布到官方源)
DSH 自带的插件管理命令(内部在 profile 目录跑 pnpm):
# ① 一条命令安装:自动写入 dependencies + 自动把本包加入 dsh.profile.bundles dsh plugin --profile web add dsh-concurrency-guard # 也支持 GitHub 地址 / 本地路径:dsh plugin --profile web add <GitHub地址> 等
(本包在 package.json 声明了 dsh.bundle.patch(cordis.patch.yml 装配补丁),
dsh plugin add 跑完后会自动把它挂进 dsh.profile.bundles,**无需手改
package.json**。)
# ② 重启 dsh 宿主 → 刷新 WebUI # 验证是否生效(三选一): # - 会话视图顶部出现「并发监控」页签 # - GET http://127.0.0.1:3080/api/concurrency-guard/status 返回 200 # - 宿主日志出现 [concurrency-guard] 已启动
# 卸载:dsh plugin --profile web remove dsh-concurrency-guard(同样自动清理 bundles),重启
ℹ️ DSH 的插件管理基于 pnpm(profile 用pnpm-lock.yaml)。请用dsh plugin
安装/卸载,不要在 profile 目录里直接 npm i(会混入 npm 锁文件状态)。
方式 2:git clone + dev_inject_plugin(本机开发 / 调试)
git clone https://github.com/fu827707013/dsh-concurrency-guard.git dev_inject_plugin <克隆目录> # 需本机装有 dsh-super-injector,热注入免重启 # 或:dsh plugin --profile web add <克隆目录>(CLI 也支持本地路径,见方式 1)
(注意:dev_reload_package 只对方式 2 的源码链接生效;CLI/pnpm 装的副本改代码后需
重装并重启。)
⚠️ 首次安装(含修改package.json的dsh.client/exports)后需重启 dsh 宿主
使 client 行生效(Node 进程级缓存 package 元数据),重启后刷新 WebUI 即出现
「并发监控」页签。宿主门闩/HTTP/工具注入后立即生效,无需重启。
使用
实时监控(四选一)
方式 · 用法
WebUI 面板 · 会话页顶部视图切换 →「并发监控」页签(1.5s 轮询,可暂停)
HTTP 端点 · GET http://127.0.0.1:3080/api/concurrency-guard/status(?full=1 带最近历史)
状态文件 · Get-Content $DSH_HOME\concurrency-guard\state.json(防抖 250ms)
工具 · 模型可直接调用 concurrency_status({"full": true} 带历史)
面板内/HTTP 热改
- 面板按钮:切换模式(排队节制/仅监控)、
🗑 清历史;「会话并发」页签每行
cap 输入 + 应用 / 暂停 / 恢复 / 清除限额;
{"mode":"monitor"}、{"maxConcurrency":8};
{"action":"clear"}(清空历史)或 {"action":"prune"}(按 TTL 清理);
{"action":"set","sessionId":"session-xxx","cap":2}(设置/覆
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::22,最后更新 2026-09-17