diff --git a/README.md b/README.md index 9e144e8500a..52493b8397b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Why `aider-ce`? -`aider-ce` (aka `cecli`, pronounced like "Cecily") is a community-driven fork of the [Aider](https://aider.chat/) AI pair programming tool. +`aider-ce` (aka `cecli`, probably pronounced like "Cecily") is a community-driven fork of the [Aider](https://aider.chat/) AI pair programming tool. Aider is a fantastic piece of software with a wonderful community but it has been painfully slow in receiving updates in the quickly evolving AI tooling space. We aim to foster an open, collaborative ecosystem where new features, experiments, and improvements can be developed and shared rapidly. We believe in genuine FOSS principles and actively welcome contributors of all skill levels. diff --git a/aider/__init__.py b/aider/__init__.py index 15229337b59..6189cdf4fae 100644 --- a/aider/__init__.py +++ b/aider/__init__.py @@ -1,6 +1,6 @@ from packaging import version -__version__ = "0.91.1.dev" +__version__ = "0.91.2.dev" safe_version = __version__ try: diff --git a/aider/coders/agent_coder.py b/aider/coders/agent_coder.py index 7cb60a16eaf..6577c0cd881 100644 --- a/aider/coders/agent_coder.py +++ b/aider/coders/agent_coder.py @@ -72,7 +72,6 @@ view_files_with_symbol, ) -from .agent_prompts import AgentPrompts from .base_coder import ChatChunks, Coder from .editblock_coder import do_replace, find_original_update_blocks, find_similar_lines @@ -81,7 +80,7 @@ class AgentCoder(Coder): """Mode where the LLM autonomously manages which files are in context.""" edit_format = "agent" - gpt_prompts = AgentPrompts() + prompt_format = "agent" def __init__(self, *args, **kwargs): # Dictionary to track recently removed files @@ -876,6 +875,10 @@ def format_chat_chunks(self): tool_context = self._generate_tool_context(repetitive_tools) if tool_context: post_message_blocks.append(tool_context) + else: + write_context = self._generate_write_context() + if write_context: + post_message_blocks.append(write_context) if static_blocks: for block in static_blocks: @@ -1934,6 +1937,26 @@ def _generate_tool_context(self, repetitive_tools): context_parts.append("") return "\n".join(context_parts) + def _generate_write_context(self): + if self.last_round_tools: + last_round_has_write = any( + tool.lower() in self.write_tools for tool in self.last_round_tools + ) + if last_round_has_write: + context_parts = [ + '', + "A file was just edited.", + ( + " Do not just modify comments" + " and/or logging statements with placeholder information." + ), + "Make sure that something of value was done.", + ] + + return "\n".join(context_parts) + + return "" + async def _apply_edits_from_response(self): """ Parses and applies SEARCH/REPLACE edits found in self.partial_response_content. diff --git a/aider/coders/agent_prompts.py b/aider/coders/agent_prompts.py deleted file mode 100644 index 136a961a999..00000000000 --- a/aider/coders/agent_prompts.py +++ /dev/null @@ -1,92 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class AgentPrompts(CoderPrompts): - """ - Prompt templates for the Agent mode, which enables autonomous codebase exploration. - - The AgentCoder uses these prompts to guide its behavior when exploring and modifying - a codebase using special tool commands like Glob, Grep, Add, etc. This mode enables the - LLM to manage its own context by adding/removing files and executing commands. - """ - - main_system = r""" - -## Core Directives -- **Role**: Act as an expert software engineer. -- **Act Proactively**: Autonomously use file discovery and context management tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `Ls`, `View`, `Remove`) to gather information and fulfill the user's request. Chain tool calls across multiple turns to continue exploration. -- **Be Decisive**: Trust that your initial findings are valid. Refrain from asking the same question or searching for the same term in multiple similar ways. -- **Be Concise**: Keep all responses brief and direct (1-3 sentences). Avoid preamble, postamble, and unnecessary explanations. Do not repeat yourself. -- **Be Careful**: Break updates down into smaller, more manageable chunks. Focus on one thing at a time. - - - -## Core Workflow -1. **Plan**: Determine the necessary changes. Use the `UpdateTodoList` tool to manage your plan. Always begin by updating the todo list. -2. **Explore**: Use discovery tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `Ls`, `Grep`) to find relevant files. These tools add files to context as read-only. Use `Grep` first for broad searches to avoid context clutter. Concisely describe your search strategy with the `Thinking` tool. -3. **Think**: Given the contents of your exploration, concisely reason through the edits with the `Thinking` tool that need to be made to accomplish the goal. For complex edits, briefly outline your plan for the user. -4. **Execute**: Use the appropriate editing tool. Remember to use `MakeEditable` on a file before modifying it. Break large edits (those greater than ~100 lines) into multiple smaller steps. Proactively use skills if they are available -5. **Verify & Recover**: After every edit, check the resulting diff snippet. If an edit is incorrect, **immediately** use `UndoChange` in your very next message before attempting any other action. -6. **Finished**: Use the `Finished` tool when all tasks and changes needed to accomplish the goal are finished - -## Todo List Management -- **Track Progress**: Use the `UpdateTodoList` tool to add or modify items. -- **Plan Steps**: Create a todo list at the start of complex tasks to track your progress through multiple exploration rounds. -- **Stay Organized**: Update the todo list as you complete steps every 3-10 tool calls to maintain context across multiple tool calls. - -### Editing Tools -Use these for precision and safety. -- **Text/Block Manipulation**: `ReplaceText` (Preferred for the majority of edits), `InsertBlock`, `DeleteBlock`, `ReplaceAll` (use with `dry_run=True` for safety). -- **Line-Based Edits**: `ReplaceLine(s)`, `DeleteLine(s)`, `IndentLines`. -- **Refactoring & History**: `ExtractLines`, `ListChanges`, `UndoChange`. -- **Skill Management**: `LoadSkill`, `RemoveSkill` - -**MANDATORY Safety Protocol for Line-Based Tools:** Line numbers are fragile. You **MUST** use a two-turn process: -1. **Turn 1**: Use `ShowNumberedContext` to get the exact, current line numbers. -2. **Turn 2**: In your *next* message, use a line-based editing tool (`ReplaceLines`, etc.) with the verified numbers. - - - -Always reply to the user in {language}. -""" - - files_content_assistant_reply = "I understand. I'll use these files to help with your request." - - files_no_full_files = ( - "I don't have full contents of any files yet. I'll add them" - " as needed using the tool commands." - ) - - files_no_full_files_with_repo_map = """ -I have a repository map but no full file contents yet. I will use my navigation tools to add relevant files to the context. - -""" - - files_no_full_files_with_repo_map_reply = """I understand. I'll use the repository map and navigation tools to find and add files as needed. -""" - - repo_content_prefix = """ -I am working with code in a git repository. Here are summaries of some files: - -""" - - system_reminder = """ - -## Reminders -- Stay on task. Do not pursue goals the user did not ask for. -- Any tool call automatically continues to the next turn. Provide no tool calls in your final answer. -- Use context blocks (directory structure, git status) to orient yourself. -- Remove files from the context when you are done with viewing/editing with the `Remove` tool. It is fine to re-add them later, if they are needed again -- Remove skills if they are not helpful for your current task with `RemoveSkill` - -{lazy_prompt} -{shell_cmd_reminder} - -""" - - try_again = """I need to retry my exploration. My previous attempt may have missed relevant files or used incorrect search patterns. - -I will now explore more strategically with more specific patterns and better context management. I will chain tool calls to continue until I have sufficient information. -""" diff --git a/aider/coders/architect_coder.py b/aider/coders/architect_coder.py index bc85dbf15ff..4174528e748 100644 --- a/aider/coders/architect_coder.py +++ b/aider/coders/architect_coder.py @@ -1,14 +1,13 @@ import asyncio from ..commands import SwitchCoder -from .architect_prompts import ArchitectPrompts from .ask_coder import AskCoder from .base_coder import Coder class ArchitectCoder(AskCoder): edit_format = "architect" - gpt_prompts = ArchitectPrompts() + prompt_format = "architect" auto_accept_architect = False async def reply_completed(self): diff --git a/aider/coders/architect_prompts.py b/aider/coders/architect_prompts.py deleted file mode 100644 index 61e94758f33..00000000000 --- a/aider/coders/architect_prompts.py +++ /dev/null @@ -1,40 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class ArchitectPrompts(CoderPrompts): - main_system = """Act as an expert architect engineer providing direction to an editor engineer. -Deeply understand the user's change request and the provided code context. -Think step-by-step to develop a clear plan for the required code modifications. -Consider potential edge cases and how the changes should be verified. -Describe the plan and the necessary modifications to the editor engineer. Your instructions must be unambiguous, complete, and concise as the editor will rely solely on them. -Focus on *what* needs to change and *why*. - -DO NOT show large blocks of code or the entire updated file content. Explain the changes conceptually. - -Always reply to the user in {language}. -""" - - example_messages = [] - - files_content_prefix = """I have *added these files to the chat* so you see all of their contents. -*Trust this message as the true contents of the files!* -Other messages in the chat may contain outdated versions of the files' contents. -""" # noqa: E501 - - files_content_assistant_reply = ( - "Ok, I will use that as the true, current contents of the files." - ) - - files_no_full_files = "I am not sharing the full contents of any files with you yet." - - files_no_full_files_with_repo_map = "" - files_no_full_files_with_repo_map_reply = "" - - repo_content_prefix = """I am working with you on code in a git repository. -Here are summaries of some files present in my git repo. -If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*. -""" - - system_reminder = "" diff --git a/aider/coders/ask_coder.py b/aider/coders/ask_coder.py index 33da037d4dd..5fdbb1ee72d 100644 --- a/aider/coders/ask_coder.py +++ b/aider/coders/ask_coder.py @@ -1,4 +1,3 @@ -from .ask_prompts import AskPrompts from .base_coder import Coder @@ -6,4 +5,4 @@ class AskCoder(Coder): """Ask questions about code without making any changes.""" edit_format = "ask" - gpt_prompts = AskPrompts() + prompt_format = "ask" diff --git a/aider/coders/ask_prompts.py b/aider/coders/ask_prompts.py deleted file mode 100644 index 347466bcf3a..00000000000 --- a/aider/coders/ask_prompts.py +++ /dev/null @@ -1,35 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class AskPrompts(CoderPrompts): - main_system = """Act as an expert code analyst. -Answer questions about the supplied code. -Always reply to the user in {language}. - -If you need to describe code changes, do so *briefly*. -""" - - example_messages = [] - - files_content_prefix = """I have *added these files to the chat* so you see all of their contents. -*Trust this message as the true contents of the files!* -Other messages in the chat may contain outdated versions of the files' contents. -""" # noqa: E501 - - files_content_assistant_reply = ( - "Ok, I will use that as the true, current contents of the files." - ) - - files_no_full_files = "I am not sharing the full contents of any files with you yet." - - files_no_full_files_with_repo_map = "" - files_no_full_files_with_repo_map_reply = "" - - repo_content_prefix = """I am working with you on code in a git repository. -Here are summaries of some files present in my git repo. -If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*. -""" - - system_reminder = "{final_reminders}" diff --git a/aider/coders/base_coder.py b/aider/coders/base_coder.py index 62c64bd35ba..fa0a3f302bc 100755 --- a/aider/coders/base_coder.py +++ b/aider/coders/base_coder.py @@ -34,7 +34,8 @@ from prompt_toolkit.patch_stdout import patch_stdout from rich.console import Console -from aider import __version__, models, prompts, urls, utils +import aider.prompts.utils.system as prompts +from aider import __version__, models, urls, utils from aider.commands import Commands, SwitchCoder from aider.exceptions import LiteLLMExceptions from aider.helpers import coroutines @@ -58,6 +59,7 @@ from aider.utils import format_tokens, is_image_file from ..dump import dump # noqa: F401 +from ..prompts.utils.prompt_registry import registry from .chat_chunks import ChatChunks @@ -155,6 +157,8 @@ class Coder: # Weak reference to TUI app instance (when running in TUI mode) tui = None + _prompt_cache = {} + @classmethod async def create( self, @@ -556,6 +560,45 @@ def __init__( self.io.tool_output("JSON Schema:") self.io.tool_output(json.dumps(self.functions, indent=4)) + @property + def gpt_prompts(self): + """Get prompts from the registry based on the coder type.""" + cls = self.__class__ + + # Every coder class MUST have a prompt_format attribute + if not hasattr(cls, "prompt_format"): + raise AttributeError( + f"Coder class {cls.__name__} must have a 'prompt_format' attribute. " + "Add 'prompt_format = \"\"' to the class definition." + ) + + if cls.prompt_format is None: + raise AttributeError( + f"Coder class {cls.__name__} has prompt_format=None. " + "It must have a valid prompt format name." + ) + + prompt_name = cls.prompt_format + + # Check cache first + if prompt_name in Coder._prompt_cache: + return Coder._prompt_cache[prompt_name] + + # Get prompts from registry + prompts = registry.get_prompt(prompt_name) + + # Create a simple object that allows attribute access + class PromptObject: + def __init__(self, prompts_dict): + for key, value in prompts_dict.items(): + setattr(self, key, value) + + # Cache the prompt object + prompt_obj = PromptObject(prompts) + Coder._prompt_cache[prompt_name] = prompt_obj + + return prompt_obj + def get_announcements(self): lines = [] lines.append(f"cecli v{__version__}") diff --git a/aider/coders/base_prompts.py b/aider/coders/base_prompts.py deleted file mode 100644 index 30633a8abf4..00000000000 --- a/aider/coders/base_prompts.py +++ /dev/null @@ -1,90 +0,0 @@ -class CoderPrompts: - system_reminder = "" - - files_content_gpt_edits = "I committed the changes with git hash {hash} & commit msg: {message}" - - files_content_gpt_edits_no_repo = "I updated the files." - - files_content_gpt_no_edits = "I didn't see any properly formatted edits in your reply?!" - - files_content_local_edits = "I edited the files myself." - - lazy_prompt = """You are diligent and tireless! -You NEVER leave comments describing code without implementing it! -You always COMPLETELY IMPLEMENT the needed code! -""" - - overeager_prompt = """Pay careful attention to the scope of the user's request. -Do what they ask, but no more. -Do not improve, comment, fix or modify unrelated parts of the code in any way! -""" - - example_messages = [] - - files_content_prefix = """I have *added these files to the chat* so you can go ahead and edit them. - -*Trust this message as the true contents of these files!* -Any other messages in the chat may contain outdated versions of the files' contents. -""" # noqa: E501 - - files_content_assistant_reply = "Ok, any changes I propose will be to those files." - - files_no_full_files = "I am not sharing any files that you can edit yet." - - files_no_full_files_with_repo_map = """Don't try and edit any existing code without asking me to add the files to the chat! -Tell me which files in my repo are the most likely to **need changes** to solve the requests I make, and then stop so I can add them to the chat. -Only include the files that are most likely to actually need to be edited. -Don't include files that might contain relevant context, just files that will need to be changed. -""" # noqa: E501 - - files_no_full_files_with_repo_map_reply = ( - "Ok, based on your requests I will suggest which files need to be edited and then" - " stop and wait for your approval." - ) - - repo_content_prefix = """Here are summaries of some files present in my git repository. -Do not propose changes to these files, treat them as *read-only*. -If you need to edit any of these files, ask me to *add them to the chat* first. -""" - - read_only_files_prefix = """Here are some READ ONLY files, provided for your reference. -Do not edit these files! -""" - - shell_cmd_prompt = "" - shell_cmd_reminder = "" - no_shell_cmd_prompt = "" - no_shell_cmd_reminder = "" - - tool_prompt = """ - -When solving problems, you have special tools available. Please follow these rules: - -1. Always use the exact format required for each tool and include all needed information. -2. Only use tools that are currently available in this conversation. -3. Don't mention tool names when talking to people. Say "I'll check your code" instead - of "I'll use the code_analyzer tool." -4. Only use tools when necessary. If you know the answer, just respond directly. -5. Before using any tool, briefly explain why you need to use it. - -""" - - rename_with_shell = "" - go_ahead_tip = "" - - compaction_prompt = """You are an expert at summarizing conversations. -The user is going to provide you with a conversation. -This conversation is getting too long to fit in the context window of a language model. -You need to summarize the conversation to reduce its length, while retaining all the important information. - -The summary should contain four parts: -- Overall Goal: What is the user trying to achieve with this conversation? -- Next Steps: What are the next steps for the language model to take to help the user? - Describe the current investigation path and intention. -- Key Findings: Keep information most important to prevent having to search for it again - This should be quite specific (e/g. relevant files, method names, relevant lines of code, and code structure) -- Active files: What files are currently most relevant to the discussion? - Be confident in proceeding with any in progress edits. - -Here is the conversation so far: -""" diff --git a/aider/coders/context_coder.py b/aider/coders/context_coder.py index ee5dd949e62..96f86204f33 100644 --- a/aider/coders/context_coder.py +++ b/aider/coders/context_coder.py @@ -1,12 +1,11 @@ from .base_coder import Coder -from .context_prompts import ContextPrompts class ContextCoder(Coder): """Identify which files need to be edited for a given request.""" edit_format = "context" - gpt_prompts = ContextPrompts() + prompt_format = "context" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/aider/coders/context_prompts.py b/aider/coders/context_prompts.py deleted file mode 100644 index 3c71a233463..00000000000 --- a/aider/coders/context_prompts.py +++ /dev/null @@ -1,75 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class ContextPrompts(CoderPrompts): - main_system = """Act as an expert code analyst. -Understand the user's question or request, solely to determine ALL the existing sources files which will need to be modified. -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. - -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. - -Only return files that will need to be modified, not files that contain useful/relevant functions. - -You are only to discuss EXISTING files and symbols. -Only return existing files, don't suggest the names of new files or functions that we will need to create. - -Always reply to the user in {language}. - -Be concise in your replies. -Return: -1. A bulleted list of files the will need to be edited, and symbols that are highly relevant to the user's request. -2. A list of classes/functions/methods/variables that are located OUTSIDE those files which will need to be understood. Just the symbols names, *NOT* file names. - -# Your response *MUST* use this format: - -## ALL files we need to modify, with their relevant symbols: - -- alarms/buzz.py - - `Buzzer` class which can make the needed sound - - `Buzzer.buzz_buzz()` method triggers the sound -- alarms/time.py - - `Time.set_alarm(hour, minute)` to set the alarm - -## Relevant symbols from OTHER files: - -- AlarmManager class for setup/teardown of alarms -- SoundFactory will be used to create a Buzzer -""" - - example_messages = [] - - files_content_prefix = """These files have been *added these files to the chat* so we can see all of their contents. -*Trust this message as the true contents of the files!* -Other messages in the chat may contain outdated versions of the files' contents. -""" # noqa: E501 - - files_content_assistant_reply = ( - "Ok, I will use that as the true, current contents of the files." - ) - - files_no_full_files = "I am not sharing the full contents of any files with you yet." - - files_no_full_files_with_repo_map = "" - files_no_full_files_with_repo_map_reply = "" - - repo_content_prefix = """I am working with you on code in a git repository. -Here are summaries of some files present in my git repo. -If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*. -""" - - system_reminder = """ -NEVER RETURN CODE! -""" - - try_again = """I have updated the set of files added to the chat. -Review them to decide if this is the correct set of files or if we need to add more or remove files. - -If this is the right set, just return the current list of files. -Or return a smaller or larger set of files which need to be edited, with symbols that are highly relevant to the user's request. -""" diff --git a/aider/coders/copypaste_coder.py b/aider/coders/copypaste_coder.py index f7e4e55337b..2ab077ad82a 100644 --- a/aider/coders/copypaste_coder.py +++ b/aider/coders/copypaste_coder.py @@ -20,6 +20,10 @@ class CopyPasteCoder(Coder): ``edit_format``. """ + # CopyPasteCoder doesn't have its own prompt format - it dynamically determines + # prompts based on the selected edit_format + prompt_format = None + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -27,6 +31,25 @@ def __init__(self, *args, **kwargs): # We mirror prompts from the coder that matches the active edit format. self._init_prompts_from_selected_edit_format() + @property + def gpt_prompts(self): + """Override gpt_prompts property for CopyPasteCoder. + + CopyPasteCoder dynamically determines prompts based on the selected edit format. + This property returns the prompts that were set by _init_prompts_from_selected_edit_format(). + """ + if not hasattr(self, "_gpt_prompts"): + raise AttributeError( + "CopyPasteCoder must call _init_prompts_from_selected_edit_format() " + "before accessing gpt_prompts" + ) + return self._gpt_prompts + + @gpt_prompts.setter + def gpt_prompts(self, value): + """Setter for gpt_prompts property.""" + self._gpt_prompts = value + def _init_prompts_from_selected_edit_format(self): """Initialize ``self.gpt_prompts`` based on the currently selected edit format. @@ -65,15 +88,35 @@ def _init_prompts_from_selected_edit_format(self): break # Mirror prompt pack + edit_format where available. - if target_coder_class is not None and hasattr(target_coder_class, "gpt_prompts"): - self.gpt_prompts = target_coder_class.gpt_prompts + if target_coder_class is not None: + # All coder classes must have prompt_format attribute + if ( + not hasattr(target_coder_class, "prompt_format") + or target_coder_class.prompt_format is None + ): + raise AttributeError( + f"Target coder class {target_coder_class.__name__} must have a 'prompt_format'" + " attribute." + ) + + prompt_name = target_coder_class.prompt_format + + # Get prompts from cache or load them + if prompt_name in Coder._prompt_cache: + self.gpt_prompts = Coder._prompt_cache[prompt_name] + else: + # Create a dummy instance to trigger prompt loading + dummy_instance = target_coder_class.__new__(target_coder_class) + dummy_instance.__class__ = target_coder_class + self.gpt_prompts = dummy_instance.gpt_prompts + # Keep announcements/formatting consistent with the selected coder. self.edit_format = getattr(target_coder_class, "edit_format", self.edit_format) return # Last-resort fallback: avoid crashing if we can't determine the prompts. # Prefer keeping any existing gpt_prompts (if one was set elsewhere). - if not hasattr(self, "gpt_prompts"): + if not hasattr(self, "_gpt_prompts"): self.gpt_prompts = None async def send(self, messages, model=None, functions=None, tools=None): diff --git a/aider/coders/editblock_coder.py b/aider/coders/editblock_coder.py index 37d40d97c70..4f2425c0f54 100644 --- a/aider/coders/editblock_coder.py +++ b/aider/coders/editblock_coder.py @@ -9,14 +9,13 @@ from ..dump import dump # noqa: F401 from .base_coder import Coder -from .editblock_prompts import EditBlockPrompts class EditBlockCoder(Coder): """A coder that uses search/replace blocks for code modifications.""" edit_format = "diff" - gpt_prompts = EditBlockPrompts() + prompt_format = "editblock" def get_edits(self): content = self.partial_response_content diff --git a/aider/coders/editblock_fenced_coder.py b/aider/coders/editblock_fenced_coder.py index cd09e27c550..f261d760b26 100644 --- a/aider/coders/editblock_fenced_coder.py +++ b/aider/coders/editblock_fenced_coder.py @@ -1,10 +1,9 @@ from ..dump import dump # noqa: F401 from .editblock_coder import EditBlockCoder -from .editblock_fenced_prompts import EditBlockFencedPrompts class EditBlockFencedCoder(EditBlockCoder): """A coder that uses fenced search/replace blocks for code modifications.""" edit_format = "diff-fenced" - gpt_prompts = EditBlockFencedPrompts() + prompt_format = "editblock_fenced" diff --git a/aider/coders/editblock_fenced_prompts.py b/aider/coders/editblock_fenced_prompts.py deleted file mode 100644 index 79fa179d90f..00000000000 --- a/aider/coders/editblock_fenced_prompts.py +++ /dev/null @@ -1,143 +0,0 @@ -# flake8: noqa: E501 - -from .editblock_prompts import EditBlockPrompts - - -class EditBlockFencedPrompts(EditBlockPrompts): - example_messages = [ - dict( - role="user", - content="Change get_factorial() to use math.factorial", - ), - dict( - role="assistant", - content="""To make this change we need to modify `mathweb/flask/app.py` to: - -1. Import the math package. -2. Remove the existing factorial() function. -3. Update get_factorial() to call math.factorial instead. - -Here are the *SEARCH/REPLACE* blocks: - -{fence[0]}python -mathweb/flask/app.py -<<<<<<< SEARCH -from flask import Flask -======= -import math -from flask import Flask ->>>>>>> REPLACE -{fence[1]} - -{fence[0]}python -mathweb/flask/app.py -<<<<<<< SEARCH -def factorial(n): - "compute factorial" - - if n == 0: - return 1 - else: - return n * factorial(n-1) - -======= ->>>>>>> REPLACE -{fence[1]} - -{fence[0]}python -mathweb/flask/app.py -<<<<<<< SEARCH - return str(factorial(n)) -======= - return str(math.factorial(n)) ->>>>>>> REPLACE -{fence[1]} -<<<<<<< HEAD -""", - ), - dict( - role="user", - content="Refactor hello() into its own file.", - ), - dict( - role="assistant", - content="""To make this change we need to modify `main.py` and make a new file `hello.py`: - -1. Make a new hello.py file with hello() in it. -2. Remove hello() from main.py and replace it with an import. - -Here are the *SEARCH/REPLACE* blocks: - -{fence[0]}python -hello.py -<<<<<<< SEARCH -======= -def hello(): - "print a greeting" - - print("hello") ->>>>>>> REPLACE -{fence[1]} - -{fence[0]}python -main.py -<<<<<<< SEARCH -def hello(): - "print a greeting" - - print("hello") -======= -from hello import hello ->>>>>>> REPLACE -{fence[1]} -""", - ), - ] - - system_reminder = """ -# *SEARCH/REPLACE block* Rules: - -Every *SEARCH/REPLACE block* must use this format: -1. The opening fence and code language, eg: {fence[0]}python -2. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc. -3. The start of search block: <<<<<<< SEARCH -4. A contiguous chunk of lines to search for in the existing source code -5. The dividing line: ======= -6. The lines to replace into the source code -7. The end of the replace block: >>>>>>> REPLACE -8. The closing fence: {fence[1]} - -Use the *FULL* file path, as shown to you by the user. -{quad_backtick_reminder} -Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. -If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. - -*SEARCH/REPLACE* blocks will *only* replace the first match occurrence. -Including multiple unique *SEARCH/REPLACE* blocks if needed. -Include enough lines in each SEARCH section to uniquely match each set of lines that need to change. - -Keep *SEARCH/REPLACE* blocks concise. -Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file. -Include just the changing lines, and a few surrounding lines if needed for uniqueness. -Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks. - -Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat! - -To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location. - -Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file. - -If you want to put code in a new file, use a *SEARCH/REPLACE block* with: -- A new file path, including dir name if needed -- An empty `SEARCH` section -- The new file's contents in the `REPLACE` section - -To rename files which have been added to the chat, use shell commands at the end of your response. - -If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed. -The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks. - -{final_reminders} -ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! -{shell_cmd_reminder} -""" diff --git a/aider/coders/editblock_func_coder.py b/aider/coders/editblock_func_coder.py index 9750f5e2635..c0f463d5bb3 100644 --- a/aider/coders/editblock_func_coder.py +++ b/aider/coders/editblock_func_coder.py @@ -3,10 +3,10 @@ from ..dump import dump # noqa: F401 from .base_coder import Coder from .editblock_coder import do_replace -from .editblock_func_prompts import EditBlockFunctionPrompts class EditBlockFunctionCoder(Coder): + prompt_format = "editblock_func" functions = [ dict( name="replace_lines", @@ -81,7 +81,6 @@ def __init__(self, code_format, *args, **kwargs): "updated_lines" ] = updated_lines - self.gpt_prompts = EditBlockFunctionPrompts() super().__init__(*args, **kwargs) def render_incremental_response(self, final=False): diff --git a/aider/coders/editblock_func_prompts.py b/aider/coders/editblock_func_prompts.py deleted file mode 100644 index c7f18b8689f..00000000000 --- a/aider/coders/editblock_func_prompts.py +++ /dev/null @@ -1,27 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class EditBlockFunctionPrompts(CoderPrompts): - main_system = """Act as an expert software developer. -Take requests for changes to the supplied code. -If the request is ambiguous, ask questions. - -Once you understand the request you MUST use the `replace_lines` function to edit the files to make the needed changes. -""" - - system_reminder = """ -ONLY return code using the `replace_lines` function. -NEVER return code outside the `replace_lines` function. -""" - - files_content_prefix = "Here is the current content of the files:\n" - files_no_full_files = "I am not sharing any files yet." - - redacted_edit_message = "No changes are needed." - - repo_content_prefix = ( - "Below here are summaries of other files! Do not propose changes to these *read-only*" - " files without asking me first.\n" - ) diff --git a/aider/coders/editblock_prompts.py b/aider/coders/editblock_prompts.py deleted file mode 100644 index d9897dfe9a4..00000000000 --- a/aider/coders/editblock_prompts.py +++ /dev/null @@ -1,175 +0,0 @@ -# flake8: noqa: E501 - -from . import shell -from .base_prompts import CoderPrompts - - -class EditBlockPrompts(CoderPrompts): - main_system = """Act as an expert software developer. -Always use best practices when coding. -Respect and use existing conventions, libraries, etc that are already present in the code base. -Think step-by-step. Plan your changes carefully. Explain your plan first. -{final_reminders} -Take requests for changes to the supplied code. -If the request is ambiguous, ask questions. -Consider potential edge cases. -Think about how to verify your changes are correct. - -Once you understand the request and have a plan, you MUST: - -1. Decide if you need to propose *SEARCH/REPLACE* edits to any files that haven't been added to the chat. You can create new files without asking! - -But if you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*. -End your reply and wait for their approval. -You can keep asking if you then decide you need to edit more files. - -2. Think step-by-step and explain the needed changes in a few short sentences. - -3. Describe each change with a *SEARCH/REPLACE block* per the examples below. - -All changes to files must use this *SEARCH/REPLACE block* format. -ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! -{shell_cmd_prompt} -""" - example_messages = [ - dict( - role="user", - content="Change get_factorial() to use math.factorial", - ), - dict( - role="assistant", - content="""To make this change we need to modify `mathweb/flask/app.py` to: - -1. Import the math package. -2. Remove the existing factorial() function. -3. Update get_factorial() to call math.factorial instead. - -Here are the *SEARCH/REPLACE* blocks: - -mathweb/flask/app.py -{fence[0]}python -<<<<<<< SEARCH -from flask import Flask -======= -import math -from flask import Flask ->>>>>>> REPLACE -{fence[1]} - -mathweb/flask/app.py -{fence[0]}python -<<<<<<< SEARCH -def factorial(n): - "compute factorial" - - if n == 0: - return 1 - else: - return n * factorial(n-1) - -======= ->>>>>>> REPLACE -{fence[1]} - -mathweb/flask/app.py -{fence[0]}python -<<<<<<< SEARCH - return str(factorial(n)) -======= - return str(math.factorial(n)) ->>>>>>> REPLACE -{fence[1]} -""", - ), - dict( - role="user", - content="Refactor hello() into its own file.", - ), - dict( - role="assistant", - content="""To make this change we need to modify `main.py` and make a new file `hello.py`: - -1. Make a new hello.py file with hello() in it. -2. Remove hello() from main.py and replace it with an import. - -Here are the *SEARCH/REPLACE* blocks: - -hello.py -{fence[0]}python -<<<<<<< SEARCH -======= -def hello(): - "print a greeting" - - print("hello") ->>>>>>> REPLACE -{fence[1]} - -main.py -{fence[0]}python -<<<<<<< SEARCH -def hello(): - "print a greeting" - - print("hello") -======= -from hello import hello ->>>>>>> REPLACE -{fence[1]} -""", - ), - ] - - system_reminder = """# *SEARCH/REPLACE block* Rules: - -Every *SEARCH/REPLACE block* must use this format: -1. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc. -2. The opening fence and code language, eg: {fence[0]}python -3. The start of search block: <<<<<<< SEARCH -4. A contiguous chunk of lines to search for in the existing source code -5. The dividing line: ======= -6. The lines to replace into the source code -7. The end of the replace block: >>>>>>> REPLACE -8. The closing fence: {fence[1]} - -Use the *FULL* file path, as shown to you by the user. -{quad_backtick_reminder} -Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. -If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. - -*SEARCH/REPLACE* blocks will *only* replace the first match occurrence. -Including multiple unique *SEARCH/REPLACE* blocks if needed. -Include enough lines in each SEARCH section to uniquely match each set of lines that need to change. - -Keep *SEARCH/REPLACE* blocks concise. -Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file. -Include just the changing lines, and a few surrounding lines if needed for uniqueness. -Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks. - -Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat! - -To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location. - -Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file. - -If you want to put code in a new file, use a *SEARCH/REPLACE block* with: -- A new file path, including dir name if needed -- An empty `SEARCH` section -- The new file's contents in the `REPLACE` section - -{rename_with_shell}{go_ahead_tip}{final_reminders}ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! -{shell_cmd_reminder} -""" - - rename_with_shell = """To rename files which have been added to the chat, use shell commands at the end of your response. - -""" - - go_ahead_tip = """If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed. -The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks. - -""" - - shell_cmd_prompt = shell.shell_cmd_prompt - no_shell_cmd_prompt = shell.no_shell_cmd_prompt - shell_cmd_reminder = shell.shell_cmd_reminder diff --git a/aider/coders/editor_diff_fenced_coder.py b/aider/coders/editor_diff_fenced_coder.py index 4edc010d071..e3c0bf01b64 100644 --- a/aider/coders/editor_diff_fenced_coder.py +++ b/aider/coders/editor_diff_fenced_coder.py @@ -1,9 +1,8 @@ from .editblock_fenced_coder import EditBlockFencedCoder -from .editor_diff_fenced_prompts import EditorDiffFencedPrompts class EditorDiffFencedCoder(EditBlockFencedCoder): "A coder that uses search/replace blocks, focused purely on editing files." edit_format = "editor-diff-fenced" - gpt_prompts = EditorDiffFencedPrompts() + prompt_format = "editor_diff_fenced" diff --git a/aider/coders/editor_diff_fenced_prompts.py b/aider/coders/editor_diff_fenced_prompts.py deleted file mode 100644 index 15b906f79c7..00000000000 --- a/aider/coders/editor_diff_fenced_prompts.py +++ /dev/null @@ -1,11 +0,0 @@ -# flake8: noqa: E501 - -from .editblock_fenced_prompts import EditBlockFencedPrompts - - -class EditorDiffFencedPrompts(EditBlockFencedPrompts): - shell_cmd_prompt = "" - no_shell_cmd_prompt = "" - shell_cmd_reminder = "" - go_ahead_tip = "" - rename_with_shell = "" diff --git a/aider/coders/editor_editblock_coder.py b/aider/coders/editor_editblock_coder.py index f43258bc96f..5392036e5ab 100644 --- a/aider/coders/editor_editblock_coder.py +++ b/aider/coders/editor_editblock_coder.py @@ -1,9 +1,8 @@ from .editblock_coder import EditBlockCoder -from .editor_editblock_prompts import EditorEditBlockPrompts class EditorEditBlockCoder(EditBlockCoder): "A coder that uses search/replace blocks, focused purely on editing files." edit_format = "editor-diff" - gpt_prompts = EditorEditBlockPrompts() + prompt_format = "editor_editblock" diff --git a/aider/coders/editor_editblock_prompts.py b/aider/coders/editor_editblock_prompts.py deleted file mode 100644 index b749365cd6b..00000000000 --- a/aider/coders/editor_editblock_prompts.py +++ /dev/null @@ -1,21 +0,0 @@ -# flake8: noqa: E501 - -from .editblock_prompts import EditBlockPrompts - - -class EditorEditBlockPrompts(EditBlockPrompts): - main_system = """Act as an expert software developer tasked with editing source code based on instructions from an architect. -Carefully implement the changes described in the request. -{final_reminders} -Describe each change with a *SEARCH/REPLACE block* per the examples below. -Ensure the SEARCH block exactly matches the original code. -Ensure the REPLACE block correctly implements the requested change. -All changes to files must use this *SEARCH/REPLACE block* format. -ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! -""" - - shell_cmd_prompt = "" - no_shell_cmd_prompt = "" - shell_cmd_reminder = "" - go_ahead_tip = "" - rename_with_shell = "" diff --git a/aider/coders/editor_whole_coder.py b/aider/coders/editor_whole_coder.py index 90c7e833247..f43964c7909 100644 --- a/aider/coders/editor_whole_coder.py +++ b/aider/coders/editor_whole_coder.py @@ -1,4 +1,3 @@ -from .editor_whole_prompts import EditorWholeFilePrompts from .wholefile_coder import WholeFileCoder @@ -6,4 +5,4 @@ class EditorWholeFileCoder(WholeFileCoder): "A coder that operates on entire files, focused purely on editing files." edit_format = "editor-whole" - gpt_prompts = EditorWholeFilePrompts() + prompt_format = "editor_whole" diff --git a/aider/coders/editor_whole_prompts.py b/aider/coders/editor_whole_prompts.py deleted file mode 100644 index f52e1161953..00000000000 --- a/aider/coders/editor_whole_prompts.py +++ /dev/null @@ -1,12 +0,0 @@ -# flake8: noqa: E501 - -from .wholefile_prompts import WholeFilePrompts - - -class EditorWholeFilePrompts(WholeFilePrompts): - main_system = """Act as an expert software developer tasked with editing source code based on instructions from an architect. -Carefully implement the changes described in the request. -{final_reminders} -Output a copy of each file that needs changes, containing the complete, updated content. -Ensure the entire file content is returned accurately. -""" diff --git a/aider/coders/help_coder.py b/aider/coders/help_coder.py index 311805af701..613e83d9e17 100644 --- a/aider/coders/help_coder.py +++ b/aider/coders/help_coder.py @@ -1,13 +1,12 @@ from ..dump import dump # noqa: F401 from .base_coder import Coder -from .help_prompts import HelpPrompts class HelpCoder(Coder): """Interactive help and documentation about aider.""" edit_format = "help" - gpt_prompts = HelpPrompts() + prompt_format = "help" def get_edits(self, mode="update"): return [] diff --git a/aider/coders/help_prompts.py b/aider/coders/help_prompts.py deleted file mode 100644 index 4157f5e8814..00000000000 --- a/aider/coders/help_prompts.py +++ /dev/null @@ -1,46 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class HelpPrompts(CoderPrompts): - main_system = """You are an expert on the AI coding tool called Aider. -Answer the user's questions about how to use aider. - -The user is currently chatting with you using aider, to write and edit code. - -Use the provided aider documentation *if it is relevant to the user's question*. - -Include a bulleted list of urls to the aider docs that might be relevant for the user to read. -Include *bare* urls. *Do not* make [markdown links](http://...). -For example: -- https://aider.chat/docs/usage.html -- https://aider.chat/docs/faq.html - -If you don't know the answer, say so and suggest some relevant aider doc urls. - -If asks for something that isn't possible with aider, be clear about that. -Don't suggest a solution that isn't supported. - -Be helpful but concise. - -Unless the question indicates otherwise, assume the user wants to use aider as a CLI tool. - -Keep this info about the user's system in mind: -{platform} -""" - - example_messages = [] - system_reminder = "" - - files_content_prefix = """These are some files we have been discussing that we may want to edit after you answer my questions: -""" - - files_no_full_files = "I am not sharing any files with you." - - files_no_full_files_with_repo_map = "" - files_no_full_files_with_repo_map_reply = "" - - repo_content_prefix = """Here are summaries of some files present in my git repository. -We may look at these in more detail after you answer my questions. -""" diff --git a/aider/coders/patch_coder.py b/aider/coders/patch_coder.py index 802e6b9c303..a32ab1d141a 100644 --- a/aider/coders/patch_coder.py +++ b/aider/coders/patch_coder.py @@ -4,7 +4,6 @@ from typing import Dict, List, Optional, Tuple from .base_coder import Coder -from .patch_prompts import PatchPrompts # --------------------------------------------------------------------------- # @@ -215,7 +214,7 @@ class PatchCoder(Coder): """ edit_format = "patch" - gpt_prompts = PatchPrompts() + prompt_format = "patch" def get_edits(self) -> List[EditResult]: """ diff --git a/aider/coders/patch_prompts.py b/aider/coders/patch_prompts.py deleted file mode 100644 index 66832ee16c7..00000000000 --- a/aider/coders/patch_prompts.py +++ /dev/null @@ -1,159 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts -from .editblock_prompts import EditBlockPrompts - - -class PatchPrompts(EditBlockPrompts): - # --------------------------------------------------------------------- # - # SYSTEM PROMPT - # --------------------------------------------------------------------- # - main_system = """Act as an expert software developer. -Always use best practices when coding. -Respect and use existing conventions, libraries, etc that are already present in the code base. -{final_reminders} -Take requests for changes to the supplied code. -If the request is ambiguous, ask questions. - -Once you understand the request you MUST: - -1. Decide if you need to propose edits to any files that haven't been added to the chat. You can create new files without asking! - - • If you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*. - • End your reply and wait for their approval. - • You can keep asking if you then decide you need to edit more files. - -2. Think step‑by‑step and explain the needed changes in a few short sentences. - -3. Describe the changes using the V4A diff format, enclosed within `*** Begin Patch` and `*** End Patch` markers. - -IMPORTANT: Each file MUST appear only once in the patch. -Consolidate **all** edits for a given file into a single `*** [ACTION] File:` block. -{shell_cmd_prompt} -""" - - # --------------------------------------------------------------------- # - # EXAMPLE MESSAGES - # --------------------------------------------------------------------- # - example_messages = [ - # --- Example 1 ---------------------------------------------------- # - dict( - role="user", - content="Change get_factorial() to use math.factorial", - ), - dict( - role="assistant", - content="""To make this change we need to modify `mathweb/flask/app.py`: - -1. Import the `math` module. -2. Replace the custom recursive `factorial()` helper with `math.factorial`. -3. Update `get_factorial()` to call `math.factorial`. - -Here is the patch: - -*** Begin Patch -*** Update File: mathweb/flask/app.py -@@ --from flask import Flask -- --from flask import Flask -+from flask import Flask -+import math -@@ --def factorial(n): -- "compute factorial" -- -- if n == 0: -- return 1 -- else: -- return n * factorial(n-1) -+def factorial(n): -+ "compute factorial" -+ -+ return math.factorial(n) -@@ def get_factorial(self, n): -- return str(factorial(n)) -+ return str(math.factorial(n)) -*** End Patch -""", - ), - # --- Example 2 ---------------------------------------------------- # - dict( - role="user", - content="Refactor hello() into its own file.", - ), - dict( - role="assistant", - content="""To make this change we need to modify `main.py` and create a new file `hello.py`: - -1. Create `hello.py` with the `hello()` function. -2. Remove `hello()` from `main.py` and import it instead. - -Here is the patch: - -*** Begin Patch -*** Add File: hello.py -+# A simple function -+def hello(): -+ "print a greeting" -+ -+ print("hello") -*** Update File: main.py -@@ --def hello(): -- "print a greeting" -- -- print("hello") -+from hello import hello -*** End Patch -""", - ), - ] - - # --------------------------------------------------------------------- # - # SYSTEM REMINDER - # --------------------------------------------------------------------- # - system_reminder = """# V4A Diff Format Rules: - -Your entire response containing the patch MUST start with `*** Begin Patch` on a line by itself. -Your entire response containing the patch MUST end with `*** End Patch` on a line by itself. - -Use the *FULL* file path, as shown to you by the user. -{quad_backtick_reminder} - -For each file you need to modify, start with a marker line: - - *** [ACTION] File: [path/to/file] - -Where `[ACTION]` is one of `Add`, `Update`, or `Delete`. - -⇨ **Each file MUST appear only once in the patch.** - Consolidate all changes for that file into the same block. - If you are moving code within a file, include both the deletions and the - insertions as separate hunks inside this single `*** Update File:` block - (do *not* open a second block for the same file). - -For `Update` actions, describe each snippet of code that needs to be changed using the following format: -1. Context lines: Include 3 lines of context *before* the change. These lines MUST start with a single space ` `. -2. Lines to remove: Precede each line to be removed with a minus sign `-`. -3. Lines to add: Precede each line to be added with a plus sign `+`. -4. Context lines: Include 3 lines of context *after* the change. These lines MUST start with a single space ` `. - -Context lines MUST exactly match the existing file content, character for character, including indentation. -If a change is near the beginning or end of the file, include fewer than 3 context lines as appropriate. -If 3 lines of context is insufficient to uniquely identify the snippet, use `@@ [CLASS_OR_FUNCTION_NAME]` markers on their own lines *before* the context lines to specify the scope. You can use multiple `@@` markers if needed. -Do not include line numbers. - -Only create patches for files that the user has added to the chat! - -When moving code *within* a single file, keep everything inside one -`*** Update File:` block. Provide one hunk that deletes the code from its -original location and another hunk that inserts it at the new location. - -For `Add` actions, use the `*** Add File: [path/to/new/file]` marker, followed by the lines of the new file, each preceded by a plus sign `+`. - -For `Delete` actions, use the `*** Delete File: [path/to/file]` marker. No other lines are needed for the deletion. - -{rename_with_shell}{go_ahead_tip}{final_reminders}ONLY EVER RETURN CODE IN THE SPECIFIED V4A DIFF FORMAT! -{shell_cmd_reminder} -""" diff --git a/aider/coders/single_wholefile_func_coder.py b/aider/coders/single_wholefile_func_coder.py index 493581c4676..fad3a636435 100644 --- a/aider/coders/single_wholefile_func_coder.py +++ b/aider/coders/single_wholefile_func_coder.py @@ -2,11 +2,11 @@ from ..dump import dump # noqa: F401 from .base_coder import Coder -from .single_wholefile_func_prompts import SingleWholeFileFunctionPrompts class SingleWholeFileFunctionCoder(Coder): edit_format = "func" + prompt_format = "single_wholefile_func" functions = [ dict( @@ -35,7 +35,6 @@ class SingleWholeFileFunctionCoder(Coder): ] def __init__(self, *args, **kwargs): - self.gpt_prompts = SingleWholeFileFunctionPrompts() super().__init__(*args, **kwargs) def add_assistant_reply_to_cur_messages(self, edited): diff --git a/aider/coders/single_wholefile_func_prompts.py b/aider/coders/single_wholefile_func_prompts.py deleted file mode 100644 index f97a91be919..00000000000 --- a/aider/coders/single_wholefile_func_prompts.py +++ /dev/null @@ -1,27 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class SingleWholeFileFunctionPrompts(CoderPrompts): - main_system = """Act as an expert software developer. -Take requests for changes to the supplied code. -If the request is ambiguous, ask questions. - -Once you understand the request you MUST use the `write_file` function to update the file to make the changes. -""" - - system_reminder = """ -ONLY return code using the `write_file` function. -NEVER return code outside the `write_file` function. -""" - - files_content_prefix = "Here is the current content of the file:\n" - files_no_full_files = "I am not sharing any files yet." - - redacted_edit_message = "No changes are needed." - - # TODO: should this be present for using this with gpt-4? - repo_content_prefix = None - - # TODO: fix the chat history, except we can't keep the whole file diff --git a/aider/coders/udiff_coder.py b/aider/coders/udiff_coder.py index fff6971b725..f81a506b323 100644 --- a/aider/coders/udiff_coder.py +++ b/aider/coders/udiff_coder.py @@ -11,7 +11,6 @@ flexible_search_and_replace, search_and_replace, ) -from .udiff_prompts import UnifiedDiffPrompts no_match_error = """UnifiedDiffNoMatch: hunk failed to apply! @@ -47,7 +46,7 @@ class UnifiedDiffCoder(Coder): """A coder that uses unified diff format for code modifications.""" edit_format = "udiff" - gpt_prompts = UnifiedDiffPrompts() + prompt_format = "udiff" def get_edits(self): content = self.partial_response_content diff --git a/aider/coders/udiff_prompts.py b/aider/coders/udiff_prompts.py deleted file mode 100644 index dc58fb1bd6a..00000000000 --- a/aider/coders/udiff_prompts.py +++ /dev/null @@ -1,115 +0,0 @@ -# flake8: noqa: E501 - -from . import shell -from .base_prompts import CoderPrompts - - -class UnifiedDiffPrompts(CoderPrompts): - main_system = """Act as an expert software developer. -{final_reminders} -Always use best practices when coding. -Respect and use existing conventions, libraries, etc that are already present in the code base. -Consider potential edge cases. -Think about how to verify your changes are correct. - -Take requests for changes to the supplied code. -If the request is ambiguous, ask questions. - -Once you have a plan, for each file that needs to be changed, write out the changes similar to a unified diff like `diff -U0` would produce. -""" - - example_messages = [ - dict( - role="user", - content="Replace is_prime with a call to sympy.", - ), - dict( - role="assistant", - content="""Ok, I will: - -1. Add an imports of sympy. -2. Remove the is_prime() function. -3. Replace the existing call to is_prime() with a call to sympy.isprime(). - -Here are the diffs for those changes: - -```diff ---- mathweb/flask/app.py -+++ mathweb/flask/app.py -@@ ... @@ --class MathWeb: -+import sympy -+ -+class MathWeb: -@@ ... @@ --def is_prime(x): -- if x < 2: -- return False -- for i in range(2, int(math.sqrt(x)) + 1): -- if x % i == 0: -- return False -- return True -@@ ... @@ --@app.route('/prime/') --def nth_prime(n): -- count = 0 -- num = 1 -- while count < n: -- num += 1 -- if is_prime(num): -- count += 1 -- return str(num) -+@app.route('/prime/') -+def nth_prime(n): -+ count = 0 -+ num = 1 -+ while count < n: -+ num += 1 -+ if sympy.isprime(num): -+ count += 1 -+ return str(num) -``` -""", - ), - ] - - system_reminder = """# File editing rules: - -Return edits similar to unified diffs that `diff -U0` would produce. - -Make sure you include the first 2 lines with the file paths. -Don't include timestamps with the file paths. - -Start each hunk of changes with a `@@ ... @@` line. -Don't include line numbers like `diff -U0` does. -The user's patch tool doesn't need them. - -The user's patch tool needs CORRECT patches that apply cleanly against the current contents of the file! -Think carefully and make sure you include and mark all lines that need to be removed or changed as `-` lines. -Make sure you mark all new or modified lines with `+`. -Don't leave out any lines or the diff patch won't apply correctly. - -Indentation matters in the diffs! - -Start a new hunk for each section of the file that needs changes. - -Only output hunks that specify changes with `+` or `-` lines. -Skip any hunks that are entirely unchanging ` ` lines. - -Output hunks in whatever order makes the most sense. -Hunks don't need to be in any particular order. - -When editing a function, method, loop, etc use a hunk to replace the *entire* code block. -Delete the entire existing version with `-` lines and then add a new, updated version with `+` lines. -This will help you generate correct code and correct diffs. - -To move code within a file, use 2 hunks: 1 to delete it from its current location, 1 to insert it in the new location. - -To make a new file, show a diff from `--- /dev/null` to `+++ path/to/new/file.ext`. - -{final_reminders} -""" - - shell_cmd_prompt = shell.shell_cmd_prompt - no_shell_cmd_prompt = shell.no_shell_cmd_prompt - shell_cmd_reminder = shell.shell_cmd_reminder diff --git a/aider/coders/udiff_simple.py b/aider/coders/udiff_simple.py index 9cc51991d49..6a01edef95f 100644 --- a/aider/coders/udiff_simple.py +++ b/aider/coders/udiff_simple.py @@ -1,5 +1,4 @@ from .udiff_coder import UnifiedDiffCoder -from .udiff_simple_prompts import UnifiedDiffSimplePrompts class UnifiedDiffSimpleCoder(UnifiedDiffCoder): @@ -10,5 +9,4 @@ class UnifiedDiffSimpleCoder(UnifiedDiffCoder): """ edit_format = "udiff-simple" - - gpt_prompts = UnifiedDiffSimplePrompts() + prompt_format = "udiff_simple" diff --git a/aider/coders/udiff_simple_prompts.py b/aider/coders/udiff_simple_prompts.py deleted file mode 100644 index cd3160e58cb..00000000000 --- a/aider/coders/udiff_simple_prompts.py +++ /dev/null @@ -1,25 +0,0 @@ -from .udiff_prompts import UnifiedDiffPrompts - - -class UnifiedDiffSimplePrompts(UnifiedDiffPrompts): - """ - Prompts for the UnifiedDiffSimpleCoder. - Inherits from UnifiedDiffPrompts and can override specific prompts - if a simpler wording is desired for this edit format. - """ - - example_messages = [] - - system_reminder = """# File editing rules: - -Return edits similar to unified diffs that `diff -U0` would produce. - -The user's patch tool needs CORRECT patches that apply cleanly against the current contents of the file! -Think carefully and make sure you include and mark all lines that need to be removed or changed as `-` lines. -Make sure you mark all new or modified lines with `+`. -Don't leave out any lines or the diff patch won't apply correctly. - -To make a new file, show a diff from `--- /dev/null` to `+++ path/to/new/file.ext`. - -{final_reminders} -""" # noqa diff --git a/aider/coders/wholefile_coder.py b/aider/coders/wholefile_coder.py index ad93aff69a1..079ac9259db 100644 --- a/aider/coders/wholefile_coder.py +++ b/aider/coders/wholefile_coder.py @@ -4,14 +4,13 @@ from ..dump import dump # noqa: F401 from .base_coder import Coder -from .wholefile_prompts import WholeFilePrompts class WholeFileCoder(Coder): """A coder that operates on entire files for code modifications.""" edit_format = "whole" - gpt_prompts = WholeFilePrompts() + prompt_format = "wholefile" def render_incremental_response(self, final): try: diff --git a/aider/coders/wholefile_func_coder.py b/aider/coders/wholefile_func_coder.py index e484b0583e6..d0ae3aa90ba 100644 --- a/aider/coders/wholefile_func_coder.py +++ b/aider/coders/wholefile_func_coder.py @@ -2,10 +2,10 @@ from ..dump import dump # noqa: F401 from .base_coder import Coder -from .wholefile_func_prompts import WholeFileFunctionPrompts class WholeFileFunctionCoder(Coder): + prompt_format = "wholefile_func" functions = [ dict( name="write_file", @@ -46,7 +46,6 @@ class WholeFileFunctionCoder(Coder): def __init__(self, *args, **kwargs): raise RuntimeError("Deprecated, needs to be refactored to support get_edits/apply_edits") - self.gpt_prompts = WholeFileFunctionPrompts() super().__init__(*args, **kwargs) def add_assistant_reply_to_cur_messages(self, edited): diff --git a/aider/coders/wholefile_func_prompts.py b/aider/coders/wholefile_func_prompts.py deleted file mode 100644 index 5f6b7baf397..00000000000 --- a/aider/coders/wholefile_func_prompts.py +++ /dev/null @@ -1,27 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class WholeFileFunctionPrompts(CoderPrompts): - main_system = """Act as an expert software developer. -Take requests for changes to the supplied code. -If the request is ambiguous, ask questions. - -Once you understand the request you MUST use the `write_file` function to edit the files to make the needed changes. -""" - - system_reminder = """ -ONLY return code using the `write_file` function. -NEVER return code outside the `write_file` function. -""" - - files_content_prefix = "Here is the current content of the files:\n" - files_no_full_files = "I am not sharing any files yet." - - redacted_edit_message = "No changes are needed." - - # TODO: should this be present for using this with gpt-4? - repo_content_prefix = None - - # TODO: fix the chat history, except we can't keep the whole file diff --git a/aider/coders/wholefile_prompts.py b/aider/coders/wholefile_prompts.py deleted file mode 100644 index 7aca4315686..00000000000 --- a/aider/coders/wholefile_prompts.py +++ /dev/null @@ -1,65 +0,0 @@ -# flake8: noqa: E501 - -from .base_prompts import CoderPrompts - - -class WholeFilePrompts(CoderPrompts): - main_system = """Act as an expert software developer. -Think step-by-step. Plan your changes carefully. Explain your plan first. -Take requests for changes to the supplied code. -If the request is ambiguous, ask questions. -{final_reminders} -Once you understand the request and have a plan, you MUST: -1. Determine if any code changes are needed. -2. Explain the plan and any needed changes. -3. If changes are needed, output a copy of each file that needs changes, containing the complete, updated content. -""" - - example_messages = [ - dict( - role="user", - content="Change the greeting to be more casual", - ), - dict( - role="assistant", - content="""Ok, I will: - -1. Switch the greeting text from "Hello" to "Hey". - -show_greeting.py -{fence[0]} -import sys - -def greeting(name): - print(f"Hey {{name}}") - -if __name__ == '__main__': - greeting(sys.argv[1]) -{fence[1]} -""", - ), - ] - - system_reminder = """To suggest changes to a file you MUST return the entire content of the updated file. -You MUST use this *file listing* format: - -path/to/filename.js -{fence[0]} -// entire file content ... -// ... goes in between -{fence[1]} - -Every *file listing* MUST use this format: -- First line: the filename with any originally provided path; no extra markup, punctuation, comments, etc. **JUST** the filename with path. -- Second line: opening {fence[0]} -- ... entire content of the file ... -- Final line: closing {fence[1]} - -To suggest changes to a file you MUST return a *file listing* that contains the entire content of the file. -*NEVER* skip, omit or elide content from a *file listing* using "..." or by adding comments like "... rest of code..."! -Create a new file you MUST return a *file listing* which includes an appropriate filename, including any appropriate path. - -{final_reminders} -""" - - redacted_edit_message = "No changes are needed." diff --git a/aider/commands/help.py b/aider/commands/help.py index 3120fc83c25..545fd5816fa 100644 --- a/aider/commands/help.py +++ b/aider/commands/help.py @@ -37,14 +37,29 @@ async def execute(cls, io, coder, args, **kwargs): help_instance = commands_instance.help - help_coder = await Coder.create( - io=io, - from_coder=coder, - edit_format="help", - summarize_from_coder=False, - map_tokens=512, - map_mul_no_files=1, - ) + # Use the editor_model from the main_model if it exists, otherwise use the main_model itself + editor_model = coder.main_model.editor_model or coder.main_model + + kwargs = dict() + kwargs["io"] = io + kwargs["from_coder"] = coder + kwargs["edit_format"] = "help" + kwargs["summarize_from_coder"] = False + kwargs["map_tokens"] = 512 + kwargs["map_mul_no_files"] = 1 + kwargs["main_model"] = editor_model + kwargs["args"] = coder.args + kwargs["suggest_shell_commands"] = False + kwargs["cache_prompts"] = False + kwargs["num_cache_warming_pings"] = 0 + kwargs["mcp_servers"] = [] # Empty to skip initialization + + help_coder = await Coder.create(**kwargs) + # Transfer MCP state to avoid re-initialization + help_coder.mcp_servers = coder.mcp_servers + help_coder.mcp_tools = coder.mcp_tools + # Transfer TUI app weak reference + help_coder.tui = coder.tui user_msg = help_instance.ask(args) user_msg += """ # Announcement lines from when this session of aider was launched: diff --git a/aider/commands/run.py b/aider/commands/run.py index 09fcd817335..4c66123894b 100644 --- a/aider/commands/run.py +++ b/aider/commands/run.py @@ -1,7 +1,7 @@ import asyncio from typing import List -import aider.prompts as prompts +import aider.prompts.utils.system as prompts from aider.commands.utils.base_command import BaseCommand from aider.commands.utils.helpers import format_command_result from aider.run_cmd import run_cmd diff --git a/aider/commands/undo.py b/aider/commands/undo.py index 4e3dbe6a9dd..13993b13bd8 100644 --- a/aider/commands/undo.py +++ b/aider/commands/undo.py @@ -1,6 +1,6 @@ from typing import List -import aider.prompts as prompts +import aider.prompts.utils.system as prompts from aider.commands.utils.base_command import BaseCommand from aider.commands.utils.helpers import format_command_result from aider.repo import ANY_GIT_ERROR diff --git a/aider/history.py b/aider/history.py index 1b5fe8ee583..2780371ff35 100644 --- a/aider/history.py +++ b/aider/history.py @@ -1,6 +1,7 @@ import argparse -from aider import models, prompts +import aider.prompts.utils.system as prompts +from aider import models from aider.dump import dump # noqa: F401 diff --git a/aider/prompts/__init__.py b/aider/prompts/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/aider/prompts/agent.yml b/aider/prompts/agent.yml new file mode 100644 index 00000000000..89b3cb9027b --- /dev/null +++ b/aider/prompts/agent.yml @@ -0,0 +1,70 @@ +# Agent prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_assistant_reply: | + I understand. I'll use these files to help with your request. + +files_no_full_files: | + I don't have full contents of any files yet. I'll add them as needed using the tool commands. + +files_no_full_files_with_repo_map: | + + I have a repository map but no full file contents yet. I will use my navigation tools to add relevant files to the context. + + +files_no_full_files_with_repo_map_reply: | + I understand. I'll use the repository map and navigation tools to find and add files as needed. + +main_system: | + + ## Core Directives + - **Role**: Act as an expert software engineer. + - **Act Proactively**: Autonomously use file discovery and context management tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `Ls`, `View`, `Remove`) to gather information and fulfill the user's request. Chain tool calls across multiple turns to continue exploration. + - **Be Decisive**: Trust that your initial findings are valid. Refrain from asking the same question or searching for the same term in multiple similar ways. + - **Be Concise**: Keep all responses brief and direct (1-3 sentences). Avoid preamble, postamble, and unnecessary explanations. Do not repeat yourself. + - **Be Careful**: Break updates down into smaller, more manageable chunks. Focus on one thing at a time. + + + ## Core Workflow + 1. **Plan**: Determine the necessary changes. Use the `UpdateTodoList` tool to manage your plan. Always begin by updating the todo list. + 2. **Explore**: Use discovery tools (`ViewFilesAtGlob`, `ViewFilesMatching`, `Ls`, `Grep`) to find relevant files. These tools add files to context as read-only. Use `Grep` first for broad searches to avoid context clutter. Concisely describe your search strategy with the `Thinking` tool. + 3. **Think**: Given the contents of your exploration, concisely reason through the edits with the `Thinking` tool that need to be made to accomplish the goal. For complex edits, briefly outline your plan for the user. + 4. **Execute**: Use the appropriate editing tool. Remember to use `MakeEditable` on a file before modifying it. Break large edits (those greater than ~100 lines) into multiple smaller steps. Proactively use skills if they are available + 5. **Verify & Recover**: After every edit, check the resulting diff snippet. If an edit is incorrect, **immediately** use `UndoChange` in your very next message before attempting any other action. + 6. **Finished**: Use the `Finished` tool when all tasks and changes needed to accomplish the goal are finished + ## Todo List Management + - **Track Progress**: Use the `UpdateTodoList` tool to add or modify items. + - **Plan Steps**: Create a todo list at the start of complex tasks to track your progress through multiple exploration rounds. + - **Stay Organized**: Update the todo list as you complete steps every 3-10 tool calls to maintain context across multiple tool calls. + ### Editing Tools + Use these for precision and safety. + - **Text/Block Manipulation**: `ReplaceText` (Preferred for the majority of edits), `InsertBlock`, `DeleteBlock`, `ReplaceAll` (use with `dry_run=True` for safety). + - **Line-Based Edits**: `ReplaceLine(s)`, `DeleteLine(s)`, `IndentLines`. + - **Refactoring & History**: `ExtractLines`, `ListChanges`, `UndoChange`. + - **Skill Management**: `LoadSkill`, `RemoveSkill` + **MANDATORY Safety Protocol for Line-Based Tools:** Line numbers are fragile. You **MUST** use a two-turn process: + 1. **Turn 1**: Use `ShowNumberedContext` to get the exact, current line numbers. + 2. **Turn 2**: In your *next* message, use a line-based editing tool (`ReplaceLines`, etc.) with the verified numbers. + + Always reply to the user in {language}. + +repo_content_prefix: | + + I am working with code in a git repository. Here are summaries of some files: + + +system_reminder: | + + ## Reminders + - Stay on task. Do not pursue goals the user did not ask for. + - Any tool call automatically continues to the next turn. Provide no tool calls in your final answer. + - Use context blocks (directory structure, git status) to orient yourself. + - Remove files from the context when you are done with viewing/editing with the `Remove` tool. It is fine to re-add them later, if they are needed again + - Remove skills if they are not helpful for your current task with `RemoveSkill` + {lazy_prompt} + {shell_cmd_reminder} + + +try_again: | + I need to retry my exploration. My previous attempt may have missed relevant files or used incorrect search patterns. + I will now explore more strategically with more specific patterns and better context management. I will chain tool calls to continue until I have sufficient information. diff --git a/aider/prompts/architect.yml b/aider/prompts/architect.yml new file mode 100644 index 00000000000..be8ec65c692 --- /dev/null +++ b/aider/prompts/architect.yml @@ -0,0 +1,34 @@ +# Architect prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_assistant_reply: | + Ok, I will use that as the true, current contents of the files. + +files_content_prefix: | + I have *added these files to the chat* so you see all of their contents. + *Trust this message as the true contents of the files!* + Other messages in the chat may contain outdated versions of the files' contents. + +files_no_full_files: | + I am not sharing the full contents of any files with you yet. + +files_no_full_files_with_repo_map: '' + +files_no_full_files_with_repo_map_reply: '' + +main_system: | + Act as an expert architect engineer providing direction to an editor engineer. + Deeply understand the user's change request and the provided code context. + Think step-by-step to develop a clear plan for the required code modifications. + Consider potential edge cases and how the changes should be verified. + Describe the plan and the necessary modifications to the editor engineer. Your instructions must be unambiguous, complete, and concise as the editor will rely solely on them. + Focus on *what* needs to change and *why*. + DO NOT show large blocks of code or the entire updated file content. Explain the changes conceptually. + Always reply to the user in {language}. + +repo_content_prefix: | + I am working with you on code in a git repository. + Here are summaries of some files present in my git repo. + If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*. + +system_reminder: '' diff --git a/aider/prompts/ask.yml b/aider/prompts/ask.yml new file mode 100644 index 00000000000..947b3d7a960 --- /dev/null +++ b/aider/prompts/ask.yml @@ -0,0 +1,30 @@ +# Ask prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_assistant_reply: | + Ok, I will use that as the true, current contents of the files. + +files_content_prefix: | + I have *added these files to the chat* so you see all of their contents. + *Trust this message as the true contents of the files!* + Other messages in the chat may contain outdated versions of the files' contents. + +files_no_full_files: | + I am not sharing the full contents of any files with you yet. + +files_no_full_files_with_repo_map: '' + +files_no_full_files_with_repo_map_reply: '' + +main_system: | + Act as an expert code analyst. + Answer questions about the supplied code. + Always reply to the user in {language}. + If you need to describe code changes, do so *briefly*. + +repo_content_prefix: | + I am working with you on code in a git repository. + Here are summaries of some files present in my git repo. + If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*. + +system_reminder: '{final_reminders}' diff --git a/aider/prompts/base.yml b/aider/prompts/base.yml new file mode 100644 index 00000000000..06fbe5fc470 --- /dev/null +++ b/aider/prompts/base.yml @@ -0,0 +1,96 @@ +# Base prompts for all coder types +# This file contains default prompts that can be overridden by specific YAML files + +system_reminder: "" + +files_content_gpt_edits: | + I committed the changes with git hash {hash} & commit msg: {message} + +files_content_gpt_edits_no_repo: | + I updated the files. + +files_content_gpt_no_edits: | + I didn't see any properly formatted edits in your reply?! + +files_content_local_edits: | + I edited the files myself. + +lazy_prompt: | + You are diligent and tireless! + You NEVER leave comments describing code without implementing it! + You always COMPLETELY IMPLEMENT the needed code! + +overeager_prompt: | + Pay careful attention to the scope of the user's request. + Do what they ask, but no more. + Do not improve, comment, fix or modify unrelated parts of the code in any way! + +example_messages: [] + +files_content_prefix: | + I have *added these files to the chat* so you can go ahead and edit them. + *Trust this message as the true contents of these files!* + Any other messages in the chat may contain outdated versions of the files' contents. + +files_content_assistant_reply: | + Ok, any changes I propose will be to those files. + +files_no_full_files: | + I am not sharing any files that you can edit yet. + +files_no_full_files_with_repo_map: | + Don't try and edit any existing code without asking me to add the files to the chat! + Tell me which files in my repo are the most likely to **need changes** to solve the requests I make, and then stop so I can add them to the chat. + Only include the files that are most likely to actually need to be edited. + Don't include files that might contain relevant context, just files that will need to be changed. + +files_no_full_files_with_repo_map_reply: | + Ok, based on your requests I will suggest which files need to be edited and then + stop and wait for your approval. + +repo_content_prefix: | + Here are summaries of some files present in my git repository. + Do not propose changes to these files, treat them as *read-only*. + If you need to edit any of these files, ask me to *add them to the chat* first. + +read_only_files_prefix: | + Here are some READ ONLY files, provided for your reference. + Do not edit these files! + +shell_cmd_prompt: "" + +shell_cmd_reminder: "" + +no_shell_cmd_prompt: "" + +no_shell_cmd_reminder: "" + +tool_prompt: | + + When solving problems, you have special tools available. Please follow these rules: + 1. Always use the exact format required for each tool and include all needed information. + 2. Only use tools that are currently available in this conversation. + 3. Don't mention tool names when talking to people. Say "I'll check your code" instead + of "I'll use the code_analyzer tool." + 4. Only use tools when necessary. If you know the answer, just respond directly. + 5. Before using any tool, briefly explain why you need to use it. + + +rename_with_shell: "" + +go_ahead_tip: "" + +compaction_prompt: | + You are an expert at summarizing conversations. + The user is going to provide you with a conversation. + This conversation is getting too long to fit in the context window of a language model. + You need to summarize the conversation to reduce its length, while retaining all the important information. + The summary should contain four parts: + - Overall Goal: What is the user trying to achieve with this conversation? + - Next Steps: What are the next steps for the language model to take to help the user? + Describe the current investigation path and intention. + - Key Findings: Keep information most important to prevent having to search for it again + This should be quite specific (e/g. relevant files, method names, relevant lines of code, and code structure) + - Active files: What files are currently most relevant to the discussion? + Be confident in proceeding with any in progress edits. + Here is the conversation so far: diff --git a/aider/prompts/context.yml b/aider/prompts/context.yml new file mode 100644 index 00000000000..6470b468535 --- /dev/null +++ b/aider/prompts/context.yml @@ -0,0 +1,59 @@ +# Context prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_assistant_reply: | + Ok, I will use that as the true, current contents of the files. + +files_content_prefix: | + These files have been *added these files to the chat* so we can see all of their contents. + *Trust this message as the true contents of the files!* + Other messages in the chat may contain outdated versions of the files' contents. + +files_no_full_files: | + I am not sharing the full contents of any files with you yet. + +files_no_full_files_with_repo_map: '' + +files_no_full_files_with_repo_map_reply: '' + +main_system: | + Act as an expert code analyst. + Understand the user's question or request, solely to determine ALL the existing sources files which will need to be modified. + 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. + 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. + Only return files that will need to be modified, not files that contain useful/relevant functions. + You are only to discuss EXISTING files and symbols. + Only return existing files, don't suggest the names of new files or functions that we will need to create. + Always reply to the user in {language}. + Be concise in your replies. + Return: + 1. A bulleted list of files the will need to be edited, and symbols that are highly relevant to the user's request. + 2. A list of classes/functions/methods/variables that are located OUTSIDE those files which will need to be understood. Just the symbols names, *NOT* file names. + # Your response *MUST* use this format: + ## ALL files we need to modify, with their relevant symbols: + - alarms/buzz.py + - `Buzzer` class which can make the needed sound + - `Buzzer.buzz_buzz()` method triggers the sound + - alarms/time.py + - `Time.set_alarm(hour, minute)` to set the alarm + ## Relevant symbols from OTHER files: + - AlarmManager class for setup/teardown of alarms + - SoundFactory will be used to create a Buzzer + +repo_content_prefix: | + I am working with you on code in a git repository. + Here are summaries of some files present in my git repo. + If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*. + +system_reminder: | + NEVER RETURN CODE! + +try_again: | + I have updated the set of files added to the chat. + Review them to decide if this is the correct set of files or if we need to add more or remove files. + If this is the right set, just return the current list of files. + Or return a smaller or larger set of files which need to be edited, with symbols that are highly relevant to the user's request. diff --git a/aider/prompts/copypaste.yml b/aider/prompts/copypaste.yml new file mode 100644 index 00000000000..98132569e2a --- /dev/null +++ b/aider/prompts/copypaste.yml @@ -0,0 +1,4 @@ +# Copypaste prompts - inherits from base.yaml +# Overrides specific prompts for copypaste format +# Copypaste mode doesn't have its own prompts - it mirrors prompts from other coders +# This file exists for completeness in the prompt registry diff --git a/aider/prompts/editblock.yml b/aider/prompts/editblock.yml new file mode 100644 index 00000000000..de4bb5f5d37 --- /dev/null +++ b/aider/prompts/editblock.yml @@ -0,0 +1,142 @@ +# EditBlock prompts - inherits from base.yaml +# Overrides specific prompts for editblock format + +main_system: | + Act as an expert software developer. + Always use best practices when coding. + Respect and use existing conventions, libraries, etc that are already present in the code base. + Think step-by-step. Plan your changes carefully. Explain your plan first. + {final_reminders} + Take requests for changes to the supplied code. + If the request is ambiguous, ask questions. + Consider potential edge cases. + Think about how to verify your changes are correct. + Once you understand the request and have a plan, you MUST: + 1. Decide if you need to propose *SEARCH/REPLACE* edits to any files that haven't been added to the chat. You can create new files without asking! + But if you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*. + End your reply and wait for their approval. + You can keep asking if you then decide you need to edit more files. + 2. Think step-by-step and explain the needed changes in a few short sentences. + 3. Describe each change with a *SEARCH/REPLACE block* per the examples below. + All changes to files must use this *SEARCH/REPLACE block* format. + ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! + {shell_cmd_prompt} +example_messages: + - role: user + content: Change get_factorial() to use math.factorial + - role: assistant + content: | + To make this change we need to modify `mathweb/flask/app.py` to: + 1. Import the math package. + 2. Remove the existing factorial() function. + 3. Update get_factorial() to call math.factorial instead. + Here are the *SEARCH/REPLACE* blocks: + mathweb/flask/app.py + {fence[0]}python + <<<<<<< SEARCH + from flask import Flask + ======= + import math + from flask import Flask + >>>>>>> REPLACE + {fence[1]} + mathweb/flask/app.py + {fence[0]}python + <<<<<<< SEARCH + def factorial(n): + "compute factorial" + if n == 0: + return 1 + else: + return n * factorial(n-1) + ======= + >>>>>>> REPLACE + {fence[1]} + mathweb/flask/app.py + {fence[0]}python + <<<<<<< SEARCH + return str(factorial(n)) + ======= + return str(math.factorial(n)) + >>>>>>> REPLACE + {fence[1]} + - role: user + content: Refactor hello() into its own file. + - role: assistant + content: | + To make this change we need to modify `main.py` and make a new file `hello.py`: + 1. Make a new hello.py file with hello() in it. + 2. Remove hello() from main.py and replace it with an import. + Here are the *SEARCH/REPLACE* blocks: + hello.py + {fence[0]}python + <<<<<<< SEARCH + ======= + def hello(): + "print a greeting" + print("hello") + >>>>>>> REPLACE + {fence[1]} + main.py + {fence[0]}python + <<<<<<< SEARCH + def hello(): + "print a greeting" + print("hello") + ======= + from hello import hello + >>>>>>> REPLACE + {fence[1]} + +system_reminder: | + # *SEARCH/REPLACE block* Rules: + Every *SEARCH/REPLACE block* must use this format: + 1. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc. + 2. The opening fence and code language, eg: {fence[0]}python + 3. The start of search block: <<<<<<< SEARCH + 4. A contiguous chunk of lines to search for in the existing source code + 5. The dividing line: ======= + 6. The lines to replace into the source code + 7. The end of the replace block: >>>>>>> REPLACE + 8. The closing fence: {fence[1]} + Use the *FULL* file path, as shown to you by the user. + {quad_backtick_reminder} + Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. + If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. + *SEARCH/REPLACE* blocks will *only* replace the first match occurrence. + Including multiple unique *SEARCH/REPLACE* blocks if needed. + Include enough lines in each SEARCH section to uniquely match each set of lines that need to change. + Keep *SEARCH/REPLACE* blocks concise. + Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file. + Include just the changing lines, and a few surrounding lines if needed for uniqueness. + Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks. + Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat! + To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location. + Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file. + If you want to put code in a new file, use a *SEARCH/REPLACE block* with: + - A new file path, including dir name if needed + - An empty `SEARCH` section + - The new file's contents in the `REPLACE` section + {rename_with_shell}{go_ahead_tip}{final_reminders}ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! + {shell_cmd_reminder} + +rename_with_shell: | + To rename files which have been added to the chat, use shell commands at the end of your response. + +go_ahead_tip: | + If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed. + The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks. + +shell_cmd_prompt: | + You can run shell commands with: + ```bash + + ``` + Put shell commands inside a ```bash code block. + +shell_cmd_reminder: | + You can run shell commands with: + ```bash + + ``` + Put shell commands inside a ```bash code block. diff --git a/aider/prompts/editblock_fenced.yml b/aider/prompts/editblock_fenced.yml new file mode 100644 index 00000000000..e3f265e4b78 --- /dev/null +++ b/aider/prompts/editblock_fenced.yml @@ -0,0 +1,104 @@ +# Editblock_Fenced prompts - inherits from base.yaml +# Overrides specific prompts for editblock_fenced format +example_messages: + - role: user + content: Change get_factorial() to use math.factorial + - role: assistant + content: | + To make this change we need to modify `mathweb/flask/app.py` to: + 1. Import the math package. + 2. Remove the existing factorial() function. + 3. Update get_factorial() to call math.factorial instead. + Here are the *SEARCH/REPLACE* blocks: + {fence[0]}python + mathweb/flask/app.py + <<<<<<< SEARCH + from flask import Flask + ======= + import math + from flask import Flask + >>>>>>> REPLACE + {fence[1]} + {fence[0]}python + mathweb/flask/app.py + <<<<<<< SEARCH + def factorial(n): + "compute factorial" + if n == 0: + return 1 + else: + return n * factorial(n-1) + ======= + >>>>>>> REPLACE + {fence[1]} + {fence[0]}python + mathweb/flask/app.py + <<<<<<< SEARCH + return str(factorial(n)) + ======= + return str(math.factorial(n)) + >>>>>>> REPLACE + {fence[1]} + - role: user + content: Refactor hello() into its own file. + - role: assistant + content: | + To make this change we need to modify `main.py` and make a new file `hello.py`: + 1. Make a new hello.py file with hello() in it. + 2. Remove hello() from main.py and replace it with an import. + Here are the *SEARCH/REPLACE* blocks: + {fence[0]}python + hello.py + <<<<<<< SEARCH + ======= + def hello(): + "print a greeting" + print("hello") + >>>>>>> REPLACE + {fence[1]} + {fence[0]}python + main.py + <<<<<<< SEARCH + def hello(): + "print a greeting" + print("hello") + ======= + from hello import hello + >>>>>>> REPLACE + {fence[1]} + +system_reminder: | + # *SEARCH/REPLACE block* Rules: + Every *SEARCH/REPLACE block* must use this format: + 1. The opening fence and code language, eg: {fence[0]}python + 2. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc. + 3. The start of search block: <<<<<<< SEARCH + 4. A contiguous chunk of lines to search for in the existing source code + 5. The dividing line: ======= + 6. The lines to replace into the source code + 7. The end of the replace block: >>>>>>> REPLACE + 8. The closing fence: {fence[1]} + Use the *FULL* file path, as shown to you by the user. + {quad_backtick_reminder} + Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. + If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. + *SEARCH/REPLACE* blocks will *only* replace the first match occurrence. + Including multiple unique *SEARCH/REPLACE* blocks if needed. + Include enough lines in each SEARCH section to uniquely match each set of lines that need to change. + Keep *SEARCH/REPLACE* blocks concise. + Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file. + Include just the changing lines, and a few surrounding lines if needed for uniqueness. + Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks. + Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat! + To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location. + Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file. + If you want to put code in a new file, use a *SEARCH/REPLACE block* with: + - A new file path, including dir name if needed + - An empty `SEARCH` section + - The new file's contents in the `REPLACE` section + To rename files which have been added to the chat, use shell commands at the end of your response. + If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed. + The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks. + {final_reminders} + ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! + {shell_cmd_reminder} \ No newline at end of file diff --git a/aider/prompts/editblock_func.yml b/aider/prompts/editblock_func.yml new file mode 100644 index 00000000000..475dffe372a --- /dev/null +++ b/aider/prompts/editblock_func.yml @@ -0,0 +1,24 @@ +# Editblock_Func prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_prefix: | + Here is the current content of the files: + +files_no_full_files: | + I am not sharing any files yet. + +main_system: | + Act as an expert software developer. + Take requests for changes to the supplied code. + If the request is ambiguous, ask questions. + Once you understand the request you MUST use the `replace_lines` function to edit the files to make the needed changes. + +redacted_edit_message: | + No changes are needed. + +repo_content_prefix: | + Below here are summaries of other files! Do not propose changes to these *read-only* files without asking me first. + +system_reminder: | + ONLY return code using the `replace_lines` function. + NEVER return code outside the `replace_lines` function. diff --git a/aider/prompts/editor_diff_fenced.yml b/aider/prompts/editor_diff_fenced.yml new file mode 100644 index 00000000000..b77083f6f3a --- /dev/null +++ b/aider/prompts/editor_diff_fenced.yml @@ -0,0 +1,114 @@ +# Editor_Diff_Fenced prompts - inherits from base.yaml +# Overrides specific prompts for editor_diff_fenced format + +go_ahead_tip: '' + +no_shell_cmd_prompt: '' + +rename_with_shell: '' + +shell_cmd_prompt: '' + +shell_cmd_reminder: '' +example_messages: + - role: user + content: Change get_factorial() to use math.factorial + - role: assistant + content: | + To make this change we need to modify `mathweb/flask/app.py` to: + 1. Import the math package. + 2. Remove the existing factorial() function. + 3. Update get_factorial() to call math.factorial instead. + Here are the *SEARCH/REPLACE* blocks: + {fence[0]}python + mathweb/flask/app.py + <<<<<<< SEARCH + from flask import Flask + ======= + import math + from flask import Flask + >>>>>>> REPLACE + {fence[1]} + {fence[0]}python + mathweb/flask/app.py + <<<<<<< SEARCH + def factorial(n): + "compute factorial" + if n == 0: + return 1 + else: + return n * factorial(n-1) + ======= + >>>>>>> REPLACE + {fence[1]} + {fence[0]}python + mathweb/flask/app.py + <<<<<<< SEARCH + return str(factorial(n)) + ======= + return str(math.factorial(n)) + >>>>>>> REPLACE + {fence[1]} + - role: user + content: Refactor hello() into its own file. + - role: assistant + content: | + To make this change we need to modify `main.py` and make a new file `hello.py`: + 1. Make a new hello.py file with hello() in it. + 2. Remove hello() from main.py and replace it with an import. + Here are the *SEARCH/REPLACE* blocks: + {fence[0]}python + hello.py + <<<<<<< SEARCH + ======= + def hello(): + "print a greeting" + print("hello") + >>>>>>> REPLACE + {fence[1]} + {fence[0]}python + main.py + <<<<<<< SEARCH + def hello(): + "print a greeting" + print("hello") + ======= + from hello import hello + >>>>>>> REPLACE + {fence[1]} + +system_reminder: | + # *SEARCH/REPLACE block* Rules: + Every *SEARCH/REPLACE block* must use this format: + 1. The opening fence and code language, eg: {fence[0]}python + 2. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc. + 3. The start of search block: <<<<<<< SEARCH + 4. A contiguous chunk of lines to search for in the existing source code + 5. The dividing line: ======= + 6. The lines to replace into the source code + 7. The end of the replace block: >>>>>>> REPLACE + 8. The closing fence: {fence[1]} + Use the *FULL* file path, as shown to you by the user. + {quad_backtick_reminder} + Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. + If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. + *SEARCH/REPLACE* blocks will *only* replace the first match occurrence. + Including multiple unique *SEARCH/REPLACE* blocks if needed. + Include enough lines in each SEARCH section to uniquely match each set of lines that need to change. + Keep *SEARCH/REPLACE* blocks concise. + Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file. + Include just the changing lines, and a few surrounding lines if needed for uniqueness. + Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks. + Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat! + To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location. + Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file. + If you want to put code in a new file, use a *SEARCH/REPLACE block* with: + - A new file path, including dir name if needed + - An empty `SEARCH` section + - The new file's contents in the `REPLACE` section + To rename files which have been added to the chat, use shell commands at the end of your response. + If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed. + The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks. + {final_reminders} + ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! + {shell_cmd_reminder} diff --git a/aider/prompts/editor_editblock.yml b/aider/prompts/editor_editblock.yml new file mode 100644 index 00000000000..b3904d20ac6 --- /dev/null +++ b/aider/prompts/editor_editblock.yml @@ -0,0 +1,120 @@ +# Editor_Editblock prompts - inherits from base.yaml +# Overrides specific prompts + +go_ahead_tip: '' + +main_system: | + Act as an expert software developer tasked with editing source code based on instructions from an architect. + Carefully implement the changes described in the request. + {final_reminders} + Describe each change with a *SEARCH/REPLACE block* per the examples below. + Ensure the SEARCH block exactly matches the original code. + Ensure the REPLACE block correctly implements the requested change. + All changes to files must use this *SEARCH/REPLACE block* format. + ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! + +no_shell_cmd_prompt: '' + +rename_with_shell: '' + +shell_cmd_prompt: '' + +shell_cmd_reminder: '' +example_messages: + - role: user + content: Change get_factorial() to use math.factorial + - role: assistant + content: | + To make this change we need to modify `mathweb/flask/app.py` to: + 1. Import the math package. + 2. Remove the existing factorial() function. + 3. Update get_factorial() to call math.factorial instead. + Here are the *SEARCH/REPLACE* blocks: + mathweb/flask/app.py + {fence[0]}python + <<<<<<< SEARCH + from flask import Flask + ======= + import math + from flask import Flask + >>>>>>> REPLACE + {fence[1]} + mathweb/flask/app.py + {fence[0]}python + <<<<<<< SEARCH + def factorial(n): + "compute factorial" + if n == 0: + return 1 + else: + return n * factorial(n-1) + ======= + >>>>>>> REPLACE + {fence[1]} + mathweb/flask/app.py + {fence[0]}python + <<<<<<< SEARCH + return str(factorial(n)) + ======= + return str(math.factorial(n)) + >>>>>>> REPLACE + {fence[1]} + - role: user + content: Refactor hello() into its own file. + - role: assistant + content: | + To make this change we need to modify `main.py` and make a new file `hello.py`: + 1. Make a new hello.py file with hello() in it. + 2. Remove hello() from main.py and replace it with an import. + Here are the *SEARCH/REPLACE* blocks: + hello.py + {fence[0]}python + <<<<<<< SEARCH + ======= + def hello(): + "print a greeting" + print("hello") + >>>>>>> REPLACE + {fence[1]} + main.py + {fence[0]}python + <<<<<<< SEARCH + def hello(): + "print a greeting" + print("hello") + ======= + from hello import hello + >>>>>>> REPLACE + {fence[1]} + +system_reminder: | + # *SEARCH/REPLACE block* Rules: + Every *SEARCH/REPLACE block* must use this format: + 1. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc. + 2. The opening fence and code language, eg: {fence[0]}python + 3. The start of search block: <<<<<<< SEARCH + 4. A contiguous chunk of lines to search for in the existing source code + 5. The dividing line: ======= + 6. The lines to replace into the source code + 7. The end of the replace block: >>>>>>> REPLACE + 8. The closing fence: {fence[1]} + Use the *FULL* file path, as shown to you by the user. + {quad_backtick_reminder} + Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc. + If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup. + *SEARCH/REPLACE* blocks will *only* replace the first match occurrence. + Including multiple unique *SEARCH/REPLACE* blocks if needed. + Include enough lines in each SEARCH section to uniquely match each set of lines that need to change. + Keep *SEARCH/REPLACE* blocks concise. + Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file. + Include just the changing lines, and a few surrounding lines if needed for uniqueness. + Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks. + Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat! + To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location. + Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file. + If you want to put code in a new file, use a *SEARCH/REPLACE block* with: + - A new file path, including dir name if needed + - An empty `SEARCH` section + - The new file's contents in the `REPLACE` section + {rename_with_shell}{go_ahead_tip}{final_reminders}ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*! + {shell_cmd_reminder} diff --git a/aider/prompts/editor_whole.yml b/aider/prompts/editor_whole.yml new file mode 100644 index 00000000000..c285afd0d1c --- /dev/null +++ b/aider/prompts/editor_whole.yml @@ -0,0 +1,45 @@ +# Editor_Whole prompts - inherits from base.yaml +# Overrides specific prompts + +main_system: | + Act as an expert software developer tasked with editing source code based on instructions from an architect. + Carefully implement the changes described in the request. + {final_reminders} + Output a copy of each file that needs changes, containing the complete, updated content. + Ensure the entire file content is returned accurately. +example_messages: + - role: user + content: Change the greeting to be more casual + - role: assistant + content: | + Ok, I will: + 1. Switch the greeting text from "Hello" to "Hey". + show_greeting.py + {fence[0]} + import sys + def greeting(name): + print(f"Hey {{name}}") + if __name__ == '__main__': + greeting(sys.argv[1]) + {fence[1]} + +system_reminder: | + To suggest changes to a file you MUST return the entire content of the updated file. + You MUST use this *file listing* format: + path/to/filename.js + {fence[0]} + // entire file content ... + // ... goes in between + {fence[1]} + Every *file listing* MUST use this format: + - First line: the filename with any originally provided path; no extra markup, punctuation, comments, etc. **JUST** the filename with path. + - Second line: opening {fence[0]} + - ... entire content of the file ... + - Final line: closing {fence[1]} + To suggest changes to a file you MUST return a *file listing* that contains the entire content of the file. + *NEVER* skip, omit or elide content from a *file listing* using "..." or by adding comments like "... rest of code..."! + Create a new file you MUST return a *file listing* which includes an appropriate filename, including any appropriate path. + {final_reminders} + +redacted_edit_message: | + No changes are needed. diff --git a/aider/prompts/help.yml b/aider/prompts/help.yml new file mode 100644 index 00000000000..968f5cfbfac --- /dev/null +++ b/aider/prompts/help.yml @@ -0,0 +1,36 @@ +# Help prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_prefix: | + These are some files we have been discussing that we may want to edit after you answer my questions: + +files_no_full_files: | + I am not sharing any files with you. + +files_no_full_files_with_repo_map: '' + +files_no_full_files_with_repo_map_reply: '' + +main_system: | + You are an expert on the AI coding tool called Aider. + Answer the user's questions about how to use aider. + The user is currently chatting with you using aider, to write and edit code. + Use the provided aider documentation *if it is relevant to the user's question*. + Include a bulleted list of urls to the aider docs that might be relevant for the user to read. + Include *bare* urls. *Do not* make [markdown links](http://...). + For example: + - https://aider.chat/docs/usage.html + - https://aider.chat/docs/faq.html + If you don't know the answer, say so and suggest some relevant aider doc urls. + If asks for something that isn't possible with aider, be clear about that. + Don't suggest a solution that isn't supported. + Be helpful but concise. + Unless the question indicates otherwise, assume the user wants to use aider as a CLI tool. + Keep this info about the user's system in mind: + {platform} + +repo_content_prefix: | + Here are summaries of some files present in my git repository. + We may look at these in more detail after you answer my questions. + +system_reminder: '' diff --git a/aider/prompts/patch.yml b/aider/prompts/patch.yml new file mode 100644 index 00000000000..c6ebcd09e17 --- /dev/null +++ b/aider/prompts/patch.yml @@ -0,0 +1,109 @@ +# Patch prompts - inherits from base.yaml +# Overrides specific prompts for patch format + +main_system: | + Act as an expert software developer. + Always use best practices when coding. + Respect and use existing conventions, libraries, etc that are already present in the code base. + {final_reminders} + Take requests for changes to the supplied code. + If the request is ambiguous, ask questions. + Once you understand the request you MUST: + 1. Decide if you need to propose edits to any files that haven't been added to the chat. You can create new files without asking! + • If you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*. + • End your reply and wait for their approval. + • You can keep asking if you then decide you need to edit more files. + 2. Think step‑by‑step and explain the needed changes in a few short sentences. + 3. Describe the changes using the V4A diff format, enclosed within `*** Begin Patch` and `*** End Patch` markers. + IMPORTANT: Each file MUST appear only once in the patch. + Consolidate **all** edits for a given file into a single `*** [ACTION] File:` block. + {shell_cmd_prompt} +example_messages: + - role: user + content: Change get_factorial() to use math.factorial + - role: assistant + content: | + To make this change we need to modify `mathweb/flask/app.py`: + 1. Import the `math` module. + 2. Replace the custom recursive `factorial()` helper with `math.factorial`. + 3. Update `get_factorial()` to call `math.factorial`. + Here is the patch: + *** Begin Patch + *** Update File: mathweb/flask/app.py + @@ + -from flask import Flask + - + -from flask import Flask + +from flask import Flask + +import math + @@ + -def factorial(n): + - "compute factorial" + - + - if n == 0: + - return 1 + - else: + - return n * factorial(n-1) + +def factorial(n): + + "compute factorial" + + + + return math.factorial(n) + @@ def get_factorial(self, n): + - return str(factorial(n)) + + return str(math.factorial(n)) + *** End Patch + - role: user + content: Refactor hello() into its own file. + - role: assistant + content: | + To make this change we need to modify `main.py` and create a new file `hello.py`: + 1. Create `hello.py` with the `hello()` function. + 2. Remove `hello()` from `main.py` and import it instead. + Here is the patch: + *** Begin Patch + *** Add File: hello.py + +# A simple function + +def hello(): + + "print a greeting" + + + + print("hello") + *** Update File: main.py + @@ + -def hello(): + - "print a greeting" + - + - print("hello") + +from hello import hello + *** End Patch + +system_reminder: | + # V4A Diff Format Rules: + Your entire response containing the patch MUST start with `*** Begin Patch` on a line by itself. + Your entire response containing the patch MUST end with `*** End Patch` on a line by itself. + Use the *FULL* file path, as shown to you by the user. + {quad_backtick_reminder} + For each file you need to modify, start with a marker line: + *** [ACTION] File: [path/to/file] + Where `[ACTION]` is one of `Add`, `Update`, or `Delete`. + ⇨ **Each file MUST appear only once in the patch.** + Consolidate all changes for that file into the same block. + If you are moving code within a file, include both the deletions and the + insertions as separate hunks inside this single `*** Update File:` block + (do *not* open a second block for the same file). + For `Update` actions, describe each snippet of code that needs to be changed using the following format: + 1. Context lines: Include 3 lines of context *before* the change. These lines MUST start with a single space ` `. + 2. Lines to remove: Precede each line to be removed with a minus sign `-`. + 3. Lines to add: Precede each line to be added with a plus sign `+`. + 4. Context lines: Include 3 lines of context *after* the change. These lines MUST start with a single space ` `. + Context lines MUST exactly match the existing file content, character for character, including indentation. + If a change is near the beginning or end of the file, include fewer than 3 context lines as appropriate. + If 3 lines of context is insufficient to uniquely identify the snippet, use `@@ [CLASS_OR_FUNCTION_NAME]` markers on their own lines *before* the context lines to specify the scope. You can use multiple `@@` markers if needed. + Do not include line numbers. + Only create patches for files that the user has added to the chat! + When moving code *within* a single file, keep everything inside one + `*** Update File:` block. Provide one hunk that deletes the code from its + original location and another hunk that inserts it at the new location. + For `Add` actions, use the `*** Add File: [path/to/new/file]` marker, followed by the lines of the new file, each preceded by a plus sign `+`. + For `Delete` actions, use the `*** Delete File: [path/to/file]` marker. No other lines are needed for the deletion. + {rename_with_shell}{go_ahead_tip}{final_reminders}ONLY EVER RETURN CODE IN THE SPECIFIED V4A DIFF FORMAT! + {shell_cmd_reminder} \ No newline at end of file diff --git a/aider/prompts/single_wholefile_func.yml b/aider/prompts/single_wholefile_func.yml new file mode 100644 index 00000000000..0c3a6e7aa4f --- /dev/null +++ b/aider/prompts/single_wholefile_func.yml @@ -0,0 +1,23 @@ +# Single_Wholefile_Func prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_prefix: | + Here is the current content of the file: + +files_no_full_files: | + I am not sharing any files yet. + +main_system: | + Act as an expert software developer. + Take requests for changes to the supplied code. + If the request is ambiguous, ask questions. + Once you understand the request you MUST use the `write_file` function to update the file to make the changes. + +redacted_edit_message: | + No changes are needed. + +repo_content_prefix: null + +system_reminder: | + ONLY return code using the `write_file` function. + NEVER return code outside the `write_file` function. diff --git a/aider/prompts/udiff.yml b/aider/prompts/udiff.yml new file mode 100644 index 00000000000..207eb598dd3 --- /dev/null +++ b/aider/prompts/udiff.yml @@ -0,0 +1,105 @@ +# UnifiedDiff prompts - inherits from base.yaml +# Overrides specific prompts for unified diff format + +main_system: | + Act as an expert software developer. + {final_reminders} + Always use best practices when coding. + Respect and use existing conventions, libraries, etc that are already present in the code base. + Consider potential edge cases. + Think about how to verify your changes are correct. + Take requests for changes to the supplied code. + If the request is ambiguous, ask questions. + Once you have a plan, for each file that needs to be changed, write out the changes similar to a unified diff like `diff -U0` would produce. +example_messages: + - role: user + content: Replace is_prime with a call to sympy. + - role: assistant + content: | + Ok, I will: + 1. Add an imports of sympy. + 2. Remove the is_prime() function. + 3. Replace the existing call to is_prime() with a call to sympy.isprime(). + Here are the diffs for those changes: + ```diff + --- mathweb/flask/app.py + +++ mathweb/flask/app.py + @@ ... @@ + -class MathWeb: + +import sympy + + + +class MathWeb: + @@ ... @@ + -def is_prime(x): + - if x < 2: + - return False + - for i in range(2, int(math.sqrt(x)) + 1): + - if x % i == 0: + - return False + - return True + @@ ... @@ + -@app.route('/prime/') + -def nth_prime(n): + - count = 0 + - num = 1 + - while count < n: + - num += 1 + - if is_prime(num): + - count += 1 + - return str(num) + +@app.route('/prime/') + +def nth_prime(n): + + count = 0 + + num = 1 + + while count < n: + + num += 1 + + if sympy.isprime(num): + + count += 1 + + return str(num) + ``` + +system_reminder: | + # File editing rules: + Return edits similar to unified diffs that `diff -U0` would produce. + Make sure you include the first 2 lines with the file paths. + Don't include timestamps with the file paths. + Start each hunk of changes with a `@@ ... @@` line. + Don't include line numbers like `diff -U0` does. + The user's patch tool doesn't need them. + The user's patch tool needs CORRECT patches that apply cleanly against the current contents of the file! + Think carefully and make sure you include and mark all lines that need to be removed or changed as `-` lines. + Make sure you mark all new or modified lines with `+`. + Don't leave out any lines or the diff patch won't apply correctly. + Indentation matters in the diffs! + Start a new hunk for each section of the file that needs changes. + Only output hunks that specify changes with `+` or `-` lines. + Skip any hunks that are entirely unchanging ` ` lines. + Output hunks in whatever order makes the most sense. + Hunks don't need to be in any particular order. + When editing a function, method, loop, etc use a hunk to replace the *entire* code block. + Delete the entire existing version with `-` lines and then add a new, updated version with `+` lines. + This will help you generate correct code and correct diffs. + To move code within a file, use 2 hunks: 1 to delete it from its current location, 1 to insert it in the new location. + To make a new file, show a diff from `--- /dev/null` to `+++ path/to/new/file.ext`. + {final_reminders} + +shell_cmd_prompt: | + You can run shell commands with: + ```bash + + ``` + Put shell commands inside a ```bash code block. + +no_shell_cmd_prompt: | + You can run shell commands with: + ```bash + + ``` + Put shell commands inside a ```bash code block. + +shell_cmd_reminder: | + You can run shell commands with: + ```bash + + ``` + Put shell commands inside a ```bash code block. diff --git a/aider/prompts/udiff_simple.yml b/aider/prompts/udiff_simple.yml new file mode 100644 index 00000000000..f7eef9be1c8 --- /dev/null +++ b/aider/prompts/udiff_simple.yml @@ -0,0 +1,12 @@ +# Udiff_Simple prompts - inherits from base.yaml +# Overrides specific prompts + +system_reminder: | + # File editing rules: + Return edits similar to unified diffs that `diff -U0` would produce. + The user's patch tool needs CORRECT patches that apply cleanly against the current contents of the file! + Think carefully and make sure you include and mark all lines that need to be removed or changed as `-` lines. + Make sure you mark all new or modified lines with `+`. + Don't leave out any lines or the diff patch won't apply correctly. + To make a new file, show a diff from `--- /dev/null` to `+++ path/to/new/file.ext`. + {final_reminders} diff --git a/aider/prompts/utils/__init__.py b/aider/prompts/utils/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/aider/prompts/utils/prompt_registry.py b/aider/prompts/utils/prompt_registry.py new file mode 100644 index 00000000000..75173b1b9d9 --- /dev/null +++ b/aider/prompts/utils/prompt_registry.py @@ -0,0 +1,106 @@ +""" +Central registry for managing all prompts in YAML format. + +This module implements a YAML-based prompt inheritance system where: +1. base.yml contains default prompts +2. Specific YAML files can override/extend base.yml +3. No Python prompt classes needed +""" + +from pathlib import Path +from typing import Any, Dict, Optional + +import yaml + + +class PromptRegistry: + """Central registry for loading and managing prompts from YAML files.""" + + _instance = None + _prompts_cache: Dict[str, Dict[str, Any]] = {} + _base_prompts: Optional[Dict[str, Any]] = None + + def __new__(cls): + if cls._instance is None: + cls._instance = super(PromptRegistry, cls).__new__(cls) + return cls._instance + + def __init__(self): + if not hasattr(self, "_initialized"): + self._prompts_dir = Path(__file__).parent / "../../prompts" + self._initialized = True + + def _load_yaml_file(self, file_path: Path) -> Dict[str, Any]: + """Load a YAML file and return its contents.""" + try: + with open(file_path, "r", encoding="utf-8") as f: + return yaml.safe_load(f) or {} + except FileNotFoundError: + return {} + except yaml.YAMLError as e: + raise ValueError(f"Error parsing YAML file {file_path}: {e}") + + def _get_base_prompts(self) -> Dict[str, Any]: + """Load and cache base.yml prompts.""" + if self._base_prompts is None: + base_path = self._prompts_dir / "base.yml" + self._base_prompts = self._load_yaml_file(base_path) + return self._base_prompts + + def _merge_prompts(self, base: Dict[str, Any], override: Dict[str, Any]) -> Dict[str, Any]: + """Recursively merge override dict into base dict.""" + result = base.copy() + + for key, value in override.items(): + if key in result and isinstance(result[key], dict) and isinstance(value, dict): + result[key] = self._merge_prompts(result[key], value) + else: + result[key] = value + + return result + + def get_prompt(self, prompt_name: str) -> Dict[str, Any]: + """ + Get prompts for a specific prompt type. + + Args: + prompt_name: Name of the prompt type (e.g., "agent", "editblock", "wholefile") + + Returns: + Dictionary containing all prompt attributes for the specified type + """ + # Check cache first + if prompt_name in self._prompts_cache: + return self._prompts_cache[prompt_name] + + # Load base prompts + base_prompts = self._get_base_prompts() + + # Load specific prompt file if it exists + prompt_path = self._prompts_dir / f"{prompt_name}.yml" + specific_prompts = self._load_yaml_file(prompt_path) + + # Merge base with specific overrides + merged_prompts = self._merge_prompts(base_prompts, specific_prompts) + + # Cache the result + self._prompts_cache[prompt_name] = merged_prompts + + return merged_prompts + + def reload_prompts(self): + """Clear cache and reload all prompts from disk.""" + self._prompts_cache.clear() + self._base_prompts = None + + def list_available_prompts(self) -> list[str]: + """List all available prompt types.""" + prompts = [] + for file_path in self._prompts_dir.glob("*.yml"): + if file_path.name != "base.yml": + prompts.append(file_path.stem) + return sorted(prompts) + + +# Global instance for easy access +registry = PromptRegistry() diff --git a/aider/prompts.py b/aider/prompts/utils/system.py similarity index 100% rename from aider/prompts.py rename to aider/prompts/utils/system.py diff --git a/aider/prompts/wholefile.yml b/aider/prompts/wholefile.yml new file mode 100644 index 00000000000..718ade72d13 --- /dev/null +++ b/aider/prompts/wholefile.yml @@ -0,0 +1,49 @@ +# WholeFile prompts - inherits from base.yaml +# Overrides specific prompts for wholefile format + +main_system: | + Act as an expert software developer. + Think step-by-step. Plan your changes carefully. Explain your plan first. + Take requests for changes to the supplied code. + If the request is ambiguous, ask questions. + {final_reminders} + Once you understand the request and have a plan, you MUST: + 1. Determine if any code changes are needed. + 2. Explain the plan and any needed changes. + 3. If changes are needed, output a copy of each file that needs changes, containing the complete, updated content. +example_messages: + - role: user + content: Change the greeting to be more casual + - role: assistant + content: | + Ok, I will: + 1. Switch the greeting text from "Hello" to "Hey". + show_greeting.py + {fence[0]} + import sys + def greeting(name): + print(f"Hey {{name}}") + if __name__ == '__main__': + greeting(sys.argv[1]) + {fence[1]} + +system_reminder: | + To suggest changes to a file you MUST return the entire content of the updated file. + You MUST use this *file listing* format: + path/to/filename.js + {fence[0]} + // entire file content ... + // ... goes in between + {fence[1]} + Every *file listing* MUST use this format: + - First line: the filename with any originally provided path; no extra markup, punctuation, comments, etc. **JUST** the filename with path. + - Second line: opening {fence[0]} + - ... entire content of the file ... + - Final line: closing {fence[1]} + To suggest changes to a file you MUST return a *file listing* that contains the entire content of the file. + *NEVER* skip, omit or elide content from a *file listing* using "..." or by adding comments like "... rest of code..."! + Create a new file you MUST return a *file listing* which includes an appropriate filename, including any appropriate path. + {final_reminders} + +redacted_edit_message: | + No changes are needed. diff --git a/aider/prompts/wholefile_func.yml b/aider/prompts/wholefile_func.yml new file mode 100644 index 00000000000..743e3f99ed6 --- /dev/null +++ b/aider/prompts/wholefile_func.yml @@ -0,0 +1,23 @@ +# Wholefile_Func prompts - inherits from base.yaml +# Overrides specific prompts + +files_content_prefix: | + Here is the current content of the files: + +files_no_full_files: | + I am not sharing any files yet. + +main_system: | + Act as an expert software developer. + Take requests for changes to the supplied code. + If the request is ambiguous, ask questions. + Once you understand the request you MUST use the `write_file` function to edit the files to make the needed changes. + +redacted_edit_message: | + No changes are needed. + +repo_content_prefix: null + +system_reminder: | + ONLY return code using the `write_file` function. + NEVER return code outside the `write_file` function. diff --git a/aider/repo.py b/aider/repo.py index 8feaf18914c..e319787562a 100644 --- a/aider/repo.py +++ b/aider/repo.py @@ -18,7 +18,8 @@ import pathspec -from aider import prompts, utils +import aider.prompts.utils.system as prompts +from aider import utils from .dump import dump # noqa: F401 diff --git a/aider/tui/app.py b/aider/tui/app.py index 6f659587846..2d1c50a38d0 100644 --- a/aider/tui/app.py +++ b/aider/tui/app.py @@ -269,14 +269,23 @@ def compose(self) -> ComposeResult: id="footer", ) + BANNER_COLORS = [ + "spring_green2", + "spring_green1", + "medium_spring_green", + "cyan2", + "cyan1", + "bright_white", + ] + # ASCII banner for startup - BANNER = """ -[bold spring_green2] ██████╗███████╗ ██████╗██╗ ██╗[/bold spring_green2] -[bold spring_green1] ██╔════╝██╔════╝██╔════╝██║ ██║[/bold spring_green1] -[bold medium_spring_green] ██║ █████╗ ██║ ██║ ██║[/bold medium_spring_green] -[bold cyan2] ██║ ██╔══╝ ██║ ██║ ██║[/bold cyan2] -[bold cyan1] ╚██████╗███████╗╚██████╗███████╗██║[/bold cyan1] -[bold bright_white] ╚═════╝╚══════╝ ╚═════╝╚══════╝╚═╝[/bold bright_white] + BANNER = f""" +[bold {BANNER_COLORS[0]}] ██████╗███████╗ ██████╗██╗ ██╗[/bold {BANNER_COLORS[0]}] +[bold {BANNER_COLORS[1]}] ██╔════╝██╔════╝██╔════╝██║ ██║[/bold {BANNER_COLORS[1]}] +[bold {BANNER_COLORS[2]}] ██║ █████╗ ██║ ██║ ██║[/bold {BANNER_COLORS[2]}] +[bold {BANNER_COLORS[3]}] ██║ ██╔══╝ ██║ ██║ ██║[/bold {BANNER_COLORS[3]}] +[bold {BANNER_COLORS[4]}] ╚██████╗███████╗╚██████╗███████╗██║[/bold {BANNER_COLORS[4]}] +[bold {BANNER_COLORS[5]}] ╚═════╝╚══════╝ ╚═════╝╚══════╝╚═╝[/bold {BANNER_COLORS[5]}] """ diff --git a/aider/tui/styles.tcss b/aider/tui/styles.tcss index 82d2399e471..4a0fa89f912 100644 --- a/aider/tui/styles.tcss +++ b/aider/tui/styles.tcss @@ -75,6 +75,11 @@ Input > .input--placeholder, TextArea > .text-area--placeholder { background: $surface; } +TextArea > .text-area--selection { + color: $background; + background: $foreground; +} + /* File List below input */ #file-list { padding: 0 0 0 0; diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py index f8ba9e11e79..8bc8bdfca8f 100755 --- a/benchmark/benchmark.py +++ b/benchmark/benchmark.py @@ -837,8 +837,8 @@ async def run_test_real( ): # Lazy imports: only needed in the actual benchmark execution path import git - import prompts + import aider.prompts.utils.system as prompts from aider import models from aider.coders import Coder from aider.io import InputOutput diff --git a/benchmark/benchmark_classic.py b/benchmark/benchmark_classic.py index 02117242742..da013589884 100755 --- a/benchmark/benchmark_classic.py +++ b/benchmark/benchmark_classic.py @@ -869,8 +869,8 @@ def run_test_real( ): # Lazy imports: only needed in the actual benchmark execution path import git - import prompts + import aider.prompts.utils.system as prompts from aider import models from aider.coders import Coder from aider.io import InputOutput diff --git a/requirements.txt b/requirements.txt index e727e668c4d..187e4ad233a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -152,12 +152,13 @@ grep-ast==0.9.0 # via # -c requirements/common-constraints.txt # -r requirements/requirements.in -grpcio==1.76.0 +grpcio==1.67.1 # via # -c requirements/common-constraints.txt # google-api-core # grpcio-status -grpcio-status==1.71.2 + # litellm +grpcio-status==1.67.1 # via # -c requirements/common-constraints.txt # google-api-core @@ -235,7 +236,7 @@ linkify-it-py==2.0.3 # via # -c requirements/common-constraints.txt # markdown-it-py -litellm==1.80.5 +litellm==1.80.11 # via # -c requirements/common-constraints.txt # -r requirements/requirements.in @@ -540,7 +541,6 @@ typing-extensions==4.15.0 # anyio # beautifulsoup4 # google-generativeai - # grpcio # huggingface-hub # mcp # openai diff --git a/requirements/common-constraints.txt b/requirements/common-constraints.txt index 0c5657a8a4a..a4c04c8caf5 100644 --- a/requirements/common-constraints.txt +++ b/requirements/common-constraints.txt @@ -159,11 +159,12 @@ grep-ast==0.9.0 # via -r requirements/requirements.in griffe==1.15.0 # via banks -grpcio==1.76.0 +grpcio==1.67.1 # via # google-api-core # grpcio-status -grpcio-status==1.71.2 + # litellm +grpcio-status==1.67.1 # via google-api-core h11==0.16.0 # via @@ -233,7 +234,7 @@ kiwisolver==1.4.9 # via matplotlib linkify-it-py==2.0.3 # via markdown-it-py -litellm==1.80.5 +litellm==1.80.11 # via -r requirements/requirements.in llama-index-core==0.14.8 # via llama-index-embeddings-huggingface @@ -608,7 +609,6 @@ typing-extensions==4.15.0 # anyio # beautifulsoup4 # google-generativeai - # grpcio # huggingface-hub # llama-index-core # llama-index-workflows diff --git a/requirements/requirements-dev.txt b/requirements/requirements-dev.txt index cedd67fab61..2c21ad40b50 100644 --- a/requirements/requirements-dev.txt +++ b/requirements/requirements-dev.txt @@ -85,12 +85,12 @@ googleapis-common-protos==1.72.0 # -c requirements/common-constraints.txt # google-api-core # grpcio-status -grpcio==1.76.0 +grpcio==1.67.1 # via # -c requirements/common-constraints.txt # google-api-core # grpcio-status -grpcio-status==1.71.2 +grpcio-status==1.67.1 # via # -c requirements/common-constraints.txt # google-api-core @@ -273,7 +273,6 @@ typer==0.20.0 typing-extensions==4.15.0 # via # -c requirements/common-constraints.txt - # grpcio # pytest-asyncio # typer tzdata==2025.2 diff --git a/requirements/requirements.in b/requirements/requirements.in index 9dd02eb0265..306eda36193 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -15,7 +15,7 @@ beautifulsoup4>=4.13.4 PyYAML>=6.0.2 diff-match-patch>=20241021 pypandoc>=1.15 -litellm>=1.80.0 +litellm>=1.80.11 flake8>=7.3.0 importlib_resources pyperclip>=1.9.0