aether_ai/
lib.rs

1//! # Aether AI
2//!
3//! AI provider implementations for the Aether code injection framework.
4//!
5//! This crate provides ready-to-use AI backends:
6//!
7//! - **OpenAI**: GPT-4, GPT-3.5-turbo
8//! - **Anthropic**: Claude models
9//! - **Local**: Ollama and other local providers
10//!
11//! ## Example
12//!
13//! ```rust,ignore
14//! use aether_ai::OpenAiProvider;
15//! use aether_core::{InjectionEngine, Template};
16//!
17//! // One-line initialization from environment
18//! let provider = OpenAiProvider::from_env()?;
19//!
20//! let engine = InjectionEngine::new(provider);
21//! let template = Template::new("{{AI:greeting}}");
22//! let result = engine.render(&template).await?;
23//! ```
24
25pub mod openai;
26pub mod anthropic;
27pub mod ollama;
28pub mod gemini;
29pub mod error;
30
31pub use openai::OpenAiProvider;
32pub use anthropic::AnthropicProvider;
33pub use ollama::OllamaProvider;
34pub use gemini::GeminiProvider;
35pub use error::AiError;
36
37/// Re-export core types for convenience.
38pub use aether_core::{
39    AiProvider, ProviderConfig, InjectionEngine, Template, Slot,
40    InjectionContext, AetherError, Result,
41};
42
43/// Create an OpenAI provider with a single line.
44///
45/// # Example
46///
47/// ```rust,ignore
48/// let provider = aether_ai::openai("gpt-5.2-thinking");
49/// ```
50pub fn openai(model: &str) -> Result<OpenAiProvider> {
51    OpenAiProvider::from_env_with_model(model)
52}
53
54/// Create an Anthropic provider with a single line.
55///
56/// # Example
57///
58/// ```rust,ignore
59/// let provider = aether_ai::anthropic("claude-opus-4-5");
60/// ```
61pub fn anthropic(model: &str) -> Result<AnthropicProvider> {
62    AnthropicProvider::from_env_with_model(model)
63}
64
65/// Create a Google Gemini provider with a single line.
66///
67/// # Example
68///
69/// ```rust,ignore
70/// let provider = aether_ai::gemini("gemini-1.5-pro");
71/// ```
72pub fn gemini(model: &str) -> Result<GeminiProvider> {
73    match GeminiProvider::from_env() {
74        Ok(mut p) => {
75             let api_key = std::env::var("GOOGLE_API_KEY")
76                .map_err(|_| AetherError::ConfigError("GOOGLE_API_KEY not set".to_string()))?;
77             let config = ProviderConfig::new(api_key, model);
78             GeminiProvider::new(config)
79        },
80        Err(e) => Err(e)
81    }
82}
83
84/// Create a Grok (xAI) provider with a single line.
85///
86/// Uses the OpenAI-compatible API from xAI.
87/// Requires `XAI_API_KEY` environment variable.
88///
89/// # Example
90///
91/// ```rust,ignore
92/// let provider = aether_ai::grok("grok-1");
93/// ```
94pub fn grok(model: &str) -> Result<OpenAiProvider> {
95    let api_key = std::env::var("XAI_API_KEY")
96        .map_err(|_| AetherError::ConfigError("XAI_API_KEY not set".to_string()))?;
97
98    let config = ProviderConfig::new(api_key, model)
99        .with_base_url("https://api.x.ai/v1/chat/completions"); // OpenAI impl appends nothing, wait.
100    
101    // Check openai.rs implementation. It appends nothing to base_url?
102    // openai.rs: let url = self.config.base_url.as_deref().unwrap_or(OPENAI_API_URL);
103    // OPENAI_API_URL is full path.
104    // So we need full path here.
105    
106    let config = config.with_base_url("https://api.x.ai/v1/chat/completions");
107
108    OpenAiProvider::new(config)
109}
110
111/// Create an Ollama provider with a single line.
112///
113/// # Example
114///
115/// ```rust,ignore
116/// let provider = aether_ai::ollama("codellama");
117/// ```
118pub fn ollama(model: &str) -> OllamaProvider {
119    OllamaProvider::new(model)
120}