Skip to main content

cmduse_core/
wire.rs

1//! Command Code API wire shapes shared by the CLI and the Zed extension.
2//! Field names map to the JSON via camelCase rename.
3use serde::Deserialize;
4
5#[derive(Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub struct Credits {
8    pub monthly_credits: f64,
9    #[serde(default)]
10    pub purchased_credits: f64,
11    #[serde(default)]
12    pub free_credits: f64,
13}
14
15#[derive(Deserialize)]
16#[serde(rename_all = "camelCase")]
17pub struct Window {
18    pub used: f64,
19    pub cap: f64,
20    #[serde(default)]
21    pub exceeded: bool,
22    #[serde(default)]
23    pub reset_at: Option<f64>,
24}
25
26#[derive(Deserialize, Default)]
27#[serde(rename_all = "camelCase")]
28pub struct WindowLimits {
29    #[serde(default)]
30    pub five_hour: Option<Window>,
31    #[serde(default)]
32    pub weekly: Option<Window>,
33}
34
35#[derive(Deserialize)]
36#[serde(rename_all = "camelCase")]
37pub struct CreditsResp {
38    pub credits: Credits,
39    #[serde(default)]
40    pub window_limits: WindowLimits,
41}
42
43#[derive(Deserialize)]
44pub struct SubscriptionsResp {
45    #[serde(default)]
46    pub data: Option<SubData>,
47}
48
49impl SubscriptionsResp {
50    /// The subscription data, or a "none/free" placeholder when the API
51    /// returns no `data` block.
52    pub fn data_or_free(self) -> SubData {
53        self.data.unwrap_or(SubData {
54            status: "none".into(),
55            plan_id: "free".into(),
56            current_period_end: None,
57            current_period_start: None,
58        })
59    }
60}
61
62#[derive(Deserialize)]
63#[serde(rename_all = "camelCase")]
64pub struct SubData {
65    #[serde(default)]
66    pub status: String,
67    #[serde(default)]
68    pub plan_id: String,
69    #[serde(default)]
70    pub current_period_end: Option<String>,
71    #[serde(default)]
72    pub current_period_start: Option<String>,
73}
74
75#[derive(Deserialize)]
76#[serde(rename_all = "camelCase")]
77pub struct UsageSummary {
78    // Option so a partial/unavailable summary renders as "—" rather than a
79    // fake 0. Callers that aggregate treat None as 0.
80    #[serde(default)]
81    pub total_count: Option<u64>,
82    #[serde(default)]
83    pub total_cost: Option<f64>,
84    #[serde(default)]
85    pub success_rate: Option<f64>,
86    #[serde(default)]
87    pub total_tokens_in: Option<u64>,
88    #[serde(default)]
89    pub total_tokens_out: Option<u64>,
90}