1use std::sync::Arc;
2
3use rmcp::model::*;
4use serde_json::{json, Map, Value};
5
6pub fn tool_def(name: &'static str, description: &'static str, schema_value: Value) -> Tool {
7 let schema: Map<String, Value> = match schema_value {
8 Value::Object(map) => map,
9 _ => Map::new(),
10 };
11 Tool::new(name, description, Arc::new(schema))
12}
13
14pub fn granular_tool_defs() -> Vec<Tool> {
15 vec![
16 tool_def(
17 "ctx_read",
18 "Read file (cached, compressed). Re-reads ~13 tok. Auto-selects optimal mode. \
19Modes: full|map|signatures|diff|aggressive|entropy|task|reference|lines:N-M. fresh=true re-reads.",
20 json!({
21 "type": "object",
22 "properties": {
23 "path": { "type": "string", "description": "Absolute file path to read" },
24 "mode": {
25 "type": "string",
26 "description": "Compression mode (default: full). Use 'map' for context-only files. For line ranges: 'lines:N-M' (e.g. 'lines:400-500')."
27 },
28 "start_line": {
29 "type": "integer",
30 "description": "Read from this line number to end of file. Bypasses cache stub — always returns actual content."
31 },
32 "fresh": {
33 "type": "boolean",
34 "description": "Bypass cache and force a full re-read. Use when running as a subagent that may not have the parent's context."
35 }
36 },
37 "required": ["path"]
38 }),
39 ),
40 tool_def(
41 "ctx_multi_read",
42 "Batch read files in one call. Same modes as ctx_read.",
43 json!({
44 "type": "object",
45 "properties": {
46 "paths": {
47 "type": "array",
48 "items": { "type": "string" },
49 "description": "Absolute file paths to read, in order"
50 },
51 "mode": {
52 "type": "string",
53 "description": "Compression mode (default: full). Same modes as ctx_read (auto, full, map, signatures, diff, aggressive, entropy, task, reference, lines:N-M)."
54 }
55 },
56 "required": ["paths"]
57 }),
58 ),
59 tool_def(
60 "ctx_tree",
61 "Directory listing with file counts.",
62 json!({
63 "type": "object",
64 "properties": {
65 "path": { "type": "string", "description": "Directory path (default: .)" },
66 "depth": { "type": "integer", "description": "Max depth (default: 3)" },
67 "show_hidden": { "type": "boolean", "description": "Show hidden files" }
68 }
69 }),
70 ),
71 tool_def(
72 "ctx_shell",
73 "Run shell command (compressed output, 90+ patterns). Use raw=true to skip compression. cwd sets working directory (persists across calls via cd tracking).",
74 json!({
75 "type": "object",
76 "properties": {
77 "command": { "type": "string", "description": "Shell command to execute" },
78 "raw": { "type": "boolean", "description": "Skip compression, return full uncompressed output. Use for small outputs or when full detail is critical." },
79 "cwd": { "type": "string", "description": "Working directory for the command. If omitted, uses last cd target or project root." }
80 },
81 "required": ["command"]
82 }),
83 ),
84 tool_def(
85 "ctx_search",
86 "Regex code search (.gitignore aware, compact results).",
87 json!({
88 "type": "object",
89 "properties": {
90 "pattern": { "type": "string", "description": "Regex pattern" },
91 "path": { "type": "string", "description": "Directory to search" },
92 "ext": { "type": "string", "description": "File extension filter" },
93 "max_results": { "type": "integer", "description": "Max results (default: 20)" },
94 "ignore_gitignore": { "type": "boolean", "description": "Set true to scan ALL files including .gitignore'd paths (default: false)" }
95 },
96 "required": ["pattern"]
97 }),
98 ),
99 tool_def(
100 "ctx_compress",
101 "Context checkpoint for long conversations.",
102 json!({
103 "type": "object",
104 "properties": {
105 "include_signatures": { "type": "boolean", "description": "Include signatures (default: true)" }
106 }
107 }),
108 ),
109 tool_def(
110 "ctx_benchmark",
111 "Benchmark compression modes for a file or project.",
112 json!({
113 "type": "object",
114 "properties": {
115 "path": { "type": "string", "description": "File path (action=file) or project directory (action=project)" },
116 "action": { "type": "string", "description": "file (default) or project", "default": "file" },
117 "format": { "type": "string", "description": "Output format for project benchmark: terminal, markdown, json", "default": "terminal" }
118 },
119 "required": ["path"]
120 }),
121 ),
122 tool_def(
123 "ctx_metrics",
124 "Session token stats, cache rates, per-tool savings.",
125 json!({
126 "type": "object",
127 "properties": {}
128 }),
129 ),
130 tool_def(
131 "ctx_analyze",
132 "Entropy analysis — recommends optimal compression mode for a file.",
133 json!({
134 "type": "object",
135 "properties": {
136 "path": { "type": "string", "description": "File path to analyze" }
137 },
138 "required": ["path"]
139 }),
140 ),
141 tool_def(
142 "ctx_cache",
143 "Cache ops: status|clear|invalidate.",
144 json!({
145 "type": "object",
146 "properties": {
147 "action": {
148 "type": "string",
149 "enum": ["status", "clear", "invalidate"],
150 "description": "Cache operation to perform"
151 },
152 "path": {
153 "type": "string",
154 "description": "File path (required for 'invalidate' action)"
155 }
156 },
157 "required": ["action"]
158 }),
159 ),
160 tool_def(
161 "ctx_discover",
162 "Find missed compression opportunities in shell history.",
163 json!({
164 "type": "object",
165 "properties": {
166 "limit": {
167 "type": "integer",
168 "description": "Max number of command types to show (default: 15)"
169 }
170 }
171 }),
172 ),
173 tool_def(
174 "ctx_smart_read",
175 "Auto-select optimal read mode for a file.",
176 json!({
177 "type": "object",
178 "properties": {
179 "path": { "type": "string", "description": "Absolute file path to read" }
180 },
181 "required": ["path"]
182 }),
183 ),
184 tool_def(
185 "ctx_delta",
186 "Incremental diff — sends only changed lines since last read.",
187 json!({
188 "type": "object",
189 "properties": {
190 "path": { "type": "string", "description": "Absolute file path" }
191 },
192 "required": ["path"]
193 }),
194 ),
195 tool_def(
196 "ctx_edit",
197 "Edit a file via search-and-replace. Works without native Read/Edit tools. Use this when the IDE's Edit tool requires Read but Read is unavailable.",
198 json!({
199 "type": "object",
200 "properties": {
201 "path": { "type": "string", "description": "Absolute file path" },
202 "old_string": { "type": "string", "description": "Exact text to find and replace (must be unique unless replace_all=true)" },
203 "new_string": { "type": "string", "description": "Replacement text" },
204 "replace_all": { "type": "boolean", "description": "Replace all occurrences (default: false)", "default": false },
205 "create": { "type": "boolean", "description": "Create a new file with new_string as content (ignores old_string)", "default": false }
206 },
207 "required": ["path", "new_string"]
208 }),
209 ),
210 tool_def(
211 "ctx_dedup",
212 "Cross-file dedup: analyze or apply shared block references.",
213 json!({
214 "type": "object",
215 "properties": {
216 "action": {
217 "type": "string",
218 "description": "analyze (default) or apply (register shared blocks for auto-dedup in ctx_read)",
219 "default": "analyze"
220 }
221 }
222 }),
223 ),
224 tool_def(
225 "ctx_fill",
226 "Budget-aware context fill — auto-selects compression per file within token limit.",
227 json!({
228 "type": "object",
229 "properties": {
230 "paths": {
231 "type": "array",
232 "items": { "type": "string" },
233 "description": "File paths to consider"
234 },
235 "budget": {
236 "type": "integer",
237 "description": "Maximum token budget to fill"
238 },
239 "task": {
240 "type": "string",
241 "description": "Optional task for POP intent-driven pruning"
242 }
243 },
244 "required": ["paths", "budget"]
245 }),
246 ),
247 tool_def(
248 "ctx_intent",
249 "Structured intent input (optional) — submit compact JSON or short text; server also infers intents automatically from tool calls.",
250 json!({
251 "type": "object",
252 "properties": {
253 "query": { "type": "string", "description": "Compact JSON intent or short text" },
254 "project_root": { "type": "string", "description": "Project root directory (default: .)" }
255 },
256 "required": ["query"]
257 }),
258 ),
259 tool_def(
260 "ctx_response",
261 "Compress LLM response text (remove filler, apply TDD).",
262 json!({
263 "type": "object",
264 "properties": {
265 "text": { "type": "string", "description": "Response text to compress" }
266 },
267 "required": ["text"]
268 }),
269 ),
270 tool_def(
271 "ctx_context",
272 "Session context overview — cached files, seen files, session state.",
273 json!({
274 "type": "object",
275 "properties": {}
276 }),
277 ),
278 tool_def(
279 "ctx_graph",
280 "Code dependency graph. Actions: build (index project), related (find files connected to path), \
281symbol (lookup definition/usages as file::name), impact (blast radius of changes to path), status (index stats).",
282 json!({
283 "type": "object",
284 "properties": {
285 "action": {
286 "type": "string",
287 "enum": ["build", "related", "symbol", "impact", "status"],
288 "description": "Graph operation: build, related, symbol, impact, status"
289 },
290 "path": {
291 "type": "string",
292 "description": "File path (related/impact) or file::symbol_name (symbol)"
293 },
294 "project_root": {
295 "type": "string",
296 "description": "Project root directory (default: .)"
297 }
298 },
299 "required": ["action"]
300 }),
301 ),
302 tool_def(
303 "ctx_session",
304 "Cross-session memory (CCP). Actions: load (restore previous session ~400 tok), \
305save, status, task (set current task), finding (record discovery), decision (record choice), \
306reset, list (show sessions), cleanup.",
307 json!({
308 "type": "object",
309 "properties": {
310 "action": {
311 "type": "string",
312 "enum": ["status", "load", "save", "task", "finding", "decision", "reset", "list", "cleanup"],
313 "description": "Session operation to perform"
314 },
315 "value": {
316 "type": "string",
317 "description": "Value for task/finding/decision actions"
318 },
319 "session_id": {
320 "type": "string",
321 "description": "Session ID for load action (default: latest)"
322 }
323 },
324 "required": ["action"]
325 }),
326 ),
327 tool_def(
328 "ctx_knowledge",
329 "Persistent project knowledge (survives sessions). Actions: remember (store fact with temporal tracking + contradiction detection), \
330recall (search), pattern (record convention), consolidate (extract session findings), \
331gotcha (record a bug/mistake to never repeat — trigger+resolution required), \
332timeline (view fact history for a category), rooms (list knowledge categories), \
333search (cross-session search across ALL projects), wakeup (compact AAAK briefing), \
334status (list all), remove, export, embeddings_status|embeddings_reset|embeddings_reindex (local semantic index management for recall).",
335 json!({
336 "type": "object",
337 "properties": {
338 "action": {
339 "type": "string",
340 "enum": ["remember", "recall", "pattern", "consolidate", "gotcha", "status", "remove", "export", "timeline", "rooms", "search", "wakeup", "embeddings_status", "embeddings_reset", "embeddings_reindex"],
341 "description": "Knowledge operation. remember: auto-detects contradictions + tracks temporal validity. timeline: view version history. rooms: list categories. search: cross-project search. wakeup: compact AAAK briefing. embeddings_*: manage local semantic index for recall."
342 },
343 "trigger": {
344 "type": "string",
345 "description": "For gotcha action: what triggers the bug (e.g. 'cargo build fails with E0507 on match arms')"
346 },
347 "resolution": {
348 "type": "string",
349 "description": "For gotcha action: how to fix/avoid it (e.g. 'Use .clone() or ref pattern')"
350 },
351 "severity": {
352 "type": "string",
353 "enum": ["critical", "warning", "info"],
354 "description": "For gotcha action: severity level (default: warning)"
355 },
356 "category": {
357 "type": "string",
358 "description": "Fact category (architecture, api, testing, deployment, conventions, dependencies)"
359 },
360 "key": {
361 "type": "string",
362 "description": "Fact key/identifier (e.g. 'auth-method', 'db-engine', 'test-framework')"
363 },
364 "value": {
365 "type": "string",
366 "description": "Fact value or pattern description"
367 },
368 "query": {
369 "type": "string",
370 "description": "Search query for recall action (matches against category, key, and value)"
371 },
372 "pattern_type": {
373 "type": "string",
374 "description": "Pattern type for pattern action (naming, structure, testing, error-handling)"
375 },
376 "examples": {
377 "type": "array",
378 "items": { "type": "string" },
379 "description": "Examples for pattern action"
380 },
381 "confidence": {
382 "type": "number",
383 "description": "Confidence score 0.0-1.0 for remember action (default: 0.8)"
384 }
385 },
386 "required": ["action"]
387 }),
388 ),
389 tool_def(
390 "ctx_agent",
391 "Multi-agent coordination (shared message bus + persistent diaries). Actions: register (join with agent_type+role), \
392post (broadcast or direct message with category), read (poll messages), status (update state: active|idle|finished), \
393handoff (transfer task to another agent with summary), sync (overview of all agents + pending messages + shared contexts), \
394diary (log discovery/decision/blocker/progress/insight — persisted across sessions), \
395recall_diary (read agent diary), diaries (list all agent diaries), \
396list, info.",
397 json!({
398 "type": "object",
399 "properties": {
400 "action": {
401 "type": "string",
402 "enum": ["register", "list", "post", "read", "status", "info", "handoff", "sync", "diary", "recall_diary", "diaries"],
403 "description": "Agent operation. diary: persistent log (category=discovery|decision|blocker|progress|insight). recall_diary: read diary. diaries: list all."
404 },
405 "agent_type": {
406 "type": "string",
407 "description": "Agent type for register (cursor, claude, codex, gemini, crush, subagent)"
408 },
409 "role": {
410 "type": "string",
411 "description": "Agent role (dev, review, test, plan)"
412 },
413 "message": {
414 "type": "string",
415 "description": "Message text for post action, or status detail for status action"
416 },
417 "category": {
418 "type": "string",
419 "description": "Message category for post (finding, warning, request, status)"
420 },
421 "to_agent": {
422 "type": "string",
423 "description": "Target agent ID for direct message (omit for broadcast)"
424 },
425 "status": {
426 "type": "string",
427 "enum": ["active", "idle", "finished"],
428 "description": "New status for status action"
429 }
430 },
431 "required": ["action"]
432 }),
433 ),
434 tool_def(
435 "ctx_share",
436 "Share cached file contexts between agents. Actions: push (share files from your cache to another agent), \
437pull (receive files shared by other agents), list (show all shared contexts), clear (remove your shared contexts).",
438 json!({
439 "type": "object",
440 "properties": {
441 "action": {
442 "type": "string",
443 "enum": ["push", "pull", "list", "clear"],
444 "description": "Share operation to perform"
445 },
446 "paths": {
447 "type": "string",
448 "description": "Comma-separated file paths to share (for push action)"
449 },
450 "to_agent": {
451 "type": "string",
452 "description": "Target agent ID (omit for broadcast to all agents)"
453 },
454 "message": {
455 "type": "string",
456 "description": "Optional context message explaining what was shared"
457 }
458 },
459 "required": ["action"]
460 }),
461 ),
462 tool_def(
463 "ctx_overview",
464 "Task-relevant project map — use at session start.",
465 json!({
466 "type": "object",
467 "properties": {
468 "task": {
469 "type": "string",
470 "description": "Task description for relevance scoring (e.g. 'fix auth bug in login flow')"
471 },
472 "path": {
473 "type": "string",
474 "description": "Project root directory (default: .)"
475 }
476 }
477 }),
478 ),
479 tool_def(
480 "ctx_preload",
481 "Proactive context loader — caches task-relevant files, returns L-curve-optimized summary (~50-100 tokens vs ~5000 for individual reads).",
482 json!({
483 "type": "object",
484 "properties": {
485 "task": {
486 "type": "string",
487 "description": "Task description (e.g. 'fix auth bug in validate_token')"
488 },
489 "path": {
490 "type": "string",
491 "description": "Project root (default: .)"
492 }
493 },
494 "required": ["task"]
495 }),
496 ),
497 tool_def(
498 "ctx_prefetch",
499 "Predictive prefetch — prewarm cache for blast radius files (graph + task signals) within budgets.",
500 json!({
501 "type": "object",
502 "properties": {
503 "root": { "type": "string", "description": "Project root (default: .)" },
504 "task": { "type": "string", "description": "Optional task for relevance scoring" },
505 "changed_files": { "type": "array", "items": { "type": "string" }, "description": "Optional changed files (paths) to compute blast radius" },
506 "budget_tokens": { "type": "integer", "description": "Soft budget hint for mode selection (default: 3000)" },
507 "max_files": { "type": "integer", "description": "Max files to prefetch (default: 10)" }
508 }
509 }),
510 ),
511 tool_def(
512 "ctx_wrapped",
513 "Savings report card. Periods: week|month|all.",
514 json!({
515 "type": "object",
516 "properties": {
517 "period": {
518 "type": "string",
519 "enum": ["week", "month", "all"],
520 "description": "Report period (default: week)"
521 }
522 }
523 }),
524 ),
525 tool_def(
526 "ctx_cost",
527 "Cost attribution (local-first). Actions: report|agent|tools|json|reset.",
528 json!({
529 "type": "object",
530 "properties": {
531 "action": {
532 "type": "string",
533 "enum": ["report", "agent", "tools", "json", "reset", "status"],
534 "description": "Operation to perform (default: report)"
535 },
536 "agent_id": {
537 "type": "string",
538 "description": "Agent ID for action=agent (optional)"
539 },
540 "limit": {
541 "type": "integer",
542 "description": "Max rows (default: 10)"
543 }
544 }
545 }),
546 ),
547 tool_def(
548 "ctx_gain",
549 "Gain report.",
550 json!({
551 "type": "object",
552 "properties": {
553 "action": {
554 "type": "string",
555 "enum": ["status", "report", "score", "cost", "tasks", "heatmap", "wrapped", "agents", "json"]
556 },
557 "period": {
558 "type": "string",
559 "enum": ["week", "month", "all"]
560 },
561 "model": {
562 "type": "string"
563 },
564 "limit": {
565 "type": "integer"
566 }
567 }
568 }),
569 ),
570 tool_def(
571 "ctx_feedback",
572 "Harness feedback for LLM output tokens/latency (local-first). Actions: record|report|json|reset|status.",
573 json!({
574 "type": "object",
575 "properties": {
576 "action": {
577 "type": "string",
578 "enum": ["record", "report", "json", "reset", "status"],
579 "description": "Operation to perform (default: report)"
580 },
581 "agent_id": { "type": "string", "description": "Agent ID (optional; defaults to current agent when available)" },
582 "intent": { "type": "string", "description": "Intent/task string (optional)" },
583 "model": { "type": "string", "description": "Model identifier (optional)" },
584 "llm_input_tokens": { "type": "integer", "description": "Required for action=record" },
585 "llm_output_tokens": { "type": "integer", "description": "Required for action=record" },
586 "latency_ms": { "type": "integer", "description": "Optional for action=record" },
587 "note": { "type": "string", "description": "Optional note (no prompts/PII)" },
588 "limit": { "type": "integer", "description": "For report/json: how many recent events to consider (default: 500)" }
589 }
590 }),
591 ),
592 tool_def(
593 "ctx_handoff",
594 "Context Ledger Protocol (hashed, deterministic, local-first). Actions: create|show|list|pull|clear.",
595 json!({
596 "type": "object",
597 "properties": {
598 "action": {
599 "type": "string",
600 "enum": ["create", "show", "list", "pull", "clear"],
601 "description": "Operation to perform (default: list)"
602 },
603 "path": { "type": "string", "description": "Ledger file path (for show/pull)" },
604 "paths": { "type": "array", "items": { "type": "string" }, "description": "Optional file paths to include as signatures-only curated refs (for create)" },
605 "apply_workflow": { "type": "boolean", "description": "For pull: apply workflow state (default: true)" },
606 "apply_session": { "type": "boolean", "description": "For pull: apply session/task snapshot (default: true)" },
607 "apply_knowledge": { "type": "boolean", "description": "For pull: import knowledge facts (default: true)" }
608 }
609 }),
610 ),
611 tool_def(
612 "ctx_heatmap",
613 "File access heatmap (local-first). Actions: status|directory|cold|json.",
614 json!({
615 "type": "object",
616 "properties": {
617 "action": {
618 "type": "string",
619 "enum": ["status", "directory", "dirs", "cold", "json"],
620 "description": "Operation to perform (default: status)"
621 },
622 "path": {
623 "type": "string",
624 "description": "Project root for cold scan (default: .)"
625 }
626 }
627 }),
628 ),
629 tool_def(
630 "ctx_task",
631 "Multi-agent task orchestration. Actions: create|update|list|get|cancel|message|info.",
632 json!({
633 "type": "object",
634 "properties": {
635 "action": {
636 "type": "string",
637 "enum": ["create", "update", "list", "get", "cancel", "message", "info"],
638 "description": "Task operation"
639 },
640 "task_id": { "type": "string", "description": "Task ID (required for update|get|cancel|message)" },
641 "to_agent": { "type": "string", "description": "Target agent ID (required for create)" },
642 "description": { "type": "string", "description": "Task description (for create)" },
643 "state": { "type": "string", "description": "New state for update (working|input-required|completed|failed|canceled)" },
644 "message": { "type": "string", "description": "Optional message / reason" }
645 },
646 "required": ["action"]
647 }),
648 ),
649 tool_def(
650 "ctx_impact",
651 "Graph-based impact analysis. Actions: analyze|chain|build|status.",
652 json!({
653 "type": "object",
654 "properties": {
655 "action": {
656 "type": "string",
657 "enum": ["analyze", "chain", "build", "status"],
658 "description": "Impact operation (default: analyze)"
659 },
660 "path": { "type": "string", "description": "Target file path (required for analyze). For chain: from->to spec." },
661 "root": { "type": "string", "description": "Project root (default: .)" },
662 "depth": { "type": "integer", "description": "Max traversal depth (default: 5)" }
663 }
664 }),
665 ),
666 tool_def(
667 "ctx_architecture",
668 "Graph-based architecture analysis. Actions: overview|clusters|layers|cycles|entrypoints|module.",
669 json!({
670 "type": "object",
671 "properties": {
672 "action": {
673 "type": "string",
674 "enum": ["overview", "clusters", "layers", "cycles", "entrypoints", "module"],
675 "description": "Architecture operation (default: overview)"
676 },
677 "path": { "type": "string", "description": "Used for action=module (module/file path)" },
678 "root": { "type": "string", "description": "Project root (default: .)" }
679 }
680 }),
681 ),
682 tool_def(
683 "ctx_workflow",
684 "Workflow rails (state machine + evidence). Actions: start|status|transition|complete|evidence_add|evidence_list|stop.",
685 json!({
686 "type": "object",
687 "properties": {
688 "action": {
689 "type": "string",
690 "enum": ["start", "status", "transition", "complete", "evidence_add", "evidence_list", "stop"],
691 "description": "Workflow operation (default: status)"
692 },
693 "name": { "type": "string", "description": "Optional workflow name override (action=start)" },
694 "spec": { "type": "string", "description": "WorkflowSpec JSON (action=start). If omitted, uses builtin plan_code_test." },
695 "to": { "type": "string", "description": "Target state (action=transition)" },
696 "key": { "type": "string", "description": "Evidence key (action=evidence_add)" },
697 "value": { "type": "string", "description": "Optional evidence value / transition note" }
698 }
699 }),
700 ),
701 tool_def(
702 "ctx_semantic_search",
703 "Semantic code search (BM25 + optional embeddings/hybrid). action=reindex to rebuild.",
704 json!({
705 "type": "object",
706 "properties": {
707 "query": { "type": "string", "description": "Natural language search query" },
708 "path": { "type": "string", "description": "Project root to search (default: .)" },
709 "top_k": { "type": "integer", "description": "Number of results (default: 10)" },
710 "action": { "type": "string", "description": "reindex to rebuild index" },
711 "mode": {
712 "type": "string",
713 "enum": ["bm25", "dense", "hybrid"],
714 "description": "Search mode (default: hybrid). bm25=lexical only, dense=embeddings only, hybrid=BM25+embeddings"
715 },
716 "languages": {
717 "type": "array",
718 "items": { "type": "string" },
719 "description": "Optional: restrict to languages/extensions (e.g. [\"rust\",\"ts\",\"py\"] or [\"rs\",\"tsx\"])"
720 },
721 "path_glob": {
722 "type": "string",
723 "description": "Optional: glob over relative file paths (e.g. \"rust/src/**\" or \"**/*.rs\")"
724 }
725 },
726 "required": ["query"]
727 }),
728 ),
729 tool_def(
730 "ctx_execute",
731 "Run code in sandbox (11 languages). Only stdout enters context. Raw data never leaves subprocess. Languages: javascript, typescript, python, shell, ruby, go, rust, php, perl, r, elixir.",
732 json!({
733 "type": "object",
734 "properties": {
735 "language": {
736 "type": "string",
737 "description": "Language: javascript|typescript|python|shell|ruby|go|rust|php|perl|r|elixir"
738 },
739 "code": {
740 "type": "string",
741 "description": "Code to execute in sandbox"
742 },
743 "intent": {
744 "type": "string",
745 "description": "What you want from the output (triggers intent-driven filtering for large results)"
746 },
747 "timeout": {
748 "type": "integer",
749 "description": "Timeout in seconds (default: 30)"
750 },
751 "action": {
752 "type": "string",
753 "description": "batch — execute multiple scripts. Provide items as JSON array [{language, code}]"
754 },
755 "items": {
756 "type": "string",
757 "description": "JSON array of [{\"language\": \"...\", \"code\": \"...\"}] for batch execution"
758 },
759 "path": {
760 "type": "string",
761 "description": "For action=file: process a file in sandbox (auto-detects language)"
762 }
763 },
764 "required": ["language", "code"]
765 }),
766 ),
767 tool_def(
768 "ctx_symbol",
769 "Read a specific symbol (function, struct, class) by name. Returns only the symbol \
770code block instead of the entire file. 90-97% fewer tokens than full file read.",
771 json!({
772 "type": "object",
773 "properties": {
774 "name": { "type": "string", "description": "Symbol name (function, struct, class, method)" },
775 "file": { "type": "string", "description": "Optional: file path to narrow search" },
776 "kind": { "type": "string", "description": "Optional: fn|struct|class|method|trait|enum" }
777 },
778 "required": ["name"]
779 }),
780 ),
781 tool_def(
782 "ctx_graph_diagram",
783 "Generate a Mermaid diagram of the dependency or call graph. Useful for understanding architecture.",
784 json!({
785 "type": "object",
786 "properties": {
787 "file": { "type": "string", "description": "Optional: scope to dependencies of a specific file" },
788 "depth": { "type": "integer", "description": "Max depth (default: 2)" },
789 "kind": { "type": "string", "description": "deps (file dependencies) or calls (symbol call graph)" }
790 }
791 }),
792 ),
793 tool_def(
794 "ctx_routes",
795 "List HTTP routes/endpoints extracted from the project. Supports Express, Flask, FastAPI, Actix, Spring, Rails, Next.js.",
796 json!({
797 "type": "object",
798 "properties": {
799 "method": { "type": "string", "description": "Optional: GET, POST, PUT, DELETE" },
800 "path": { "type": "string", "description": "Optional: path prefix filter, e.g. /api/users" }
801 }
802 }),
803 ),
804 tool_def(
805 "ctx_compress_memory",
806 "Compress a memory/config file (CLAUDE.md, .cursorrules, etc.) to save tokens on every session start. \
807Preserves code blocks, URLs, paths, headings, tables. Creates .original.md backup.",
808 json!({
809 "type": "object",
810 "properties": {
811 "path": { "type": "string", "description": "Path to memory file" }
812 },
813 "required": ["path"]
814 }),
815 ),
816 tool_def(
817 "ctx_callers",
818 "Find all symbols that call a given function/method. Returns caller file, symbol, and line.",
819 json!({
820 "type": "object",
821 "properties": {
822 "symbol": { "type": "string", "description": "Symbol name to find callers of" },
823 "file": { "type": "string", "description": "Optional: scope to a specific file" }
824 },
825 "required": ["symbol"]
826 }),
827 ),
828 tool_def(
829 "ctx_callees",
830 "Find all functions/methods called by a given symbol. Returns callee name, file, and line.",
831 json!({
832 "type": "object",
833 "properties": {
834 "symbol": { "type": "string", "description": "Symbol name to find callees of" },
835 "file": { "type": "string", "description": "Optional: scope to a specific file" }
836 },
837 "required": ["symbol"]
838 }),
839 ),
840 tool_def(
841 "ctx_outline",
842 "List all symbols in a file (functions, structs, classes, methods) with signatures. \
843Much fewer tokens than reading the full file.",
844 json!({
845 "type": "object",
846 "properties": {
847 "path": { "type": "string", "description": "File path" },
848 "kind": { "type": "string", "description": "Optional filter: fn|struct|class|all" }
849 },
850 "required": ["path"]
851 }),
852 ),
853 ]
854}
855
856pub fn unified_tool_defs() -> Vec<Tool> {
857 vec![
858 tool_def(
859 "ctx_read",
860 "Read file (cached, compressed). Modes: full|map|signatures|diff|aggressive|entropy|task|reference|lines:N-M. fresh=true re-reads.",
861 json!({
862 "type": "object",
863 "properties": {
864 "path": { "type": "string", "description": "File path" },
865 "mode": { "type": "string" },
866 "start_line": { "type": "integer" },
867 "fresh": { "type": "boolean" }
868 },
869 "required": ["path"]
870 }),
871 ),
872 tool_def(
873 "ctx_shell",
874 "Run shell command (compressed output). raw=true skips compression. cwd sets working directory.",
875 json!({
876 "type": "object",
877 "properties": {
878 "command": { "type": "string", "description": "Shell command" },
879 "raw": { "type": "boolean", "description": "Skip compression for full output" },
880 "cwd": { "type": "string", "description": "Working directory (defaults to last cd or project root)" }
881 },
882 "required": ["command"]
883 }),
884 ),
885 tool_def(
886 "ctx_search",
887 "Regex code search (.gitignore aware).",
888 json!({
889 "type": "object",
890 "properties": {
891 "pattern": { "type": "string", "description": "Regex pattern" },
892 "path": { "type": "string" },
893 "ext": { "type": "string" },
894 "max_results": { "type": "integer" },
895 "ignore_gitignore": { "type": "boolean" }
896 },
897 "required": ["pattern"]
898 }),
899 ),
900 tool_def(
901 "ctx_tree",
902 "Directory listing with file counts.",
903 json!({
904 "type": "object",
905 "properties": {
906 "path": { "type": "string" },
907 "depth": { "type": "integer" },
908 "show_hidden": { "type": "boolean" }
909 }
910 }),
911 ),
912 tool_def(
913 "ctx",
914 "Meta-tool: set tool= to sub-tool name. Sub-tools: compress (checkpoint), metrics (stats), \
915analyze (entropy), cache (status|clear|invalidate), discover (missed patterns), smart_read (auto-mode), \
916delta (incremental diff), dedup (cross-file), fill (budget-aware batch read), intent (auto-read by task), \
917response (compress LLM text), context (session state), graph (build|related|symbol|impact|status), \
918session (load|save|task|finding|decision|status|reset|list|cleanup), \
919knowledge (remember|recall|pattern|consolidate|timeline|rooms|search|wakeup|status|remove|export|embeddings_status|embeddings_reset|embeddings_reindex), \
920agent (register|post|read|status|list|info|diary|recall_diary|diaries), overview (project map), \
921wrapped (savings report), benchmark (file|project), multi_read (batch), semantic_search (BM25), \
922cost (attribution), heatmap (file access), impact (graph impact), architecture (graph structure), \
923task (A2A tasks), workflow (state machine).",
924 json!({
925 "type": "object",
926 "properties": {
927 "tool": {
928 "type": "string",
929 "description": "compress|metrics|analyze|cache|discover|smart_read|delta|dedup|fill|intent|response|context|graph|session|knowledge|agent|overview|wrapped|benchmark|multi_read|semantic_search|cost|heatmap|impact|architecture|task|workflow"
930 },
931 "action": { "type": "string" },
932 "path": { "type": "string" },
933 "paths": { "type": "array", "items": { "type": "string" } },
934 "query": { "type": "string" },
935 "value": { "type": "string" },
936 "category": { "type": "string" },
937 "key": { "type": "string" },
938 "to": { "type": "string" },
939 "spec": { "type": "string" },
940 "budget": { "type": "integer" },
941 "task": { "type": "string" },
942 "mode": { "type": "string" },
943 "text": { "type": "string" },
944 "message": { "type": "string" },
945 "session_id": { "type": "string" },
946 "period": { "type": "string" },
947 "format": { "type": "string" },
948 "agent_type": { "type": "string" },
949 "role": { "type": "string" },
950 "status": { "type": "string" },
951 "pattern_type": { "type": "string" },
952 "examples": { "type": "array", "items": { "type": "string" } },
953 "confidence": { "type": "number" },
954 "project_root": { "type": "string" },
955 "include_signatures": { "type": "boolean" },
956 "limit": { "type": "integer" },
957 "to_agent": { "type": "string" },
958 "task_id": { "type": "string" },
959 "agent_id": { "type": "string" },
960 "description": { "type": "string" },
961 "state": { "type": "string" },
962 "root": { "type": "string" },
963 "depth": { "type": "integer" },
964 "show_hidden": { "type": "boolean" }
965 },
966 "required": ["tool"]
967 }),
968 ),
969 ]
970}
971
972const CORE_TOOL_NAMES: &[&str] = &[
973 "ctx_read",
974 "ctx_multi_read",
975 "ctx_shell",
976 "ctx_search",
977 "ctx_tree",
978 "ctx_edit",
979 "ctx_session",
980 "ctx_knowledge",
981];
982
983pub fn lazy_tool_defs() -> Vec<Tool> {
984 let all = granular_tool_defs();
985 let mut core: Vec<Tool> = all
986 .into_iter()
987 .filter(|t| CORE_TOOL_NAMES.contains(&t.name.as_ref()))
988 .collect();
989
990 core.push(tool_def(
991 "ctx_discover_tools",
992 "Search available lean-ctx tools by keyword. Returns matching tool names + descriptions for on-demand loading.",
993 json!({
994 "type": "object",
995 "properties": {
996 "query": {
997 "type": "string",
998 "description": "Search keyword (e.g. 'graph', 'cost', 'workflow', 'dedup')"
999 }
1000 },
1001 "required": ["query"]
1002 }),
1003 ));
1004
1005 core
1006}
1007
1008pub fn discover_tools(query: &str) -> String {
1009 let all = list_all_tool_defs();
1010 let query_lower = query.to_lowercase();
1011 let matches: Vec<(&str, &str)> = all
1012 .iter()
1013 .filter(|(name, desc, _)| {
1014 name.to_lowercase().contains(&query_lower) || desc.to_lowercase().contains(&query_lower)
1015 })
1016 .map(|(name, desc, _)| (*name, *desc))
1017 .collect();
1018
1019 if matches.is_empty() {
1020 return format!("No tools found matching '{query}'. Try broader terms like: graph, cost, session, search, compress, agent, workflow, gain.");
1021 }
1022
1023 let mut out = format!("{} tools matching '{query}':\n", matches.len());
1024 for (name, desc) in &matches {
1025 let short = if desc.len() > 80 { &desc[..80] } else { desc };
1026 out.push_str(&format!(" {name} — {short}\n"));
1027 }
1028 out.push_str("\nCall the tool directly by name to use it.");
1029 out
1030}
1031
1032pub fn is_lazy_mode() -> bool {
1033 std::env::var("LEAN_CTX_LAZY_TOOLS").is_ok()
1034}
1035
1036pub fn list_all_tool_defs() -> Vec<(&'static str, &'static str, Value)> {
1037 vec![
1038 ("ctx_read", "Read file (cached, compressed). Re-reads ~13 tok. Auto-selects optimal mode. \
1039Modes: full|map|signatures|diff|aggressive|entropy|task|reference|lines:N-M. fresh=true re-reads.", json!({"type": "object", "properties": {"path": {"type": "string"}, "mode": {"type": "string"}, "start_line": {"type": "integer"}, "fresh": {"type": "boolean"}}, "required": ["path"]})),
1040 ("ctx_multi_read", "Batch read files in one call. Same modes as ctx_read.", json!({"type": "object", "properties": {"paths": {"type": "array", "items": {"type": "string"}}, "mode": {"type": "string"}}, "required": ["paths"]})),
1041 ("ctx_tree", "Directory listing with file counts.", json!({"type": "object", "properties": {"path": {"type": "string"}, "depth": {"type": "integer"}, "show_hidden": {"type": "boolean"}}})),
1042 ("ctx_shell", "Run shell command (compressed output, 90+ patterns). cwd sets working directory.", json!({"type": "object", "properties": {"command": {"type": "string"}, "cwd": {"type": "string", "description": "Working directory"}}, "required": ["command"]})),
1043 ("ctx_search", "Regex code search (.gitignore aware, compact results).", json!({"type": "object", "properties": {"pattern": {"type": "string"}, "path": {"type": "string"}, "ext": {"type": "string"}, "max_results": {"type": "integer"}}, "required": ["pattern"]})),
1044 ("ctx_compress", "Context checkpoint for long conversations.", json!({"type": "object", "properties": {"include_signatures": {"type": "boolean"}}})),
1045 ("ctx_benchmark", "Benchmark compression modes for a file or project.", json!({"type": "object", "properties": {"path": {"type": "string"}, "action": {"type": "string"}, "format": {"type": "string"}}, "required": ["path"]})),
1046 ("ctx_metrics", "Session token stats, cache rates, per-tool savings.", json!({"type": "object", "properties": {}})),
1047 ("ctx_analyze", "Entropy analysis — recommends optimal compression mode for a file.", json!({"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]})),
1048 ("ctx_cache", "Cache ops: status|clear|invalidate.", json!({"type": "object", "properties": {"action": {"type": "string"}, "path": {"type": "string"}}, "required": ["action"]})),
1049 ("ctx_discover", "Find missed compression opportunities in shell history.", json!({"type": "object", "properties": {"limit": {"type": "integer"}}})),
1050 ("ctx_smart_read", "Auto-select optimal read mode for a file.", json!({"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]})),
1051 ("ctx_delta", "Incremental diff — sends only changed lines since last read.", json!({"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]})),
1052 ("ctx_edit", "Edit a file via search-and-replace. Works without native Read/Edit tools. Use when Edit requires Read but Read is unavailable.", json!({"type": "object", "properties": {"path": {"type": "string"}, "old_string": {"type": "string"}, "new_string": {"type": "string"}, "replace_all": {"type": "boolean"}, "create": {"type": "boolean"}}, "required": ["path", "new_string"]})),
1053 ("ctx_dedup", "Cross-file dedup: analyze or apply shared block references.", json!({"type": "object", "properties": {"action": {"type": "string"}}})),
1054 ("ctx_fill", "Budget-aware context fill — auto-selects compression per file within token limit.", json!({"type": "object", "properties": {"paths": {"type": "array", "items": {"type": "string"}}, "budget": {"type": "integer"}, "task": {"type": "string"}}, "required": ["paths", "budget"]})),
1055 ("ctx_intent", "Structured intent input (optional) — submit compact JSON or short text; server also infers intents automatically from tool calls.", json!({"type": "object", "properties": {"query": {"type": "string"}, "project_root": {"type": "string"}}, "required": ["query"]})),
1056 ("ctx_response", "Compress LLM response text (remove filler, apply TDD).", json!({"type": "object", "properties": {"text": {"type": "string"}}, "required": ["text"]})),
1057 ("ctx_context", "Session context overview — cached files, seen files, session state.", json!({"type": "object", "properties": {}})),
1058 ("ctx_graph", "Code dependency graph. Actions: build (index project), related (find files connected to path), \
1059symbol (lookup definition/usages as file::name), impact (blast radius of changes to path), status (index stats).", json!({"type": "object", "properties": {"action": {"type": "string"}, "path": {"type": "string"}, "project_root": {"type": "string"}}, "required": ["action"]})),
1060 ("ctx_session", "Cross-session memory (CCP). Actions: load (restore previous session ~400 tok), \
1061save, status, task (set current task), finding (record discovery), decision (record choice), \
1062reset, list (show sessions), cleanup, snapshot (build compaction snapshot ~2KB), \
1063restore (rebuild state from snapshot after context compaction).", json!({"type": "object", "properties": {"action": {"type": "string"}, "value": {"type": "string"}, "session_id": {"type": "string"}}, "required": ["action"]})),
1064 ("ctx_knowledge", "Persistent project knowledge with temporal facts + contradiction detection. Actions: remember (auto-tracks validity + detects contradictions), recall, pattern, consolidate, \
1065gotcha (record a bug to never repeat — trigger+resolution), timeline (fact version history), rooms (list knowledge categories), \
1066search (cross-session/cross-project), wakeup (compact AAAK briefing), status, remove, export, embeddings_status|embeddings_reset|embeddings_reindex.", json!({"type": "object", "properties": {"action": {"type": "string"}, "category": {"type": "string"}, "key": {"type": "string"}, "value": {"type": "string"}, "query": {"type": "string"}, "trigger": {"type": "string"}, "resolution": {"type": "string"}, "severity": {"type": "string"}}, "required": ["action"]})),
1067 ("ctx_agent", "Multi-agent coordination with persistent diaries. Actions: register, \
1068post, read, status, handoff, sync, diary (log discovery/decision/blocker/progress/insight — persisted), \
1069recall_diary (read diary), diaries (list all), list, info.", json!({"type": "object", "properties": {"action": {"type": "string"}, "agent_type": {"type": "string"}, "role": {"type": "string"}, "message": {"type": "string"}, "to_agent": {"type": "string"}, "status": {"type": "string"}}, "required": ["action"]})),
1070 ("ctx_share", "Share cached file contexts between agents. Actions: push (share files from cache), \
1071pull (receive shared files), list (show all shared contexts), clear (remove your shared contexts).", json!({"type": "object", "properties": {"action": {"type": "string"}, "paths": {"type": "string"}, "to_agent": {"type": "string"}, "message": {"type": "string"}}, "required": ["action"]})),
1072 ("ctx_overview", "Task-relevant project map — use at session start.", json!({"type": "object", "properties": {"task": {"type": "string"}, "path": {"type": "string"}}})),
1073 ("ctx_preload", "Proactive context loader — reads and caches task-relevant files, returns compact L-curve-optimized summary with critical lines, imports, and signatures. Costs ~50-100 tokens instead of ~5000 for individual reads.", json!({"type": "object", "properties": {"task": {"type": "string", "description": "Task description (e.g. 'fix auth bug in validate_token')"}, "path": {"type": "string", "description": "Project root (default: .)"}}, "required": ["task"]})),
1074 ("ctx_prefetch", "Predictive prefetch — prewarm cache for blast radius files (graph + task signals) within budgets.", json!({"type": "object", "properties": {"root": {"type": "string"}, "task": {"type": "string"}, "changed_files": {"type": "array", "items": {"type": "string"}}, "budget_tokens": {"type": "integer"}, "max_files": {"type": "integer"}}})),
1075 ("ctx_wrapped", "Savings report card. Periods: week|month|all.", json!({"type": "object", "properties": {"period": {"type": "string"}}})),
1076 ("ctx_cost", "Cost attribution (local-first). Actions: report|agent|tools|json|reset.", json!({"type": "object", "properties": {"action": {"type": "string"}, "agent_id": {"type": "string"}, "limit": {"type": "integer"}}})),
1077 ("ctx_gain", "Gain report.", json!({"type": "object", "properties": {"action": {"type": "string"}, "period": {"type": "string"}, "model": {"type": "string"}, "limit": {"type": "integer"}}})),
1078 ("ctx_feedback", "Harness feedback for LLM output tokens/latency (local-first). Actions: record|report|json|reset|status.", json!({"type": "object", "properties": {"action": {"type": "string"}, "agent_id": {"type": "string"}, "intent": {"type": "string"}, "model": {"type": "string"}, "llm_input_tokens": {"type": "integer"}, "llm_output_tokens": {"type": "integer"}, "latency_ms": {"type": "integer"}, "note": {"type": "string"}, "limit": {"type": "integer"}}})),
1079 ("ctx_handoff", "Context Ledger Protocol (hashed, deterministic, local-first). Actions: create|show|list|pull|clear.", json!({"type": "object", "properties": {"action": {"type": "string"}, "path": {"type": "string"}, "paths": {"type": "array", "items": {"type": "string"}}, "apply_workflow": {"type": "boolean"}, "apply_session": {"type": "boolean"}, "apply_knowledge": {"type": "boolean"}}})),
1080 ("ctx_heatmap", "File access heatmap (local-first). Actions: status|directory|cold|json.", json!({"type": "object", "properties": {"action": {"type": "string"}, "path": {"type": "string"}}})),
1081 ("ctx_task", "Multi-agent task orchestration. Actions: create|update|list|get|cancel|message|info.", json!({"type": "object", "properties": {"action": {"type": "string"}, "task_id": {"type": "string"}, "to_agent": {"type": "string"}, "description": {"type": "string"}, "state": {"type": "string"}, "message": {"type": "string"}}, "required": ["action"]})),
1082 ("ctx_impact", "Graph-based impact analysis. Actions: analyze|chain|build|status.", json!({"type": "object", "properties": {"action": {"type": "string"}, "path": {"type": "string"}, "root": {"type": "string"}, "depth": {"type": "integer"}}})),
1083 ("ctx_architecture", "Graph-based architecture analysis. Actions: overview|clusters|layers|cycles|entrypoints|module.", json!({"type": "object", "properties": {"action": {"type": "string"}, "path": {"type": "string"}, "root": {"type": "string"}}})),
1084 ("ctx_workflow", "Workflow rails (state machine + evidence). Actions: start|status|transition|complete|evidence_add|evidence_list|stop.", json!({"type": "object", "properties": {"action": {"type": "string"}, "name": {"type": "string"}, "spec": {"type": "string"}, "to": {"type": "string"}, "key": {"type": "string"}, "value": {"type": "string"}}})),
1085 ("ctx_semantic_search", "Semantic code search (BM25 + optional embeddings/hybrid). action=reindex to rebuild.", json!({"type": "object", "properties": {"query": {"type": "string"}, "path": {"type": "string"}, "top_k": {"type": "integer"}, "action": {"type": "string"}, "mode": {"type": "string", "enum": ["bm25","dense","hybrid"]}, "languages": {"type": "array", "items": {"type": "string"}}, "path_glob": {"type": "string"}}, "required": ["query"]})),
1086 ("ctx_execute", "Run code in sandbox (11 languages). Only stdout enters context. Languages: javascript, typescript, python, shell, ruby, go, rust, php, perl, r, elixir. Actions: batch (multiple scripts), file (process file in sandbox).", json!({"type": "object", "properties": {"language": {"type": "string"}, "code": {"type": "string"}, "intent": {"type": "string"}, "timeout": {"type": "integer"}, "action": {"type": "string"}, "items": {"type": "string"}, "path": {"type": "string"}}, "required": ["language", "code"]})),
1087 ("ctx_symbol", "Read a specific symbol (function, struct, class) by name. Returns only the symbol code block instead of the entire file. 90-97% fewer tokens than full file read.", json!({"type": "object", "properties": {"name": {"type": "string"}, "file": {"type": "string"}, "kind": {"type": "string"}}, "required": ["name"]})),
1088 ("ctx_outline", "List all symbols in a file with signatures. Much fewer tokens than reading the full file.", json!({"type": "object", "properties": {"path": {"type": "string"}, "kind": {"type": "string"}}, "required": ["path"]})),
1089 ("ctx_compress_memory", "Compress a memory/config file (CLAUDE.md, .cursorrules) preserving code, URLs, paths. Creates .original.md backup.", json!({"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]})),
1090 ("ctx_callers", "Find all symbols that call a given function/method.", json!({"type": "object", "properties": {"symbol": {"type": "string"}, "file": {"type": "string"}}, "required": ["symbol"]})),
1091 ("ctx_callees", "Find all functions/methods called by a given symbol.", json!({"type": "object", "properties": {"symbol": {"type": "string"}, "file": {"type": "string"}}, "required": ["symbol"]})),
1092 ("ctx_routes", "List HTTP routes/endpoints extracted from the project. Supports Express, Flask, FastAPI, Actix, Spring, Rails, Next.js.", json!({"type": "object", "properties": {"method": {"type": "string"}, "path": {"type": "string"}}})),
1093 ("ctx_graph_diagram", "Generate a Mermaid diagram of the dependency or call graph.", json!({"type": "object", "properties": {"file": {"type": "string"}, "depth": {"type": "integer"}, "kind": {"type": "string"}}})),
1094 ]
1095}