unified tool dispatch: remove memory_ special case
All tools go through tools::dispatch() — no more separate dispatch path for memory tools in the runner. The only remaining special case is tagging memory_render results as ConversationEntry::Memory for context deduplication, which is a result-handling concern, not dispatch. Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
61deb7d488
commit
39d6ca3fe0
1 changed files with 14 additions and 50 deletions
|
|
@ -422,6 +422,7 @@ impl Agent {
|
|||
if let Some(ref tool_calls) = msg.tool_calls {
|
||||
if !tool_calls.is_empty() {
|
||||
self.push_message(msg.clone());
|
||||
|
||||
for call in tool_calls {
|
||||
self.dispatch_tool_call(call, None, ui_tx, &mut ds)
|
||||
.await;
|
||||
|
|
@ -499,53 +500,7 @@ impl Agent {
|
|||
return;
|
||||
}
|
||||
|
||||
// Handle memory tools — needs &mut self for node tracking
|
||||
if call.function.name.starts_with("memory_") {
|
||||
let result = tools::memory::dispatch(&call.function.name, &args, None);
|
||||
let text = match &result {
|
||||
Ok(s) => s.clone(),
|
||||
Err(e) => format!("Error: {:#}", e),
|
||||
};
|
||||
|
||||
// Disambiguate memory renders from other tool results
|
||||
let memory_key = if result.is_ok() {
|
||||
match call.function.name.as_str() {
|
||||
"memory_render" =>
|
||||
args.get("key").and_then(|v| v.as_str()).map(String::from),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let output = tools::ToolOutput {
|
||||
text,
|
||||
is_yield: false,
|
||||
images: Vec::new(),
|
||||
model_switch: None,
|
||||
dmn_pause: false,
|
||||
};
|
||||
let _ = ui_tx.send(UiMessage::ToolResult {
|
||||
name: call.function.name.clone(),
|
||||
result: output.text.clone(),
|
||||
});
|
||||
let _ = ui_tx.send(UiMessage::ToolFinished { id: call.id.clone() });
|
||||
let mut msg = Message::tool_result(&call.id, &output.text);
|
||||
msg.stamp();
|
||||
if let Some(key) = memory_key {
|
||||
self.push_entry(ConversationEntry::Memory { key, message: msg });
|
||||
} else {
|
||||
self.push_entry(ConversationEntry::Message(msg));
|
||||
}
|
||||
ds.had_tool_calls = true;
|
||||
if output.text.starts_with("Error:") {
|
||||
ds.tool_errors += 1;
|
||||
}
|
||||
|
||||
self.publish_context_state();
|
||||
return;
|
||||
}
|
||||
|
||||
// Dispatch through unified path
|
||||
let output =
|
||||
tools::dispatch(&call.function.name, &args, &self.process_tracker).await;
|
||||
|
||||
|
|
@ -555,7 +510,7 @@ impl Agent {
|
|||
ds.had_tool_calls = true;
|
||||
}
|
||||
if output.model_switch.is_some() {
|
||||
ds.model_switch = output.model_switch;
|
||||
ds.model_switch = output.model_switch.clone();
|
||||
}
|
||||
if output.dmn_pause {
|
||||
ds.dmn_pause = true;
|
||||
|
|
@ -570,11 +525,20 @@ impl Agent {
|
|||
});
|
||||
let _ = ui_tx.send(UiMessage::ToolFinished { id: call.id.clone() });
|
||||
|
||||
// Tag memory_render results for context deduplication
|
||||
if call.function.name == "memory_render" && !output.text.starts_with("Error:") {
|
||||
if let Some(key) = args.get("key").and_then(|v| v.as_str()) {
|
||||
let mut msg = Message::tool_result(&call.id, &output.text);
|
||||
msg.stamp();
|
||||
self.push_entry(ConversationEntry::Memory { key: key.to_string(), message: msg });
|
||||
self.publish_context_state();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.push_message(Message::tool_result(&call.id, &output.text));
|
||||
|
||||
if !output.images.is_empty() {
|
||||
// Only one live image in context at a time — age out any
|
||||
// previous ones to avoid accumulating ~90KB+ per image.
|
||||
self.age_out_images();
|
||||
self.push_message(Message::user_with_images(
|
||||
"Here is the image you requested:",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue