Skip to content

fix(ai,coding-agent): deliver Anthropic error status and recover a native tool-search 400 on the same model - #1487

Merged
code-yeongyu merged 6 commits into
mainfrom
fix/tool-search-400-recovery
Sep 8, 2026
Merged

fix(ai,coding-agent): deliver Anthropic error status and recover a native tool-search 400 on the same model#1487
code-yeongyu merged 6 commits into
mainfrom
fix/tool-search-400-recovery

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the remaining native tool-search 400 cluster:

Changes

  • packages/ai/src/api/anthropic-messages.ts: when the complete retryProviderRequest operation finally rejects, a numeric HTTP status carried by the SDK error is delivered once through options.onResponse before the error propagates; errors without a status (network, aborts) report nothing rather than a fabricated code.
  • tool-search/service.ts: the provider-scope-scoped ToolSearchService carries a one-shot pending flag (noteNativeInjectionFailure/takeNativeInjectionFailure) recording that a native-injected request was rejected.
  • tool-search/index.ts: the adapter's 400 onFallback records that reason on the service.
  • agent-session.ts: the hard-error branch consumes the flag first — no tryFallback(), a zero-delay auto_retry_start, and the shared continuation on the SAME model (the adapter is already disabled for the session, and the retry rebuilds the request so the fix(ai): fold gateway-namespaced Anthropic tool references onto the request's tools #1480 reference repair applies). The flag is consumed once, so a second rejection takes the ordinary hard-error chain.

Evidence (all remote, mengmotaMac, bun 1.4.0)

  • RED (test patch on 933307abb6): onResponse called 0 times on 400/500 rejections; takeNativeInjectionFailure is not a function; noteNativeInjectionFailure is not a function. The status-less case passes without fabrication.
  • GREEN with the fix: new anthropic-on-response-error 3/3; test/tool-search/native-anthropic.test.ts 16/16; test/suite/retry-fallback-hard-error.test.ts 11/11 (2 new: one same-model retry with zero fallback events, one normal switch on the second 400); ai integrity + deferred-tools + provider-native-replay 52/52; retry-fallback-hardening + refusal + mcp/native-anthropic 20/20.
  • bun run check green; changelog gate PASS (nearest trackers for both production paths + [Unreleased] entries).

Closes #1481, closes #1482.


Summary by cubic

Fixes native tool-search 400 recovery so the same model is retried in place instead of demoting the user to a fallback, and delivers Anthropic HTTP error statuses that previously never reached the response hook.

  • The Anthropic SDK rejects HTTP failures instead of returning a Response, so onResponse/after_provider_response never fired on error and the native adapter's 400 fallback was dead code.
  • The rejection path now reports the SDK's numeric status once through onResponse before propagating; errors without a status (network, aborts) report nothing.
  • After a native tool-search 400, the session retries once on the same model with zero delay since native injection is already disabled; only a second rejection takes the fallback chain.

Closes #1481 and #1482.

Written for commit 6bedcc1. Summary will update on new commits.

Review in cubic

…ame model

A native tool-search 400 hard-errored the model and the hard-error branch
always switched to the next fallback candidate, demoting the user mid-task
even though the same model succeeds once native injection is off (senpi
#1482). The adapter's 400 fallback now records a one-shot pending flag on
the provider-scoped ToolSearchService, and the session's hard-error branch
consumes it first: no tryFallback(), a zero-delay auto_retry_start, and the
shared continuation on the same model. A second rejection takes the
ordinary hard-error chain.
… retry

Wiring case: emitBeforeProviderRequest with a supported Anthropic model and
an MCP feed injects native search, after_provider_response 400 sets the
pending flag once, it is consumed once, and injection stays off. Session
cases: one same-model retry with no fallback events, and a normal fallback
switch on the second consecutive 400.
…ecovery

# Conflicts:
#	packages/coding-agent/CHANGELOG.md
@code-yeongyu
code-yeongyu merged commit cf2f615 into main Sep 8, 2026
23 checks passed
@code-yeongyu
code-yeongyu deleted the fix/tool-search-400-recovery branch September 8, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant