Repository navigation
[PR] fix: salvage double-escaped newline in compress line-form string content - #3785
Conversation
📦 Built Package ArtifactBranch: Option A — Install this exact build (recommended)npm install -g billion-context@0.0.4499-pr.3785.4a7aadeThis exact version is immutable and reproducible. The rolling Option B — Download artifact
tar xzf billion-context-pr3785.tgz
npm install -g packageInstall instructions are refreshed on each push. |
(ai: vllm-qwen/qwen3.8-27b) 查重: 不重复——按失败签名( 标签: bug + dsh + scope/kernel + p2(缺陷修复;复现环境为 dsh desktop 插件 lane,机制本身是模型参数序列化漂移、非客户端专属;属压缩管线参数解析;能用但特定条件下有明显问题→p2)。 审核进行中(agent 提交的 PR,按规则不重做、只核对代码与 CI):
|
…ent (#3780) A model serializing its compress args as text escapes the header/summary separator twice, so the documented line-form 'content' string carries a literal backslash+n instead of a real break. Undecoded, the kernel finds no newline, yields an empty summary, and rejects with kind=content-not-array — hiding the real missing-summary reason and sending the model to retry the same broken shape. Host-side pre-normalization in parseCompressInput (same discipline as #1494): when the first parse is not ok, decode backslash-n / backslash-r-backslash-n once and retry, adopting the result only if it yields strictly more ranges. A string with no real newline always parses to zero ranges undecoded, so a working parse can never be degraded; payloads that already carry a real newline are left untouched. The kernel parser stays the shared home for any later multi-lane fix.
123301b to
c824436
Compare
(ai: vllm-qwen/qwen3.8-27b) PR #3785 审核结论(独立重审)已执行:rebase 到最新 master( 八问:
测试有效性(④):4 个新测试有牙——正例钉死 startRef/endRef/topic/summary 映射 + 已知残留(不阻塞):同一字符串内真实换行与字面 \n 混合转义的 payload 不救(设计如此,避免动到有效载荷);OP 建议 2(model-facing FAILED 消息暴露 invalidReasons / 独立 kind)属内核诊断面,留待另行决策——rescue 落地后该误导 kind 场景已大幅收窄。 §7.4 auto-merge 判定:全部满足(单模块、回归测试复现原 bug、rebased head 绿、无 config/persistence/wire/kernel 触碰、纯 fix:、diff 干净、Fixes #3780、不涉 load-bearing infra)→ 可合入,等待人工合并。 |
📦 Merged Build PublishedThis merge to master was published as npm install -g billion-context@0.0.622-master.f74f266 # this exact build
npm install -g billion-context@master # always the newest merged build
|
What this fixes
A model that serializes its
compressargs as text escapes the header/summary separator twice, so the documented line-formcontentstring carries a literal backslash+n (two characters) instead of a real newline. Undecoded, the kernel finds no newline → empty summary → rejects withkind=content-not-array, which hides the real reason (missing summary after the refs header line) and sends the model to retry the same broken shape. This is the next rung of the compress-arg shape-drift ladder (#1494 / #1559).Repro from the issue:
{"content": "m00003–m00107 example topic\\nTASK AS OF THIS BLOCK: ..."}fails, while the identical payload with a real newline succeeds.Root cause
parseCompressInput→ kernelparseObjectValue: acontentstring with no real newline goes throughsplitLineEntries(single chunk = whole string) →parseLineEntry(nl === -1) →summary === ""→ rejected. The bare branch then setsdiag.kind = "content-not-array"and returns without surfacing the per-entry reasons it did collect.Fix (host-side, no kernel change)
In
src/compress-tool.tsparseCompressInput, when the first parse is not ok, decode\n/\r\nonce from a double-escapedcontentstring and retry, adopting the result only if it yields strictly more ranges. Same pre-normalization discipline as #1494.Safety invariant: a string with no real newline always parses to zero ranges undecoded, so adopting only on strictly-more-ranges can never degrade a working parse. A payload that already carries a real newline is left untouched (a literal backslash-n inside its summary body survives verbatim).
Behavior change (disclosed)
[Compression FAILED: ... kind=content-not-array ...]; the model retried the same shape.No wire-shape change; both compression modes are unaffected (arg parsing precedes mode-specific handling); no message-ref/id reissue.
Config surface
None. No new env var, config key, or CLI flag.
Tests
tests/issue1494-compress-params.test.ts(+4):applyRanges(noFAILED, nocontent-not-array)Targeted suite green locally (13/13 in the file); the full-suite verdict is remote CI.
Closes #3780