Skip to main content

wisp/conversation/
turn.rs

1/// Context-window usage as the status line displays it.
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub struct ContextUsageDisplay {
4    pub used_tokens: u32,
5    pub limit_tokens: u32,
6}
7
8impl ContextUsageDisplay {
9    pub fn used_ratio(&self) -> f64 {
10        if self.limit_tokens == 0 {
11            return 0.0;
12        }
13        (f64::from(self.used_tokens) / f64::from(self.limit_tokens)).clamp(0.0, 1.0)
14    }
15}
16
17#[derive(Debug, Default)]
18pub struct TurnState {
19    prompt_in_flight: bool,
20    compaction_active: bool,
21    context_usage: Option<ContextUsageDisplay>,
22    spinner_tick: usize,
23}
24
25impl TurnState {
26    pub fn is_prompt_in_flight(&self) -> bool {
27        self.prompt_in_flight
28    }
29
30    pub fn set_prompt_in_flight(&mut self, value: bool) {
31        self.prompt_in_flight = value;
32    }
33
34    pub fn is_compaction_active(&self) -> bool {
35        self.compaction_active
36    }
37
38    pub fn set_compaction_active(&mut self, value: bool) {
39        self.compaction_active = value;
40    }
41
42    pub fn set_context_usage(&mut self, context_usage: Option<ContextUsageDisplay>) {
43        self.context_usage = context_usage;
44    }
45
46    pub fn context_usage(&self) -> Option<ContextUsageDisplay> {
47        self.context_usage
48    }
49
50    pub fn spinner_tick(&self) -> usize {
51        self.spinner_tick
52    }
53
54    pub fn advance_spinner(&mut self) {
55        self.spinner_tick = self.spinner_tick.wrapping_add(1);
56    }
57
58    pub fn reset(&mut self) {
59        let spinner_tick = self.spinner_tick;
60        *self = Self { spinner_tick, ..Self::default() };
61    }
62}