pub const DAEMON_SUPPORTED_TOOL_NAMES: &[&str] = &[
"complexity_metrics",
"dependency_impact",
"direct_callees",
"direct_callers",
"export_graph",
"find_cycles",
"find_unused",
"is_node_in_cycle",
"rebuild_index",
"relation_query",
"semantic_diff",
"semantic_search",
"show_dependencies",
"subgraph",
"trace_path",
];
#[must_use]
pub fn daemon_supported_tools() -> Vec<rmcp::model::Tool> {
use crate::feature_flags::FeatureFlags;
use crate::server::SqryServer;
let server = SqryServer::new(FeatureFlags::from_env());
server
.get_filtered_tools()
.into_iter()
.filter(|t| DAEMON_SUPPORTED_TOOL_NAMES.contains(&t.name.as_ref()))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn daemon_supported_tool_names_is_exactly_15_sorted_unique() {
assert_eq!(
DAEMON_SUPPORTED_TOOL_NAMES.len(),
15,
"DAEMON_SUPPORTED_TOOL_NAMES must contain exactly 15 tools"
);
let mut sorted = DAEMON_SUPPORTED_TOOL_NAMES.to_vec();
sorted.sort_unstable();
assert_eq!(
sorted.as_slice(),
DAEMON_SUPPORTED_TOOL_NAMES,
"DAEMON_SUPPORTED_TOOL_NAMES must be alphabetically sorted"
);
let set: HashSet<&str> = DAEMON_SUPPORTED_TOOL_NAMES.iter().copied().collect();
assert_eq!(
set.len(),
DAEMON_SUPPORTED_TOOL_NAMES.len(),
"DAEMON_SUPPORTED_TOOL_NAMES must contain no duplicates"
);
}
#[test]
fn daemon_supported_tools_returns_exact_15_under_default_flags() {
let tools = daemon_supported_tools();
let names: HashSet<&str> = tools.iter().map(|t| t.name.as_ref()).collect();
let expected: HashSet<&str> = DAEMON_SUPPORTED_TOOL_NAMES.iter().copied().collect();
assert_eq!(
names,
expected,
"daemon_supported_tools must return exactly the 15 DAEMON_SUPPORTED_TOOL_NAMES \
(default feature flags). Got {} tools, expected 15.",
tools.len()
);
}
#[test]
fn daemon_supported_tool_names_is_strict_subset_of_standalone() {
use crate::feature_flags::FeatureFlags;
use crate::server::SqryServer;
let server = SqryServer::new(FeatureFlags::from_env());
let standalone_names: HashSet<String> = server
.get_filtered_tools()
.into_iter()
.map(|t| t.name.as_ref().to_owned())
.collect();
for &daemon_name in DAEMON_SUPPORTED_TOOL_NAMES {
assert!(
standalone_names.contains(daemon_name),
"daemon-supported tool {daemon_name:?} not found in standalone inventory \
(DAEMON_SUPPORTED_TOOL_NAMES must be a strict subset of \
SqryServer::get_filtered_tools)"
);
}
assert!(
standalone_names.len() > DAEMON_SUPPORTED_TOOL_NAMES.len(),
"standalone inventory ({} tools) must be strictly larger than daemon subset ({} tools) — \
otherwise the daemon-subset rationale is broken",
standalone_names.len(),
DAEMON_SUPPORTED_TOOL_NAMES.len()
);
}
}