1pub mod circuit_breaker;
8pub mod client;
9pub mod context;
10pub mod models;
11pub mod provider;
12pub mod registry;
13pub mod types;
14
15pub use circuit_breaker::CircuitBreaker;
16pub use client::AiClient;
17pub use models::{AiModel, ModelProvider};
18pub use provider::AiProvider;
19pub use registry::{ProviderConfig, all_providers, get_provider};
20pub use types::{CreateIssueResponse, CreditsStatus, TriageResponse};
21
22use crate::history::AiStats;
23
24pub const CEREBRAS_API_URL: &str = "https://api.cerebras.ai/v1/chat/completions";
26
27pub const CEREBRAS_API_KEY_ENV: &str = "CEREBRAS_API_KEY";
29
30pub const GEMINI_API_URL: &str =
32 "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions";
33
34pub const GEMINI_API_KEY_ENV: &str = "GEMINI_API_KEY";
36
37pub const GROQ_API_URL: &str = "https://api.groq.com/openai/v1/chat/completions";
39
40pub const GROQ_API_KEY_ENV: &str = "GROQ_API_KEY";
42
43pub const OPENROUTER_API_URL: &str = "https://openrouter.ai/api/v1/chat/completions";
45
46pub const OPENROUTER_API_KEY_ENV: &str = "OPENROUTER_API_KEY";
48
49#[derive(Debug, Clone)]
51pub struct AiResponse {
52 pub triage: TriageResponse,
54 pub stats: AiStats,
56}
57
58#[must_use]
61pub fn is_free_model(model: &str) -> bool {
62 model.ends_with(":free")
63}
64
65pub async fn create_issue(
80 title: &str,
81 body: &str,
82 repo: &str,
83) -> anyhow::Result<(CreateIssueResponse, AiStats)> {
84 let config = crate::config::load_config()?;
85
86 let client = AiClient::new(&config.ai.provider, &config.ai)?;
88 client.create_issue(title, body, repo).await
89}