claude_agent/tokens/
budget.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
4pub struct TokenBudget {
5 pub input_tokens: u64,
6 pub cache_read_tokens: u64,
7 pub cache_write_tokens: u64,
8 pub output_tokens: u64,
9}
10
11impl TokenBudget {
12 #[inline]
13 pub fn context_usage(&self) -> u64 {
14 self.input_tokens + self.cache_read_tokens + self.cache_write_tokens
15 }
16
17 #[inline]
18 pub fn total(&self) -> u64 {
19 self.context_usage() + self.output_tokens
20 }
21
22 pub fn add(&mut self, other: &TokenBudget) {
23 self.input_tokens = self.input_tokens.saturating_add(other.input_tokens);
24 self.cache_read_tokens = self
25 .cache_read_tokens
26 .saturating_add(other.cache_read_tokens);
27 self.cache_write_tokens = self
28 .cache_write_tokens
29 .saturating_add(other.cache_write_tokens);
30 self.output_tokens = self.output_tokens.saturating_add(other.output_tokens);
31 }
32
33 pub fn is_empty(&self) -> bool {
34 self.context_usage() == 0 && self.output_tokens == 0
35 }
36}
37
38impl From<&crate::types::Usage> for TokenBudget {
39 fn from(usage: &crate::types::Usage) -> Self {
40 Self {
41 input_tokens: usage.input_tokens as u64,
42 cache_read_tokens: usage.cache_read_input_tokens.unwrap_or(0) as u64,
43 cache_write_tokens: usage.cache_creation_input_tokens.unwrap_or(0) as u64,
44 output_tokens: usage.output_tokens as u64,
45 }
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn test_context_usage() {
55 let budget = TokenBudget {
56 input_tokens: 100,
57 cache_read_tokens: 200_000,
58 cache_write_tokens: 0,
59 output_tokens: 500,
60 };
61
62 assert_eq!(budget.context_usage(), 200_100);
63 assert_eq!(budget.total(), 200_600);
64 }
65
66 #[test]
67 fn test_add() {
68 let mut a = TokenBudget {
69 input_tokens: 100,
70 cache_read_tokens: 50,
71 cache_write_tokens: 25,
72 output_tokens: 200,
73 };
74 let b = TokenBudget {
75 input_tokens: 100,
76 cache_read_tokens: 50,
77 cache_write_tokens: 25,
78 output_tokens: 200,
79 };
80
81 a.add(&b);
82 assert_eq!(a.input_tokens, 200);
83 assert_eq!(a.cache_read_tokens, 100);
84 }
85}