git_iris/agents/
provider.rs

1//! Dynamic provider abstraction for rig-core 0.27+
2//!
3//! This module provides runtime provider selection using enum dispatch,
4//! allowing git-iris to work with any supported provider based on config.
5
6use rig::{
7    agent::{Agent, AgentBuilder, PromptResponse},
8    client::{CompletionClient, ProviderClient},
9    completion::{Prompt, PromptError},
10    providers::{anthropic, gemini, openai},
11};
12
13/// Completion model types for each provider
14pub type OpenAIModel = openai::completion::CompletionModel;
15pub type AnthropicModel = anthropic::completion::CompletionModel;
16pub type GeminiModel = gemini::completion::CompletionModel;
17
18/// Agent builder types for each provider
19pub type OpenAIBuilder = AgentBuilder<OpenAIModel>;
20pub type AnthropicBuilder = AgentBuilder<AnthropicModel>;
21pub type GeminiBuilder = AgentBuilder<GeminiModel>;
22
23/// Dynamic agent that can be any provider's agent type
24pub enum DynAgent {
25    OpenAI(Agent<OpenAIModel>),
26    Anthropic(Agent<AnthropicModel>),
27    Gemini(Agent<GeminiModel>),
28}
29
30impl DynAgent {
31    /// Simple prompt - returns response string
32    pub async fn prompt(&self, msg: &str) -> Result<String, PromptError> {
33        match self {
34            Self::OpenAI(a) => a.prompt(msg).await,
35            Self::Anthropic(a) => a.prompt(msg).await,
36            Self::Gemini(a) => a.prompt(msg).await,
37        }
38    }
39
40    /// Multi-turn prompt with specified depth for tool calling
41    pub async fn prompt_multi_turn(&self, msg: &str, depth: usize) -> Result<String, PromptError> {
42        match self {
43            Self::OpenAI(a) => a.prompt(msg).multi_turn(depth).await,
44            Self::Anthropic(a) => a.prompt(msg).multi_turn(depth).await,
45            Self::Gemini(a) => a.prompt(msg).multi_turn(depth).await,
46        }
47    }
48
49    /// Multi-turn prompt with extended details (token usage, etc.)
50    pub async fn prompt_extended(
51        &self,
52        msg: &str,
53        depth: usize,
54    ) -> Result<PromptResponse, PromptError> {
55        match self {
56            Self::OpenAI(a) => a.prompt(msg).multi_turn(depth).extended_details().await,
57            Self::Anthropic(a) => a.prompt(msg).multi_turn(depth).extended_details().await,
58            Self::Gemini(a) => a.prompt(msg).multi_turn(depth).extended_details().await,
59        }
60    }
61}
62
63/// Create an `OpenAI` agent builder
64pub fn openai_builder(model: &str) -> OpenAIBuilder {
65    let client = openai::Client::from_env();
66    client.completions_api().agent(model)
67}
68
69/// Create an Anthropic agent builder
70pub fn anthropic_builder(model: &str) -> AnthropicBuilder {
71    let client = anthropic::Client::from_env();
72    client.agent(model)
73}
74
75/// Create a Gemini agent builder
76pub fn gemini_builder(model: &str) -> GeminiBuilder {
77    let client = gemini::Client::from_env();
78    client.agent(model)
79}