Skip to main content

winx_code_agent/tools/
code_map.rs

1//! Implementation of the `CodeMap` tool: tree-sitter code navigation.
2//!
3//! One tool with two operations, consolidating what used to be the separate
4//! `Outline` and `FindReferences` tools (to keep the MCP surface small). It is a
5//! thin dispatcher: it builds the corresponding internal request and delegates to
6//! the unchanged `outline` / `references` implementations, so all the tree-sitter
7//! and ranking logic is reused as-is.
8
9use std::sync::Arc;
10
11use tokio::sync::Mutex;
12use tracing::instrument;
13
14use crate::errors::{Result, WinxError};
15use crate::state::bash_state::BashState;
16use crate::types::{CodeMap, CodeMapOperation, FindReferences, Outline};
17
18#[instrument(level = "info", skip(bash_state_arc, code_map))]
19pub async fn handle_tool_call(
20    bash_state_arc: &Arc<Mutex<Option<BashState>>>,
21    code_map: CodeMap,
22) -> Result<(String, serde_json::Value)> {
23    match code_map.operation {
24        CodeMapOperation::Outline => {
25            let outline = Outline {
26                path: code_map.path,
27                max_results: code_map.max_results,
28                thread_id: code_map.thread_id,
29            };
30            crate::tools::outline::handle_tool_call(bash_state_arc, outline).await
31        }
32        CodeMapOperation::References => {
33            if code_map.name.trim().is_empty() {
34                return Err(WinxError::ArgumentParseError(
35                    "CodeMap operation 'references' requires a non-empty 'name' (the symbol to \
36                     find)."
37                        .to_string(),
38                ));
39            }
40            let find = FindReferences {
41                name: code_map.name,
42                path: code_map.path,
43                max_results: code_map.max_results,
44                thread_id: code_map.thread_id,
45            };
46            crate::tools::references::handle_tool_call(bash_state_arc, find).await
47        }
48    }
49}