Skip to main content

lean_ctx/tools/registered/
ctx_dedup.rs

1use rmcp::ErrorData;
2use rmcp::model::Tool;
3use serde_json::{Map, Value, json};
4
5use crate::server::tool_trait::{McpTool, ToolContext, ToolOutput, get_str};
6use crate::tool_defs::tool_def;
7
8pub struct CtxDedupTool;
9
10impl McpTool for CtxDedupTool {
11    fn name(&self) -> &'static str {
12        "ctx_dedup"
13    }
14
15    fn tool_def(&self) -> Tool {
16        tool_def(
17            "ctx_dedup",
18            "WORKFLOW: action=analyze first to find shared imports/code across files, then action=apply to register dedup hints for ctx_read output.\n\
19            ANTIPATTERN: NOT for permanent dedup — only compression hints for read output.",
20            json!({
21                "type": "object",
22                "properties": {
23                    "action": {
24                        "type": "string",
25                        "description": "analyze (find shared) | apply (register dedup)",
26                        "default": "analyze"
27                    }
28                }
29            }),
30        )
31    }
32
33    fn handle(
34        &self,
35        args: &Map<String, Value>,
36        ctx: &ToolContext,
37    ) -> Result<ToolOutput, ErrorData> {
38        let action = get_str(args, "action").unwrap_or_default();
39        let cache = ctx
40            .cache
41            .as_ref()
42            .ok_or_else(|| ErrorData::internal_error("cache not available", None))?;
43        let result = if action == "apply" {
44            let Some(mut guard) = crate::server::bounded_lock::write(cache, "ctx_dedup:apply")
45            else {
46                return Ok(ToolOutput::simple(
47                    "[dedup unavailable — cache busy, retry]".to_string(),
48                ));
49            };
50            crate::tools::ctx_dedup::handle_action(&mut guard, &action)
51        } else {
52            let Some(guard) = crate::server::bounded_lock::read(cache, "ctx_dedup:status") else {
53                return Ok(ToolOutput::simple(
54                    "[dedup status unavailable — cache busy, retry]".to_string(),
55                ));
56            };
57            crate::tools::ctx_dedup::handle(&guard)
58        };
59        Ok(ToolOutput::simple(result))
60    }
61}