dsh-image-count-guard:网关图片张数超限时的会话恢复

前言

在 DSH 里切到视觉模型后,若会话历史里已经堆了很多截图或附件,请求有时会在上游网关处直接被拒:错误里常见「单请求最多 N 张图片」一类说明。适配器 dsh-llm-pi-ai 默认按 base64 体积(maxRequestImageBytes,常见默认 20 MiB)做预算,并不按张数限流,因此可能出现「总字节仍在预算内、但图片张数已超过网关硬上限」的情况。官方 dsh-compaction-image-offload 主要识别 IMAGE_OFFLOAD_REQUIRED,对这种 INVALID_REQUEST 类张数错误往往帮不上忙,会话会逐步卡死——再发「继续」也每步失败。

下面介绍社区插件 dsh-image-count-guard(维护者 MacilyDots,分类:工作流):在网关按图片张数拒绝请求时,把最旧的图片卸载为占位文本并重试,复用官方 image/offload 投影,尽量恢复已卡死的视觉模型会话。

这是什么

dsh-image-count-guard 是 DeepSeek Harness 的兜底型工作流插件(npm 包名 dsh-image-count-guard,当前资料中版本 0.1.0,MIT 许可证)。它挂在 agent/request-error 瀑布流上:当失败信息匹配「图片张数上限」类英文表述时,统计当前面上尚未 omitted 的图片出现次数,按模型请求顺序选出最旧的一批写入 image/offload 决策,并返回 { kind: 'retry' } 重试该步(不消耗 provider 的重试预算)。

与官方卸载插件的分工如下(资料原文表格):

情况 由谁处理
适配器因字节预算自行拒绝(IMAGE_OFFLOAD_REQUIRED) 官方 dsh-compaction-image-offload
上游网关因图片张数拒绝(如 INVALID_REQUEST 等) 本插件

两者写入同一类 image/offload 事件,语义与占位、回放、token 与 KV cache 行为与官方卸载一致;本插件不依赖官方 handler 的注册顺序,只要求 image/offload 投影已注册。

它要解决的具体问题

资料中以 OpenCode Go 为例:网关单请求硬上限为 20 张图片。而 dsh-llm-pi-ai 仅按 base64 字节预算时,可能出现:

  1. 会话历史里图片不断累积(资料实测一例:36 张,原始约 11.79 MiB,base64 约 15.72 MiB);
  2. 切换到视觉模型(如 opencode-go/deepseek-v4.1-flash)后,15.72 MiB 仍低于 20 MiB 默认预算,适配器认为可发送,将全部 36 张 inline 发出;
  3. 网关返回 400 INVALID_REQUEST:a request may include at most 20 images;
  4. 官方 image-offload 不识别该错误 → 步骤失败;
  5. 此后该会话每一步都会失败,会话完全卡死。

本插件则在匹配到张数限制文案后,卸载 max(1, total - (limit - safetyMargin)) 个最旧出现位置(total 为当前未 omitted 的图片出现次数),每次重试至少 omit 一处,因此恢复过程会终止:要么请求通过,要么无图可卸、原失败仍为终态(不会无限重试)。

错误文案匹配需同时包含 image 与数量短语,资料列举的模式包括:at most N images、maximum of N images、no more than N images、up to N images、too many images 等。

安装与启用

安装方式来自仓库 README:在插件源码目录下执行 PowerShell 安装脚本(脚本会手工改 profile 三处:dependencies、dsh.profile.bundles、pnpm-lock.yaml,并复制一份 node_modules 副本且不运行 pnpm install;修改前备份到 .backup\<timestamp>\,仅保留最近 5 份)。DSH 主目录取自 $env:DSH_HOME,否则为 ~\.dsh。

安装后必须重启 DSH。

# 在插件源码目录执行
pwsh -File .\install.ps1                 # 安装到 desktop profile(默认)
pwsh -File .\install.ps1 -Profile web    # 安装到指定 profile

卸载:

pwsh -File .\install.ps1 -Uninstall

说明:本插件以当前 DSH 进程权限运行;安装前请自行查看 GitHub 源码 与 LICENSE,确认符合你的环境与合规要求。DeepSeek Harness 生态强调「一切皆插件」;社区目录站点(如 SkillHub)与 DeepSeek / 幻方无官方从属关系,本文不以「官方应用商店」口吻描述安装来源。

安装结束时,install.ps1 会打印四项静态检查:deps / bundles / node_modules / lock。

可选配置

默认无需配置。若需覆盖,在 profile 的 cordis.patch.yml 中按 id 写入:

- id: image-count-guard
  config:
    defaultImageLimit: 20      # 错误文案未给出数字时假设的上限
    safetyMargin: 2            # 卸载后保留的余量,避免再加一张又失败
    maxOffloadPerRetry: 80     # 单次重试最多 omit 的图片出现次数

典型用法与验证

恢复已卡死的会话(联调验证)

  1. 安装插件并重启 DSH;
  2. 打开此前因图片张数超限而卡死的会话,发送「continue」;
  3. 插件生效时,会话应记录 image/offload 事件,下一步请求成功。

离线单元测试

在插件目录执行:

node --test test/guard.test.mjs

资料说明共 11 个用例,覆盖匹配、选择、收敛轮次上界、无副作用边界等。

可选装配检查

将插件挂到临时 profile 后运行 --dump-config,输出中应包含 # == dsh-image-count-guard 与 - id: image-count-guard,退出码 0。

诊断:会话内图片统计

PowerShell 示例(路径按你的 DSH 会话目录调整):

# 单会话:张数、已 omit 数、原始字节、base64 估计、平均图大小
node tools\session-image-report.mjs `
     "$env:USERPROFILE\.dsh\sessions\<workspace>\session-<id>\session.v4.jsonl.zstd"

# 扫描最近会话,按图片张数排序
node tools\session-image-report.mjs "$env:USERPROFILE\.dsh\sessions" --limit 20

资料中两例会话说明「仅字节预算无法对齐张数上限」:session-c312057f 为 36 张、base64 约 15.72 MiB(低于 20 MiB 默认预算仍会因 20 张上限被拒);session-b15b99cb 为 25 张、base64 仅约 1.52 MiB。这正是需要按张数处理、而非只靠 maxRequestImageBytes 的场景。

适用场景与注意

适合谁

  • 长期使用视觉模型、会话里截图/附件较多的 DSH 用户;
  • 上游网关对单请求图片张数有硬上限,而本地适配器仍按体积预算放行的情况;
  • 已安装或计划安装官方 dsh-compaction-image-offload(需其注册的 image/offload 投影);若官方插件被禁用、投影未注册,本插件在 append 失败时会捕获并将失败交回下游,无副作用。

已知限制(资料原文)

  • 卸载不可撤销:被 omit 的图片之后以占位文本呈现(含只读附件路径),与官方 image/offload 一致;若需再看图,需让模型再次调用 read_image。
  • 错误文案须为英文且同时含 image 与数量短语;新网关措辞出现时,需在 src/index.js 的 LIMIT_PATTERNS 中增补条目。
  • 修改 src/index.js 后须重新运行 install.ps1 同步 node_modules 副本,否则 DSH 仍加载旧代码。

链接

  • 社区目录页:https://www.skillhub.cn/plugins/MacilyDots/dsh-image-count-guard
  • 源码与说明:https://github.com/MacilyDots/dsh-image-count-guard

当网关因图片张数拒绝请求、官方字节卸载又无法识别错误码时,dsh-image-count-guard 用同一套 image/offload 语义卸最旧图片并重试,是工作流里专门补「张数上限」这一环的兜底插件;安装以 README 中的 install.ps1 为准,改配置走 cordis.patch.yml,联调与诊断可按上文命令复现。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye