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 deepseek;
27mod fallback_policy;
28pub mod gemini_web;
29pub mod glm5;
30pub mod google;
31pub mod limits;
32#[cfg(feature = "candle-cuda")]
33pub mod local_cuda;
34pub mod pricing;
35pub mod util;
36#[cfg(not(feature = "candle-cuda"))]
37#[allow(dead_code)]
38pub mod local_cuda {
39    //! Stub when CUDA is not compiled in.
40    use super::*;
41    use anyhow::{Result, anyhow};
42    use async_trait::async_trait;
43    use futures::stream::BoxStream;
44
45    fn feature_error() -> anyhow::Error {
46        anyhow!("local_cuda requires --features candle-cuda")
47    }
48
49    /// Stub provider type when CUDA support is not compiled in.
50    ///
51    /// All methods return errors; use `cfg(feature = "candle-cuda")` for the
52    /// real implementation.
53    ///
54    /// # Examples
55    ///
56    /// ```rust
57    /// use codetether_agent::provider::local_cuda::LocalCudaProvider;
58    /// assert!(!LocalCudaProvider::is_cuda_available());
59    /// ```
60    pub struct LocalCudaProvider;
61
62    impl LocalCudaProvider {
63        pub fn new(_m: String) -> Result<Self> {
64            Err(feature_error())
65        }
66        pub fn with_model(_m: String, _p: String) -> Result<Self> {
67            Err(feature_error())
68        }
69        pub fn with_paths(
70            _m: String,
71            _p: String,
72            _t: Option<String>,
73            _a: Option<String>,
74        ) -> Result<Self> {
75            Err(feature_error())
76        }
77        pub fn is_cuda_available() -> bool {
78            false
79        }
80        pub fn device_info() -> String {
81            "CUDA unavailable".into()
82        }
83    }
84
85    #[async_trait]
86    impl Provider for LocalCudaProvider {
87        fn name(&self) -> &str {
88            "local_cuda"
89        }
90        async fn list_models(&self) -> Result<Vec<ModelInfo>> {
91            Err(feature_error())
92        }
93        async fn complete(&self, _: CompletionRequest) -> Result<CompletionResponse> {
94            Err(feature_error())
95        }
96        async fn complete_stream(
97            &self,
98            _: CompletionRequest,
99        ) -> Result<BoxStream<'static, StreamChunk>> {
100            Err(feature_error())
101        }
102    }
103
104    #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
105    pub struct LocalCudaConfig {
106        pub model_name: String,
107        pub model_path: Option<String>,
108        pub context_window: Option<usize>,
109        pub max_new_tokens: Option<usize>,
110        pub temperature: Option<f32>,
111        pub top_p: Option<f32>,
112        pub repeat_penalty: Option<f32>,
113        pub cuda_device: Option<usize>,
114    }
115
116    impl Default for LocalCudaConfig {
117        fn default() -> Self {
118            Self {
119                model_name: "qwen3.5-9b".into(),
120                model_path: None,
121                context_window: Some(8192),
122                max_new_tokens: Some(4096),
123                temperature: Some(0.7),
124                top_p: Some(0.9),
125                repeat_penalty: Some(1.1),
126                cuda_device: Some(0),
127            }
128        }
129    }
130}
131
132pub mod metrics;
133pub mod models;
134pub mod moonshot;
135pub mod openai;
136pub mod openai_codex;
137pub mod openrouter;
138pub mod retry;
139pub mod shared_http;
140pub mod stepfun;
141pub mod tetherscript_provider;
142pub mod vertex_anthropic;
143pub mod vertex_glm;
144pub mod zai;
145
146// ── Internal split modules ──────────────────────────────────────────
147
148mod init_dispatch;
149mod init_dispatch_impl;
150mod init_env;
151mod parse;
152mod registry;
153mod tenant_keys;
154mod traits;
155mod types;
156
157// ── Public re-exports (preserve the original API surface) ───────────
158
159pub use parse::parse_model_string;
160pub use registry::ProviderRegistry;
161pub use tenant_keys::{PerTaskProviderKeys, TenantProviderKeyPayload};
162pub use traits::{ModelInfo, Provider};
163pub use types::{
164    CompletionRequest, CompletionResponse, ContentPart, EmbeddingRequest, EmbeddingResponse,
165    FinishReason, Message, Role, StreamChunk, ToolDefinition, Usage,
166};
167
168// ── Initialisation modules (impls on ProviderRegistry) ──────────────
169
170mod init_config;
171mod init_vault;