fix(ai): fold recased gateway-namespaced tool references onto request tools - #1489
Merged
Merged
Conversation
The tool-reference integrity pass (demoteUnavailableToolReferences and its helpers) was a fork-only block inside the 2.7k-line anthropic-messages.ts. Move it to anthropic-tool-references.ts next to anthropic-tool-pairs.ts, and split its test suite into a shared harness plus one file per behavior cluster (client tool_reference/tool_use integrity, native tool-search replay). No behavior change.
… tools A native tool search replayed through a gateway can hand its references back both namespaced and recased: `mcp__a4e6__Memory` for the request tool `memory`, `mcp__a4e6__LspSymbols` for `lsp_symbols`. The exact-suffix fold from #1480 left those unresolved, so the discoveries were dropped (and on the shipped 2026.9.7-2 engine, which predates #1480, the block replayed verbatim and every request failed with `Tool reference 'mcp__a4e6__Memory' not found in available tools`, forcing a fallback model each turn). Compare names with case and `_`/`-` separators folded away after the literal lookups fail, resolving a folded key only when exactly one request tool owns it. Same seam as #1480: the repair runs against the final tools array right before the SDK call. Observed 2026-09-08 in session 01a08016 (omo 5.0.0-0.beta.48, claude-fable-5-1 via ccapi); the real search-result block now folds all eight references with none dangling.
…og gate covers it
Owner
Author
Re-verification on the rebased commits (mengmotaMac, fresh worktree,
|
| commit | check | result |
|---|---|---|
13a944481 refactor |
anthropic-tool-reference-{integrity,native-search} + anthropic-on-response-error |
13 passed / 0 failed |
13a944481 refactor |
root tsc --noEmit |
exit 0 |
9d98c1b77 fix |
same three files (verbose) | 16 passed / 0 failed |
9d98c1b77 fix |
coding-agent test/tool-search/native-anthropic + test/suite/retry-fallback-hard-error |
27 passed / 0 failed |
9d98c1b77 fix |
incident replay (real 01a08016 blocks through streamAnthropic) |
8/8 references folded, 0 dangling |
9d98c1b77 fix |
root tsc --noEmit |
exit 0 |
9d98c1b77 fix |
full packages/ai vitest |
2597 passed / 0 failed; 1 pre-existing file load failure (codex-apply-patch-wire-schema.test.ts, pi-tui entry unresolved in a fresh worktree) |
9d98c1b77 fix |
biome check (5 touched files) |
1 format error in the test harness -> fixed in 9512a91c9 |
Mutation evidence (pre-rebase tree, same code): identity fold -> the 3 new cases fail; ambiguity guard removed -> the ambiguity case fails; restored -> 13 passed.
09ef7161a only names packages/ai/src/api/anthropic-messages.ts by full path in changes.md so the changelog gate covers the moved block.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Incident (2026-09-08, session
01a08016, omo 5.0.0-0.beta.48 / senpi 2026.9.7-2,claude-fable-5-1through ccapi). A native tool search returned itstool_referencenames both namespaced and recased:mcp__a4e6__Memory,mcp__a4e6__LspSymbols,mcp__a4e6__XSearch,mcp__a4e6__Evalfor the request toolsmemory,lsp_symbols,x_search,eval(plusmcp__a4e6__cloudflare-docs_search_cloudflare_documentation, whose suffix stayed literal). Every later Anthropic request failed withTool reference 'mcp__a4e6__Memory' not found in available toolsand the session fell back to another model each turn (3 identical 400s in the transcript; the earlier attempts were masked by pool 429s, so the fallback/revert dance was a symptom, not the cause).main, fix(ai): fold gateway-namespaced Anthropic tool references onto the request's tools #1480's exact-suffix fold would have turnedMemoryinto a dropped reference (Memory !== memory): no 400, but the discovery was lost and the search pair demoted to text.Fix.
resolveAvailableToolNamenow compares names with case and_/-separators folded away after the literal and namespace-stripped literal lookups fail. The folded index is built once per request from thetoolsarray and drops any key that two request tools share, so the fold never guesses between candidates (such a reference stays unresolved and is dropped, as before). Same seam as #1480: the repair runs against the finaltoolsarray right before the SDK call.Refactor (first commit, no behavior change). The tool-reference integrity pass was a fork-only block (since
5ecb30463) inside the 2.7k-lineanthropic-messages.ts; it now lives inpackages/ai/src/api/anthropic-tool-references.tsnext toanthropic-tool-pairs.ts, and its suite is split into a shared harness (anthropic-tool-reference-harness.ts) plus one file per behavior cluster (clienttool_reference/tool_useintegrity; native tool-search replay). Fewer lines of fork-only code left in the upstream-shared file.Tests
test/anthropic-tool-reference-native-search.test.ts: recased namespaced native references fold ontomemory/lsp_symbols/x_search(+ hyphenated literal kept); an ambiguous fold (x_searchvsx-search) is dropped.test/anthropic-tool-reference-integrity.test.ts: a recased namespaced historytool_use(mcp__a4e6__XSearch) is renamed tox_search.Evidence (mengmotaMac, fresh worktree,
bun install --frozen-lockfile)server_tool_use+tool_search_tool_resultblocks from session 01a08016 throughstreamAnthropicwith a capturing fake client -> all 8 references fold (memory, web_search, lsp_symbols, tool_search, cloudflare-docs_search_cloudflare_documentation, tool_search_tool_bm25, x_search, eval), 0 dangling.biome checkon the 5 touched files: clean. Roottsc --noEmit: exit 0.scripts/check-pr-changelog.mjs: PASS.packages/aivitest: 2594 passed / 0 failed; 1 pre-existing file load failure (test/codex-apply-patch-wire-schema.test.ts,@earendil-works/pi-tuientry unresolved in a fresh worktree - identical on the unpatched base, see fix(ai): fold gateway-namespaced Anthropic tool references onto the request's tools #1480).cf2f61564); the only conflict washttpStatusOfErrorlanding inside the moved block, kept inanthropic-messages.ts. Re-verification on the rebased commits is recorded in the PR comments.Trackers
packages/ai/src/changes.md(2026-09-08 entry) andpackages/coding-agent/CHANGELOG.md[Unreleased] Fixed.Summary by cubic
Fixes native tool-search references that the gateway hands back both namespaced and recased (
mcp__a4e6__Memoryfor the request toolmemory), which previously either hard-failed the request withTool reference not found(forcing a weaker fallback model) or silently dropped the discovered tool. Tool-name matching now folds case and_/-separators after literal lookups fail, and only resolves a fold when exactly one request tool matches; ambiguous folds stay dropped.Refactors
anthropic-messages.tsinto the newanthropic-tool-references.tsmodule.Written for commit 09ef716. Summary will update on new commits.