SIGN IN SIGN UP

fix(#77 AromaACG): tiered tool preamble compaction — 修 opus-4-7 短回复 14 字符

#77 里 AromaACG 报的不是 zhangzhang-bit 的 30 秒空错误, 是 200 OK 但
Cascade short reply textLen=14. 日志关键行:

  toolPreamble 71KB exceeds soft cap 23KB; falling back to names-only
  preamble (2KB, 25 tools)

claude-opus-4-7 + response_format=json_schema + 25 个 MCP tool, full
preamble 71-150KB, 硬撞 24KB soft cap 直接降级 names-only (2KB), 丢
所有 schema. opus-4.6 抗压能 hold, opus-4-7 没 schema 直接懵, 吐 14
字符短回复敷衍.

根因: applyToolPreambleBudget 是 binary fallback (full <-> names-only,
跳得太狠). 改成四档分层降级:

  full         pretty-printed full schema           ~150KB
  schema-compact  (新) minified JSON + 剥 desc       ~10KB
  skinny       (新) name + 一行描述 + 参数签名         ~5KB
  names-only   仅函数名                             ~2KB

walk 从大到小逐层降级, 第一个塞进 soft cap 就用. AromaACG 25 工具
71KB 案例现在落 schema-compact (~10KB), opus-4-7 看得到 param 名字
和类型, 能正常出 json_schema 响应.

src/handlers/tool-emulation.js:
- buildSchemaCompactToolPreambleForProto (新): 用 minified JSON, strip
  schema 内部的 description / examples / default / title /
  additionalProperties; 保留 type / enum / required / oneOf / items
- buildSkinnyToolPreambleForProto (新): name + first-sentence desc +
  param signature (file_path: string, mode?: "a"|"b"). 小 enum (<=6) 内联
- stripSchemaDocs / firstSentence / paramSignature helper

src/handlers/chat.js:
- applyToolPreambleBudget tiered walk, 返回 tier 字段
- 日志从 "falling back to names-only" 改 "using <tier> tier", operator
  一眼看到落哪档

tests:
- 25 工具 70KB 案例必须落 schema-compact 或 skinny, 不能直接 names-only
- schema-compact 必须保留 enum 和 param 名字
- 既有 forbidden-wording / 56-tool budget 测试仍 pass

253/253 tests pass.
D
dwgx committed
7bbb8c3834b1ab18e7b74089d2eb363ae44d3252
Parent: c6c1ff2