diff --git a/aider/coders/__init__.py b/aider/coders/__init__.py index 88bcddfaa..69a2d40cb 100644 --- a/aider/coders/__init__.py +++ b/aider/coders/__init__.py @@ -1,5 +1,6 @@ from .architect_coder import ArchitectCoder from .ask_coder import AskCoder +from .auto_coder import AutoCoder from .base_coder import Coder from .context_coder import ContextCoder from .editblock_coder import EditBlockCoder @@ -31,4 +32,5 @@ __all__ = [ EditorWholeFileCoder, EditorDiffFencedCoder, ContextCoder, + AutoCoder, ] diff --git a/aider/coders/auto_coder.py b/aider/coders/auto_coder.py new file mode 100644 index 000000000..f8a763090 --- /dev/null +++ b/aider/coders/auto_coder.py @@ -0,0 +1,77 @@ +from .context_coder import ContextCoder +from .auto_prompts import AutoPrompts + + +class AutoCoder(ContextCoder): + """Automatically identify files and make changes without confirmation.""" + + edit_format = "auto" + gpt_prompts = AutoPrompts() + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Set yes_to_all to bypass confirmations + self.io.yes = True + + # Ensure auto_accept_architect is True + self.auto_accept_architect = True + + # Enable auto-linting and auto-testing if configured + self.auto_lint = kwargs.get('auto_lint', True) + self.auto_test = kwargs.get('auto_test', False) + + def reply_completed(self): + # First use ContextCoder's functionality to identify relevant files + content = self.partial_response_content + if not content or not content.strip(): + return True + + # Get files mentioned in the response + current_rel_fnames = set(self.get_inchat_relative_files()) + mentioned_rel_fnames = set(self.get_file_mentions(content, ignore_current=True)) + + # If the files are different, automatically add the mentioned files + if mentioned_rel_fnames != current_rel_fnames: + self.abs_fnames = set() + for fname in mentioned_rel_fnames: + self.add_rel_fname(fname) + + # Now that we've added the files, we need to get the content again + # and apply the changes automatically + self.io.tool_output(f"Automatically added files: {', '.join(mentioned_rel_fnames)}") + + # Refresh the repository map if needed + if self.repo_map: + self.get_repo_map(force_refresh=True) + + # Create a new message to apply the changes + self.reflected_message = "I've identified the relevant files. Now I'll make the requested changes." + return False + + # If we already have all the files, apply the changes + edited = self.apply_updates() + + if edited: + self.io.tool_output(f"Automatically applied changes to: {', '.join(edited)}") + self.aider_edited_files.update(edited) + saved_message = self.auto_commit(edited) + + if saved_message: + self.move_back_cur_messages(saved_message) + + # Run linting if enabled + if self.auto_lint: + lint_errors = self.lint_edited(edited) + if lint_errors: + self.io.tool_output("Linting found errors. Attempting to fix...") + self.reflected_message = lint_errors + return False + + # Run tests if enabled + if self.auto_test: + test_output = self.run_tests() + if test_output: + self.io.tool_output(f"Test results: {test_output}") + + return True diff --git a/aider/coders/auto_prompts.py b/aider/coders/auto_prompts.py new file mode 100644 index 000000000..2d36896f6 --- /dev/null +++ b/aider/coders/auto_prompts.py @@ -0,0 +1,29 @@ +# flake8: noqa: E501 + +from .context_prompts import ContextPrompts + + +class AutoPrompts(ContextPrompts): + main_system = """Act as an expert code analyst and developer. +First, understand the user's question or request to determine ALL the existing source files which will need to be modified. +Then, make the necessary changes to implement the requested feature or fix the issue. + +Your task has two phases: +1. Identify all relevant files that need to be modified +2. Make the necessary changes to implement the requested feature or fix + +For phase 1: +- Return the *complete* list of files which will need to be modified based on the user's request +- Explain why each file is needed, including names of key classes/functions/methods/variables +- Be sure to include or omit the names of files already added to the chat, based on whether they are actually needed or not + +For phase 2: +- Implement the requested changes in the identified files +- Follow the codebase's style and conventions +- Ensure your changes are complete and functional +- Explain the changes you've made and why they address the user's request + +The user will use every file you mention, regardless of your commentary. +So *ONLY* mention the names of relevant files. +If a file is not relevant DO NOT mention it. +""" diff --git a/aider/commands.py b/aider/commands.py index 81fc80093..84b01d6d9 100644 --- a/aider/commands.py +++ b/aider/commands.py @@ -162,6 +162,10 @@ class Commands: "context", "Automatically identify which files will need to be edited.", ), + ( + "auto", + "Automatically identify files and make changes without confirmation.", + ), ] ) @@ -1150,6 +1154,9 @@ class Commands: def completions_context(self): raise CommandCompletionException() + def completions_auto(self): + raise CommandCompletionException() + def cmd_ask(self, args): """Ask questions about the code base without editing any files. If no prompt provided, switches to ask mode.""" # noqa return self._generic_chat_command(args, "ask") @@ -1162,6 +1169,10 @@ class Commands: """Enter architect/editor mode using 2 different models. If no prompt provided, switches to architect/editor mode.""" # noqa return self._generic_chat_command(args, "architect") + def cmd_auto(self, args): + """Enter auto mode to automatically identify files and make changes without confirmation. If no prompt provided, switches to auto mode.""" # noqa + return self._generic_chat_command(args, "auto") + def cmd_context(self, args): """Enter context mode to see surrounding code context. If no prompt provided, switches to context mode.""" # noqa return self._generic_chat_command(args, "context", placeholder=args.strip() or None)