vtcode_commons/ui_protocol/
activity.rs1#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
4pub enum ActivityState {
5 #[default]
6 Idle,
7 Planning,
9 PreparingFreshExecutionThread,
10 RestoringApprovedPlan,
11 Building,
13 StartingBuild,
14}
15
16impl ActivityState {
17 pub const fn is_busy(self) -> bool {
19 matches!(self, Self::PreparingFreshExecutionThread | Self::RestoringApprovedPlan | Self::StartingBuild)
20 }
21
22 pub const fn is_stage(self) -> bool {
24 matches!(self, Self::Planning | Self::Building)
25 }
26
27 pub const fn status(self) -> Option<&'static str> {
28 match self {
29 Self::Idle => None,
30 Self::Planning => Some("Planning..."),
31 Self::PreparingFreshExecutionThread => Some("Preparing fresh execution thread..."),
32 Self::RestoringApprovedPlan => Some("Restoring approved plan..."),
33 Self::Building => Some("Building..."),
34 Self::StartingBuild => Some("Starting build..."),
35 }
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::ActivityState;
42
43 #[test]
44 fn idle_has_no_status_and_is_not_busy_or_stage() {
45 assert_eq!(ActivityState::Idle.status(), None);
46 assert!(!ActivityState::Idle.is_busy());
47 assert!(!ActivityState::Idle.is_stage());
48 }
49
50 #[test]
51 fn stages_are_not_busy_but_keep_a_status() {
52 for state in [ActivityState::Planning, ActivityState::Building] {
53 assert!(!state.is_busy());
54 assert!(state.is_stage());
55 assert!(state.status().is_some());
56 }
57 assert_eq!(ActivityState::Planning.status(), Some("Planning..."));
58 assert_eq!(ActivityState::Building.status(), Some("Building..."));
59 }
60
61 #[test]
62 fn transient_handoffs_are_busy_but_not_stages() {
63 for state in [
64 ActivityState::PreparingFreshExecutionThread,
65 ActivityState::RestoringApprovedPlan,
66 ActivityState::StartingBuild,
67 ] {
68 assert!(state.is_busy());
69 assert!(!state.is_stage());
70 assert!(state.status().is_some());
71 }
72 }
73}