ai-agent 0.13.4

Idiomatic agent sdk inspired by the claude code source leak
Documentation
// Source: /data/home/swei/claudecode/openclaudecode/src/commands/usage/usage.tsx
//! API usage tracking - translated from usage.ts

use serde::{Deserialize, Serialize};

/// Rate limit information from the API
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct RateLimit {
    /// A percentage from 0 to 100
    pub utilization: Option<f64>,
    /// ISO 8601 timestamp
    #[serde(rename = "resets_at")]
    pub resets_at: Option<String>,
}

/// Extra usage information
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ExtraUsage {
    pub is_enabled: bool,
    #[serde(rename = "monthly_limit")]
    pub monthly_limit: Option<i64>,
    #[serde(rename = "used_credits")]
    pub used_credits: Option<i64>,
    pub utilization: Option<f64>,
}

/// Utilization data from the API
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Utilization {
    #[serde(rename = "five_hour")]
    pub five_hour: Option<RateLimit>,
    #[serde(rename = "seven_day")]
    pub seven_day: Option<RateLimit>,
    #[serde(rename = "seven_day_oauth_apps")]
    pub seven_day_oauth_apps: Option<RateLimit>,
    #[serde(rename = "seven_day_opus")]
    pub seven_day_opus: Option<RateLimit>,
    #[serde(rename = "seven_day_sonnet")]
    pub seven_day_sonnet: Option<RateLimit>,
    #[serde(rename = "extra_usage")]
    pub extra_usage: Option<ExtraUsage>,
}

/// Fetch utilization data from the API
/// Returns None if not a Claude AI subscriber or no profile scope
pub async fn fetch_utilization() -> Result<Utilization, String> {
    // In a real implementation, this would check auth state
    // and make the API call
    Ok(Utilization::default())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_rate_limit_default() {
        let rl = RateLimit::default();
        assert!(rl.utilization.is_none());
        assert!(rl.resets_at.is_none());
    }

    #[test]
    fn test_extra_usage_default() {
        let eu = ExtraUsage::default();
        assert!(!eu.is_enabled);
        assert!(eu.monthly_limit.is_none());
        assert!(eu.used_credits.is_none());
    }

    #[test]
    fn test_utilization_default() {
        let u = Utilization::default();
        assert!(u.five_hour.is_none());
        assert!(u.seven_day.is_none());
        assert!(u.extra_usage.is_none());
    }
}