diff --git a/src/codegen/extensions/langchain/tools.py b/src/codegen/extensions/langchain/tools.py index 2ab5b0179..0ce6b97a1 100644 --- a/src/codegen/extensions/langchain/tools.py +++ b/src/codegen/extensions/langchain/tools.py @@ -119,7 +119,6 @@ class SearchInput(BaseModel): description="""The search query to find in the codebase. When ripgrep is available, this will be passed as a ripgrep pattern. For regex searches, set use_regex=True. Ripgrep is the preferred method.""", ) - target_directories: Optional[list[str]] = Field(default=None, description="Optional list of directories to search in") file_extensions: Optional[list[str]] = Field(default=None, description="Optional list of file extensions to search (e.g. ['.py', '.ts'])") page: int = Field(default=1, description="Page number to return (1-based, default: 1)") files_per_page: int = Field(default=10, description="Number of files to return per page (default: 10)") @@ -138,7 +137,7 @@ def __init__(self, codebase: Codebase) -> None: super().__init__(codebase=codebase) def _run(self, query: str, target_directories: Optional[list[str]] = None, file_extensions: Optional[list[str]] = None, page: int = 1, files_per_page: int = 10, use_regex: bool = False) -> str: - result = search(self.codebase, query, target_directories=target_directories, file_extensions=file_extensions, page=page, files_per_page=files_per_page, use_regex=use_regex) + result = search(self.codebase, query, file_extensions=file_extensions, page=page, files_per_page=files_per_page, use_regex=use_regex) return result.render() diff --git a/src/codegen/extensions/tools/relace_edit_prompts.py b/src/codegen/extensions/tools/relace_edit_prompts.py index 7ef357463..2c189d5c8 100644 --- a/src/codegen/extensions/tools/relace_edit_prompts.py +++ b/src/codegen/extensions/tools/relace_edit_prompts.py @@ -2,19 +2,31 @@ RELACE_EDIT_PROMPT = """Edit a file using the Relace Instant Apply API. +⚠️ IMPORTANT: The 'edit_snippet' parameter must be provided as a direct string, NOT as a dictionary or JSON object. +For example, use: edit_snippet="// ... code here ..." NOT edit_snippet={"code": "// ... code here ..."} +DO NOT pass the edit_snippet as a dictionary or JSON object or dictionary with a 'code' key . + The Relace Instant Apply API is a high-speed code generation engine optimized for real-time performance at 2000 tokens/second. It splits code generation into two specialized steps: 1. Hard Reasoning: Uses SOTA models like Claude for complex code understanding 2. Fast Integration: Rapidly merges edits into existing code -To use this tool, provide: -1. The path to the file you want to edit -2. An edit snippet that describes the changes you want to make +To use this tool effectively, provide: +1. The path to the file you want to edit (filepath) +2. An edit snippet that describes the changes you want to make (edit_snippet) -The edit snippet should: +The edit snippet is crucial for successful merging and should follow these guidelines: - Include complete code blocks that will appear in the final output -- Clearly indicate which parts of the code remain unchanged with comments like "// ... rest of code ..." -- Maintain correct indentation and code structure +- Clearly indicate which parts of the code remain unchanged with descriptive comments like: + * "// ... keep existing imports ..." + * "// ... rest of the class definition ..." + * "// ... existing function implementations ..." +- Maintain correct indentation and code structure exactly as it should appear in the final code +- Use comments to indicate the purpose of your changes (e.g., "// Add new function") +- For removing sections, provide sufficient context so it's clear what should be removed +- Focus only on the modifications, not other aspects of the code +- Preserve language-specific syntax (comment style may vary by language) +- Include more context than just the minimal changes - surrounding code helps the API understand where and how to apply the edit Example edit snippet: ``` @@ -28,7 +40,33 @@ // ... keep existing code ... ``` +Another example (Python): +``` +# ... existing imports ... + +# Add new helper function +def validate_input(data): + '''Validates the input data structure.''' + if not isinstance(data, dict): + raise TypeError("Input must be a dictionary") + if "id" not in data: + raise ValueError("Input must contain an 'id' field") + return True + +# ... rest of the file ... +``` + The API will merge your edit snippet with the existing code to produce the final result. +The API key will be automatically retrieved from the RELACE_API environment variable. + +Common pitfalls to avoid: +- Not providing enough context around changes +- Providing too little surrounding code (include more than just the changed lines) +- Incorrect indentation in the edit snippet +- Forgetting to indicate unchanged sections with comments +- Using inconsistent comment styles +- Being too vague about where changes should be applied +- Passing the edit_snippet as a dictionary or JSON object instead of a direct string """ RELACE_EDIT_SYSTEM_PROMPT = """You are an expert at creating edit snippets for the Relace Instant Apply API. diff --git a/src/codegen/extensions/tools/search.py b/src/codegen/extensions/tools/search.py index 08a52c48b..47df419c7 100644 --- a/src/codegen/extensions/tools/search.py +++ b/src/codegen/extensions/tools/search.py @@ -114,7 +114,6 @@ def render(self) -> str: def _search_with_ripgrep( codebase: Codebase, query: str, - target_directories: Optional[list[str]] = None, file_extensions: Optional[list[str]] = None, page: int = 1, files_per_page: int = 10, @@ -141,9 +140,6 @@ def _search_with_ripgrep( # Add target directories if specified search_path = codebase.repo_path - if target_directories: - # We'll handle target directories by filtering results later - pass # Add the query and path cmd.append(f"{query}") @@ -189,10 +185,6 @@ def _search_with_ripgrep( # Convert to relative path within the codebase rel_path = os.path.relpath(filepath, codebase.repo_path) - # Skip if not in target directories - if target_directories and not any(rel_path.startswith(d) for d in target_directories): - continue - try: line_number = int(line_number_str) @@ -264,7 +256,6 @@ def _search_with_ripgrep( def _search_with_python( codebase: Codebase, query: str, - target_directories: Optional[list[str]] = None, file_extensions: Optional[list[str]] = None, page: int = 1, files_per_page: int = 10, @@ -304,10 +295,6 @@ def _search_with_python( all_results = [] for file in codebase.files(extensions=extensions): - # Skip if file doesn't match target directories - if target_directories and not any(file.filepath.startswith(d) for d in target_directories): - continue - # Skip binary files try: content = file.content @@ -366,7 +353,6 @@ def _search_with_python( def search( codebase: Codebase, query: str, - target_directories: Optional[list[str]] = None, file_extensions: Optional[list[str]] = None, page: int = 1, files_per_page: int = 10, @@ -383,7 +369,6 @@ def search( Args: codebase: The codebase to operate on query: The text to search for or regex pattern to match - target_directories: Optional list of directories to search in file_extensions: Optional list of file extensions to search (e.g. ['.py', '.ts']). If None, searches all files ('*') page: Page number to return (1-based, default: 1) @@ -395,7 +380,7 @@ def search( """ # Try to use ripgrep first try: - return _search_with_ripgrep(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) + return _search_with_ripgrep(codebase, query, file_extensions, page, files_per_page, use_regex) except (FileNotFoundError, subprocess.SubprocessError): # Fall back to Python implementation if ripgrep fails or isn't available - return _search_with_python(codebase, query, target_directories, file_extensions, page, files_per_page, use_regex) + return _search_with_python(codebase, query, file_extensions, page, files_per_page, use_regex)