feat: Created the explore agent for exploring codebases to help answer questions
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# Explore
|
||||
|
||||
An AI agent specialized in exploring codebases, finding patterns, and understanding project structures.
|
||||
|
||||
This agent is designed to be delegated to by the **[Sisyphus](../sisyphus/README.md)** agent to gather information and context. Sisyphus
|
||||
acts as the coordinator/architect, while Explore handles the research and discovery phase.
|
||||
|
||||
It can also be used as a standalone tool for understanding codebases and finding specific information.
|
||||
|
||||
## Features
|
||||
|
||||
- 🔍 Deep codebase exploration and pattern matching
|
||||
- 📂 File system navigation and content analysis
|
||||
- 🧠 Context gathering for complex tasks
|
||||
- 🛡️ Read-only operations for safe investigation
|
||||
@@ -0,0 +1,74 @@
|
||||
name: explore
|
||||
description: Fast codebase exploration agent - finds patterns, structures, and relevant files
|
||||
version: 1.0.0
|
||||
temperature: 0.1
|
||||
top_p: 0.95
|
||||
|
||||
variables:
|
||||
- name: project_dir
|
||||
description: Project directory to explore
|
||||
default: '.'
|
||||
|
||||
global_tools:
|
||||
- fs_read.sh
|
||||
- fs_grep.sh
|
||||
- fs_glob.sh
|
||||
- fs_ls.sh
|
||||
|
||||
instructions: |
|
||||
You are a codebase explorer. Your job: Search, find, report. Nothing else.
|
||||
|
||||
## Your Mission
|
||||
|
||||
Given a search task, you:
|
||||
1. Search for relevant files and patterns
|
||||
2. Read key files to understand structure
|
||||
3. Report findings concisely
|
||||
4. Signal completion with EXPLORE_COMPLETE
|
||||
|
||||
## File Reading Strategy (IMPORTANT - minimize token usage)
|
||||
|
||||
1. **Find first, read second** - Never read a file without knowing why
|
||||
2. **Use grep to locate** - `fs_grep --pattern "struct User" --include "*.rs"` finds exactly where things are
|
||||
3. **Use glob to discover** - `fs_glob --pattern "*.rs" --path src/` finds files by name
|
||||
4. **Read targeted sections** - `fs_read --path "src/main.rs" --offset 50 --limit 30` reads only lines 50-79
|
||||
5. **Never read entire large files** - If a file is 500+ lines, read the relevant section only
|
||||
|
||||
## Available Actions
|
||||
|
||||
- `fs_grep --pattern "struct User" --include "*.rs"` - Find content across files
|
||||
- `fs_glob --pattern "*.rs" --path src/` - Find files by name pattern
|
||||
- `fs_read --path "src/main.rs"` - Read a file (with line numbers)
|
||||
- `fs_read --path "src/main.rs" --offset 100 --limit 50` - Read lines 100-149 only
|
||||
- `get_structure` - See project layout
|
||||
- `search_content --pattern "struct User"` - Agent-level content search
|
||||
|
||||
## Output Format
|
||||
|
||||
Always end your response with a findings summary:
|
||||
|
||||
```
|
||||
FINDINGS:
|
||||
- [Key finding 1]
|
||||
- [Key finding 2]
|
||||
- Relevant files: [list]
|
||||
|
||||
EXPLORE_COMPLETE
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
1. **Be fast** - Don't read every file, read representative ones
|
||||
2. **Be focused** - Answer the specific question asked
|
||||
3. **Be concise** - Report findings, not your process
|
||||
4. **Never modify files** - You are read-only
|
||||
5. **Limit reads** - Max 5 file reads per exploration
|
||||
|
||||
## Context
|
||||
- Project: {{project_dir}}
|
||||
- CWD: {{__cwd__}}
|
||||
|
||||
conversation_starters:
|
||||
- 'Find how authentication is implemented'
|
||||
- 'What patterns are used for API endpoints'
|
||||
- 'Show me the project structure'
|
||||
Executable
+157
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
# shellcheck disable=SC1090
|
||||
source "$LLM_PROMPT_UTILS_FILE"
|
||||
source "$LLM_ROOT_DIR/agents/.shared/utils.sh"
|
||||
|
||||
# @env LLM_OUTPUT=/dev/stdout
|
||||
# @env LLM_AGENT_VAR_PROJECT_DIR=.
|
||||
# @describe Explore agent tools for codebase search and analysis
|
||||
|
||||
_project_dir() {
|
||||
local dir="${LLM_AGENT_VAR_PROJECT_DIR:-.}"
|
||||
(cd "${dir}" 2>/dev/null && pwd) || echo "${dir}"
|
||||
}
|
||||
|
||||
# @cmd Get project structure and layout
|
||||
get_structure() {
|
||||
local project_dir
|
||||
project_dir=$(_project_dir)
|
||||
|
||||
info "Project structure:" >> "$LLM_OUTPUT"
|
||||
echo "" >> "$LLM_OUTPUT"
|
||||
|
||||
local project_info
|
||||
project_info=$(detect_project "${project_dir}")
|
||||
|
||||
{
|
||||
echo "Type: $(echo "${project_info}" | jq -r '.type')"
|
||||
echo ""
|
||||
|
||||
get_tree "${project_dir}" 3
|
||||
} >> "$LLM_OUTPUT"
|
||||
}
|
||||
|
||||
# @cmd Search for files by name pattern
|
||||
# @option --pattern! File name pattern (e.g., "*.rs", "config*", "*test*")
|
||||
search_files() {
|
||||
# shellcheck disable=SC2154
|
||||
local pattern="${argc_pattern}"
|
||||
local project_dir
|
||||
project_dir=$(_project_dir)
|
||||
|
||||
info "Files matching: ${pattern}" >> "$LLM_OUTPUT"
|
||||
echo "" >> "$LLM_OUTPUT"
|
||||
|
||||
local results
|
||||
results=$(search_files "${pattern}" "${project_dir}")
|
||||
|
||||
if [[ -n "${results}" ]]; then
|
||||
echo "${results}" >> "$LLM_OUTPUT"
|
||||
else
|
||||
warn "No files found" >> "$LLM_OUTPUT"
|
||||
fi
|
||||
}
|
||||
|
||||
# @cmd Search for content in files
|
||||
# @option --pattern! Text or regex pattern to search for
|
||||
# @option --file-type Filter by file extension (e.g., "rs", "py", "ts")
|
||||
search_content() {
|
||||
local pattern="${argc_pattern}"
|
||||
local file_type="${argc_file_type:-}"
|
||||
local project_dir
|
||||
project_dir=$(_project_dir)
|
||||
|
||||
info "Searching: ${pattern}" >> "$LLM_OUTPUT"
|
||||
echo "" >> "$LLM_OUTPUT"
|
||||
|
||||
local include_arg=""
|
||||
if [[ -n "${file_type}" ]]; then
|
||||
include_arg="--include=*.${file_type}"
|
||||
fi
|
||||
|
||||
local results
|
||||
# shellcheck disable=SC2086
|
||||
results=$(grep -rn ${include_arg} "${pattern}" "${project_dir}" 2>/dev/null | \
|
||||
grep -v '/target/' | \
|
||||
grep -v '/node_modules/' | \
|
||||
grep -v '/.git/' | \
|
||||
grep -v '/dist/' | \
|
||||
head -30) || true
|
||||
|
||||
if [[ -n "${results}" ]]; then
|
||||
echo "${results}" >> "$LLM_OUTPUT"
|
||||
else
|
||||
warn "No matches found" >> "$LLM_OUTPUT"
|
||||
fi
|
||||
}
|
||||
|
||||
# @cmd Read a file's contents
|
||||
# @option --path! Path to the file (relative to project root)
|
||||
# @option --lines Maximum lines to read (default: 200)
|
||||
read_file() {
|
||||
# shellcheck disable=SC2154
|
||||
local file_path="${argc_path}"
|
||||
local max_lines="${argc_lines:-200}"
|
||||
local project_dir
|
||||
project_dir=$(_project_dir)
|
||||
|
||||
local full_path="${project_dir}/${file_path}"
|
||||
|
||||
if [[ ! -f "${full_path}" ]]; then
|
||||
error "File not found: ${file_path}" >> "$LLM_OUTPUT"
|
||||
return 1
|
||||
fi
|
||||
|
||||
{
|
||||
info "File: ${file_path}"
|
||||
echo ""
|
||||
} >> "$LLM_OUTPUT"
|
||||
|
||||
head -n "${max_lines}" "${full_path}" >> "$LLM_OUTPUT"
|
||||
|
||||
local total_lines
|
||||
total_lines=$(wc -l < "${full_path}")
|
||||
if [[ "${total_lines}" -gt "${max_lines}" ]]; then
|
||||
echo "" >> "$LLM_OUTPUT"
|
||||
warn "... truncated (${total_lines} total lines)" >> "$LLM_OUTPUT"
|
||||
fi
|
||||
}
|
||||
|
||||
# @cmd Find similar files to a given file (for pattern matching)
|
||||
# @option --path! Path to the reference file
|
||||
find_similar() {
|
||||
local file_path="${argc_path}"
|
||||
local project_dir
|
||||
project_dir=$(_project_dir)
|
||||
|
||||
local ext="${file_path##*.}"
|
||||
local dir
|
||||
dir=$(dirname "${file_path}")
|
||||
|
||||
info "Files similar to: ${file_path}" >> "$LLM_OUTPUT"
|
||||
echo "" >> "$LLM_OUTPUT"
|
||||
|
||||
local results
|
||||
results=$(find "${project_dir}/${dir}" -maxdepth 1 -type f -name "*.${ext}" \
|
||||
! -name "$(basename "${file_path}")" \
|
||||
! -name "*test*" \
|
||||
! -name "*spec*" \
|
||||
2>/dev/null | head -5)
|
||||
|
||||
if [[ -n "${results}" ]]; then
|
||||
echo "${results}" >> "$LLM_OUTPUT"
|
||||
else
|
||||
results=$(find "${project_dir}" -type f -name "*.${ext}" \
|
||||
! -name "$(basename "${file_path}")" \
|
||||
! -name "*test*" \
|
||||
-not -path '*/target/*' \
|
||||
2>/dev/null | head -5)
|
||||
if [[ -n "${results}" ]]; then
|
||||
echo "${results}" >> "$LLM_OUTPUT"
|
||||
else
|
||||
warn "No similar files found" >> "$LLM_OUTPUT"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
Reference in New Issue
Block a user