Skip to content

fix(opencode): restore free-tier stub tool names to client casing on all response paths - #32

Merged
6Kmfi6HP merged 1 commit into
mainfrom
fix/freetier-tool-name-case
Sep 28, 2026
Merged

6Kmfi6HP merged 1 commit into
mainfrom
fix/freetier-tool-name-case

Conversation

@6Kmfi6HP

Copy link
Copy Markdown
Owner

问题

Claude Code 全程报 Error: No such tool available: glob/read(Tool names are case-sensitive: call Read instead.)。

根因:不是上游改写客户端工具名,而是 476314e 为满足免费层指纹门禁(2026-09-18 起要求 tools 必含 bash/glob/grep/read 四件,缺一即 403)向请求注入了四件小写占位工具。模型看到小写名后以小写名发起 tool_use,而 Claude Code 按大小写敏感注册 Bash/Glob/Grep/Read,直接拒绝。

外部同款根因:router-for-me/CLIProxyAPI#1741、diegosouzapw/OmniRoute#11487。

修复(三机制,不依赖上游大小写归一假设)

  1. 防调用: 四件占位工具 description 统一加 Fingerprint only. Do NOT invoke this tool. 前缀(三种协议形状)。
  2. 大小写还原: 新增 freeTierStubCanonicalCase{bash→Bash, glob→Glob, grep→Grep, read→Read} + restoreToolNameCase(name)——只命中四个精确小写串,幂等、不误伤普通工具(如 weather 原样)。
  3. 全触点 restore: 所有把上游 tool 名回写客户端的路径统一过 restoreToolNameCase:
    • chat↔anthropic(非流 tool_use、流式 content_block_start)
    • claude→responses(输入转换/非流/流式)
    • claude→chat(openAIToClaudeResponse + claudeStreamHandler)
    • 免费层非流聚合 aggregateOpenAIStream
    • chat→responses 流式/聚合、responses 入站流式
    • responses 原生透传(restore 加 stub fallback,放宽空表守卫)
    • claude→anthropic 直通 byte-relay(新增 restoreAnthropicStreamLineCase 流式+peek 首帧、restoreAnthropicBodyToolCase 缓冲非流)

对抗验证(verify.isCorrect=false)曾抓出 4 条漏网路径(尤其 anthropic 直通 byte-relay 不解析行),均已补全。

测试

  • 新增 free_tier_case_restore_test.go(10 例):大小写表驱动、anti-invoke 前缀、聚合还原、callOpenCodeAPI 端到端(PascalCase 客户端工具 + 免费模型注入后客户端收到 Glob)、anthropic 流式/缓冲还原、claude→responses 流式还原、非 stub 透传不变、已正确大小写幂等。
  • 两处旧测试预期修正:TestAggregate_ToolCallsAssembledByIndex(小写→PascalCase 还原)、TestResponsesSSEToChatStream_ToolArgumentsShareIndex(原夹具用小写 bash 恰是该 bug,改用中性 Bash)。
  • go build ./... / go vet / gofmt 干净;go test ./... 全绿。

Refs: #19

🤖 Generated with Claude Code

…all response paths

Claude Code 全程报 `Error: No such tool available: glob/read`。根因不是
上游改写客户端工具名,而是 476314e 为满足免费层指纹门禁(2026-09-18
要求 tools 必含 bash/glob/grep/read 四件,缺一即 403),向请求注入了四件
**小写**占位工具。模型看到小写名后以小写名发起 tool_use,而 Claude Code
按大小写敏感注册 `Bash`/`Glob`/`Grep`/`Read`,直接拒绝。外部同款根因见
router-for-me/CLIProxyAPI#1741、diegosouzapw/OmniRoute#11487。

修复(不依赖上游是否大小写归一的假设),三机制:

1. 防调用: 四件占位工具 description 统一加
   `Fingerprint only. Do NOT invoke this tool. ` 前缀(三种协议形状),
   降低模型误调概率(软兜底)。

2. 大小写还原: 新增 freeTierStubCanonicalCase{bash→Bash, glob→Glob,
   grep→Grep, read→Read} + restoreToolNameCase(name)。只命中四个精确
   小写串,幂等、不误伤普通工具(weather 等原样)。

3. 全触点 restore —— 所有把上游 tool 名回写客户端的路径统一过
   restoreToolNameCase:
   - chat↔anthropic: 非流 tool_use、流式 content_block_start
     (chat_to_anthropic.go)
   - claude→responses: 输入转换/非流/流式 (claude_responses.go)
   - claude→chat: openAIToClaudeResponse + claudeStreamHandler (claude.go)
   - 免费层非流聚合 aggregateOpenAIStream (opencode_fingerprint.go)
   - chat→responses 流式/聚合 (chat_to_responses_upstream.go)
   - responses 入站流式 (responses.go)
   - responses 原生透传: responsesNameRewrites.restore 加 fallback,
     restoreResponsesPayloadNames 放宽空表守卫 (responses_passthrough.go)
   - claude→anthropic 直通 byte-relay: 新增 restoreAnthropicStreamLineCase
     (流式+peek 首帧) / restoreAnthropicBodyToolCase (缓冲非流)
     (anthropic_upstream.go)

测试:
- 新增 free_tier_case restore 回归套件(10 例): 大小写表驱动、anti-invoke
  前缀、聚合还原、callOpenCodeAPI 端到端(PascalCase 客户端工具 + 免费
  模型注入后客户端收到 Glob)、anthropic 流式/缓冲还原、claude→responses
  流式还原、非 stub 透传不变、已正确大小写幂等。
- TestAggregate_ToolCallsAssembledByIndex 预期更新为小写→PascalCase 还原。
- TestResponsesSSEToChatStream_ToolArgumentsShareIndex 夹具用小写 "bash"
  (旧代码下透传小写,正是该 bug),改用中性 "Bash" 聚焦同 index 参数共享。
- go build ./... / go vet / gofmt 干净; go test ./... 全绿。

Refs: #19

Co-Authored-By: Claude Code <noreply@anthropic.com>
@6Kmfi6HP
6Kmfi6HP merged commit 7b2965a into main Sep 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant