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