vtcode_commons/ui_protocol/
progress.rs1use std::sync::atomic::{AtomicU64, Ordering};
2use std::time::Instant;
3
4static NEXT_OPERATION: AtomicU64 = AtomicU64::new(1);
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct ProgressOperation {
9 id: u64,
10 started_at: Instant,
11}
12
13impl ProgressOperation {
14 pub fn start() -> Self {
15 Self {
16 id: NEXT_OPERATION.fetch_add(1, Ordering::Relaxed),
17 started_at: Instant::now(),
18 }
19 }
20
21 pub fn id(self) -> u64 {
22 self.id
23 }
24
25 pub fn started_at(self) -> Instant {
26 self.started_at
27 }
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum ProgressPhase {
33 Initializing,
34 PreparingContext,
35 SavingCheckpoint,
36 WaitingForModel,
37 Processing,
38 ReceivingResponse,
39 Retrying,
40 CheckingPermissions,
41 WaitingForApproval,
42 RunningTools,
43}
44
45impl ProgressPhase {
46 pub fn label(self) -> &'static str {
47 match self {
48 Self::Initializing => "Initializing session",
49 Self::PreparingContext => "Preparing context",
50 Self::SavingCheckpoint => "Saving checkpoint",
51 Self::WaitingForModel => "Waiting for model",
52 Self::Processing => "Processing",
53 Self::ReceivingResponse => "Receiving response",
54 Self::Retrying => "Retrying request",
55 Self::CheckingPermissions => "Checking permissions",
56 Self::WaitingForApproval => "Waiting for approval",
57 Self::RunningTools => "Running tools",
58 }
59 }
60
61 pub fn is_animated(self) -> bool {
62 self != Self::WaitingForApproval
63 }
64
65 pub fn format(self, elapsed_secs: u64) -> String {
66 if elapsed_secs == 0 {
67 self.label().to_string()
68 } else {
69 format!("{} ยท {elapsed_secs}s", self.label())
70 }
71 }
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum ProgressUpdate {
76 Begin {
77 operation: ProgressOperation,
78 phase: ProgressPhase,
79 },
80 Phase {
81 operation: ProgressOperation,
82 phase: ProgressPhase,
83 },
84 Finish {
85 operation: ProgressOperation,
86 },
87}