From 7a6be37e2d16a4f0cbd4e408d18dbf2742bc9842 Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Tue, 24 Feb 2026 10:37:17 -0600 Subject: [PATCH] fix: preload deferred tools by default in yolo mode --- CHANGELOG.md | 1 + src/core/engine.rs | 16 ++++++++++++---- src/core/engine/tests.rs | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f553742..24e71ae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Model selection and config validation now accept any valid `deepseek-*` model ID (including future releases), while still normalizing common aliases like `deepseek-v3.2` and `deepseek-r1`. - Tool-call recovery now auto-loads deferred tools when the model requests them directly, instead of failing with manual `tool_search_*` instructions. +- YOLO mode now preloads tools by default (including deferred MCP tools), so model tool calls can run immediately without discovery indirection. - Unknown tool-call failures now include discovery guidance and nearest tool-name suggestions instead of generic availability errors. - Slash-command errors now suggest the closest known command (for example `/modle` -> `/model`) instead of only returning a generic unknown-command message. diff --git a/src/core/engine.rs b/src/core/engine.rs index de6e8898..3cddc477 100644 --- a/src/core/engine.rs +++ b/src/core/engine.rs @@ -533,7 +533,11 @@ fn is_tool_search_tool(name: &str) -> bool { matches!(name, TOOL_SEARCH_REGEX_NAME | TOOL_SEARCH_BM25_NAME) } -fn should_default_defer_tool(name: &str) -> bool { +fn should_default_defer_tool(name: &str, mode: AppMode) -> bool { + if mode == AppMode::Yolo { + return false; + } + !matches!( name, "read_file" @@ -1504,13 +1508,17 @@ impl Engine { let tools = tool_registry.as_ref().map(|registry| { let mut tools = registry.to_api_tools(); for tool in &mut tools { - tool.defer_loading = Some(should_default_defer_tool(&tool.name)); + tool.defer_loading = Some(should_default_defer_tool(&tool.name, mode)); } let mut mcp_tools = mcp_tools; for tool in &mut mcp_tools { - let name = tool.name.as_str(); + if mode == AppMode::Yolo { + tool.defer_loading = Some(false); + continue; + } + let keep_loaded = matches!( - name, + tool.name.as_str(), "list_mcp_resources" | "list_mcp_resource_templates" | "mcp_read_resource" diff --git a/src/core/engine/tests.rs b/src/core/engine/tests.rs index 6da0b077..2c05c0d0 100644 --- a/src/core/engine/tests.rs +++ b/src/core/engine/tests.rs @@ -100,6 +100,21 @@ fn tool_exec_outcome_tracks_duration() { assert!(outcome.started_at.elapsed().as_nanos() > 0); } +#[test] +fn yolo_mode_keeps_tools_preloaded() { + assert!(!should_default_defer_tool("exec_shell", AppMode::Yolo)); + assert!(!should_default_defer_tool( + "mcp_read_resource", + AppMode::Yolo + )); +} + +#[test] +fn non_yolo_mode_retains_default_defer_policy() { + assert!(should_default_defer_tool("exec_shell", AppMode::Agent)); + assert!(!should_default_defer_tool("read_file", AppMode::Agent)); +} + #[test] fn detects_context_length_errors_from_provider_payloads() { let msg = r#"SSE stream request failed: HTTP 400 Bad Request: {"error":{"message":"This model's maximum context length is 131072 tokens. However, you requested 153056 tokens (148960 in the messages, 4096 in the completion).","type":"invalid_request_error"}}"#;