前言¶
在 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 目录页。