use std::io::Write;
use anyhow::Result;
use clap::Subcommand;
use crate::mcp::BasemindServer;
use crate::mcp::params::*;
use super::render::emit;
use super::run_tool;
#[derive(Subcommand, Debug)]
pub enum QueryCmd {
Outline {
path: String,
#[arg(long)]
l2: bool,
},
Symbol {
needle: String,
#[arg(long)]
kind: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
Search {
needle: String,
#[arg(long)]
kind: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
References {
name: String,
#[arg(long)]
limit: Option<u32>,
},
Callers {
path: String,
name: String,
#[arg(long)]
kind: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
Implementations {
trait_name: String,
#[arg(long)]
language: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
CallGraph {
name: String,
#[arg(long, default_value = "callers")]
direction: String,
#[arg(long)]
path: Option<String>,
#[arg(long)]
max_depth: Option<u32>,
#[arg(long)]
max_nodes: Option<u32>,
},
Grep {
pattern: String,
#[arg(long)]
language: Option<String>,
#[arg(long)]
path_contains: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
ListFiles {
#[arg(long)]
path_contains: Option<String>,
#[arg(long)]
language: Option<String>,
#[arg(long)]
limit: Option<u32>,
},
Status,
RepoInfo,
Dependents { module: String },
}
pub async fn run(
server: &BasemindServer,
cmd: QueryCmd,
json: bool,
out: &mut impl Write,
) -> Result<()> {
match cmd {
QueryCmd::Outline { path, l2 } => {
let p = OutlineParams {
path: path.as_str().into(),
l2,
};
let r = run_tool("outline", server.outline(Parameters(p)).await)?;
emit("outline", &r, json, out)
}
QueryCmd::Symbol {
needle,
kind,
limit,
}
| QueryCmd::Search {
needle,
kind,
limit,
} => {
let p = SearchSymbolsParams {
needle,
kind,
limit,
cursor: None,
};
let r = run_tool("search_symbols", server.search_symbols(Parameters(p)).await)?;
emit("search_symbols", &r, json, out)
}
QueryCmd::References { name, limit } => {
let p = FindReferencesParams {
name,
limit,
cursor: None,
};
let r = run_tool(
"find_references",
server.find_references(Parameters(p)).await,
)?;
emit("find_references", &r, json, out)
}
QueryCmd::Callers {
path,
name,
kind,
limit,
} => {
let p = FindCallersParams {
path: path.as_str().into(),
name,
kind,
limit,
cursor: None,
};
let r = run_tool("find_callers", server.find_callers(Parameters(p)).await)?;
emit("find_callers", &r, json, out)
}
QueryCmd::Implementations {
trait_name,
language,
limit,
} => {
let p = FindImplementationsParams {
trait_name,
language,
limit,
cursor: None,
};
let r = run_tool(
"find_implementations",
server.find_implementations(Parameters(p)).await,
)?;
emit("find_implementations", &r, json, out)
}
QueryCmd::CallGraph {
name,
direction,
path,
max_depth,
max_nodes,
} => {
let p = CallGraphParams {
name,
direction,
path: path.map(|s| s.as_str().into()),
max_depth,
max_nodes,
};
let r = run_tool("call_graph", server.call_graph(Parameters(p)).await)?;
emit("call_graph", &r, json, out)
}
QueryCmd::Grep {
pattern,
language,
path_contains,
limit,
} => {
let p = WorkspaceGrepParams {
pattern,
language,
path_contains,
limit,
include_context: true,
};
let r = run_tool("workspace_grep", server.workspace_grep(Parameters(p)).await)?;
emit("workspace_grep", &r, json, out)
}
QueryCmd::ListFiles {
path_contains,
language,
limit,
} => {
let p = ListFilesParams {
path_contains,
language,
limit,
cursor: None,
};
let r = run_tool("list_files", server.list_files(Parameters(p)).await)?;
emit("list_files", &r, json, out)
}
QueryCmd::Status => {
let r = run_tool("status", server.status(Parameters(StatusParams {})).await)?;
emit("status", &r, json, out)
}
QueryCmd::RepoInfo => {
let r = run_tool(
"repo_info",
server.repo_info(Parameters(RepoInfoParams {})).await,
)?;
emit("repo_info", &r, json, out)
}
QueryCmd::Dependents { module } => {
let p = DependentsParams { module };
let r = run_tool("dependents", server.dependents(Parameters(p)).await)?;
emit("dependents", &r, json, out)
}
}
}