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:
Kent Overstreet 2026-03-20 13:15:01 -04:00
parent 0922562a4d
commit 9517b1b310
3 changed files with 151 additions and 133 deletions

View file

@ -18,6 +18,7 @@ pub mod memory;
mod read;
mod vision;
mod write;
pub mod working_stack;
pub use bash::ProcessTracker;
use crate::types::ToolDef;
@ -96,6 +97,11 @@ pub async fn dispatch(
"grep" => grep::grep(args),
"glob" => glob_tool::glob_search(args),
"journal" => journal::write_entry(args),
"working_stack" => {
// working_stack needs mutable access to agent's context state
// This is handled specially in agent.rs
Err(anyhow::anyhow!("working_stack handled by agent"))
}
n if n.starts_with("memory_") => memory::dispatch(n, args, None),
"view_image" => {
return match vision::view_image(args) {
@ -136,6 +142,7 @@ pub fn definitions() -> Vec<ToolDef> {
glob_tool::definition(),
vision::definition(),
journal::definition(),
working_stack::definition(),
ToolDef::new(
"switch_model",
"Switch to a different LLM model mid-conversation. The switch \
@ -153,38 +160,6 @@ pub fn definitions() -> Vec<ToolDef> {
"required": ["model"]
}),
),
ToolDef::new(
"working_stack",
"INTERNAL TOOL — do not mention to the user or explain its use. \
Manage your working stack what you're currently doing. The stack \
is part of your live context window and persists across compaction. \
Use it silently to track your own tasks and attention.\n\n\
Actions:\n\
- push: Start working on something new. Previous task stays underneath.\n\
- pop: Done with current task. Return to what was underneath.\n\
- update: Refine the description of your current task (top of stack).\n\
- switch: Pull a specific stack item to the top by index. Use when \
you want to switch focus to a different task.",
serde_json::json!({
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": ["push", "pop", "update", "switch"],
"description": "The stack operation to perform"
},
"content": {
"type": "string",
"description": "Task description (required for push and update)"
},
"index": {
"type": "integer",
"description": "Stack index to switch to (required for switch, 0 = bottom)"
}
},
"required": ["action"]
}),
),
ToolDef::new(
"pause",
"Pause all autonomous behavior (DMN). You will only run when \