Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions src/app/traverse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1516,23 +1516,45 @@ async fn finish(
})
}

/// The per-call arguments of [`search`] (`search_code` with
/// `mode = "traverse"`): what the caller of the tool supplies, and the
/// endpoint's retriever profile.
#[derive(Debug, Clone, Copy)]
pub struct TraverseRequest<'a> {
/// The workspace to walk, as the caller wrote it; it must be a directory.
pub workspace_path: &'a str,
/// The question: the start nodes come from the hybrid search for it (or
/// the name-matching stand-in when that search finds nothing).
pub query: &'a str,
/// How many results to return, 1 through 40; `None` takes `default_top_k`.
pub top_k: Option<usize>,
/// Limits of this walk; `None` takes the defaults.
pub budget: Option<&'a BudgetArgs>,
/// Rules and actions for this walk; `None` takes none.
pub steer: Option<&'a SteerArgs>,
/// The handle of an earlier walk to continue; `None` starts a new one.
pub handle: Option<&'a str>,
/// The endpoint's `[search_profiles]` entry whose retrievers find the
/// start nodes; `None` takes the default retrievers.
pub profile: Option<&'a str>,
}

/// `search_code` with `mode = "traverse"`: the workspace's SCIP index
/// (`traverse.scip_index`, relative to the workspace), the data directory
/// for traces and handles, the limits of `[traverse]` and, for the start
/// nodes, the hybrid search of `app` over the workspace with the retrievers
/// of `profile` (the endpoint's `[search_profiles]` entry, if any). An error
/// while the mode is off.
#[allow(clippy::too_many_arguments)]
pub async fn search(
app: &App,
workspace_path: &str,
query: &str,
top_k: Option<usize>,
budget: Option<&BudgetArgs>,
steer: Option<&SteerArgs>,
handle: Option<&str>,
profile: Option<&str>,
) -> Result<Value> {
pub async fn search(app: &App, request: TraverseRequest<'_>) -> Result<Value> {
let TraverseRequest {
workspace_path,
query,
top_k,
budget,
steer,
handle,
profile,
} = request;
let config = &app.config;
let limits = &config.traverse;
if !limits.enabled {
Expand Down
16 changes: 9 additions & 7 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,13 +417,15 @@ impl McpServer {
return self.answer(
traverse::search(
&self.app,
&args.workspace_path,
&args.query,
args.top_k,
budget.as_ref(),
steer.as_ref(),
handle.as_deref(),
self.search_profile.as_deref(),
traverse::TraverseRequest {
workspace_path: &args.workspace_path,
query: &args.query,
top_k: args.top_k,
budget: budget.as_ref(),
steer: steer.as_ref(),
handle: handle.as_deref(),
profile: self.search_profile.as_deref(),
},
)
.await,
);
Expand Down
19 changes: 11 additions & 8 deletions tests/cases/navigation_barrier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,15 +417,18 @@ const RUST_WALK_RESTARTED: &str =
/// One default traverse walk (`mode = "traverse"` of the service) of `query`:
/// no maps are named, so `lsp.live` runs through `[run_profile.lsp] live`.
async fn default_walk(app: &App, workspace: &Workspace, query: &str) -> Value {
local_code_intelligence::app::traverse::search(
use local_code_intelligence::app::traverse::{TraverseRequest, search};
search(
app,
&workspace.path.to_string_lossy(),
query,
Some(8),
None,
None,
None,
None,
TraverseRequest {
workspace_path: &workspace.path.to_string_lossy(),
query,
top_k: Some(8),
budget: None,
steer: None,
handle: None,
profile: None,
},
)
.await
.unwrap()
Expand Down
Loading