mirror of
https://github.com/Aider-AI/aider.git
synced 2025-06-14 08:34:59 +00:00
Make it clearer that Add commands view, not adding
This commit is contained in:
parent
dea5bd54f2
commit
bbc16ca60a
2 changed files with 67 additions and 68 deletions
|
@ -522,31 +522,31 @@ class NavigatorCoder(Coder):
|
||||||
# Normalize tool name for case-insensitive matching
|
# Normalize tool name for case-insensitive matching
|
||||||
norm_tool_name = tool_name.lower()
|
norm_tool_name = tool_name.lower()
|
||||||
|
|
||||||
if norm_tool_name == 'glob':
|
if norm_tool_name == 'viewfilesatglob':
|
||||||
pattern = params.get('pattern')
|
pattern = params.get('pattern')
|
||||||
if pattern is not None:
|
if pattern is not None:
|
||||||
result_message = self._execute_glob(pattern)
|
result_message = self._execute_view_files_at_glob(pattern)
|
||||||
else:
|
else:
|
||||||
result_message = "Error: Missing 'pattern' parameter for Glob"
|
result_message = "Error: Missing 'pattern' parameter for ViewFilesAtGlob"
|
||||||
elif norm_tool_name == 'grep':
|
elif norm_tool_name == 'viewfilesmatching':
|
||||||
pattern = params.get('pattern')
|
pattern = params.get('pattern')
|
||||||
file_pattern = params.get('file_pattern') # Optional
|
file_pattern = params.get('file_pattern') # Optional
|
||||||
if pattern is not None:
|
if pattern is not None:
|
||||||
result_message = self._execute_grep(pattern, file_pattern)
|
result_message = self._execute_view_files_matching(pattern, file_pattern)
|
||||||
else:
|
else:
|
||||||
result_message = "Error: Missing 'pattern' parameter for Grep"
|
result_message = "Error: Missing 'pattern' parameter for ViewFilesMatching"
|
||||||
elif norm_tool_name == 'ls':
|
elif norm_tool_name == 'ls':
|
||||||
directory = params.get('directory')
|
directory = params.get('directory')
|
||||||
if directory is not None:
|
if directory is not None:
|
||||||
result_message = self._execute_ls(directory)
|
result_message = self._execute_ls(directory)
|
||||||
else:
|
else:
|
||||||
result_message = "Error: Missing 'directory' parameter for Ls"
|
result_message = "Error: Missing 'directory' parameter for Ls"
|
||||||
elif norm_tool_name == 'add':
|
elif norm_tool_name == 'view':
|
||||||
file_path = params.get('file_path')
|
file_path = params.get('file_path')
|
||||||
if file_path is not None:
|
if file_path is not None:
|
||||||
result_message = self._execute_add(file_path)
|
result_message = self._execute_view(file_path)
|
||||||
else:
|
else:
|
||||||
result_message = "Error: Missing 'file_path' parameter for Add"
|
result_message = "Error: Missing 'file_path' parameter for View"
|
||||||
elif norm_tool_name == 'remove':
|
elif norm_tool_name == 'remove':
|
||||||
file_path = params.get('file_path')
|
file_path = params.get('file_path')
|
||||||
if file_path is not None:
|
if file_path is not None:
|
||||||
|
@ -565,12 +565,12 @@ class NavigatorCoder(Coder):
|
||||||
result_message = self._execute_make_readonly(file_path)
|
result_message = self._execute_make_readonly(file_path)
|
||||||
else:
|
else:
|
||||||
result_message = "Error: Missing 'file_path' parameter for MakeReadonly"
|
result_message = "Error: Missing 'file_path' parameter for MakeReadonly"
|
||||||
elif norm_tool_name == 'find':
|
elif norm_tool_name == 'viewfileswithsymbol':
|
||||||
symbol = params.get('symbol')
|
symbol = params.get('symbol')
|
||||||
if symbol is not None:
|
if symbol is not None:
|
||||||
result_message = self._execute_find(symbol)
|
result_message = self._execute_view_files_with_symbol(symbol)
|
||||||
else:
|
else:
|
||||||
result_message = "Error: Missing 'symbol' parameter for Find"
|
result_message = "Error: Missing 'symbol' parameter for ViewFilesWithSymbol"
|
||||||
elif norm_tool_name == 'command':
|
elif norm_tool_name == 'command':
|
||||||
command_string = params.get('command_string')
|
command_string = params.get('command_string')
|
||||||
if command_string is not None:
|
if command_string is not None:
|
||||||
|
@ -916,9 +916,9 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
|
|
||||||
return edited_files
|
return edited_files
|
||||||
|
|
||||||
def _execute_glob(self, pattern):
|
def _execute_view_files_at_glob(self, pattern):
|
||||||
"""
|
"""
|
||||||
Execute a glob pattern and add matching files to context.
|
Execute a glob pattern and add matching files to context as read-only.
|
||||||
|
|
||||||
This tool helps the LLM find files by pattern matching, similar to
|
This tool helps the LLM find files by pattern matching, similar to
|
||||||
how a developer would use glob patterns to find files.
|
how a developer would use glob patterns to find files.
|
||||||
|
@ -965,12 +965,12 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
self.io.tool_output(f"⚠️ No files found matching '{pattern}'")
|
self.io.tool_output(f"⚠️ No files found matching '{pattern}'")
|
||||||
return f"No files found matching '{pattern}'"
|
return f"No files found matching '{pattern}'"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.io.tool_error(f"Error in glob: {str(e)}")
|
self.io.tool_error(f"Error in ViewFilesAtGlob: {str(e)}")
|
||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
def _execute_grep(self, search_pattern, file_pattern=None):
|
def _execute_view_files_matching(self, search_pattern, file_pattern=None):
|
||||||
"""
|
"""
|
||||||
Search for pattern in files and add matching files to context.
|
Search for pattern in files and add matching files to context as read-only.
|
||||||
|
|
||||||
This tool lets the LLM search for content within files, mimicking
|
This tool lets the LLM search for content within files, mimicking
|
||||||
how a developer would use grep to find relevant code.
|
how a developer would use grep to find relevant code.
|
||||||
|
@ -1034,7 +1034,7 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
self.io.tool_output(f"⚠️ Pattern '{search_pattern}' not found in any files")
|
self.io.tool_output(f"⚠️ Pattern '{search_pattern}' not found in any files")
|
||||||
return f"Pattern not found in any files"
|
return f"Pattern not found in any files"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.io.tool_error(f"Error in grep: {str(e)}")
|
self.io.tool_error(f"Error in ViewFilesMatching: {str(e)}")
|
||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
def _execute_ls(self, dir_path):
|
def _execute_ls(self, dir_path):
|
||||||
|
@ -1084,17 +1084,18 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
self.io.tool_error(f"Error in ls: {str(e)}")
|
self.io.tool_error(f"Error in ls: {str(e)}")
|
||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
def _execute_add(self, file_path):
|
def _execute_view(self, file_path):
|
||||||
"""
|
"""
|
||||||
Explicitly add a file to context as read-only.
|
Explicitly add a file to context as read-only.
|
||||||
|
|
||||||
This gives the LLM explicit control over what files to add,
|
This gives the LLM explicit control over what files to view,
|
||||||
rather than relying on indirect mentions.
|
rather than relying on indirect mentions.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self._add_file_to_context(file_path, True)
|
# Use the helper, marking it as an explicit view request
|
||||||
|
return self._add_file_to_context(file_path, explicit=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.io.tool_error(f"Error adding file: {str(e)}")
|
self.io.tool_error(f"Error viewing file: {str(e)}")
|
||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
def _add_file_to_context(self, file_path, explicit=False):
|
def _add_file_to_context(self, file_path, explicit=False):
|
||||||
|
@ -1103,7 +1104,7 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- file_path: Path to the file to add
|
- file_path: Path to the file to add
|
||||||
- explicit: Whether this was an explicit add command (vs. implicit through glob/grep)
|
- explicit: Whether this was an explicit view command (vs. implicit through ViewFilesAtGlob/ViewFilesMatching)
|
||||||
"""
|
"""
|
||||||
# Check if file exists
|
# Check if file exists
|
||||||
abs_path = self.abs_root_path(file_path)
|
abs_path = self.abs_root_path(file_path)
|
||||||
|
@ -1150,15 +1151,15 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
|
|
||||||
# Inform user
|
# Inform user
|
||||||
if explicit:
|
if explicit:
|
||||||
self.io.tool_output(f"📎 Added '{file_path}' to context as read-only")
|
self.io.tool_output(f"📎 Viewed '{file_path}' (added to context as read-only)")
|
||||||
return f"Added file to context as read-only"
|
return f"Viewed file (added to context as read-only)"
|
||||||
else:
|
else:
|
||||||
# For implicit adds (from glob/grep), just return success
|
# For implicit adds (from ViewFilesAtGlob/ViewFilesMatching), just return success
|
||||||
return f"Added file to context as read-only"
|
return f"Added file to context as read-only"
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.io.tool_error(f"Error adding file '{file_path}': {str(e)}")
|
self.io.tool_error(f"Error adding file '{file_path}' for viewing: {str(e)}")
|
||||||
return f"Error adding file: {str(e)}"
|
return f"Error adding file for viewing: {str(e)}"
|
||||||
|
|
||||||
def _execute_make_editable(self, file_path):
|
def _execute_make_editable(self, file_path):
|
||||||
"""
|
"""
|
||||||
|
@ -1266,17 +1267,17 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
self.io.tool_error(f"Error removing file: {str(e)}")
|
self.io.tool_error(f"Error removing file: {str(e)}")
|
||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
def _execute_find(self, symbol):
|
def _execute_view_files_with_symbol(self, symbol):
|
||||||
"""
|
"""
|
||||||
Find files containing a specific symbol and add them to context as read-only.
|
Find files containing a specific symbol and add them to context as read-only.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if not self.repo_map:
|
if not self.repo_map:
|
||||||
self.io.tool_output("⚠️ Repo map not available, cannot use Find tool.")
|
self.io.tool_output("⚠️ Repo map not available, cannot use ViewFilesWithSymbol tool.")
|
||||||
return "Repo map not available"
|
return "Repo map not available"
|
||||||
|
|
||||||
if not symbol:
|
if not symbol:
|
||||||
return "Error: Missing 'symbol' parameter for Find"
|
return "Error: Missing 'symbol' parameter for ViewFilesWithSymbol"
|
||||||
|
|
||||||
self.io.tool_output(f"🔎 Searching for symbol '{symbol}'...")
|
self.io.tool_output(f"🔎 Searching for symbol '{symbol}'...")
|
||||||
found_files = set()
|
found_files = set()
|
||||||
|
@ -1337,7 +1338,7 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
return f"Symbol '{symbol}' not found in searchable files."
|
return f"Symbol '{symbol}' not found in searchable files."
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.io.tool_error(f"Error in find: {str(e)}")
|
self.io.tool_error(f"Error in ViewFilesWithSymbol: {str(e)}")
|
||||||
return f"Error: {str(e)}"
|
return f"Error: {str(e)}"
|
||||||
|
|
||||||
def _execute_command(self, command_string):
|
def _execute_command(self, command_string):
|
||||||
|
@ -1407,19 +1408,17 @@ Just reply with fixed versions of the {blocks} above that failed to match.
|
||||||
# Get new files to add (not already in context)
|
# Get new files to add (not already in context)
|
||||||
new_files = mentioned_files - current_files
|
new_files = mentioned_files - current_files
|
||||||
|
|
||||||
# In navigator mode, we *only* add files via explicit tool commands.
|
# In navigator mode, we *only* add files via explicit tool commands (`View`, `ViewFilesAtGlob`, etc.).
|
||||||
# Do nothing here for implicit mentions.
|
# Do nothing here for implicit mentions.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_for_file_mentions(self, content):
|
def check_for_file_mentions(self, content):
|
||||||
"""
|
"""
|
||||||
Override parent's method to use our own file processing logic.
|
Override parent's method to use our own file processing logic.
|
||||||
|
|
||||||
Override parent's method to disable implicit file mention handling in navigator mode.
|
Override parent's method to disable implicit file mention handling in navigator mode.
|
||||||
Files should only be added via explicit tool commands (`Add`, `Glob`, `Grep`).
|
Files should only be added via explicit tool commands (`View`, `ViewFilesAtGlob`, `ViewFilesMatching`, `ViewFilesWithSymbol`).
|
||||||
"""
|
"""
|
||||||
# Do nothing - disable implicit file adds in navigator mode.
|
# Do nothing - disable implicit file adds in navigator mode.
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -31,23 +31,23 @@ Act as an expert software engineer with the ability to autonomously navigate and
|
||||||
## Available Tools
|
## Available Tools
|
||||||
|
|
||||||
### File Discovery Tools
|
### File Discovery Tools
|
||||||
- **Glob**: `[tool_call(Glob, pattern="**/*.py")]`
|
- **ViewFilesAtGlob**: `[tool_call(ViewFilesAtGlob, pattern="**/*.py")]`
|
||||||
Find files matching a glob pattern and add them to context as read-only.
|
Find files matching a glob pattern and add them to context as read-only.
|
||||||
Supports patterns like "src/**/*.ts" or "*.json".
|
Supports patterns like "src/**/*.ts" or "*.json".
|
||||||
|
|
||||||
- **Grep**: `[tool_call(Grep, pattern="class User", file_pattern="*.py")]`
|
- **ViewFilesMatching**: `[tool_call(ViewFilesMatching, pattern="class User", file_pattern="*.py")]`
|
||||||
Search for text in files and add matching files to context as read-only.
|
Search for text in files and add matching files to context as read-only.
|
||||||
Files with more matches are prioritized. `file_pattern` is optional.
|
Files with more matches are prioritized. `file_pattern` is optional.
|
||||||
|
|
||||||
- **Ls**: `[tool_call(Ls, directory="src/components")]`
|
- **Ls**: `[tool_call(Ls, directory="src/components")]`
|
||||||
List files in a directory. Useful for exploring the project structure.
|
List files in a directory. Useful for exploring the project structure.
|
||||||
|
|
||||||
- **Find**: `[tool_call(Find, symbol="my_function")]`
|
- **ViewFilesWithSymbol**: `[tool_call(ViewFilesWithSymbol, symbol="my_function")]`
|
||||||
Find files containing a specific symbol (function, class, variable) and add them to context as read-only.
|
Find files containing a specific symbol (function, class, variable) and add them to context as read-only.
|
||||||
Leverages the repo map for accurate symbol lookup.
|
Leverages the repo map for accurate symbol lookup.
|
||||||
|
|
||||||
### Context Management Tools
|
### Context Management Tools
|
||||||
- **Add**: `[tool_call(Add, file_path="src/main.py")]`
|
- **View**: `[tool_call(View, file_path="src/main.py")]`
|
||||||
Explicitly add a specific file to context as read-only.
|
Explicitly add a specific file to context as read-only.
|
||||||
|
|
||||||
- **Remove**: `[tool_call(Remove, file_path="tests/old_test.py")]`
|
- **Remove**: `[tool_call(Remove, file_path="tests/old_test.py")]`
|
||||||
|
@ -104,8 +104,8 @@ When you include any tool call, the system will automatically continue to the ne
|
||||||
## Navigation Workflow
|
## Navigation Workflow
|
||||||
|
|
||||||
### Exploration Strategy
|
### Exploration Strategy
|
||||||
1. **Initial Discovery**: Use `Glob`, `Grep`, `Ls`, or `Find` to identify relevant files
|
1. **Initial Discovery**: Use `ViewFilesAtGlob`, `ViewFilesMatching`, `Ls`, or `ViewFilesWithSymbol` to identify relevant files
|
||||||
2. **Focused Investigation**: Add promising files to context with `Add`
|
2. **Focused Investigation**: Add promising files to context with `View`
|
||||||
3. **Context Management**: Remove irrelevant files with `Remove` to maintain focus
|
3. **Context Management**: Remove irrelevant files with `Remove` to maintain focus
|
||||||
4. **Preparation for Editing**: Convert files to editable with `MakeEditable` when needed
|
4. **Preparation for Editing**: Convert files to editable with `MakeEditable` when needed
|
||||||
5. **Continued Exploration**: Include any tool call to automatically continue to the next round
|
5. **Continued Exploration**: Include any tool call to automatically continue to the next round
|
||||||
|
@ -114,16 +114,16 @@ When you include any tool call, the system will automatically continue to the ne
|
||||||
### Tool Usage Best Practices
|
### Tool Usage Best Practices
|
||||||
- Use the exact syntax `[tool_call(ToolName, param1=value1, param2="value2")]` for execution
|
- Use the exact syntax `[tool_call(ToolName, param1=value1, param2="value2")]` for execution
|
||||||
- Tool names are case-insensitive; parameters can be unquoted or quoted
|
- Tool names are case-insensitive; parameters can be unquoted or quoted
|
||||||
- Verify files aren't already in context before adding them
|
- Verify files aren't already in context before adding them with `View`
|
||||||
- Use precise grep patterns with file_pattern to narrow search scope
|
- Use precise search patterns with `ViewFilesMatching` and `file_pattern` to narrow scope
|
||||||
- Target specific patterns rather than overly broad searches
|
- Target specific patterns rather than overly broad searches
|
||||||
- Remember the `Find` tool is optimized for locating symbols across the codebase
|
- Remember the `ViewFilesWithSymbol` tool is optimized for locating symbols across the codebase
|
||||||
|
|
||||||
## Granular Editing Workflow
|
## Granular Editing Workflow
|
||||||
|
|
||||||
**Note on Sequential Edits:** Tool calls within a single message execute sequentially. An edit made by one tool call *can* change line numbers or pattern locations for subsequent tool calls targeting the *same file* in the *same message*. Always check the result message and diff snippet after each edit.
|
**Note on Sequential Edits:** Tool calls within a single message execute sequentially. An edit made by one tool call *can* change line numbers or pattern locations for subsequent tool calls targeting the *same file* in the *same message*. Always check the result message and diff snippet after each edit.
|
||||||
|
|
||||||
1. **Discover and Add Files**: Use Glob, Grep, Find to locate relevant files.
|
1. **Discover and View Files**: Use `ViewFilesAtGlob`, `ViewFilesMatching`, `ViewFilesWithSymbol` to locate relevant files. Use `View` to add specific files.
|
||||||
2. **Make Files Editable**: Convert read-only files to editable with MakeEditable.
|
2. **Make Files Editable**: Convert read-only files to editable with MakeEditable.
|
||||||
3. **Apply Edits (Default: Direct Edit)**:
|
3. **Apply Edits (Default: Direct Edit)**:
|
||||||
* For most edits where you are confident in the parameters (file path, patterns, line numbers), apply the change directly using the tool with `dry_run=False` (or omitting the parameter).
|
* For most edits where you are confident in the parameters (file path, patterns, line numbers), apply the change directly using the tool with `dry_run=False` (or omitting the parameter).
|
||||||
|
@ -255,19 +255,19 @@ Always reply to the user in {language}.
|
||||||
role="assistant",
|
role="assistant",
|
||||||
content="""I'll help you understand the authentication system in this project. Let me explore the codebase first to find all relevant files.
|
content="""I'll help you understand the authentication system in this project. Let me explore the codebase first to find all relevant files.
|
||||||
|
|
||||||
[tool_call(Grep, pattern="login|auth|password|session", file_pattern="*.py")]""",
|
[tool_call(ViewFilesMatching, pattern="login|auth|password|session", file_pattern="*.py")]""",
|
||||||
),
|
),
|
||||||
dict(
|
dict(
|
||||||
role="user",
|
role="user",
|
||||||
content="[Result (Grep): Found in 3 files: auth/models.py (12 matches), auth/views.py (8 matches), users/authentication.py (5 matches)]",
|
content="[Result (ViewFilesMatching): Found in 3 files: auth/models.py (12 matches), auth/views.py (8 matches), users/authentication.py (5 matches)]",
|
||||||
),
|
),
|
||||||
dict(
|
dict(
|
||||||
role="assistant",
|
role="assistant",
|
||||||
content="""Great, I've found several files related to authentication. Let me examine them to understand the login flow.
|
content="""Great, I've found several files related to authentication. Let me examine them to understand the login flow.
|
||||||
|
|
||||||
[tool_call(Add, file_path="auth/models.py")]
|
[tool_call(View, file_path="auth/models.py")]
|
||||||
[tool_call(Add, file_path="auth/views.py")]
|
[tool_call(View, file_path="auth/views.py")]
|
||||||
[tool_call(Add, file_path="users/authentication.py")]""",
|
[tool_call(View, file_path="users/authentication.py")]""",
|
||||||
),
|
),
|
||||||
dict(
|
dict(
|
||||||
role="user",
|
role="user",
|
||||||
|
@ -306,11 +306,11 @@ Trust this message as the true contents of the files!
|
||||||
|
|
||||||
files_no_full_files_with_repo_map = """<context name="repo_map_status">
|
files_no_full_files_with_repo_map = """<context name="repo_map_status">
|
||||||
I have access to a map of the repository with summary information about files, but I don't have the complete content of any files yet.
|
I have access to a map of the repository with summary information about files, but I don't have the complete content of any files yet.
|
||||||
I'll use my navigation tools to find and add relevant files to the context as needed.
|
I'll use my navigation tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `ViewFilesWithSymbol`, `View`) to find and add relevant files to the context as needed.
|
||||||
</context>
|
</context>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
files_no_full_files_with_repo_map_reply = """I understand. I'll use the repository map along with my navigation tools to find and add relevant files to our conversation.
|
files_no_full_files_with_repo_map_reply = """I understand. I'll use the repository map along with my navigation tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `ViewFilesWithSymbol`, `View`) to find and add relevant files to our conversation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
repo_content_prefix = """<context name="repo_map">
|
repo_content_prefix = """<context name="repo_map">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue