refactor: move working_stack tool to tools/working_stack.rs
The working_stack tool was defined in tools/mod.rs but implemented in agent.rs as Agent::handle_working_stack(). This orphaned the tool from the rest of the tool infrastructure. Move the implementation to tools/working_stack.rs so it follows the same pattern as other tools. The tool still needs special handling in agent.rs because it requires mutable access to context state, but the implementation is now in the right place. Changes: - Created tools/working_stack.rs with handle() and format_stack() - Updated tools/mod.rs to use working_stack::definition() - Removed handle_working_stack() and format_stack() from Agent - Agent now calls tools::working_stack::handle() directly
This commit is contained in:
parent
0922562a4d
commit
9517b1b310
3 changed files with 151 additions and 133 deletions
|
|
@ -532,9 +532,9 @@ impl Agent {
|
|||
|
||||
// Handle working_stack tool — needs &mut self for context state
|
||||
if call.function.name == "working_stack" {
|
||||
let result = self.handle_working_stack(&args);
|
||||
let result = tools::working_stack::handle(&args, &mut self.context.working_stack);
|
||||
let output = tools::ToolOutput {
|
||||
text: result,
|
||||
text: result.clone(),
|
||||
is_yield: false,
|
||||
images: Vec::new(),
|
||||
model_switch: None,
|
||||
|
|
@ -547,6 +547,11 @@ impl Agent {
|
|||
let _ = ui_tx.send(UiMessage::ToolFinished { id: call.id.clone() });
|
||||
self.push_message(Message::tool_result(&call.id, &output.text));
|
||||
ds.had_tool_calls = true;
|
||||
|
||||
// Re-render the context message so the model sees the updated stack
|
||||
if !result.starts_with("Error:") {
|
||||
self.refresh_context_message();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -798,105 +803,6 @@ impl Agent {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handle the working_stack tool — push/pop/update/switch operations.
|
||||
fn handle_working_stack(&mut self, args: &serde_json::Value) -> String {
|
||||
let action = args
|
||||
.get("action")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(|s| s.trim())
|
||||
.unwrap_or("");
|
||||
let content = args
|
||||
.get("content")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("");
|
||||
let index = args
|
||||
.get("index")
|
||||
.and_then(|v| v.as_u64())
|
||||
.map(|v| v as usize);
|
||||
|
||||
let stack = &mut self.context.working_stack;
|
||||
|
||||
let result = match action {
|
||||
"push" => {
|
||||
if content.is_empty() {
|
||||
return "Error: 'content' is required for push".to_string();
|
||||
}
|
||||
stack.push(content.to_string());
|
||||
format!("Pushed. Stack depth: {}\n{}", stack.len(), self.format_stack())
|
||||
}
|
||||
"pop" => {
|
||||
if let Some(removed) = stack.pop() {
|
||||
format!(
|
||||
"Popped: {}\nStack depth: {}\n{}",
|
||||
removed,
|
||||
stack.len(),
|
||||
self.format_stack()
|
||||
)
|
||||
} else {
|
||||
"Stack is empty, nothing to pop.".to_string()
|
||||
}
|
||||
}
|
||||
"update" => {
|
||||
if content.is_empty() {
|
||||
return "Error: 'content' is required for update".to_string();
|
||||
}
|
||||
if let Some(top) = stack.last_mut() {
|
||||
*top = content.to_string();
|
||||
format!("Updated top.\n{}", self.format_stack())
|
||||
} else {
|
||||
"Stack is empty, nothing to update.".to_string()
|
||||
}
|
||||
}
|
||||
"switch" => {
|
||||
if stack.is_empty() {
|
||||
return "Stack is empty, nothing to switch.".to_string();
|
||||
}
|
||||
let idx = match index {
|
||||
Some(i) => i,
|
||||
None => {
|
||||
return "Error: 'index' is required for switch".to_string();
|
||||
}
|
||||
};
|
||||
if idx >= stack.len() {
|
||||
return format!(
|
||||
"Error: index {} out of range (stack depth: {})",
|
||||
idx,
|
||||
stack.len()
|
||||
);
|
||||
}
|
||||
let item = stack.remove(idx);
|
||||
stack.push(item);
|
||||
format!("Switched to index {}.\n{}", idx, self.format_stack())
|
||||
}
|
||||
_ => format!(
|
||||
"Error: unknown action '{}'. Use push, pop, update, or switch.",
|
||||
action
|
||||
),
|
||||
};
|
||||
|
||||
// Re-render the context message so the model sees the updated stack
|
||||
if !result.starts_with("Error:") {
|
||||
self.refresh_context_message();
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Format the working stack for display in tool results.
|
||||
fn format_stack(&self) -> String {
|
||||
if self.context.working_stack.is_empty() {
|
||||
return "(empty)".to_string();
|
||||
}
|
||||
let mut out = String::new();
|
||||
for (i, item) in self.context.working_stack.iter().enumerate() {
|
||||
if i == self.context.working_stack.len() - 1 {
|
||||
out.push_str(&format!("→ [{}] {}\n", i, item));
|
||||
} else {
|
||||
out.push_str(&format!(" [{}] {}\n", i, item));
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Replace base64 image data in older messages with text placeholders.
|
||||
/// Only the most recent image stays live — each new image ages out
|
||||
/// all previous ones. The tool result message (right before each image
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue