1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7pub struct Usage {
8 #[serde(default)]
10 pub prompt_tokens: u32,
11 #[serde(default)]
13 pub completion_tokens: u32,
14 #[serde(default)]
16 pub total_tokens: u32,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub reasoning_tokens: Option<u32>,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub prompt_tokens_details: Option<PromptTokensDetails>,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub completion_tokens_details: Option<CompletionTokensDetails>,
26}
27
28impl Usage {
29 pub fn new() -> Self {
31 Self::default()
32 }
33
34 pub fn cached_tokens(&self) -> u32 {
36 self.prompt_tokens_details
37 .as_ref()
38 .and_then(|d| d.cached_tokens)
39 .unwrap_or(0)
40 }
41
42 pub fn reasoning_tokens(&self) -> u32 {
44 self.reasoning_tokens.unwrap_or(0)
45 }
46}
47
48#[derive(Debug, Clone, Default, Serialize, Deserialize)]
50pub struct PromptTokensDetails {
51 #[serde(default, skip_serializing_if = "Option::is_none")]
53 pub cached_tokens: Option<u32>,
54}
55
56#[derive(Debug, Clone, Default, Serialize, Deserialize)]
58pub struct CompletionTokensDetails {
59 #[serde(default, skip_serializing_if = "Option::is_none")]
61 pub reasoning_tokens: Option<u32>,
62}
63
64#[derive(Debug, Clone, Default, Serialize, Deserialize)]
66pub struct ServerSideToolUsage {
67 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub web_search: Option<u32>,
70 #[serde(default, skip_serializing_if = "Option::is_none")]
72 pub x_search: Option<u32>,
73 #[serde(default, skip_serializing_if = "Option::is_none")]
75 pub code_interpreter: Option<u32>,
76 #[serde(default, skip_serializing_if = "Option::is_none")]
78 pub view_image: Option<u32>,
79}