Repository navigation
fix(provider): preserve transport and surface clone failures [P2; independent] #4582
Description
🤖 Automated architect agent — this comment was posted by the architect bot from Docker Agentic Platform, not by a human engineer
What
Make provider reconstruction fail visibly and preserve the selected transport and explicit user options. A title, MCP sampling request or compaction operation must not silently run against the unmodified base provider when the requested clone cannot be built.
Preserve native Vertex dispatch/authentication independently of the provider identity used for catalog lookup. Preserve explicit thinking-off intent through defaults, environment expansion, custom providers and routing without sharing mutable options.
This is independently shippable on already available models (for example Claude 4.6 / Haiku 4.5); it does not need to activate new 5.x policy or wait for #4576.
Why
Internal defects: immutable source evidence
The research revision is 49e4ca657fd454e9d46ea258e8cf61c517df9aab, not a selected implementation base. These are static observations to reproduce with caller-level tests:
- CloneWithOptions, lines 15–29 logs a warning and returns the original provider when a rebuilder is absent or fails. The requested restrictions can therefore be ignored without an error reaching the caller.
- Title generation applies no-thinking, max-token and structured-output options, then immediately uses the returned provider. MCP sampling likewise continues to inference after cloning. Compaction and context-window resolution also call the same helper.
- Vertex construction rewrites
Providerfor models.dev identity before giving the configuration to the Anthropic-native client. The attached rebuilder reconstructs from the supplied configuration. A catalog identity must not replace the original dispatch identity. - Existing mergeCloneOptions already writes a disabled sentinel to avoid provider-default resurrection. Preserve and extend that work; do not claim the sentinel is missing. fix(provider): WithNoThinking clone no longer leaks provider-level thinking_budget #3238 and refactor(provider): replace ProviderRegistry any with typed RebuildProviderFunc #4278 are merged predecessors, not the remaining fail-visible/dispatch fix. Closed CloneWithOptions uses the wrong environment.Provider #676 concerned the environment provider, not this full contract.
These are docker-agent correctness requirements, not vendor requirements to adopt a particular Go API.
Official documentation: why the transport and intent differences matter
- Claude on Vertex uses Google-authenticated native prediction with project/location/model in the URL and
anthropic_version: vertex-2023-10-16in the body. A clone must not switch to the Claude API or leak a direct API key. The current Vertex auth code explicitly clears that key and supports request-context token sourcing. - Thinking and effort distinguish disabled thinking, adaptive thinking and effort. A failed strict-off clone cannot be treated as permission to reason at a lower effort. Model-specific 5.x validation belongs to the core issue, not this prerequisite.
How — indicative
Prefer an additive checked-clone API returning (Provider, error) and migrate internal callers. If the public single-return API must remain for Go compatibility, document deprecation and ensure failed strict options cannot cause inference on the base provider (for example, an error-returning provider using existing contracts). Do not silently break a public signature or add a hidden retry loop.
Keep original dispatch configuration separate from catalog/display identity and carry it through the existing rebuilder. Preserve project, location, selected host, credentials/token source, gateway bypass and ordered option precedence. Keep state request/session-scoped where it varies between conversations; do not mutate shared configuration maps.
Handle failures at the caller boundary: title candidate exhaustion is nonfatal to chat; MCP returns an actionable error; compaction/context-limit resolution propagates failure without replacing session context or performing an unrequested base-model inference. Existing explicit title-candidate behavior may remain; a hidden base fallback is not a candidate.
Acceptance criteria
- Missing rebuilder and synthetic reconstruction errors reach the actual title/MCP/compaction/context-limit callers. Fake-server call counts show no base-provider inference after a failed clone; a helper-only test is insufficient.
- Cloning
google+publisher: anthropicpreserves native rawPredict/streamRawPredict, model-in-URL dialect, project/location and OAuth request context; no direct endpoint/API-key leakage. Test both supported native auth construction paths. - Literal/environment/inherited/custom/routed configurations and cumulative options retain strict off, max tokens and structured-output removal/preservation as requested. No thinking resurrection or mutable option sharing.
- Titles exhaust existing candidates cleanly; MCP with and without tools exposes the error; compaction and window resolution leave context intact when reconstruction fails.
- Legacy models, non-Claude providers, embedders, restricted registries and the existing disabled sentinel have regression controls. Do not globally reinterpret legacy thinking budgets or activate 5.x modes here.
- Go SDK/failure-behavior documentation and caller-level tests ship in the same PR. During authorized implementation, run
task build,task test,task lint, relevant targeted/race checks and review the exact final head. No unauthorized dependency acquisition is implied. - The complete caller-visible fix is merged/delivered, not merely a compiling checked helper.
Dependencies and boundaries
No technical dependencies. This may ship before or after the independent routing-price work in #4576, which is being handled separately and must not be duplicated or expanded here. It is a prerequisite for the 5.x core, not an assurance that all 5.x configurations already work. #4116 remains related and separate. Do not modify or close #4553 as part of this issue.
Implementation PR linkage: pending.
External pricing work: PR #4579 — price routed turns using the serving model is now listed as open. Discovery only; not reviewed here. This link does not establish the full per-stream origin/P3 contract or per-attempt fallback accounting. Do not duplicate or intervene in that workstream.
Epic: #4580
Cross-links
Epic: #4580. Documentation: #4581 (independent). This fix is a prerequisite for #4583, and transitively #4584. External #4576 / #4579 is independent work; its full origin-contract coverage is unreviewed. No implementation PR is linked for this issue yet.
Activity