Skip to main content

usage_monitor_cli/provider/
mod.rs

1pub mod abacus;
2pub mod anthropic;
3pub mod antigravity;
4pub mod claude;
5pub mod codex;
6pub mod copilot;
7pub mod cursor;
8pub mod deepgram;
9pub mod deepseek;
10pub mod devin;
11pub mod elevenlabs;
12pub mod gemini;
13pub mod grok;
14pub mod groq;
15pub mod kimi;
16pub mod kimik2;
17pub mod llmproxy;
18pub mod minimax;
19pub mod mistral;
20pub mod moonshot;
21pub mod ollama;
22pub mod openai;
23pub mod opencode_go;
24pub mod openrouter;
25pub mod perplexity;
26pub mod proto;
27pub mod registry;
28pub mod venice;
29pub mod windsurf;
30pub mod zai;
31
32use async_trait::async_trait;
33use std::collections::HashMap;
34
35use crate::error::SpendPanelError;
36use crate::model::UsageSnapshot;
37
38/// Context for fetching from a provider.
39#[derive(Debug, Clone)]
40pub struct ProviderContext {
41    /// Provider-specific configuration (key-value).
42    pub config: HashMap<String, String>,
43    /// Timeout in seconds.
44    pub timeout_secs: u64,
45}
46
47impl Default for ProviderContext {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl ProviderContext {
54    pub fn new() -> Self {
55        Self {
56            config: HashMap::new(),
57            timeout_secs: 30,
58        }
59    }
60
61    pub fn with_api_key(key: impl Into<String>) -> Self {
62        let mut ctx = Self::new();
63        ctx.config.insert("api_key".into(), key.into());
64        ctx
65    }
66}
67
68/// Provider metadata.
69#[derive(Debug, Clone)]
70pub struct ProviderMetadata {
71    pub id: &'static str,
72    pub name: &'static str,
73    pub description: &'static str,
74    pub auth_methods: &'static [&'static str],
75    pub website: Option<&'static str>,
76}
77
78/// Trait every usage provider must implement.
79#[async_trait]
80pub trait UsageProvider: Send + Sync {
81    /// Returns the provider metadata.
82    fn metadata(&self) -> &ProviderMetadata;
83
84    /// Fetches usage data.
85    async fn fetch_usage(&self, ctx: &ProviderContext) -> Result<UsageSnapshot, SpendPanelError>;
86
87    /// Whether credentials for this provider are detectable on this machine
88    /// (used to auto-enable providers without an explicit toggle).
89    fn detect_credentials(&self) -> bool {
90        false
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn test_provider_context_default() {
100        let ctx = ProviderContext::new();
101        assert!(ctx.config.is_empty());
102        assert_eq!(ctx.timeout_secs, 30);
103    }
104
105    #[test]
106    fn test_provider_context_with_api_key() {
107        let ctx = ProviderContext::with_api_key("sk-test");
108        assert_eq!(ctx.config.get("api_key").unwrap(), "sk-test");
109    }
110}