Skip to main content

mermaid_cli/tui/state/
generation.rs

1//! Generation state machine
2//!
3//! Tracks the application lifecycle during model interactions.
4
5use std::time::Instant;
6
7/// Generation status for the status line
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum GenerationStatus {
10    /// Not currently generating
11    Idle,
12    /// Message sent upstream, waiting for model to start responding
13    Sending,
14    /// Waiting for first token from model (thinking/reasoning)
15    Thinking,
16    /// Actively receiving and displaying tokens
17    Streaming,
18}
19
20impl GenerationStatus {
21    pub fn display_text(&self) -> &str {
22        match self {
23            GenerationStatus::Idle => "Idle",
24            GenerationStatus::Sending => "Sending",
25            GenerationStatus::Thinking => "Thinking",
26            GenerationStatus::Streaming => "Streaming",
27        }
28    }
29}
30
31/// Comprehensive state machine for the application lifecycle
32/// Impossible states become impossible to represent
33#[derive(Debug, Clone)]
34pub enum AppState {
35    /// Idle - not doing anything, ready for input
36    Idle,
37
38    /// Currently generating a response from the model
39    Generating {
40        status: GenerationStatus,
41        start_time: Instant,
42        tokens_received: usize,
43        abort_handle: Option<tokio::task::AbortHandle>,
44        /// Accumulated streaming response text for this model call
45        response_buffer: String,
46    },
47}
48
49impl AppState {
50    /// Get generation status if we're generating
51    pub fn generation_status(&self) -> Option<GenerationStatus> {
52        match self {
53            AppState::Generating { status, .. } => Some(*status),
54            _ => None,
55        }
56    }
57
58    /// Check if we're currently generating
59    pub fn is_generating(&self) -> bool {
60        matches!(self, AppState::Generating { .. })
61    }
62
63    /// Check if we're idle
64    pub fn is_idle(&self) -> bool {
65        matches!(self, AppState::Idle)
66    }
67
68    /// Get generation start time if we're generating
69    pub fn generation_start_time(&self) -> Option<Instant> {
70        match self {
71            AppState::Generating { start_time, .. } => Some(*start_time),
72            _ => None,
73        }
74    }
75
76    /// Get tokens received if we're generating
77    pub fn tokens_received(&self) -> Option<usize> {
78        match self {
79            AppState::Generating {
80                tokens_received, ..
81            } => Some(*tokens_received),
82            _ => None,
83        }
84    }
85
86    /// Get abort handle if we're generating
87    pub fn abort_handle(&self) -> Option<&tokio::task::AbortHandle> {
88        match self {
89            AppState::Generating { abort_handle, .. } => abort_handle.as_ref(),
90            _ => None,
91        }
92    }
93}