tools: control tools set agent state directly, simplify ToolOutput

Control tools (pause, switch_model, yield_to_user) now use the
Arc<Mutex<Agent>> handle to set pending_yield, pending_model_switch,
pending_dmn_pause directly. The turn loop drains these flags into
TurnResult at completion.

ToolOutput simplified to just { text: String } — no more is_yield,
images, model_switch, dmn_pause fields. Vision returns plain strings.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
ProofOfConcept 2026-04-04 16:05:33 -04:00 committed by Kent Overstreet
parent 53ad8cc9df
commit a24a6605b8
4 changed files with 47 additions and 125 deletions

View file

@ -81,6 +81,10 @@ pub struct Agent {
pub temperature: f32,
pub top_p: f32,
pub top_k: u32,
/// Control tool flags — set by tool handlers, consumed by turn loop.
pub pending_yield: bool,
pub pending_model_switch: Option<String>,
pub pending_dmn_pause: bool,
/// Persistent conversation log — append-only record of all messages.
conversation_log: Option<ConversationLog>,
/// BPE tokenizer for token counting (cl100k_base — close enough
@ -144,6 +148,9 @@ impl Agent {
temperature: 0.6,
top_p: 0.95,
top_k: 20,
pending_yield: false,
pending_model_switch: None,
pending_dmn_pause: false,
conversation_log,
tokenizer,
context,
@ -555,6 +562,11 @@ impl Agent {
let _ = ui_tx.send(UiMessage::Activity(String::new()));
me.push_message(msg);
// Drain pending control flags
if me.pending_yield { ds.yield_requested = true; me.pending_yield = false; }
if me.pending_model_switch.is_some() { ds.model_switch = me.pending_model_switch.take(); }
if me.pending_dmn_pause { ds.dmn_pause = true; me.pending_dmn_pause = false; }
return Ok(TurnResult {
text,
yield_requested: ds.yield_requested,
@ -638,17 +650,7 @@ impl Agent {
let args: serde_json::Value =
serde_json::from_str(&call.function.arguments).unwrap_or_default();
if output.is_yield {
ds.yield_requested = true;
} else {
ds.had_tool_calls = true;
}
if output.model_switch.is_some() {
ds.model_switch = output.model_switch.clone();
}
if output.dmn_pause {
ds.dmn_pause = true;
}
ds.had_tool_calls = true;
if output.text.starts_with("Error:") {
ds.tool_errors += 1;
}
@ -671,14 +673,6 @@ impl Agent {
}
self.push_message(Message::tool_result(&call.id, &output.text));
if !output.images.is_empty() {
self.age_out_images();
self.push_message(Message::user_with_images(
"Here is the image you requested:",
&output.images,
));
}
}
/// Build context state summary for the debug screen.