1use std::time::Duration;
7
8use clap::ValueEnum;
9
10use crate::usage::VendorSnapshot;
11use crate::widget::cli::Cli;
12
13pub const HTTP_CLIENT_TIMEOUT: Duration = Duration::from_secs(30);
16
17#[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 Deepseek,
28 Kimi,
29}
30
31impl VendorId {
32 pub fn slug(self) -> &'static str {
33 match self {
34 VendorId::Anthropic => "anthropic",
35 VendorId::Openai => "openai",
36 VendorId::Zai => "zai",
37 VendorId::Openrouter => "openrouter",
38 VendorId::Deepseek => "deepseek",
39 VendorId::Kimi => "kimi",
40 }
41 }
42
43 pub fn all() -> &'static [VendorId] {
44 &[
45 VendorId::Anthropic,
46 VendorId::Openai,
47 VendorId::Zai,
48 VendorId::Openrouter,
49 VendorId::Deepseek,
50 VendorId::Kimi,
51 ]
52 }
53}
54
55#[derive(Debug, Clone)]
58pub struct VendorOutcome {
59 pub snapshot: VendorSnapshot,
60 pub stale: bool,
61 pub last_error: Option<(u16, String)>,
62 pub cache_age: Option<std::time::Duration>,
63}
64
65#[derive(Debug, Clone)]
67pub struct RenderOpts {
68 pub format: Option<String>,
69 pub tooltip_format: Option<String>,
70 pub icon: Option<String>,
71 pub pace_tolerance: u32,
72 pub format_pace_color: bool,
73 pub tooltip_pace_pts: bool,
74}
75
76impl RenderOpts {
77 pub fn from_cli(cli: &Cli) -> Self {
78 Self {
79 format: cli.format.clone(),
80 tooltip_format: cli.tooltip_format.clone(),
81 icon: cli.icon.clone(),
82 pace_tolerance: cli.pace_tolerance,
83 format_pace_color: cli.format_pace_color,
84 tooltip_pace_pts: cli.tooltip_pace_pts,
85 }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn vendor_id_slug_round_trip() {
95 for id in VendorId::all() {
96 assert_eq!(
97 id.slug(),
98 serde_json::to_value(id).unwrap().as_str().unwrap()
99 );
100 }
101 }
102}