🐛 fix(sdk): utils 域八项修复——结构化输出兜底、Retry-After 退避、审批大小写等 - #427
Conversation
模型输出前带说明文字时,锚定围栏正则剥不掉前缀,JSON.parse 直接失败,
重试耗尽后整 run 误判 error_max_structured_output_retries。
- parseStructuredOutput 失败后新增首个平衡 {} 块提取兜底,
正确跳过字符串字面量与转义序列
- 重试提示强化:首字符必须是 {,禁止前置散文/围栏/注释
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
标准 YAML 允许列表项不缩进,旧实现强制要求缩进导致顶格项被静默丢弃, key 落空串(skills 的 allowedTools 等字段丢失)。 - 终止条件收敛为:遇到非 "- " 形状行(新 key 或其他内容)或 "---" - 顶格与缩进列表项均接受 - key 值为空且未收集到任何列表项时输出告警 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
getRetryDelay 纯指数退避,两个 OpenAI provider 构造错误对象时丢弃 Retry-After 头,429 限流时按固定节奏盲重试。 - 新增 parseRetryAfterHeader:支持 delta-seconds 与 HTTP-date 两种格式 - 错误对象挂 err.retryAfterMs,withRetry 经 computeRetryDelay 优先采用, 无抖动,硬上限 120s;未携带时回退指数退避 - openai / openai-responses 构造错误时解析并挂载该头 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
microCompact 只截断 string 形态 tool_result,数组形态(读图 base64、 web-fetch 结果)原样进 provider,预算形同虚设。 - 数组分支 text 块按预算首尾截断,与 string 分支同一标记 - image / document 块整体替换为占位 text 块,注明原块类型与原始大小 - 无变化时保持原引用,避免无谓重建 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
窗口表纯硬编码名称子串,gemini/qwen 等 1M 窗口模型落默认 200k; findModelMeta 已 import 但只用于价格。 - 表未命中后回退 findModelMeta(model)?.contextWindow,再落默认值 - 已知模型的表内结果保持不变 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
通配符规则提前 return 绕过别名归一且前缀比较大小写敏感,deny 规则 大小写不一致时漏配 fail-open;MCP 未知名精确匹配同样受影响。 - 通配符分支改为原始名小写前缀比较,不对前缀套别名归一 (归一会剥坏 mcp__ 结构) - 别名比对两侧统一小写,未知名精确匹配随之大小写不敏感 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
settings 的 user 分支硬编码 ~/.lume,不读 LUME_CONFIG_DIR,与同包 fs-loader/worktree-tools 及 desktop/sidecar 行为不一致,自定义配置目录 下 user 级 settings.json 永远读不到。 - 按 fs-loader 同款逻辑解析 env(空白回退默认、相对路径基于 cwd 解析) - 未设置时行为不变 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
catch 把 ENOENT 与 JSON.parse 失败同等静默吞掉,安全相关配置损坏时 fail-open 无任何痕迹。 - 非 ENOENT(坏 JSON、权限等)console.warn 输出文件路径与错误信息 - 缺失文件维持静默跳过 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
review 发现 34a35dbfe 对数组 tool_result 里 image/document 块一律替换 占位,而 microCompact 每轮对全量消息执行,小图也被剥掉,SDK 直接消费者 的图片/PDF 视觉能力整体失效。 - 媒体块加尺寸门槛:序列化大小超过 maxToolResultChars 预算才替换为 占位 text 块(注明类型与原始大小),小图原样保留 - 测试同步修正:超大 image/document 占位、小 image 深比较原样保留 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Linux CI 上 join("D:", ...) 非绝对路径,被 resolve 正确地拼到 cwd 后,
断言失败;实现行为无误,属测试的平台假设错误。
- win32 取 D:\custom-lume,POSIX 取 /tmp/custom-lume
- 两侧均断言 resolve 后的精确路径
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Code Review八项逐项核对完毕,全部真实落地、无虚报,无 P0/P1,可合。以下为修复深度/跨层一致性的遗留发现。 逐项结论#318(兜底+提示强化)、#350(放行顶格列表+空值告警)、#354(ENOENT 静默/其余 warn 带路径,判定正确)、#364(超预算才占位的设计保住了视觉能力)、#366(registry 回退已验证 gemini-2.5-pro=1048576 且 bundled seed 使测试非空洞)、#379、#291(与 发现[P2] #318 兜底只尝试首个 [P2] #364 数组形态预算逐块生效而非逐结果,多中块 tool_result 聚合仍不设防( [P2] #351 与 sidecar 形成两套 Retry-After 语义,sdk 侧在 Retry-After: 0 时退化为零延迟风暴( [P3] #366 硬编码 includes 表仍遮蔽 registry 较新数据( [P3] #364 热路径对所有媒体块做完整 stringify 计长( [P3] 新重试提示语对数组根 schema 是错误指引( [P3] #350 空列表告警对合法 YAML null 值键误报( [P3] #379 测试缺口:别名通配符场景(issue 的核心反例)未钉住( CI 6/6 全绿、typecheck 绿。建议 #318 循环提取与 Retry-After 上限统一随本 PR 或紧跟 #422 处理;其余 P3 可入 follow-up。 |
概述
修复 sdk 全量 review 提出的 8 个 issue(utils / prompt / token 域),每个 commit 独立可跑绿。
{LUME_CONFIG_DIR(与 fs-loader 同款语义:trim/空白回退/相对路径基于 cwd)-列表项,items 为空时告警(skills allowedTools 不再静默丢失)验证
bun run typecheck六 workspace 全部 exit 0bun test src:591 pass / 0 fail / 1 skip(skip 为既有 natives 双态)Notes
parseRetryAfterHeader/computeRetryDelay保留在 retry 层并有测试;生产挂载点随 provider 移除迁至 sidecar 传输层,跟踪于 [P2][sdk/providers] Retry-After 挂载点需随 provider 移除迁移至 sidecar 传输层 #422。Closes #318, closes #350, closes #351, closes #354, closes #364, closes #366, closes #379, closes #291
🤖 Generated with Claude Code