Skip to main content

ai_agent/services/api/
usage.rs

1// Source: /data/home/swei/claudecode/openclaudecode/src/commands/usage/usage.tsx
2//! API usage tracking - translated from usage.ts
3
4use serde::{Deserialize, Serialize};
5
6/// Rate limit information from the API
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8pub struct RateLimit {
9    /// A percentage from 0 to 100
10    pub utilization: Option<f64>,
11    /// ISO 8601 timestamp
12    #[serde(rename = "resets_at")]
13    pub resets_at: Option<String>,
14}
15
16/// Extra usage information
17#[derive(Debug, Clone, Serialize, Deserialize, Default)]
18pub struct ExtraUsage {
19    pub is_enabled: bool,
20    #[serde(rename = "monthly_limit")]
21    pub monthly_limit: Option<i64>,
22    #[serde(rename = "used_credits")]
23    pub used_credits: Option<i64>,
24    pub utilization: Option<f64>,
25}
26
27/// Utilization data from the API
28#[derive(Debug, Clone, Serialize, Deserialize, Default)]
29pub struct Utilization {
30    #[serde(rename = "five_hour")]
31    pub five_hour: Option<RateLimit>,
32    #[serde(rename = "seven_day")]
33    pub seven_day: Option<RateLimit>,
34    #[serde(rename = "seven_day_oauth_apps")]
35    pub seven_day_oauth_apps: Option<RateLimit>,
36    #[serde(rename = "seven_day_opus")]
37    pub seven_day_opus: Option<RateLimit>,
38    #[serde(rename = "seven_day_sonnet")]
39    pub seven_day_sonnet: Option<RateLimit>,
40    #[serde(rename = "extra_usage")]
41    pub extra_usage: Option<ExtraUsage>,
42}
43
44/// Fetch utilization data from the API
45/// Returns None if not a Claude AI subscriber or no profile scope
46pub async fn fetch_utilization() -> Result<Utilization, String> {
47    // In a real implementation, this would check auth state
48    // and make the API call
49    Ok(Utilization::default())
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn test_rate_limit_default() {
58        let rl = RateLimit::default();
59        assert!(rl.utilization.is_none());
60        assert!(rl.resets_at.is_none());
61    }
62
63    #[test]
64    fn test_extra_usage_default() {
65        let eu = ExtraUsage::default();
66        assert!(!eu.is_enabled);
67        assert!(eu.monthly_limit.is_none());
68        assert!(eu.used_credits.is_none());
69    }
70
71    #[test]
72    fn test_utilization_default() {
73        let u = Utilization::default();
74        assert!(u.five_hour.is_none());
75        assert!(u.seven_day.is_none());
76        assert!(u.extra_usage.is_none());
77    }
78}