vtcode_commons/ui_protocol/
tool_summary.rs1use crate::tool_types::CompactStr;
4
5pub type ToolOutputId = u64;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct CompactActivityMetadata {
20 pub group_id: u64,
22 pub command_count: usize,
24 pub command: Option<CompactStr>,
26 pub hidden_line_count: usize,
28 pub suffix: Option<CompactStr>,
30 pub review_anchor: Option<ToolOutputId>,
32 pub review_anchors: Vec<ToolOutputId>,
38}
39
40impl CompactActivityMetadata {
41 pub fn display_text(&self) -> String {
43 let mut text = if self.command_count > 1 {
44 format!("• Ran {} commands", self.command_count)
45 } else {
46 format!("• Ran {}", self.command.as_deref().unwrap_or("command"))
47 };
48
49 if self.command_count == 1 && self.hidden_line_count > 0 {
50 text.push_str(&format!(" · … +{} lines", self.hidden_line_count));
51 }
52 if let Some(suffix) = self.suffix.as_deref().filter(|suffix| !suffix.is_empty()) {
53 text.push_str(" · ");
54 text.push_str(suffix);
55 }
56 text
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct DiffReviewAnchor {
66 pub file_path: String,
68 pub unified: String,
70 pub omitted_lines: u64,
72 pub notice: String,
74}
75
76#[must_use]
78pub fn is_generic_diff_review_path(path: &str) -> bool {
79 path.is_empty() || path == "diff" || path == "file" || path.starts_with("diff.")
80}
81
82#[must_use]
87pub fn diff_review_notice(file_path: &str, omitted_lines: u64, safety_capped: bool) -> String {
88 let _ = safety_capped;
89 if omitted_lines > 0 {
90 format!("… +{omitted_lines} lines — review full diff for {file_path}")
91 } else {
92 format!("… diff truncated — review full diff for {file_path}")
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::CompactActivityMetadata;
99
100 #[test]
101 fn compact_activity_display_includes_single_command_output_count() {
102 let activity = CompactActivityMetadata {
103 group_id: 1,
104 command_count: 1,
105 command: Some("cargo check".into()),
106 hidden_line_count: 3,
107 suffix: None,
108 review_anchor: Some(7),
109 review_anchors: vec![7],
110 };
111
112 assert_eq!(activity.display_text(), "• Ran cargo check · … +3 lines");
113 }
114
115 #[test]
116 fn compact_activity_display_collapses_grouped_commands() {
117 let activity = CompactActivityMetadata {
118 group_id: 2,
119 command_count: 4,
120 command: None,
121 hidden_line_count: 12,
122 suffix: Some("output retained".into()),
123 review_anchor: Some(9),
124 review_anchors: vec![9],
125 };
126
127 assert_eq!(activity.display_text(), "• Ran 4 commands · output retained");
128 }
129}
130
131#[derive(Debug, Clone, PartialEq, Eq)]
132pub struct CompactToolSummaryLine {
133 pub kind: CompactToolSummaryLineKind,
134 pub text: String,
135}
136
137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138pub enum CompactToolSummaryLineKind {
139 Info,
140 Detail,
141}