Skip to main content

ai_usagebar/
vendor.rs

1//! Shared vendor IDs and renderer/fetcher structs used by the widget and TUI.
2//!
3//! Snapshots remain a discriminated `VendorSnapshot` enum because the four
4//! vendors have genuinely different shapes — see `usage.rs`.
5
6use std::time::Duration;
7
8use clap::ValueEnum;
9
10use crate::usage::VendorSnapshot;
11use crate::widget::cli::Cli;
12
13/// Outer reqwest client timeout shared by widget and TUI entry points.
14/// Vendor fetchers still apply their own tighter per-request timeouts.
15pub const HTTP_CLIENT_TIMEOUT: Duration = Duration::from_secs(30);
16
17/// Stable enum used by `--vendor` and in config files.
18#[derive(
19    Debug, Clone, Copy, ValueEnum, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize,
20)]
21#[serde(rename_all = "lowercase")]
22pub enum VendorId {
23    Anthropic,
24    Openai,
25    Zai,
26    Openrouter,
27}
28
29impl VendorId {
30    pub fn slug(self) -> &'static str {
31        match self {
32            VendorId::Anthropic => "anthropic",
33            VendorId::Openai => "openai",
34            VendorId::Zai => "zai",
35            VendorId::Openrouter => "openrouter",
36        }
37    }
38
39    pub fn all() -> &'static [VendorId] {
40        &[
41            VendorId::Anthropic,
42            VendorId::Openai,
43            VendorId::Zai,
44            VendorId::Openrouter,
45        ]
46    }
47}
48
49/// What a vendor returns from a successful fetch — snapshot + meta. Mirrors
50/// `anthropic::fetch::FetchOutcome` but vendor-agnostic.
51#[derive(Debug, Clone)]
52pub struct VendorOutcome {
53    pub snapshot: VendorSnapshot,
54    pub stale: bool,
55    pub last_error: Option<(u16, String)>,
56    pub cache_age: Option<std::time::Duration>,
57}
58
59/// Options forwarded to renderers from the CLI.
60#[derive(Debug, Clone)]
61pub struct RenderOpts {
62    pub format: Option<String>,
63    pub tooltip_format: Option<String>,
64    pub icon: Option<String>,
65    pub pace_tolerance: u32,
66    pub format_pace_color: bool,
67    pub tooltip_pace_pts: bool,
68}
69
70impl RenderOpts {
71    pub fn from_cli(cli: &Cli) -> Self {
72        Self {
73            format: cli.format.clone(),
74            tooltip_format: cli.tooltip_format.clone(),
75            icon: cli.icon.clone(),
76            pace_tolerance: cli.pace_tolerance,
77            format_pace_color: cli.format_pace_color,
78            tooltip_pace_pts: cli.tooltip_pace_pts,
79        }
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn vendor_id_slug_round_trip() {
89        for id in VendorId::all() {
90            assert_eq!(
91                id.slug(),
92                serde_json::to_value(id).unwrap().as_str().unwrap()
93            );
94        }
95    }
96}