Refactor provider dispatch behind a Backend trait#32
Closed
bddap-bot wants to merge 2 commits into
Closed
Conversation
main.rs::refactor() matched on Provider, re-derived the API key inline, and called a free anthropic::complete / openai::complete — a match-and-duplicate that grows worse with each new call shape. Introduce a Backend trait and a single resolve() that turns a provider choice into a key-bearing, callable backend, so the rest of refac stays provider-agnostic. No behavior change: wire formats, error paths, and "no key" messages are identical. Paves the way for an Anthropic-only tool/edit capability (a separate trait, hence Box<dyn Backend> over a closed enum). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…only Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
Author
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.
PR A of the two-PR plan in #31: a pure refactor that introduces a common provider interface, no behavior change. PR B (function-call edits, the #31 rewrite) stacks on this.
What
main.rs::refactor()matched onProvider, re-derived the API key inline, and called a freeanthropic::complete/openai::complete. That match-and-duplicate is exactly what gets ugly when a second call shape (tool edits) lands.src/backend.rs:trait Backend { fn complete(&self, &[Message]) -> Result<String>; }andresolve(provider, model, &secrets) -> Result<Box<dyn Backend>>— the one place that knows how each provider sources its key and errors when it's missing.anthropic.rs/openai.rseach gain anAnthropic/Openaistruct thatimpl Backend, forwarding to the (now private)send()wire call.refactor()collapses tobackend::resolve(provider, &model, sc)?.complete(&messages).Why
Box<dyn Backend>and not a closed enumTool/function-call edits (PR B) are Anthropic-only. A trait expresses that as a separate
Editstrait that onlyAnthropicimplements — no enum arm faking "unsupported" at runtime. Documented inbackend.rs.No behavior change
Wire formats untouched. The "no key" trigger conditions and messages are byte-identical (moved verbatim into
resolve). Provider/model resolution unchanged.Tests
cargo test→ 7 passing (the 5 existing + 2 newresolvetests covering missing-key and present-key for both providers). clippy clean on the changed files. Built with nixpkgs rust 1.91.Self-reviewed via two rounds of fan-out review agents (correctness, security, Niko-style design): no correctness/security findings; applied the design refinements (borrow
model, rename the private wire fn tosend, document thedynchoice).🤖 Generated with Claude Code