steer_core/app/
cancellation.rs

1use std::fmt;
2
3/// Identifies a tool that was active during cancellation
4#[derive(Debug, Clone)]
5pub struct ActiveTool {
6    pub id: String,   // The unique tool call ID
7    pub name: String, // The name of the tool (e.g., "Bash", "GlobTool")
8}
9
10impl fmt::Display for ActiveTool {
11    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12        write!(f, "{} (ID: {})", self.name, self.id)
13    }
14}
15
16/// Represents the state of operations when cancellation occurred
17#[derive(Debug, Clone)]
18pub struct CancellationInfo {
19    /// Whether there was an API call in progress
20    pub api_call_in_progress: bool,
21
22    /// Tools that were active at cancellation time
23    pub active_tools: Vec<ActiveTool>,
24
25    /// Whether there were tools pending approval
26    pub pending_tool_approvals: bool,
27}
28
29impl fmt::Display for CancellationInfo {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        let mut activities = Vec::new();
32
33        if self.api_call_in_progress {
34            activities.push("API call".to_string());
35        }
36
37        if !self.active_tools.is_empty() {
38            if self.active_tools.len() == 1 {
39                activities.push(format!("tool execution: {}", self.active_tools[0]));
40            } else {
41                activities.push(format!(
42                    "multiple tool executions ({} tools)",
43                    self.active_tools.len()
44                ));
45            }
46        }
47
48        if self.pending_tool_approvals {
49            activities.push("waiting for tool approval".to_string());
50        }
51
52        if activities.is_empty() {
53            write!(f, "no active operations")
54        } else {
55            write!(f, "{}", activities.join(", "))
56        }
57    }
58}