dsh-surrogate-guard:在会话日志写入前中和 UTF-16 孤立代理

前言

在 DeepSeek Harness(DSH)里跑智能体时,工具结果会原样进入会话历史,并在后续每一轮随请求重发。若某次 read、grep 或命令输出在截断路径上把 emoji 从 UTF-16 代理对中间切开,日志里会留下一个合法的 JavaScript 字符串、却在 API 侧无法被正确解析的「落单代理」。表现往往是 serde_json: unexpected end of hex escape,对应 HTTP 400 INVALID_REQUEST;一旦写进会话,重试和重启都无法恢复,只能手工改会话文件。下面介绍社区插件 dsh-surrogate-guard(维护者 fengxiforcy,分类:工作流),它在内容进入会话日志之前,把这些孤立代理替换成 U+FFFD,避免会话被永久拖死。

这是什么

dsh-surrogate-guard 是 DSH 工作流类插件:在工具结果与用户消息写入会话之前,扫描并中和 UTF-16 孤立代理(高位 0xD800–0xDBFF 或低位 0xDC00–0xDFFF 单独出现、未组成合法代理对的情况)。源码与说明见 GitHub,目录页见 SkillHub。许可为 MIT;当前 package 版本为 0.1.4(以仓库 package.json 为准)。

它解决什么问题

工具结果在部分截断实现里会对行文本做固定长度截取(例如核心侧 truncateLine 使用裸 substring),可能从代理对中间切断,只保留半个字符。在 JS 里 JSON.stringify 仍会安静转义,但 DeepSeek API 解析会失败:

serde_json: unexpected end of hex escape at line 1 column NNNNN
→ 400 INVALID_REQUEST

官方 Harness 讨论里也有同类现象(如 deepseek-ai/deepseek-harness 的 #8846、#1449)。本插件做的是事后中和,不能从截断源头消除孤立代理;与针对「区域指示符对 / 国旗 emoji」、报错多为 Content Exists Risk 的 dsh-text-guard 靶子不同——两种症状都可能让会话永久 400,需要按病因分别安装。

核心功能

插件通过 Cordis patch 挂在若干入口上,对经过的字符串做扫描:发现孤立代理则替换为配置的替换符(默认 U+FFFD),合法代理对与普通文本不动;无命中时返回原引用,不额外分配。

默认配置项如下(写入 profile 插件配置即可调整):

- id: surrogate-guard
  config:
    replacement: '?'      # 默认 U+FFFD
    toolResults: true     # tools/post-execute + tools/ptc-dispatch-log
    userMessages: true    # agent/pre-step
    log: true             # 只记数量,不记内容

tools/post-execute 侧会按 value → content → meta → data → output → result → lines 的顺序找第一处命中并只改一处,以满足 accept 决策不能同时替换 value 与 content 的合约;read 工具行文本在 data.meta.lines[].text 等字段也会被覆盖到(0.1.1 起修复 read 路径漏扫,0.1.4 修复同时改 value/content 的回归)。

已知限制(README 原文):

  • 经由系统提示段落的文本不经过这些入口。
  • 改写有损,但只影响残字本身。
  • 无命中时零额外分配。

安装与启用

插件以当前 DSH 进程权限运行;安装前请自行查看仓库源码与 MIT 许可证。Node 引擎要求为 ^22.19 || >=24。

安装命令以 README 为准:

dsh plugin --profile <profile> add github:<your-github>/dsh-surrogate-guard
# 或发到 npm 后:dsh plugin --profile <profile> add dsh-surrogate-guard

将实际 GitHub 路径替换为维护者仓库(例如 fengxiforcy/dsh-surrogate-guard 时使用 github:fengxiforcy/dsh-surrogate-guard)。然后把 dsh-surrogate-guard 加入该 profile 的 package.json 里 dsh.profile.bundles,重启 DSH 后生效。

典型用法与自测

日常无需额外调用:启用 bundle 后,工具结果与配置开启的 userMessages 会在进入会话前自动处理。

离线自测可在插件目录执行:

node test/guard.test.mjs

README 说明共 17 项检查(含干净文本、孤立高位/低位代理、合法代理对、read 结构、同时命中只改一处等);npm 包自 0.1.3 起包含 test/ 目录,装包后可直接运行上述命令。

适用场景与注意

适合:经常 read 大文件、grep 含 emoji 或二进制误读文本、依赖联网抓取结果写入会话的 DSH 工作流;已遇到过 unexpected end of hex escape 或希望与 dsh-text-guard 互补覆盖两种「永久 400」病因的场景。

注意:插件不能替代核心侧码点对齐截断;若只需合规过滤国旗类 emoji,应使用 dsh-text-guard。社区目录 SkillHub 与 DeepSeek / 幻方无官方从属关系,安装来源以你信任的 GitHub 或 npm 为准。

结尾

dsh-surrogate-guard 把工具与用户消息里因截断产生的 UTF-16 孤立代理在进会话前换成安全替换符,降低整段会话因 400 无法继续的风险。详情与更新日志见 GitHub 仓库,插件条目见 SkillHub 目录页。

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

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

小夜