added ast-grep use
g3 tool use of ast-grep command with batching for faster code exploration.
This commit is contained in:
@@ -2,6 +2,7 @@ pub mod error_handling;
|
||||
pub mod project;
|
||||
pub mod task_result;
|
||||
pub mod ui_writer;
|
||||
pub mod code_search;
|
||||
pub use task_result::TaskResult;
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -1184,10 +1185,26 @@ The tool will execute immediately and you'll receive the result (success or erro
|
||||
# Instructions
|
||||
|
||||
1. Analyze the request and break down into smaller tasks if appropriate
|
||||
2. Execute ONE tool at a time
|
||||
2. Execute ONE tool at a time. An exception exists for when you're writing files. See below.
|
||||
3. STOP when the original request was satisfied
|
||||
4. Call the final_output tool when done
|
||||
|
||||
Exception to using ONE tool at a time:
|
||||
If all you’re doing is WRITING files, and you don’t need to do anything else between each step.
|
||||
You can issue MULTIPLE write_file tool calls in a request, however you may ONLY make a SINGLE write_file call for any file in that request.
|
||||
For example you may call:
|
||||
[START OF REQUEST]
|
||||
write_file(\"helper.rs\", \"...\")
|
||||
write_file(\"file2.txt\", \"...\")
|
||||
[DONE]
|
||||
|
||||
But NOT:
|
||||
[START OF REQUEST]
|
||||
write_file(\"helper.rs\", \"...\")
|
||||
write_file(\"file2.txt\", \"...\")
|
||||
write_file(\"helper.rs\", \"...\")
|
||||
[DONE]
|
||||
|
||||
# Task Management
|
||||
|
||||
Use todo_read and todo_write for tasks with 3+ steps, multiple files/components, or uncertain scope.
|
||||
@@ -1860,6 +1877,64 @@ Template:
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
// Add code_search tool
|
||||
tools.push(Tool {
|
||||
name: "code_search".to_string(),
|
||||
description: "Batch syntax-aware searches via ast-grep. Supports up to 20 pattern or YAML-rule searches in parallel; returns JSON matches (stream-collated).".to_string(),
|
||||
input_schema: json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"searches": {
|
||||
"type": "array",
|
||||
"maxItems": 20,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Label for this search." },
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["pattern", "yaml"],
|
||||
"description": "`pattern` uses `ast-grep run`; `yaml` uses `ast-grep scan --inline-rules`."
|
||||
},
|
||||
// pattern mode (fast one-off)
|
||||
"pattern": { "type": "string", "description": "ast-grep pattern code (e.g., \"async fn $NAME($$$ARGS) { $$$ }\")"},
|
||||
"language": { "type": "string", "description": "Optional language for pattern mode; ast-grep may infer from file extensions if omitted." },
|
||||
// yaml mode (full rule object)
|
||||
"rule_yaml": { "type": "string", "description": "A full YAML rule object text. Must include `id`, `language`, and `rule`." },
|
||||
// targeting
|
||||
"paths": { "type": "array", "items": { "type": "string" }, "description": "Paths/dirs to search. Defaults to current dir if empty." },
|
||||
"globs": { "type": "array", "items": { "type": "string" }, "description": "Optional include/exclude globs for CLI --globs." },
|
||||
// result formatting & performance knobs
|
||||
"json_style": { "type": "string", "enum": ["pretty","stream","compact"], "default": "stream", "description": "Use stream for large codebases." },
|
||||
"context": { "type": "integer", "minimum": 0, "maximum": 20, "default": 0, "description": "CLI -C context lines in text output; also affects JSON `lines` field." },
|
||||
"threads": { "type": "integer", "minimum": 1, "description": "Optional override for ast-grep -j (per process)." },
|
||||
"include_metadata": { "type": "boolean", "default": false, "description": "If yaml mode and rule has metadata, add --include-metadata." },
|
||||
// robustness
|
||||
"no_ignore": {
|
||||
"type": "array",
|
||||
"items": { "type": "string", "enum": ["hidden","dot","exclude","global","parent","vcs"] },
|
||||
"description": "Forwarded to --no-ignore to bypass ignore files/hidden."
|
||||
},
|
||||
// severity overrides for yaml mode
|
||||
"severity": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "type": "string", "enum": ["error","warning","info","hint","off"] },
|
||||
"description": "Optional map<ruleId, severity> -> passed via --error/--warning/--info/--hint/--off."
|
||||
},
|
||||
// per-search timeout seconds (default 60)
|
||||
"timeout_secs": { "type": "integer", "minimum": 1, "default": 60 }
|
||||
},
|
||||
"required": ["name","mode"]
|
||||
}
|
||||
},
|
||||
// global concurrency & truncation
|
||||
"max_concurrency": { "type": "integer", "minimum": 1, "default": 4 },
|
||||
"max_matches_per_search": { "type": "integer", "minimum": 1, "default": 500 }
|
||||
},
|
||||
"required": ["searches"]
|
||||
}),
|
||||
});
|
||||
|
||||
// Add WebDriver tools if enabled
|
||||
if enable_webdriver {
|
||||
@@ -4437,6 +4512,41 @@ Template:
|
||||
Ok("❌ Computer control not enabled. Set computer_control.enabled = true in config.".to_string())
|
||||
}
|
||||
}
|
||||
"code_search" => {
|
||||
debug!("Processing code_search tool call");
|
||||
|
||||
// Parse the request
|
||||
let request: crate::code_search::CodeSearchRequest = match serde_json::from_value(tool_call.args.clone()) {
|
||||
Ok(req) => req,
|
||||
Err(e) => {
|
||||
return Ok(format!("❌ Invalid code_search arguments: {}", e));
|
||||
}
|
||||
};
|
||||
|
||||
// Execute the code search
|
||||
match crate::code_search::execute_code_search(request).await {
|
||||
Ok(response) => {
|
||||
// Serialize the response to JSON
|
||||
match serde_json::to_string_pretty(&response) {
|
||||
Ok(json_output) => {
|
||||
Ok(format!("✅ Code search completed\n{}", json_output))
|
||||
}
|
||||
Err(e) => {
|
||||
Ok(format!("❌ Failed to serialize response: {}", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
// Check if it's an ast-grep not found error and provide helpful message
|
||||
let error_msg = e.to_string();
|
||||
if error_msg.contains("ast-grep not found") {
|
||||
Ok(format!("❌ {}", error_msg))
|
||||
} else {
|
||||
Ok(format!("❌ Code search failed: {}", error_msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn!("Unknown tool: {}", tool_call.tool);
|
||||
Ok(format!("❓ Unknown tool: {}", tool_call.tool))
|
||||
|
||||
Reference in New Issue
Block a user