Skip to content

Commit 20192f8

Browse files
committed
made operations be not optional
1 parent fd53a1c commit 20192f8

File tree

1 file changed

+112
-129
lines changed

1 file changed

+112
-129
lines changed

crates/chat-cli/src/cli/chat/tools/fs_read.rs

Lines changed: 112 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use crate::os::Os;
4040
#[derive(Debug, Clone, Deserialize)]
4141
pub struct FsRead {
4242
// For batch operations
43-
pub operations: Option<Vec<FsReadOperation>>,
43+
pub operations: Vec<FsReadOperation>,
4444
pub summary: Option<String>,
4545
}
4646

@@ -55,146 +55,129 @@ pub enum FsReadOperation {
5555

5656
impl FsRead {
5757
pub async fn validate(&mut self, os: &Os) -> Result<()> {
58-
if let Some(operations) = &mut self.operations {
59-
if operations.is_empty() {
60-
bail!("At least one operation must be provided");
61-
}
62-
63-
for op in operations {
64-
op.validate(os).await?;
65-
}
66-
Ok(())
67-
} else {
68-
bail!("'operations' field must be provided")
58+
if self.operations.is_empty() {
59+
bail!("At least one operation must be provided");
60+
}
61+
for op in &mut self.operations {
62+
op.validate(os).await?;
6963
}
64+
Ok(())
7065
}
7166

7267
pub async fn queue_description(&self, os: &Os, updates: &mut impl Write) -> Result<()> {
73-
if let Some(operations) = &self.operations {
74-
if operations.len() == 1 {
75-
// Single operation - display without batch prefix
76-
operations[0].queue_description(os, updates).await
77-
} else {
78-
// Multiple operations - display as batch
79-
queue!(
80-
updates,
81-
style::Print("Batch fs_read operation with "),
82-
style::SetForegroundColor(Color::Green),
83-
style::Print(operations.len()),
84-
style::ResetColor,
85-
style::Print(" operations:\n")
86-
)?;
87-
88-
// Display purpose if available for batch operations
89-
let _ = display_purpose(self.summary.as_ref(), updates);
90-
91-
for (i, op) in operations.iter().enumerate() {
92-
queue!(updates, style::Print(format!("\n↱ Operation {}: ", i + 1)))?;
93-
op.queue_description(os, updates).await?;
94-
}
95-
Ok(())
96-
}
68+
if self.operations.len() == 1 {
69+
// Single operation - display without batch prefix
70+
self.operations[0].queue_description(os, updates).await
9771
} else {
98-
bail!("'operations' field must be provided")
72+
// Multiple operations - display as batch
73+
queue!(
74+
updates,
75+
style::Print("Batch fs_read operation with "),
76+
style::SetForegroundColor(Color::Green),
77+
style::Print(self.operations.len()),
78+
style::ResetColor,
79+
style::Print(" operations:\n")
80+
)?;
81+
82+
// Display purpose if available for batch operations
83+
let _ = display_purpose(self.summary.as_ref(), updates);
84+
85+
for (i, op) in self.operations.iter().enumerate() {
86+
queue!(updates, style::Print(format!("\n↱ Operation {}: ", i + 1)))?;
87+
op.queue_description(os, updates).await?;
88+
}
89+
Ok(())
9990
}
10091
}
10192

10293
pub async fn invoke(&self, os: &Os, updates: &mut impl Write) -> Result<InvokeOutput> {
103-
if let Some(operations) = &self.operations {
104-
if operations.len() == 1 {
105-
// Single operation - return result directly
106-
operations[0].invoke(os, updates).await
107-
} else {
108-
// Multiple operations - combine results
109-
let mut combined_results = Vec::new();
110-
let mut all_images = Vec::new();
111-
let mut has_non_image_ops = false;
112-
let mut success_ops = 0usize;
113-
let mut failed_ops = 0usize;
114-
115-
for (i, op) in operations.iter().enumerate() {
116-
match op.invoke(os, updates).await {
117-
Ok(result) => {
118-
success_ops += 1;
119-
120-
match &result.output {
121-
OutputKind::Text(text) => {
122-
combined_results.push(format!(
123-
"=== Operation {} Result (Text) ===\n{}",
124-
i + 1,
125-
text
126-
));
127-
has_non_image_ops = true;
128-
},
129-
OutputKind::Json(json) => {
130-
combined_results.push(format!(
131-
"=== Operation {} Result (Json) ===\n{}",
132-
i + 1,
133-
serde_json::to_string_pretty(json)?
134-
));
135-
has_non_image_ops = true;
136-
},
137-
OutputKind::Images(images) => {
138-
all_images.extend(images.clone());
139-
combined_results.push(format!(
140-
"=== Operation {} Result (Images) ===\n[{} images processed]",
141-
i + 1,
142-
images.len()
143-
));
144-
},
145-
// This branch won't be reached because single operation execution never returns a Mixed
146-
// result
147-
OutputKind::Mixed { text: _, images: _ } => {},
148-
}
149-
},
150-
151-
Err(err) => {
152-
failed_ops += 1;
153-
combined_results.push(format!("=== Operation {} Error ===\n{}", i + 1, err));
154-
},
155-
}
94+
if self.operations.len() == 1 {
95+
// Single operation - return result directly
96+
self.operations[0].invoke(os, updates).await
97+
} else {
98+
// Multiple operations - combine results
99+
let mut combined_results = Vec::new();
100+
let mut all_images = Vec::new();
101+
let mut has_non_image_ops = false;
102+
let mut success_ops = 0usize;
103+
let mut failed_ops = 0usize;
104+
105+
for (i, op) in self.operations.iter().enumerate() {
106+
match op.invoke(os, updates).await {
107+
Ok(result) => {
108+
success_ops += 1;
109+
110+
match &result.output {
111+
OutputKind::Text(text) => {
112+
combined_results.push(format!("=== Operation {} Result (Text) ===\n{}", i + 1, text));
113+
has_non_image_ops = true;
114+
},
115+
OutputKind::Json(json) => {
116+
combined_results.push(format!(
117+
"=== Operation {} Result (Json) ===\n{}",
118+
i + 1,
119+
serde_json::to_string_pretty(json)?
120+
));
121+
has_non_image_ops = true;
122+
},
123+
OutputKind::Images(images) => {
124+
all_images.extend(images.clone());
125+
combined_results.push(format!(
126+
"=== Operation {} Result (Images) ===\n[{} images processed]",
127+
i + 1,
128+
images.len()
129+
));
130+
},
131+
// This branch won't be reached because single operation execution never returns a Mixed
132+
// result
133+
OutputKind::Mixed { text: _, images: _ } => {},
134+
}
135+
},
136+
137+
Err(err) => {
138+
failed_ops += 1;
139+
combined_results.push(format!("=== Operation {} Error ===\n{}", i + 1, err));
140+
},
156141
}
142+
}
157143

158-
queue!(
159-
updates,
160-
style::Print("\n"),
161-
style::Print(CONTINUATION_LINE),
162-
style::Print("\n")
163-
)?;
164-
super::queue_function_result(
165-
&format!(
166-
"Summary: {} operations processed, {} successful, {} failed",
167-
operations.len(),
168-
success_ops,
169-
failed_ops
170-
),
171-
updates,
172-
false,
173-
true,
174-
)?;
175-
176-
let combined_text = combined_results.join("\n\n");
177-
178-
if !all_images.is_empty() && has_non_image_ops {
179-
queue!(updates, style::Print("\nherherherherherh"),)?;
180-
Ok(InvokeOutput {
181-
output: OutputKind::Mixed {
182-
text: combined_text,
183-
images: all_images,
184-
},
185-
})
186-
} else if !all_images.is_empty() {
187-
Ok(InvokeOutput {
188-
output: OutputKind::Images(all_images),
189-
})
190-
} else {
191-
Ok(InvokeOutput {
192-
output: OutputKind::Text(combined_text),
193-
})
194-
}
144+
queue!(
145+
updates,
146+
style::Print("\n"),
147+
style::Print(CONTINUATION_LINE),
148+
style::Print("\n")
149+
)?;
150+
super::queue_function_result(
151+
&format!(
152+
"Summary: {} operations processed, {} successful, {} failed",
153+
self.operations.len(),
154+
success_ops,
155+
failed_ops
156+
),
157+
updates,
158+
false,
159+
true,
160+
)?;
161+
162+
let combined_text = combined_results.join("\n\n");
163+
164+
if !all_images.is_empty() && has_non_image_ops {
165+
queue!(updates, style::Print("\nherherherherherh"),)?;
166+
Ok(InvokeOutput {
167+
output: OutputKind::Mixed {
168+
text: combined_text,
169+
images: all_images,
170+
},
171+
})
172+
} else if !all_images.is_empty() {
173+
Ok(InvokeOutput {
174+
output: OutputKind::Images(all_images),
175+
})
176+
} else {
177+
Ok(InvokeOutput {
178+
output: OutputKind::Text(combined_text),
179+
})
195180
}
196-
} else {
197-
bail!("'operations' field must be provided")
198181
}
199182
}
200183
}

0 commit comments

Comments
 (0)