Skip to main content

codetether_agent/provider/
mod.rs

1//! AI Provider abstraction layer.
2//!
3//! Unified interface for multiple AI providers (OpenAI, Anthropic, Google,
4//! StepFun, Bedrock, etc.).
5//!
6//! # Architecture
7//!
8//! - [`types`] — shared data types (`Message`, `StreamChunk`, etc.)
9//! - [`traits`] — the `Provider` trait and `ModelInfo`
10//! - [`registry`] — `ProviderRegistry` (name → provider map)
11//! - [`parse`] — model-string parser (`"openai/gpt-4o"` → `(provider, model)`)
12//! - [`init_vault`] — Vault-based provider initialization
13//! - [`init_config`] — TOML-config-based initialization
14//! - [`init_env`] — environment-variable fallback
15//! - [`init_dispatch`] / [`init_dispatch_impl`] — per-provider constructors
16//!
17//! Provider implementations live in their own modules (`openai`, `anthropic`,
18//! `bedrock/`, etc.).
19
20// ── Sub-module declarations ─────────────────────────────────────────
21
22pub mod anthropic;
23pub mod bedrock;
24pub mod body_cap;
25pub mod copilot;
26pub mod gemini_web;
27pub mod glm5;
28pub mod google;
29pub mod limits;
30#[cfg(feature = "candle-cuda")]
31pub mod local_cuda;
32pub mod pricing;
33pub mod util;
34#[cfg(not(feature = "candle-cuda"))]
35#[allow(dead_code)]
36pub mod local_cuda {
37    //! Stub when CUDA is not compiled in.
38    use super::*;
39    use anyhow::{Result, anyhow};
40    use async_trait::async_trait;
41    use futures::stream::BoxStream;
42
43    fn feature_error() -> anyhow::Error {
44        anyhow!("local_cuda requires --features candle-cuda")
45    }
46
47    /// Stub provider type when CUDA support is not compiled in.
48    ///
49    /// All methods return errors; use `cfg(feature = "candle-cuda")` for the
50    /// real implementation.
51    ///
52    /// # Examples
53    ///
54    /// ```rust
55    /// use codetether_agent::provider::local_cuda::LocalCudaProvider;
56    /// assert!(!LocalCudaProvider::is_cuda_available());
57    /// ```
58    pub struct LocalCudaProvider;
59
60    impl LocalCudaProvider {
61        pub fn new(_m: String) -> Result<Self> {
62            Err(feature_error())
63        }
64        pub fn with_model(_m: String, _p: String) -> Result<Self> {
65            Err(feature_error())
66        }
67        pub fn with_paths(
68            _m: String,
69            _p: String,
70            _t: Option<String>,
71            _a: Option<String>,
72        ) -> Result<Self> {
73            Err(feature_error())
74        }
75        pub fn is_cuda_available() -> bool {
76            false
77        }
78        pub fn device_info() -> String {
79            "CUDA unavailable".into()
80        }
81    }
82
83    #[async_trait]
84    impl Provider for LocalCudaProvider {
85        fn name(&self) -> &str {
86            "local_cuda"
87        }
88        async fn list_models(&self) -> Result<Vec<ModelInfo>> {
89            Err(feature_error())
90        }
91        async fn complete(&self, _: CompletionRequest) -> Result<CompletionResponse> {
92            Err(feature_error())
93        }
94        async fn complete_stream(
95            &self,
96            _: CompletionRequest,
97        ) -> Result<BoxStream<'static, StreamChunk>> {
98            Err(feature_error())
99        }
100    }
101
102    #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
103    pub struct LocalCudaConfig {
104        pub model_name: String,
105        pub model_path: Option<String>,
106        pub context_window: Option<usize>,
107        pub max_new_tokens: Option<usize>,
108        pub temperature: Option<f32>,
109        pub top_p: Option<f32>,
110        pub repeat_penalty: Option<f32>,
111        pub cuda_device: Option<usize>,
112    }
113
114    impl Default for LocalCudaConfig {
115        fn default() -> Self {
116            Self {
117                model_name: "qwen3.5-9b".into(),
118                model_path: None,
119                context_window: Some(8192),
120                max_new_tokens: Some(4096),
121                temperature: Some(0.7),
122                top_p: Some(0.9),
123                repeat_penalty: Some(1.1),
124                cuda_device: Some(0),
125            }
126        }
127    }
128}
129
130pub mod metrics;
131pub mod models;
132pub mod moonshot;
133pub mod openai;
134pub mod openai_codex;
135pub mod openrouter;
136pub mod retry;
137pub mod shared_http;
138pub mod stepfun;
139pub mod vertex_anthropic;
140pub mod vertex_glm;
141pub mod zai;
142
143// ── Internal split modules ──────────────────────────────────────────
144
145mod init_dispatch;
146mod init_dispatch_impl;
147mod init_env;
148mod parse;
149mod registry;
150mod traits;
151mod types;
152
153// ── Public re-exports (preserve the original API surface) ───────────
154
155pub use parse::parse_model_string;
156pub use registry::ProviderRegistry;
157pub use traits::{ModelInfo, Provider};
158pub use types::{
159    CompletionRequest, CompletionResponse, ContentPart, EmbeddingRequest, EmbeddingResponse,
160    FinishReason, Message, Role, StreamChunk, ToolDefinition, Usage,
161};
162
163// ── Initialisation modules (impls on ProviderRegistry) ──────────────
164
165mod init_config;
166mod init_vault;