pub struct AiClient { /* private fields */ }Expand description
Generic AI client for all providers.
Holds HTTP client, API key, and model configuration for reuse across multiple requests. Uses the provider registry to get provider-specific configuration.
Implementations§
Source§impl AiClient
impl AiClient
Sourcepub fn new(provider_name: &str, config: &AiConfig) -> Result<Self>
pub fn new(provider_name: &str, config: &AiConfig) -> Result<Self>
Creates a new AI client from configuration.
Validates the model against cost control settings and fetches the API key from the environment.
§Arguments
provider_name- Name of the provider (e.g., “openrouter”, “gemini”)config- AI configuration with model, timeout, and cost control settings
§Errors
Returns an error if:
- Provider is not found in registry
- Model is not in free tier and
allow_paid_modelsis false (forOpenRouter) - API key environment variable is not set
- HTTP client creation fails
Sourcepub fn with_api_key(
provider_name: &str,
api_key: SecretString,
model_name: &str,
config: &AiConfig,
) -> Result<Self>
pub fn with_api_key( provider_name: &str, api_key: SecretString, model_name: &str, config: &AiConfig, ) -> Result<Self>
Creates a new AI client with a provided API key and validates the model exists.
This constructor validates that the model exists via the runtime model registry before creating the client. It allows callers to provide an API key directly, enabling multi-platform credential resolution (e.g., from iOS keychain via FFI).
§Arguments
provider_name- Name of the provider (e.g., “openrouter”, “gemini”)api_key- API key as aSecretStringmodel_name- Model name to use (e.g., “gemini-3-flash-preview”)config- AI configuration with timeout and cost control settings
§Errors
Returns an error if:
- Provider is not found in registry
- Model is not in free tier and
allow_paid_modelsis false (forOpenRouter) - HTTP client creation fails
Sourcepub fn circuit_breaker(&self) -> &CircuitBreaker
pub fn circuit_breaker(&self) -> &CircuitBreaker
Get the circuit breaker for this client.
Trait Implementations§
Source§impl AiProvider for AiClient
impl AiProvider for AiClient
Source§fn api_key_env(&self) -> &str
fn api_key_env(&self) -> &str
Returns the environment variable name for the API key.
Source§fn http_client(&self) -> &Client
fn http_client(&self) -> &Client
Returns the HTTP client for making requests.
Source§fn api_key(&self) -> &SecretString
fn api_key(&self) -> &SecretString
Returns the API key for authentication.
Source§fn max_tokens(&self) -> u32
fn max_tokens(&self) -> u32
Returns the maximum tokens for API responses.
Source§fn temperature(&self) -> f32
fn temperature(&self) -> f32
Returns the temperature for API requests.
Source§fn circuit_breaker(&self) -> Option<&CircuitBreaker>
fn circuit_breaker(&self) -> Option<&CircuitBreaker>
Returns the circuit breaker for this provider (optional). Read more
Source§fn build_headers(&self) -> HeaderMap
fn build_headers(&self) -> HeaderMap
Builds HTTP headers for API requests. Read more
Source§fn send_request_inner<'life0, 'life1, 'async_trait>(
&'life0 self,
request: &'life1 ChatCompletionRequest,
) -> Pin<Box<dyn Future<Output = Result<ChatCompletionResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn send_request_inner<'life0, 'life1, 'async_trait>(
&'life0 self,
request: &'life1 ChatCompletionRequest,
) -> Pin<Box<dyn Future<Output = Result<ChatCompletionResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sends a chat completion request to the provider’s API (HTTP-only, no retry). Read more
Source§fn send_and_parse<'life0, 'life1, 'async_trait, T>(
&'life0 self,
request: &'life1 ChatCompletionRequest,
) -> Pin<Box<dyn Future<Output = Result<(T, AiStats)>> + Send + 'async_trait>>where
T: 'async_trait + DeserializeOwned,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn send_and_parse<'life0, 'life1, 'async_trait, T>(
&'life0 self,
request: &'life1 ChatCompletionRequest,
) -> Pin<Box<dyn Future<Output = Result<(T, AiStats)>> + Send + 'async_trait>>where
T: 'async_trait + DeserializeOwned,
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sends a chat completion request and parses the response with retry logic. Read more
Source§fn analyze_issue<'life0, 'life1, 'async_trait>(
&'life0 self,
issue: &'life1 IssueDetails,
) -> Pin<Box<dyn Future<Output = Result<AiResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn analyze_issue<'life0, 'life1, 'async_trait>(
&'life0 self,
issue: &'life1 IssueDetails,
) -> Pin<Box<dyn Future<Output = Result<AiResponse>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Analyzes a GitHub issue using the provider’s API. Read more
Source§fn create_issue<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
title: &'life1 str,
body: &'life2 str,
repo: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<(CreateIssueResponse, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn create_issue<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
title: &'life1 str,
body: &'life2 str,
repo: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<(CreateIssueResponse, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Creates a formatted GitHub issue using the provider’s API. Read more
Source§fn build_system_prompt(custom_guidance: Option<&str>) -> String
fn build_system_prompt(custom_guidance: Option<&str>) -> String
Builds the system prompt for issue triage.
Source§fn build_user_prompt(issue: &IssueDetails) -> String
fn build_user_prompt(issue: &IssueDetails) -> String
Builds the user prompt containing the issue details.
Source§fn build_create_system_prompt(custom_guidance: Option<&str>) -> String
fn build_create_system_prompt(custom_guidance: Option<&str>) -> String
Builds the system prompt for issue creation/formatting.
Source§fn build_create_user_prompt(title: &str, body: &str, _repo: &str) -> String
fn build_create_user_prompt(title: &str, body: &str, _repo: &str) -> String
Builds the user prompt for issue creation/formatting.
Source§fn review_pr<'life0, 'life1, 'async_trait>(
&'life0 self,
pr: &'life1 PrDetails,
) -> Pin<Box<dyn Future<Output = Result<(PrReviewResponse, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn review_pr<'life0, 'life1, 'async_trait>(
&'life0 self,
pr: &'life1 PrDetails,
) -> Pin<Box<dyn Future<Output = Result<(PrReviewResponse, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Reviews a pull request using the provider’s API. Read more
Source§fn suggest_pr_labels<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
title: &'life1 str,
body: &'life2 str,
file_paths: &'life3 [String],
) -> Pin<Box<dyn Future<Output = Result<(Vec<String>, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn suggest_pr_labels<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
title: &'life1 str,
body: &'life2 str,
file_paths: &'life3 [String],
) -> Pin<Box<dyn Future<Output = Result<(Vec<String>, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Suggests labels for a pull request using the provider’s API. Read more
Source§fn build_pr_review_system_prompt(custom_guidance: Option<&str>) -> String
fn build_pr_review_system_prompt(custom_guidance: Option<&str>) -> String
Builds the system prompt for PR review.
Source§fn build_pr_review_user_prompt(pr: &PrDetails) -> String
fn build_pr_review_user_prompt(pr: &PrDetails) -> String
Builds the user prompt for PR review.
Source§fn build_pr_label_system_prompt(custom_guidance: Option<&str>) -> String
fn build_pr_label_system_prompt(custom_guidance: Option<&str>) -> String
Builds the system prompt for PR label suggestion.
Source§fn build_pr_label_user_prompt(
title: &str,
body: &str,
file_paths: &[String],
) -> String
fn build_pr_label_user_prompt( title: &str, body: &str, file_paths: &[String], ) -> String
Builds the user prompt for PR label suggestion.
Source§fn generate_release_notes<'life0, 'life1, 'async_trait>(
&'life0 self,
prs: Vec<PrSummary>,
version: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(ReleaseNotesResponse, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn generate_release_notes<'life0, 'life1, 'async_trait>(
&'life0 self,
prs: Vec<PrSummary>,
version: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(ReleaseNotesResponse, AiStats)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Generate release notes from PR summaries. Read more
Auto Trait Implementations§
impl !Freeze for AiClient
impl !RefUnwindSafe for AiClient
impl Send for AiClient
impl Sync for AiClient
impl Unpin for AiClient
impl !UnwindSafe for AiClient
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more