pub mod dispatch;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Instant;
use anyhow::Result;
use rmcp::ErrorData as McpError;
use serde::Serialize;
use sqry_core::graph::unified::concurrent::CodeGraph;
use sqry_core::query::executor::QueryExecutor;
use crate::engine::canonicalize_in_workspace;
use crate::execution::ToolExecution;
use crate::execution::types::{
ComplexityMetricsData, DependencyGraphData, DependencyImpactData, DirectCalleesData,
DirectCallersData, FindCyclesData, FindUnusedData, NodeInCycleData, RelationQueryData,
SemanticDiffData, SemanticSearchData, TracePathData,
};
use crate::execution::{
analysis_inner, graph_inner, introspection_inner, relations_inner, search_inner, trace_inner,
};
use crate::tools::{
ComplexityMetricsArgs, DependencyImpactArgs, DirectCalleesArgs, DirectCallersArgs,
ExportGraphArgs, FindCyclesArgs, FindUnusedArgs, IsNodeInCycleArgs, RelationQueryArgs,
SemanticDiffArgs, SemanticSearchArgs, ShowDependenciesArgs, SubgraphArgs, TracePathArgs,
};
#[derive(Clone)]
pub struct WorkspaceContext {
pub workspace_root: PathBuf,
pub graph: Arc<CodeGraph>,
pub executor: Arc<QueryExecutor>,
}
impl std::fmt::Debug for WorkspaceContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WorkspaceContext")
.field("workspace_root", &self.workspace_root)
.field("graph", &"Arc<CodeGraph>")
.field("executor", &"Arc<QueryExecutor>")
.finish()
}
}
pub fn execute_semantic_search_for_daemon(
ctx: &WorkspaceContext,
args: &SemanticSearchArgs,
) -> Result<ToolExecution<SemanticSearchData>> {
let search_root = canonicalize_in_workspace(&args.path, &ctx.workspace_root)?;
let start = Instant::now();
search_inner::execute_semantic_search(ctx, args, &search_root, start)
}
pub fn execute_relation_query_for_daemon(
ctx: &WorkspaceContext,
args: &RelationQueryArgs,
) -> Result<ToolExecution<RelationQueryData>> {
relations_inner::execute_relation_query(ctx, args)
}
pub fn execute_direct_callers_for_daemon(
ctx: &WorkspaceContext,
args: &DirectCallersArgs,
) -> Result<ToolExecution<DirectCallersData>> {
let start = Instant::now();
analysis_inner::execute_direct_callers(ctx, args, start)
}
pub fn execute_direct_callees_for_daemon(
ctx: &WorkspaceContext,
args: &DirectCalleesArgs,
) -> Result<ToolExecution<DirectCalleesData>> {
let start = Instant::now();
analysis_inner::execute_direct_callees(ctx, args, start)
}
pub fn execute_find_unused_for_daemon(
ctx: &WorkspaceContext,
args: &FindUnusedArgs,
) -> Result<ToolExecution<FindUnusedData>> {
let start = Instant::now();
analysis_inner::execute_find_unused(ctx, args, start)
}
pub fn execute_find_cycles_for_daemon(
ctx: &WorkspaceContext,
args: &FindCyclesArgs,
) -> Result<ToolExecution<FindCyclesData>> {
let start = Instant::now();
analysis_inner::execute_find_cycles(ctx, args, start)
}
pub fn execute_is_node_in_cycle_for_daemon(
ctx: &WorkspaceContext,
args: &IsNodeInCycleArgs,
) -> Result<ToolExecution<NodeInCycleData>> {
let start = Instant::now();
analysis_inner::execute_is_node_in_cycle(ctx, args, start)
}
pub fn execute_trace_path_for_daemon(
ctx: &WorkspaceContext,
args: &TracePathArgs,
) -> Result<ToolExecution<TracePathData>> {
let start = Instant::now();
trace_inner::execute_trace_path(ctx, args, start)
}
pub fn execute_subgraph_for_daemon(
ctx: &WorkspaceContext,
args: &SubgraphArgs,
) -> Result<ToolExecution<DependencyGraphData>> {
let start = Instant::now();
graph_inner::execute_subgraph(ctx, args, start)
}
pub fn execute_export_graph_for_daemon(
ctx: &WorkspaceContext,
args: &ExportGraphArgs,
) -> Result<ToolExecution<DependencyGraphData>> {
let start = Instant::now();
graph_inner::execute_export_graph(ctx, args, start)
}
pub fn execute_complexity_metrics_for_daemon(
ctx: &WorkspaceContext,
args: &ComplexityMetricsArgs,
) -> Result<ToolExecution<ComplexityMetricsData>> {
let start = Instant::now();
introspection_inner::execute_complexity_metrics(ctx, args, start)
}
pub fn execute_semantic_diff_for_daemon(
ctx: &WorkspaceContext,
args: &SemanticDiffArgs,
) -> Result<ToolExecution<SemanticDiffData>> {
let start = Instant::now();
analysis_inner::execute_semantic_diff(ctx, args, start)
}
pub fn execute_dependency_impact_for_daemon(
ctx: &WorkspaceContext,
args: &DependencyImpactArgs,
) -> Result<ToolExecution<DependencyImpactData>> {
let start = Instant::now();
analysis_inner::execute_dependency_impact(ctx, args, start)
}
pub fn execute_show_dependencies_for_daemon(
ctx: &WorkspaceContext,
args: &ShowDependenciesArgs,
) -> Result<ToolExecution<DependencyGraphData>> {
let start = Instant::now();
graph_inner::execute_get_dependencies(ctx, args, start)
}
pub fn tool_response_json<T: Serialize>(
exec: ToolExecution<T>,
) -> Result<serde_json::Value, McpError> {
crate::response::build_tool_response(exec, false)
}