AiClient

Struct AiClient 

Source
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

Source

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_models is false (for OpenRouter)
  • API key environment variable is not set
  • HTTP client creation fails
Source

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 a SecretString
  • model_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_models is false (for OpenRouter)
  • HTTP client creation fails
Source

pub fn circuit_breaker(&self) -> &CircuitBreaker

Get the circuit breaker for this client.

Trait Implementations§

Source§

impl AiProvider for AiClient

Source§

fn name(&self) -> &str

Returns the name of the provider (e.g., “gemini”, “openrouter”).
Source§

fn api_url(&self) -> &str

Returns the API URL for this provider.
Source§

fn api_key_env(&self) -> &str

Returns the environment variable name for the API key.
Source§

fn http_client(&self) -> &Client

Returns the HTTP client for making requests.
Source§

fn api_key(&self) -> &SecretString

Returns the API key for authentication.
Source§

fn model(&self) -> &str

Returns the model name.
Source§

fn max_tokens(&self) -> u32

Returns the maximum tokens for API responses.
Source§

fn temperature(&self) -> f32

Returns the temperature for API requests.
Source§

fn circuit_breaker(&self) -> Option<&CircuitBreaker>

Returns the circuit breaker for this provider (optional). Read more
Source§

fn build_headers(&self) -> HeaderMap

Builds HTTP headers for API requests. Read more
Source§

fn validate_model(&self) -> Result<()>

Validates the model configuration. 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,

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,

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,

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,

Creates a formatted GitHub issue using the provider’s API. Read more
Source§

fn build_system_prompt(custom_guidance: Option<&str>) -> String

Builds the system prompt for issue triage.
Source§

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

Builds the system prompt for issue creation/formatting.
Source§

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,

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,

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

Builds the system prompt for PR review.
Source§

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

Builds the system prompt for PR label suggestion.
Source§

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,

Generate release notes from PR summaries. Read more
Source§

fn build_release_notes_prompt(prs: &[PrSummary], version: &str) -> String

Build the user prompt for release notes generation.
Source§

impl Debug for AiClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

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
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more