use serde_json::{json, Value};
pub const CONTEXT_STATUS: &str = "context_status";
pub const CONTEXT_FOCUS: &str = "context_focus";
pub const CONTEXT_EVICT: &str = "context_evict";
pub const CONTEXT_RECOMMEND: &str = "context_recommend";
pub const CONTEXT_LOAD_SKELETON: &str = "context_load_skeleton";
pub const CONTEXT_BULK_READ: &str = "context_bulk_read";
pub const CONTEXT_SUMMARY: &str = "context_summary";
pub const CONTEXT_TOOL_NAMES: &[&str] = &[
CONTEXT_STATUS,
CONTEXT_FOCUS,
CONTEXT_EVICT,
CONTEXT_RECOMMEND,
CONTEXT_LOAD_SKELETON,
CONTEXT_BULK_READ,
CONTEXT_SUMMARY,
];
pub fn is_context_tool(name: &str) -> bool {
CONTEXT_TOOL_NAMES.contains(&name)
}
pub fn context_tool_descriptions() -> Vec<ToolDesc> {
vec![
ToolDesc {
name: CONTEXT_STATUS,
description: "Show current context window status: budget usage, loaded files at each level (L1 tree / L2 skeleton / L3 full), and recommendations.",
schema: json!({
"type": "object",
"properties": {},
"required": []
}),
},
ToolDesc {
name: CONTEXT_FOCUS,
description: "Promote files relevant to a query to full detail (L3). Automatically downgrades less relevant files to make room. Use this instead of reading many files manually.",
schema: json!({
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query to find relevant files (e.g., 'context compression', 'token estimation', 'file_read tool')"
},
"max_files": {
"type": "integer",
"description": "Maximum number of files to promote to L3 (default: 5)",
"default": 5
}
},
"required": ["query"]
}),
},
ToolDesc {
name: CONTEXT_EVICT,
description: "Remove a file from context (downgrade to L1 tree level), freeing tokens for other content.",
schema: json!({
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "File path to evict from context"
}
},
"required": ["path"]
}),
},
ToolDesc {
name: CONTEXT_RECOMMEND,
description: "Get AI-powered recommendations for what context to load or evict for the current task. Returns a list of files to promote and files to evict with reasons.",
schema: json!({
"type": "object",
"properties": {
"task": {
"type": "string",
"description": "Description of what you're trying to do (used to determine relevance)"
}
},
"required": ["task"]
}),
},
ToolDesc {
name: CONTEXT_LOAD_SKELETON,
description: "Load a file at skeleton level (L2) — shows function/struct/trait signatures without bodies. Much cheaper than full read (~90% fewer tokens).",
schema: json!({
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "File path to load at skeleton level"
}
},
"required": ["path"]
}),
},
ToolDesc {
name: CONTEXT_BULK_READ,
description: "Read multiple source files in parallel into the context. Much faster than reading one at a time. Automatically manages budget by compressing older files. Use glob pattern to select files.",
schema: json!({
"type": "object",
"properties": {
"pattern": {
"type": "string",
"description": "Glob pattern for files to read (e.g., 'src/agent/*.rs', 'src/**/*.rs')"
},
"max_files": {
"type": "integer",
"description": "Maximum number of files to read (default: 20)",
"default": 20
}
},
"required": ["pattern"]
}),
},
ToolDesc {
name: CONTEXT_SUMMARY,
description: "Generate a structured per-module summary of the codebase. Shows file counts, function/struct counts per module, and what's loaded at each level. Use this to understand the codebase without reading every file.",
schema: json!({
"type": "object",
"properties": {},
"required": []
}),
},
]
}
pub struct ToolDesc {
pub name: &'static str,
pub description: &'static str,
pub schema: Value,
}
#[cfg(test)]
#[path = "../../tests/unit/tools/context/context_test.rs"]
mod tests;