Add MCP for SubAgents / BrowserMode for Mention Menu Item#2377
Conversation
…ings This commit addresses several critical configuration path issues: 1. Environment Variable Fallback: codewhale_home() and legacy_deepseek_home() now explicitly check the $HOME environment variable before falling back to dirs::home_dir(). This fixes a bug on Windows where dirs::home_dir() could resolve to a different path than $HOME, causing split configuration states. 2. Robust Settings Migration: Added migrate_settings_if_needed() to safely migrate settings.toml from legacy DeepSeek folders (and Windows AppData) to the new CodeWhale configuration directory. 3. Loud Migration Exit: If any configuration or settings files are migrated on startup, the application now loudly notifies the user with colorful terminal output, displaying the exact paths to the new and legacy files, and safely exits to ensure the user verifies the new configuration before continuing.
fix: resolve configuration mismatch and implement loud migration warnings
This commit replaces the hardcoded MENTION_MENU_LIMIT (previously hardcoded to 6) with a configurable mention_menu_limit setting in settings.toml. The default limit is now increased to 128. This allows users to view and scroll through a much larger list of candidate files when using the @-mention popup in the composer widget, significantly improving the file search experience in large workspaces.
feat: make mention menu limit configurable (fixes Hmbown#2360)
This commit introduces significant enhancements to the @-mention file completion menu: 1. Mention Menu Behavior (mention_menu_behavior): Adds a new setting to toggle between uzzy (default) and �rowser mode. In �rowser mode, the menu acts as a strict directory-level file browser, making it much easier to navigate through specific folders without fuzzy matching cluttering the results. 2. Configurable Walk Depth (mention_walk_depth): Replaces the hardcoded COMPLETIONS_WALK_DEPTH of 6 with a configurable setting. Users with deeply-nested workspaces can increase this to ensure deep files are discovered, or set it to 0 for unlimited depth (with caution). 3. Local Reference Path Scanning: Increases the LOCAL_REFERENCE_SCAN_LIMIT from 4,096 to 100,000, ensuring massive repositories can fully populate the completion menu when requested.
# Conflicts: # crates/tui/src/settings.rs # crates/tui/src/tui/app.rs
feat: add mention menu browser mode and configure walk depth
This commit allows subagents to inherit the main agent's MCP tool pool. Previously, subagents did not have the MCP tool pool attached to their runtime, meaning they were unable to call MCP tools even when the user had them enabled. This passes the mcp_pool down when initializing the SubAgentRuntime and wires it up to the SubAgentToolRegistry.
feat: allow subagents to inherit MCP tool access
Adds balance cost calculation for the Xiaomi provider. It allows mimo models to pass through the pricing checks and wires Xiaomi into the /balance command scaffold.
feat: Implement Xiaomi Balance Cost Tracking
There was a problem hiding this comment.
Code Review
This pull request introduces configuration and settings migration from legacy paths to the new codewhale directory, wires up MCP tools to subagents, adds Xiaomi to the balance command, and implements configurable @-mention file completion behaviors (including a new directory-level browser mode and configurable walk depth/limits). Feedback focuses on critical performance and correctness issues in the workspace file completion logic: specifically, the risk of UI freezes due to an excessively high LOCAL_REFERENCE_SCAN_LIMIT combined with an unlimited default walk depth, incorrect path splitting on mixed-separator paths (Windows), and inefficient string allocations during case-insensitive sorting.
| } | ||
|
|
||
| const LOCAL_REFERENCE_SCAN_LIMIT: usize = 4096; | ||
| const LOCAL_REFERENCE_SCAN_LIMIT: usize = 100000; |
There was a problem hiding this comment.
Increasing LOCAL_REFERENCE_SCAN_LIMIT to 100,000 combined with default_mention_walk_depth being 0 (unlimited) and git_ignore(false) means that on every single keystroke when typing a path-like mention (e.g., @src/), the TUI will synchronously walk up to 100,000 files on the main UI thread. This will completely freeze the user interface on medium-to-large repositories. Please keep this limit much lower (e.g., 4096 or 10000) and ensure the default walk depth is bounded.
| const LOCAL_REFERENCE_SCAN_LIMIT: usize = 100000; | |
| const LOCAL_REFERENCE_SCAN_LIMIT: usize = 4096; |
| fn default_mention_walk_depth() -> usize { | ||
| 0 | ||
| } |
There was a problem hiding this comment.
The doc comment for mention_walk_depth states that the default is 6, and 0 means unlimited depth (use with caution). However, default_mention_walk_depth() is implemented to return 0. This means by default, users will have unlimited walk depth, which can cause severe performance issues in large repositories. Please change the default to 6 to match the documentation and prevent accidental performance degradation.
fn default_mention_walk_depth() -> usize {
6
}| let (walk_depth, cwd_walk_root, root_walk_root) = if self.mention_menu_behavior == crate::settings::MentionMenuBehavior::Browser { | ||
| let dir_prefix = if let Some((dir, _)) = partial.rsplit_once('/') { | ||
| Some(dir) | ||
| } else if let Some((dir, _)) = partial.rsplit_once('\\') { | ||
| Some(dir) | ||
| } else { | ||
| None | ||
| }; | ||
|
|
||
| let cwd_walk_root = if let Some(cwd) = self.cwd.as_deref() { | ||
| if let Some(p) = dir_prefix { Some(cwd.join(p)) } else { Some(cwd.to_path_buf()) } | ||
| } else { | ||
| None | ||
| }; | ||
| let root_walk_root = if let Some(p) = dir_prefix { self.root.join(p) } else { self.root.clone() }; | ||
| (1, cwd_walk_root, root_walk_root) | ||
| } else { | ||
| (self.walk_depth, self.cwd.clone(), self.root.clone()) | ||
| }; |
There was a problem hiding this comment.
The code splits partial using rsplit_once('/') first, and only if that fails, it tries rsplit_once('\\'). In mixed-separator paths (common on Windows, e.g., foo/bar\baz), this will split at the / instead of the rightmost separator \. This results in an incorrect dir_prefix (foo instead of foo/bar), which breaks directory-level completion walks because the walk depth is set to 1 and it won't descend into bar. Using rfind to find the rightmost separator of either / or \ is much more robust.
let (walk_depth, cwd_walk_root, root_walk_root) = if self.mention_menu_behavior == crate::settings::MentionMenuBehavior::Browser {
let dir_prefix = partial
.rfind(|c| c == '/' || c == '\\')
.map(|idx| &partial[..idx]);
let cwd_walk_root = if let Some(cwd) = self.cwd.as_deref() {
if let Some(p) = dir_prefix { Some(cwd.join(p)) } else { Some(cwd.to_path_buf()) }
} else {
None
};
let root_walk_root = if let Some(p) = dir_prefix { self.root.join(p) } else { self.root.clone() };
(1, cwd_walk_root, root_walk_root)
} else {
(self.walk_depth, self.cwd.clone(), self.root.clone())
};| let filter_str = if let Some((_, f)) = partial.rsplit_once('/') { | ||
| f | ||
| } else if let Some((_, f)) = partial.rsplit_once('\\') { | ||
| f | ||
| } else { | ||
| partial | ||
| }; |
There was a problem hiding this comment.
Similar to the directory prefix splitting issue, using rsplit_once('/') first will fail to correctly identify the rightmost filename filter in mixed-separator paths (e.g., foo/bar\.baz). This causes filter_str to be evaluated as bar\.baz instead of .baz, which prevents dotfile filtering from working correctly when the user explicitly types a dotfile. Using rfind avoids this issue.
let filter_str = partial
.rfind(|c| c == '/' || c == '\\')
.map(|idx| &partial[idx + 1..])
.unwrap_or(partial);| prefix_hits.sort_by(|a, b| a.to_ascii_lowercase().cmp(&b.to_ascii_lowercase())); | ||
| substring_hits.sort_by(|a, b| a.to_ascii_lowercase().cmp(&b.to_ascii_lowercase())); |
There was a problem hiding this comment.
Calling to_ascii_lowercase() on every comparison in sort_by allocates a new String each time. Since sorting is an O(N log N) operation, this results in a large number of temporary allocations. You can perform an allocation-free case-insensitive comparison by comparing character/byte iterators directly.
prefix_hits.sort_by(|a, b| {
let a_iter = a.as_bytes().iter().map(|&b| b.to_ascii_lowercase());
let b_iter = b.as_bytes().iter().map(|&b| b.to_ascii_lowercase());
a_iter.cmp(b_iter)
});
substring_hits.sort_by(|a, b| {
let a_iter = a.as_bytes().iter().map(|&b| b.to_ascii_lowercase());
let b_iter = b.as_bytes().iter().map(|&b| b.to_ascii_lowercase());
a_iter.cmp(b_iter)
});…i Mimo pricing, fix exhaustive matches
|
I've pushed the fixes for the issues raised in the review. Here is a summary of the updates:
All tests have been updated and are passing successfully locally! |
This PR adds several critical fixes for CodeWhale that were encountered during the first evaluation phase. It adds MCP support for subagents and adds an option to turn the menu mention into a simple file browser. It also adds several important fixes to support Xiaomi Mimo v2.5.
Testing
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-featurescargo test --workspace --all-featuresChecklist
Greptile Summary
This PR adds MCP tool support for subagents, introduces a configurable file-browser mode for the
@-mention menu, and wires in Xiaomi (Mimo v2.5) as a new API provider alongside a config migration that notifies users and exits cleanly on first run.SubAgentRuntimegains an optionalmcp_poolfield; the engine propagates the parent's pool to child runtimes so subagents can invoke MCP tools. Thewith_mcp_toolsdead-code suppression is removed now that the builder is actively used.Workspaceis extended withwalk_depth,mention_scan_limit, andmention_menu_behavior;MentionMenuBehavior::Browserlimits the walk to one directory level, skips frecency re-ranking, and sorts results case-insensitively. The hard-codedMENTION_MENU_LIMIT = 6constant is replaced by the per-app setting.ApiProvider::Xiaomiintegration with pricing formimo-v2.5-proandmimo-v2.5; unknownmimo-*models returnNonefrom pricing. Config migration now returns aboolso the caller can print a one-time notice and exit cleanly viareturn Ok(()).Confidence Score: 4/5
Safe to merge for most users; one correctness gap in mention resolution affects users who explicitly raise mention_scan_limit above 4096.
The new mention_scan_limit setting is correctly threaded into the autocomplete popup and Workspace internals, but context_references_from_input and local_context_from_file_mentions both hard-code the limit to 4096 when constructing their resolution workspace. For users who increase the setting to surface files in a large monorepo, those files will appear in the completion menu but then silently fail to resolve when the message is sent. All other changes look self-consistent and correct.
crates/tui/src/tui/file_mention.rs hard-codes a 4096 scan limit in two resolution functions; the three test_*.rs scripts at the repo root should also be removed.
Important Files Changed
mention_scan_limitis hardcoded to 4096 incontext_references_from_inputandlocal_context_from_file_mentions, making the user-configured setting ineffective for actual mention resolution at message-send time.Sequence Diagram
sequenceDiagram participant Engine participant McpPool participant SubAgentRuntime participant SubAgentToolRegistry participant McpTool Engine->>McpPool: ensure_mcp_pool() (if Feature::Mcp enabled) McpPool-->>Engine: "Arc<Mutex<McpPool>>" Engine->>SubAgentRuntime: new(...).with_mcp_pool(pool) Engine->>SubAgentRuntime: background_runtime() SubAgentRuntime->>SubAgentToolRegistry: build registry SubAgentToolRegistry->>SubAgentToolRegistry: with_full_agent_surface(...) alt mcp_pool is Some SubAgentToolRegistry->>SubAgentToolRegistry: with_mcp_tools(Arc::clone(pool)) end SubAgentToolRegistry-->>SubAgentRuntime: registered tools incl. MCP SubAgentRuntime->>McpTool: execute MCP tool call McpTool-->>SubAgentRuntime: resultReviews (2): Last reviewed commit: "Fix Codewhale PR 2377 issues: Make scan ..." | Re-trigger Greptile