Repository navigation
feat(provider-anthropic): Anthropic Messages API provider worker - #247
Conversation
skill-check — worker0 verified, 17 skipped (no docs/).
Four for four. Nicely done. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (29)
📝 WalkthroughWalkthroughThis PR adds a ChangesRouter and Anthropic provider implementation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
94683cb to
d520fd3
Compare
d520fd3 to
cc4b2ae
Compare
cc4b2ae to
0991666
Compare
8ae77e2 to
0104986
Compare
7a28a81 to
def74d2
Compare
def74d2 to
2731bbc
Compare
0104986 to
b5e8070
Compare
8e16f09 to
436ffe3
Compare
…table-assistant anchor)
…s and formula fallback
…artial/all-thinking anchor cases
… and cache markers
…-on-channel-close
…s and add redacted thinking payload
…s, quickstart guide, and detailed configuration options
…al mapping Delete code orphaned or made redundant by the hardening pass: the write-only PartialState.open_block field, the build_final alias of build_partial, classify_sse_error (identical to classify(None, _)), the duplicated empty_assistant constructor (tests now use the router's empty_partial), merge_usage's unobservable cumulative flag, and build_content's unreachable seen-bitvec fallback loops. The delta arms bind the slot index directly in the match pattern instead of re-destructuring. The Credential -> (secret, auth mode) mapping and the auth header pair now exist once (config::credential_parts, request::auth_header), shared by the streaming and discovery paths. One behavior change: the content_block_stop slot clear is get_mut- guarded, so a stop for a never-started index is a no-op instead of an out-of-bounds panic.
Opus 4.7/4.8 and Fable/Mythos 5 hard-reject thinking.type "enabled" —
the upstream 400s with 'use thinking.type.adaptive and output_config.effort'.
Every model this provider serves with thinking (Sonnet 4.6 onward) accepts
adaptive, so the legacy budget path is dropped entirely: thinking_level maps
to {type: adaptive, display: summarized} plus output_config.effort
(minimal/low → low, medium, high, xhigh; xhigh still degrades to high when
the catalog says unsupported). Budget arithmetic, thinking_budgets seeding,
and the interleaved-thinking beta header (adaptive interleaves natively) go
with it, and the curated snapshot gains claude-opus-4-8.
… truth Drop the hand-maintained capability snapshot: live discovery now reads ids, display names, context/output limits, and the capabilities tree (thinking, effort.xhigh, image_input) straight from the API, and the registration declaration carries no static models — a refresh fires right after registering, so the slice fills from Anthropic within seconds of boot (reconcile-to-empty still prunes when the key is missing or revoked). The only local data left is pricing, which the API does not expose.
… the catalog The live capability tree cleanly splits Anthropic's generations: thinking.types.adaptive.supported is true from Opus 4.6/Sonnet 4.6 onward and explicitly false for everything older. Since this provider only implements adaptive thinking, a model that can think but not adaptively (Sonnet 4.5, Haiku 4.5, Opus 4.5 and older) would 400 the moment a thinking_level arrives — those rows are now dropped at parse time, so the picker offers only models every feature works on. Rows without capability data stay (permissive for future shapes), and models that cannot think at all stay with thinking gated off. supports_thinking now reflects adaptive support, the operative flag for this provider.
…hinking gated off Haiku is the cheap tier and has no adaptive-generation release yet, so the legacy-thinking filter now exempts claude-haiku-*: the row stays in the slice with supports_thinking false, and a thinking_level on it degrades with a warning instead of erroring. The rest of the non-adaptive generation stays excluded.
c235d1b to
d9f2445
Compare
Summary
Stacked on #241 (
feat/llm-router-rs) — first real provider implementing the router's provider protocol fromtech-specs/2026-06-agentic/llm-router.md.provider-anthropic — Anthropic Messages API provider behind llm-router:
provider::anthropic::stream: SSE →AssistantMessageEventstate machine with ping watchdog, abort-on-channel-close, and the shared error taxonomyPROVIDER_ANTHROPIC_CACHE=0kill switch)provider::anthropic::refresh_models: liveGET /v1/models∪ curated capability snapshot (context windows, output ceilings, thinking budgets, pricing), reconciled into the router catalog with no cold-catalog holerouter::readyStreaming robustness:
message_stop) surface as error frames instead of a cleandoneindexfield; unknown block types cannot corrupt neighboring blocksmessage_deltatotals)errorevents and router bus errors (registration_rejectedis not reported as transient)RedactedThinkingcontent-block variant to llm-router types — the only router-crate change in this PR, +4 lines)Docs: consumer-facing README per the worker-readme guide, runnable
examples/stream_chat.rsdemo, provider cross-reference in the router README.Agent exposure is locked down per
iii-permissions.yaml:provider::anthropic::*is never agent-callable — the router invokes it worker-to-worker.Test plan
III_ENGINE_BIN=… cargo test --test integration): 5 passed — registration + token persistence, re-declare onrouter::ready, discovery reconcile, end-to-end chat stream with cost fill, upstream 401 →auth_expiredframe (real engine + real router + stub upstream, no external API calls)Summary by CodeRabbit