pub use lean_ctx::core::dynamic_tools::*;
#[must_use]
pub fn targets_internal_host_tool(
name: &str,
args: Option<&serde_json::Map<String, serde_json::Value>>,
) -> bool {
crate::tools::registered::ctx_call::resolve(name, args)
.is_ok_and(|(inner, _)| INTERNAL_HOST_TOOLS.contains(&inner.as_str()))
}
#[must_use]
pub fn withheld_hive_tool_refusal(
name: &str,
args: Option<&serde_json::Map<String, serde_json::Value>>,
) -> Option<&'static str> {
crate::tools::registered::ctx_call::resolve(name, args)
.is_ok_and(|(inner, _)| is_withheld_hive_tool(&inner))
.then_some(lean_ctx_hive::TOOL_NOT_AVAILABLE)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn removed_tools_point_at_a_live_public_tool() {
assert_eq!(
removed_tool("ctx_multi_read").unwrap().replacement,
Some("ctx_read")
);
assert!(removed_tool("ctx_read").is_none());
let registry = crate::server::registry::build_registry();
let live = registry.names();
for name in [
"ctx_smart_read",
"ctx_multi_read",
"ctx_semantic_search",
"ctx_symbol",
"ctx_overview",
"ctx_summary",
"ctx_explore",
"ctx_plan",
"ctx_compile",
"ctx_fill",
"ctx_impact",
"ctx_architecture",
"ctx_repomap",
"ctx_routes",
"ctx_retrieve",
"ctx_cache",
] {
let replacement = removed_tool(name).and_then(|r| r.replacement).unwrap();
assert!(!live.contains(&name), "{name} is still registered");
assert!(
live.contains(&replacement) && is_publicly_advertised_tool(replacement),
"{name} points at {replacement}, which is not a live public tool"
);
}
}
#[test]
fn host_hook_calls_are_recognised_in_every_spelling() {
let args = |v: serde_json::Value| v.as_object().cloned();
let shape = args(serde_json::json!({"tool": "Bash", "output": "x"}));
assert!(targets_internal_host_tool("ctx_shape", shape.as_ref()));
let via_call =
args(serde_json::json!({"name": "ctx_shape", "arguments": {"tool": "Bash"}}));
assert!(targets_internal_host_tool("ctx_call", via_call.as_ref()));
let via_ctx = args(serde_json::json!({"tool": "shape", "output": "x"}));
assert!(targets_internal_host_tool("ctx", via_ctx.as_ref()));
let read = args(serde_json::json!({"name": "ctx_read", "arguments": {"path": "a"}}));
assert!(!targets_internal_host_tool("ctx_call", read.as_ref()));
assert!(!targets_internal_host_tool("ctx_read", None));
assert!(!targets_internal_host_tool("ctx_call", None));
}
}