Skip to main content

seher/opencode_go/
types.rs

1use chrono::{DateTime, Utc};
2
3const LIMIT_EPSILON: f64 = 1e-9;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum OpencodeGoUsageSource {
7    LocalDatabase,
8}
9
10#[derive(Debug, Clone, PartialEq)]
11pub struct OpencodeGoUsageWindow {
12    pub entry_type: &'static str,
13    pub spent_usd: f64,
14    pub limit_usd: f64,
15    pub resets_at: Option<DateTime<Utc>>,
16}
17
18impl OpencodeGoUsageWindow {
19    /// A `limit_usd <= 0` window is **disabled** (the user opted out of this
20    /// window via env): never limited, regardless of spend.
21    #[must_use]
22    pub fn is_limited(&self) -> bool {
23        self.limit_usd > 0.0 && self.spent_usd + LIMIT_EPSILON >= self.limit_usd
24    }
25
26    #[must_use]
27    pub fn utilization(&self) -> f64 {
28        if self.limit_usd <= 0.0 {
29            0.0
30        } else {
31            self.spent_usd / self.limit_usd * 100.0
32        }
33    }
34}
35
36#[derive(Debug, Clone, PartialEq)]
37pub struct OpencodeGoUsageSnapshot {
38    pub source: OpencodeGoUsageSource,
39    pub credentials_available: bool,
40    pub total_messages: usize,
41    pub windows: Vec<OpencodeGoUsageWindow>,
42}
43
44impl OpencodeGoUsageSnapshot {
45    #[must_use]
46    pub fn reset_time(&self) -> Option<DateTime<Utc>> {
47        self.windows
48            .iter()
49            .filter(|window| window.is_limited())
50            .filter_map(|window| window.resets_at)
51            .max()
52    }
53}