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 CheckingToolOutput,
44}
45
46impl ProgressPhase {
47 pub fn label(self) -> &'static str {
48 match self {
49 Self::Initializing => "Initializing session",
50 Self::PreparingContext => "Preparing context",
51 Self::SavingCheckpoint => "Saving checkpoint",
52 Self::WaitingForModel => "Waiting for model",
53 Self::Processing => "Processing",
54 Self::ReceivingResponse => "Receiving response",
55 Self::Retrying => "Retrying request",
56 Self::CheckingPermissions => "Checking permissions",
57 Self::WaitingForApproval => "Waiting for approval",
58 Self::RunningTools => "Running tools",
59 Self::CheckingToolOutput => "Checking tool output...",
60 }
61 }
62
63 pub fn is_animated(self) -> bool {
64 self != Self::WaitingForApproval
65 }
66
67 pub fn format(self, elapsed_secs: u64) -> String {
68 if elapsed_secs == 0 {
69 self.label().to_string()
70 } else {
71 format!("{} ยท {elapsed_secs}s", self.label())
72 }
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub enum ProgressUpdate {
78 Begin {
79 operation: ProgressOperation,
80 phase: ProgressPhase,
81 },
82 Phase {
83 operation: ProgressOperation,
84 phase: ProgressPhase,
85 },
86 Finish {
87 operation: ProgressOperation,
88 },
89}