[Bug] auto-compact 对 OpenAI-compatible 模型静默失效致超限报错;95% 阈值硬编码且不可配置
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
问题类别 · Category
对话 / Agent 交互 · Agent chat(auto-compact / 上下文压缩)
涉及框架 · Agent framework
ZCode Agent(自研)
严重程度 · Severity
阻塞使用 · Blocking — 上下文增长到一定规模后会话直接不可用,且无法自行恢复
复现频率 · Reproducibility
必现 · Always(对话足够长 + OpenAI-compatible 小上下文模型)
问题描述 · Description
使用自建 OpenAI-compatible 模型(sglang 部署 nvidia/GLM-5.2-NVFP4,contextWindow=409600)长时间对话后,出现 The input (410089 tokens) is longer than the model's context length (409600 tokens) 硬报错,auto-compact 从未自动触发。根因有两层:
第 1 层(#93 的下游后果):OpenAI-compatible 流式请求未带 stream_options.include_usage,服务端不返回 usage → auto-compact 拿不到真实 token 数 → 永久回退到本地估算(source:"estimate"),本地估算对长会话偏低 → compact 永远不触发。完整源码证据链见我在 #93 的补充评论。
第 2 层(本 issue 的核心诉求):即使 #93 修复,auto-compact 触发阈值硬编码 95%(glm/zcode.cjs 常量 DTt=95)。thresholdPercentOverride 钩子已存在(函数 OTt,接受 1–100)但从未接到任何用户入口——config / setting / env / CLI / 设置面板都没有。对 409600 的小窗口,95% = 389120,只剩 ~20K 缓冲;单次 send(尤其带大文件/大附件)极易从 <95% 一步跨过 100%,越过 compact 窗口直接超限。
此外,超限后会话反复重发同一上下文:session 一旦因超限进入 error 状态,后续每次 send 都带着同一份超限上下文发出去,重复失败,无法恢复——既不自动 compact,也不提示用户新开 session。
复现步骤 · Steps to reproduce
- ZCode 3.3.4,macOS,添加自定义 OpenAI-compatible provider 指向 sglang(
nvidia/GLM-5.2-NVFP4,contextWindow=409600) - 在同一 session 持续对话至 ~500 条消息、上下文接近 40 万 tokens
- 发送一条消息(即便很短,如 2 字符)
- 报错:
The input (410089 tokens) is longer than the model's context length (409600 tokens) - 此后该 session 处于
error状态,任何后续 send 都带着同一超限上下文重复失败,无法恢复
期望表现 · Expected behavior
- 逼近上限时 auto-compact 自动触发,且基于服务端真实 token 数(而非偏低的本地估算)
- 阈值可由用户配置,小上下文模型可调低(如 80%)留足缓冲
- 上下文超限报错后,不应反复重发同一超限上下文;应自动 compact 或明确提示用户新开 session / 执行
/compact
实际表现 · Actual behavior
- auto-compact 从未触发(本地估算未达 95%,真实用量已超 100%)
- 单次 send 从 <95% 直接跳到 100.1%,越过 compact 窗口
- session 进入
error后,后续 send 反复失败、无法恢复
证据 · Evidence
日志时序(~/.zcode/v2/logs/2026-07-10.log,session sess_c1234ab7-...):
| 时间 | 事件 | messageCount | 说明 |
|---|---|---|---|
| 22:16:29 | resume+send | 493 | 上下文安全(< 95%) |
| 22:17:35 | resume+send | 497 | 又发两条消息 |
| 22:20:26 | resume | 506,sessionStatus:"error" |
上次请求已超限,session 被标记 error |
| 22:20:27 | send(textLength: 2) | — | 410089 > 409600 → 拒绝 |
源码证据(glm/zcode.cjs):
- auto-compact 判定函数
xW:tokenCount = tokenOverride?.tokenCount ?? 本地估算,source默认"estimate" tokenOverride来自syn(latestProviderContextUsage),而latestProviderContextUsage = Ojt(g, ...)Ojt:仅当y4e(e.usage)有值且 >0 才返回;usage 为空 → 返回 undefined → 无 tokenOverride → 永久走本地估算- 阈值常量
DTt = 95(硬编码);OTt中thresholdPercentOverride钩子接受 1–100,但在整个out/目录出现 0 次赋值,未接入任何 zod schema,手填 config/setting 也不会被解析
服务端验证(同一 sglang 端点):
- 流式不带
stream_options→ 末尾 chunk 无 usage(grep -c '"usage"'= 0) - 流式带
stream_options:{include_usage:true}→ 末尾 chunk 正常返回{"usage":{"prompt_tokens":13,"total_tokens":18,...}} - 非流式 → usage 正常
- 即服务端符合 OpenAI 规范,是 ZCode 没主动要
ZCode 版本 · Version
3.3.4(desktop,production,darwin-aarch64)
设备 / 系统 · Device / OS
macOS 25.5.0 arm64;后端 sglang nvidia/GLM-5.2-NVFP4(OpenAI-compatible,contextWindow=409600)
关联 · Related
- #93 ——
include_usage不发送的根因(本 issue 第 1 层根因的上游)。我在 #93 补充了完整源码证据链与超限复现。
建议 · Asks
- 修复 #93:给 openai-compatible 工厂传
includeUsage: true,让 auto-compact 拿到服务端真实 token 数。 - 暴露
thresholdPercentOverride到用户配置(config.json / setting.json),小上下文模型可调低阈值留缓冲。钩子代码已就绪,只差接线。 - 超限报错后停止重复发送同一上下文:改为自动触发一次 compact,或明确提示用户新开 session / 执行
/compact,避免 error 状态下的重复失败循环。
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with glm/zcode.cjs and trace xW, Ojt, OTt, and the hard-coded DTt threshold, then compare the behavior with the evidence and reproduction steps in the issue. Review related issue #93 for the missing usage path and inspect how configuration is parsed. Done means real provider usage reaches auto-compact, the threshold is user-configurable, and an over-limit session does not repeatedly resend the same context.
Written by the indexing model from the issue text.
Assessment
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100