aider-ce 0.88.20__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aider/__init__.py +20 -0
- aider/__main__.py +4 -0
- aider/_version.py +34 -0
- aider/analytics.py +258 -0
- aider/args.py +1056 -0
- aider/args_formatter.py +228 -0
- aider/change_tracker.py +133 -0
- aider/coders/__init__.py +36 -0
- aider/coders/agent_coder.py +2166 -0
- aider/coders/agent_prompts.py +104 -0
- aider/coders/architect_coder.py +48 -0
- aider/coders/architect_prompts.py +40 -0
- aider/coders/ask_coder.py +9 -0
- aider/coders/ask_prompts.py +35 -0
- aider/coders/base_coder.py +3613 -0
- aider/coders/base_prompts.py +87 -0
- aider/coders/chat_chunks.py +64 -0
- aider/coders/context_coder.py +53 -0
- aider/coders/context_prompts.py +75 -0
- aider/coders/editblock_coder.py +657 -0
- aider/coders/editblock_fenced_coder.py +10 -0
- aider/coders/editblock_fenced_prompts.py +143 -0
- aider/coders/editblock_func_coder.py +141 -0
- aider/coders/editblock_func_prompts.py +27 -0
- aider/coders/editblock_prompts.py +175 -0
- aider/coders/editor_diff_fenced_coder.py +9 -0
- aider/coders/editor_diff_fenced_prompts.py +11 -0
- aider/coders/editor_editblock_coder.py +9 -0
- aider/coders/editor_editblock_prompts.py +21 -0
- aider/coders/editor_whole_coder.py +9 -0
- aider/coders/editor_whole_prompts.py +12 -0
- aider/coders/help_coder.py +16 -0
- aider/coders/help_prompts.py +46 -0
- aider/coders/patch_coder.py +706 -0
- aider/coders/patch_prompts.py +159 -0
- aider/coders/search_replace.py +757 -0
- aider/coders/shell.py +37 -0
- aider/coders/single_wholefile_func_coder.py +102 -0
- aider/coders/single_wholefile_func_prompts.py +27 -0
- aider/coders/udiff_coder.py +429 -0
- aider/coders/udiff_prompts.py +115 -0
- aider/coders/udiff_simple.py +14 -0
- aider/coders/udiff_simple_prompts.py +25 -0
- aider/coders/wholefile_coder.py +144 -0
- aider/coders/wholefile_func_coder.py +134 -0
- aider/coders/wholefile_func_prompts.py +27 -0
- aider/coders/wholefile_prompts.py +65 -0
- aider/commands.py +2173 -0
- aider/copypaste.py +72 -0
- aider/deprecated.py +126 -0
- aider/diffs.py +128 -0
- aider/dump.py +29 -0
- aider/editor.py +147 -0
- aider/exceptions.py +115 -0
- aider/format_settings.py +26 -0
- aider/gui.py +545 -0
- aider/help.py +163 -0
- aider/help_pats.py +19 -0
- aider/helpers/__init__.py +9 -0
- aider/helpers/similarity.py +98 -0
- aider/history.py +180 -0
- aider/io.py +1608 -0
- aider/linter.py +304 -0
- aider/llm.py +55 -0
- aider/main.py +1415 -0
- aider/mcp/__init__.py +174 -0
- aider/mcp/server.py +149 -0
- aider/mdstream.py +243 -0
- aider/models.py +1313 -0
- aider/onboarding.py +429 -0
- aider/openrouter.py +129 -0
- aider/prompts.py +56 -0
- aider/queries/tree-sitter-language-pack/README.md +7 -0
- aider/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/c-tags.scm +9 -0
- aider/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
- aider/queries/tree-sitter-language-pack/clojure-tags.scm +7 -0
- aider/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
- aider/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
- aider/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
- aider/queries/tree-sitter-language-pack/d-tags.scm +26 -0
- aider/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
- aider/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
- aider/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
- aider/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
- aider/queries/tree-sitter-language-pack/go-tags.scm +42 -0
- aider/queries/tree-sitter-language-pack/java-tags.scm +20 -0
- aider/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
- aider/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
- aider/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
- aider/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
- aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
- aider/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
- aider/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/python-tags.scm +14 -0
- aider/queries/tree-sitter-language-pack/r-tags.scm +21 -0
- aider/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
- aider/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
- aider/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
- aider/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
- aider/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
- aider/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
- aider/queries/tree-sitter-languages/README.md +24 -0
- aider/queries/tree-sitter-languages/c-tags.scm +9 -0
- aider/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
- aider/queries/tree-sitter-languages/cpp-tags.scm +15 -0
- aider/queries/tree-sitter-languages/dart-tags.scm +91 -0
- aider/queries/tree-sitter-languages/elisp-tags.scm +8 -0
- aider/queries/tree-sitter-languages/elixir-tags.scm +54 -0
- aider/queries/tree-sitter-languages/elm-tags.scm +19 -0
- aider/queries/tree-sitter-languages/fortran-tags.scm +15 -0
- aider/queries/tree-sitter-languages/go-tags.scm +30 -0
- aider/queries/tree-sitter-languages/haskell-tags.scm +3 -0
- aider/queries/tree-sitter-languages/hcl-tags.scm +77 -0
- aider/queries/tree-sitter-languages/java-tags.scm +20 -0
- aider/queries/tree-sitter-languages/javascript-tags.scm +88 -0
- aider/queries/tree-sitter-languages/julia-tags.scm +60 -0
- aider/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
- aider/queries/tree-sitter-languages/matlab-tags.scm +10 -0
- aider/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
- aider/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
- aider/queries/tree-sitter-languages/php-tags.scm +26 -0
- aider/queries/tree-sitter-languages/python-tags.scm +12 -0
- aider/queries/tree-sitter-languages/ql-tags.scm +26 -0
- aider/queries/tree-sitter-languages/ruby-tags.scm +64 -0
- aider/queries/tree-sitter-languages/rust-tags.scm +60 -0
- aider/queries/tree-sitter-languages/scala-tags.scm +65 -0
- aider/queries/tree-sitter-languages/typescript-tags.scm +41 -0
- aider/queries/tree-sitter-languages/zig-tags.scm +3 -0
- aider/reasoning_tags.py +82 -0
- aider/repo.py +621 -0
- aider/repomap.py +1174 -0
- aider/report.py +260 -0
- aider/resources/__init__.py +3 -0
- aider/resources/model-metadata.json +776 -0
- aider/resources/model-settings.yml +2068 -0
- aider/run_cmd.py +133 -0
- aider/scrape.py +293 -0
- aider/sendchat.py +242 -0
- aider/sessions.py +256 -0
- aider/special.py +203 -0
- aider/tools/__init__.py +72 -0
- aider/tools/command.py +105 -0
- aider/tools/command_interactive.py +122 -0
- aider/tools/delete_block.py +182 -0
- aider/tools/delete_line.py +155 -0
- aider/tools/delete_lines.py +184 -0
- aider/tools/extract_lines.py +341 -0
- aider/tools/finished.py +48 -0
- aider/tools/git_branch.py +129 -0
- aider/tools/git_diff.py +60 -0
- aider/tools/git_log.py +57 -0
- aider/tools/git_remote.py +53 -0
- aider/tools/git_show.py +51 -0
- aider/tools/git_status.py +46 -0
- aider/tools/grep.py +256 -0
- aider/tools/indent_lines.py +221 -0
- aider/tools/insert_block.py +288 -0
- aider/tools/list_changes.py +86 -0
- aider/tools/ls.py +93 -0
- aider/tools/make_editable.py +85 -0
- aider/tools/make_readonly.py +69 -0
- aider/tools/remove.py +91 -0
- aider/tools/replace_all.py +126 -0
- aider/tools/replace_line.py +173 -0
- aider/tools/replace_lines.py +217 -0
- aider/tools/replace_text.py +187 -0
- aider/tools/show_numbered_context.py +147 -0
- aider/tools/tool_utils.py +313 -0
- aider/tools/undo_change.py +95 -0
- aider/tools/update_todo_list.py +156 -0
- aider/tools/view.py +57 -0
- aider/tools/view_files_matching.py +141 -0
- aider/tools/view_files_with_symbol.py +129 -0
- aider/urls.py +17 -0
- aider/utils.py +456 -0
- aider/versioncheck.py +113 -0
- aider/voice.py +205 -0
- aider/waiting.py +38 -0
- aider/watch.py +318 -0
- aider/watch_prompts.py +12 -0
- aider/website/Gemfile +8 -0
- aider/website/_includes/blame.md +162 -0
- aider/website/_includes/get-started.md +22 -0
- aider/website/_includes/help-tip.md +5 -0
- aider/website/_includes/help.md +24 -0
- aider/website/_includes/install.md +5 -0
- aider/website/_includes/keys.md +4 -0
- aider/website/_includes/model-warnings.md +67 -0
- aider/website/_includes/multi-line.md +22 -0
- aider/website/_includes/python-m-aider.md +5 -0
- aider/website/_includes/recording.css +228 -0
- aider/website/_includes/recording.md +34 -0
- aider/website/_includes/replit-pipx.md +9 -0
- aider/website/_includes/works-best.md +1 -0
- aider/website/_sass/custom/custom.scss +103 -0
- aider/website/docs/config/adv-model-settings.md +2261 -0
- aider/website/docs/config/agent-mode.md +194 -0
- aider/website/docs/config/aider_conf.md +548 -0
- aider/website/docs/config/api-keys.md +90 -0
- aider/website/docs/config/dotenv.md +493 -0
- aider/website/docs/config/editor.md +127 -0
- aider/website/docs/config/mcp.md +95 -0
- aider/website/docs/config/model-aliases.md +104 -0
- aider/website/docs/config/options.md +890 -0
- aider/website/docs/config/reasoning.md +210 -0
- aider/website/docs/config.md +44 -0
- aider/website/docs/faq.md +384 -0
- aider/website/docs/git.md +76 -0
- aider/website/docs/index.md +47 -0
- aider/website/docs/install/codespaces.md +39 -0
- aider/website/docs/install/docker.md +57 -0
- aider/website/docs/install/optional.md +100 -0
- aider/website/docs/install/replit.md +8 -0
- aider/website/docs/install.md +115 -0
- aider/website/docs/languages.md +264 -0
- aider/website/docs/legal/contributor-agreement.md +111 -0
- aider/website/docs/legal/privacy.md +104 -0
- aider/website/docs/llms/anthropic.md +77 -0
- aider/website/docs/llms/azure.md +48 -0
- aider/website/docs/llms/bedrock.md +132 -0
- aider/website/docs/llms/cohere.md +34 -0
- aider/website/docs/llms/deepseek.md +32 -0
- aider/website/docs/llms/gemini.md +49 -0
- aider/website/docs/llms/github.md +111 -0
- aider/website/docs/llms/groq.md +36 -0
- aider/website/docs/llms/lm-studio.md +39 -0
- aider/website/docs/llms/ollama.md +75 -0
- aider/website/docs/llms/openai-compat.md +39 -0
- aider/website/docs/llms/openai.md +58 -0
- aider/website/docs/llms/openrouter.md +78 -0
- aider/website/docs/llms/other.md +117 -0
- aider/website/docs/llms/vertex.md +50 -0
- aider/website/docs/llms/warnings.md +10 -0
- aider/website/docs/llms/xai.md +53 -0
- aider/website/docs/llms.md +54 -0
- aider/website/docs/more/analytics.md +127 -0
- aider/website/docs/more/edit-formats.md +116 -0
- aider/website/docs/more/infinite-output.md +165 -0
- aider/website/docs/more-info.md +8 -0
- aider/website/docs/recordings/auto-accept-architect.md +31 -0
- aider/website/docs/recordings/dont-drop-original-read-files.md +35 -0
- aider/website/docs/recordings/index.md +21 -0
- aider/website/docs/recordings/model-accepts-settings.md +69 -0
- aider/website/docs/recordings/tree-sitter-language-pack.md +80 -0
- aider/website/docs/repomap.md +112 -0
- aider/website/docs/scripting.md +100 -0
- aider/website/docs/sessions.md +203 -0
- aider/website/docs/troubleshooting/aider-not-found.md +24 -0
- aider/website/docs/troubleshooting/edit-errors.md +76 -0
- aider/website/docs/troubleshooting/imports.md +62 -0
- aider/website/docs/troubleshooting/models-and-keys.md +54 -0
- aider/website/docs/troubleshooting/support.md +79 -0
- aider/website/docs/troubleshooting/token-limits.md +96 -0
- aider/website/docs/troubleshooting/warnings.md +12 -0
- aider/website/docs/troubleshooting.md +11 -0
- aider/website/docs/usage/browser.md +57 -0
- aider/website/docs/usage/caching.md +49 -0
- aider/website/docs/usage/commands.md +133 -0
- aider/website/docs/usage/conventions.md +119 -0
- aider/website/docs/usage/copypaste.md +121 -0
- aider/website/docs/usage/images-urls.md +48 -0
- aider/website/docs/usage/lint-test.md +118 -0
- aider/website/docs/usage/modes.md +211 -0
- aider/website/docs/usage/not-code.md +179 -0
- aider/website/docs/usage/notifications.md +87 -0
- aider/website/docs/usage/tips.md +79 -0
- aider/website/docs/usage/tutorials.md +30 -0
- aider/website/docs/usage/voice.md +121 -0
- aider/website/docs/usage/watch.md +294 -0
- aider/website/docs/usage.md +102 -0
- aider/website/share/index.md +101 -0
- aider_ce-0.88.20.dist-info/METADATA +187 -0
- aider_ce-0.88.20.dist-info/RECORD +279 -0
- aider_ce-0.88.20.dist-info/WHEEL +5 -0
- aider_ce-0.88.20.dist-info/entry_points.txt +2 -0
- aider_ce-0.88.20.dist-info/licenses/LICENSE.txt +202 -0
- aider_ce-0.88.20.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
|
|
3
|
+
schema = {
|
|
4
|
+
"type": "function",
|
|
5
|
+
"function": {
|
|
6
|
+
"name": "UndoChange",
|
|
7
|
+
"description": "Undo a previously applied change.",
|
|
8
|
+
"parameters": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"change_id": {"type": "string"},
|
|
12
|
+
"file_path": {"type": "string"},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
# Normalized tool name for lookup
|
|
19
|
+
NORM_NAME = "undochange"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _execute_undo_change(coder, change_id=None, file_path=None):
|
|
23
|
+
"""
|
|
24
|
+
Undo a specific change by ID, or the last change to a file.
|
|
25
|
+
|
|
26
|
+
Parameters:
|
|
27
|
+
- coder: The Coder instance
|
|
28
|
+
- change_id: ID of the change to undo
|
|
29
|
+
- file_path: Path to file where the last change should be undone
|
|
30
|
+
|
|
31
|
+
Returns a result message.
|
|
32
|
+
"""
|
|
33
|
+
# Note: Undo does not have a dry_run parameter as it's inherently about reverting a previous action.
|
|
34
|
+
try:
|
|
35
|
+
# Validate parameters
|
|
36
|
+
if change_id is None and file_path is None:
|
|
37
|
+
coder.io.tool_error("Must specify either change_id or file_path for UndoChange")
|
|
38
|
+
return "Error: Must specify either change_id or file_path"
|
|
39
|
+
|
|
40
|
+
# If file_path is specified, get the most recent change for that file
|
|
41
|
+
if file_path:
|
|
42
|
+
abs_path = coder.abs_root_path(file_path)
|
|
43
|
+
rel_path = coder.get_rel_fname(abs_path)
|
|
44
|
+
|
|
45
|
+
change_id = coder.change_tracker.get_last_change(rel_path)
|
|
46
|
+
if not change_id:
|
|
47
|
+
coder.io.tool_error(f"No tracked changes found for file '{file_path}' to undo.")
|
|
48
|
+
return f"Error: No changes found for file '{file_path}'"
|
|
49
|
+
|
|
50
|
+
# Attempt to get undo information from the tracker
|
|
51
|
+
success, message, change_info = coder.change_tracker.undo_change(change_id)
|
|
52
|
+
|
|
53
|
+
if not success:
|
|
54
|
+
coder.io.tool_error(f"Failed to undo change '{change_id}': {message}")
|
|
55
|
+
return f"Error: {message}"
|
|
56
|
+
|
|
57
|
+
# Apply the undo by restoring the original content
|
|
58
|
+
if change_info:
|
|
59
|
+
file_path = change_info["file_path"]
|
|
60
|
+
abs_path = coder.abs_root_path(file_path)
|
|
61
|
+
# Write the original content back to the file
|
|
62
|
+
coder.io.write_text(abs_path, change_info["original"])
|
|
63
|
+
coder.aider_edited_files.add(file_path) # Track that the file was modified by the undo
|
|
64
|
+
|
|
65
|
+
change_type = change_info["type"]
|
|
66
|
+
coder.io.tool_output(f"✅ Undid {change_type} change '{change_id}' in {file_path}")
|
|
67
|
+
return f"Successfully undid {change_type} change '{change_id}'."
|
|
68
|
+
else:
|
|
69
|
+
# This case should ideally not be reached if tracker returns success
|
|
70
|
+
coder.io.tool_error(
|
|
71
|
+
f"Failed to undo change '{change_id}': Change info missing after successful tracker"
|
|
72
|
+
" update."
|
|
73
|
+
)
|
|
74
|
+
return f"Error: Failed to undo change '{change_id}' (missing change info)"
|
|
75
|
+
|
|
76
|
+
except Exception as e:
|
|
77
|
+
coder.io.tool_error(f"Error in UndoChange: {str(e)}\n{traceback.format_exc()}")
|
|
78
|
+
return f"Error: {str(e)}"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def process_response(coder, params):
|
|
82
|
+
"""
|
|
83
|
+
Process the UndoChange tool response.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
coder: The Coder instance
|
|
87
|
+
params: Dictionary of parameters
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
str: Result message
|
|
91
|
+
"""
|
|
92
|
+
change_id = params.get("change_id")
|
|
93
|
+
file_path = params.get("file_path")
|
|
94
|
+
|
|
95
|
+
return _execute_undo_change(coder, change_id, file_path)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
from .tool_utils import (
|
|
2
|
+
ToolError,
|
|
3
|
+
format_tool_result,
|
|
4
|
+
generate_unified_diff_snippet,
|
|
5
|
+
handle_tool_error,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
schema = {
|
|
9
|
+
"type": "function",
|
|
10
|
+
"function": {
|
|
11
|
+
"name": "UpdateTodoList",
|
|
12
|
+
"description": "Update the todo list with new items or modify existing ones.",
|
|
13
|
+
"parameters": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"content": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The new content for the todo list.",
|
|
19
|
+
},
|
|
20
|
+
"append": {
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"description": (
|
|
23
|
+
"Whether to append to existing content instead of replacing it. Defaults to"
|
|
24
|
+
" False."
|
|
25
|
+
),
|
|
26
|
+
},
|
|
27
|
+
"change_id": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Optional change ID for tracking.",
|
|
30
|
+
},
|
|
31
|
+
"dry_run": {
|
|
32
|
+
"type": "boolean",
|
|
33
|
+
"description": (
|
|
34
|
+
"Whether to perform a dry run without actually updating the file. Defaults"
|
|
35
|
+
" to False."
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
"required": ["content"],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Normalized tool name for lookup
|
|
45
|
+
NORM_NAME = "updatetodolist"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _execute_update_todo_list(coder, content, append=False, change_id=None, dry_run=False):
|
|
49
|
+
"""
|
|
50
|
+
Update the todo list file (.aider.todo.txt) with new content.
|
|
51
|
+
Can either replace the entire content or append to it.
|
|
52
|
+
"""
|
|
53
|
+
tool_name = "UpdateTodoList"
|
|
54
|
+
try:
|
|
55
|
+
# Define the todo file path
|
|
56
|
+
todo_file_path = ".aider.todo.txt"
|
|
57
|
+
abs_path = coder.abs_root_path(todo_file_path)
|
|
58
|
+
|
|
59
|
+
# Get existing content if appending
|
|
60
|
+
existing_content = ""
|
|
61
|
+
import os
|
|
62
|
+
|
|
63
|
+
if os.path.isfile(abs_path):
|
|
64
|
+
existing_content = coder.io.read_text(abs_path) or ""
|
|
65
|
+
|
|
66
|
+
# Prepare new content
|
|
67
|
+
if append:
|
|
68
|
+
if existing_content and not existing_content.endswith("\n"):
|
|
69
|
+
existing_content += "\n"
|
|
70
|
+
new_content = existing_content + content
|
|
71
|
+
else:
|
|
72
|
+
new_content = content
|
|
73
|
+
|
|
74
|
+
# Check if content exceeds 4096 characters and warn
|
|
75
|
+
if len(new_content) > 4096:
|
|
76
|
+
coder.io.tool_warning(
|
|
77
|
+
"⚠️ Todo list content exceeds 4096 characters. Consider summarizing the plan before"
|
|
78
|
+
" proceeding."
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Check if content actually changed
|
|
82
|
+
if existing_content == new_content:
|
|
83
|
+
coder.io.tool_warning("No changes made: new content is identical to existing")
|
|
84
|
+
return "Warning: No changes made (content identical to existing)"
|
|
85
|
+
|
|
86
|
+
# Generate diff for feedback
|
|
87
|
+
diff_snippet = generate_unified_diff_snippet(existing_content, new_content, todo_file_path)
|
|
88
|
+
|
|
89
|
+
# Handle dry run
|
|
90
|
+
if dry_run:
|
|
91
|
+
action = "append to" if append else "replace"
|
|
92
|
+
dry_run_message = f"Dry run: Would {action} todo list in {todo_file_path}."
|
|
93
|
+
return format_tool_result(
|
|
94
|
+
coder,
|
|
95
|
+
tool_name,
|
|
96
|
+
"",
|
|
97
|
+
dry_run=True,
|
|
98
|
+
dry_run_message=dry_run_message,
|
|
99
|
+
diff_snippet=diff_snippet,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Apply change
|
|
103
|
+
metadata = {
|
|
104
|
+
"append": append,
|
|
105
|
+
"existing_length": len(existing_content),
|
|
106
|
+
"new_length": len(new_content),
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# Write the file directly since it's a special file
|
|
110
|
+
coder.io.write_text(abs_path, new_content)
|
|
111
|
+
|
|
112
|
+
# Track the change
|
|
113
|
+
final_change_id = coder.change_tracker.track_change(
|
|
114
|
+
file_path=todo_file_path,
|
|
115
|
+
change_type="updatetodolist",
|
|
116
|
+
original_content=existing_content,
|
|
117
|
+
new_content=new_content,
|
|
118
|
+
metadata=metadata,
|
|
119
|
+
change_id=change_id,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
coder.aider_edited_files.add(todo_file_path)
|
|
123
|
+
|
|
124
|
+
# Format and return result
|
|
125
|
+
action = "appended to" if append else "updated"
|
|
126
|
+
success_message = f"Successfully {action} todo list in {todo_file_path}"
|
|
127
|
+
return format_tool_result(
|
|
128
|
+
coder, tool_name, success_message, change_id=final_change_id, diff_snippet=diff_snippet
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
except ToolError as e:
|
|
132
|
+
return handle_tool_error(coder, tool_name, e, add_traceback=False)
|
|
133
|
+
except Exception as e:
|
|
134
|
+
return handle_tool_error(coder, tool_name, e)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def process_response(coder, params):
|
|
138
|
+
"""
|
|
139
|
+
Process the UpdateTodoList tool response.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
coder: The Coder instance
|
|
143
|
+
params: Dictionary of parameters
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
str: Result message
|
|
147
|
+
"""
|
|
148
|
+
content = params.get("content")
|
|
149
|
+
append = params.get("append", False)
|
|
150
|
+
change_id = params.get("change_id")
|
|
151
|
+
dry_run = params.get("dry_run", False)
|
|
152
|
+
|
|
153
|
+
if content is not None:
|
|
154
|
+
return _execute_update_todo_list(coder, content, append, change_id, dry_run)
|
|
155
|
+
else:
|
|
156
|
+
return "Error: Missing required 'content' parameter for UpdateTodoList"
|
aider/tools/view.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
schema = {
|
|
2
|
+
"type": "function",
|
|
3
|
+
"function": {
|
|
4
|
+
"name": "View",
|
|
5
|
+
"description": (
|
|
6
|
+
"View a specific file and add it to context."
|
|
7
|
+
"Only use this when the file is not already in the context "
|
|
8
|
+
"and when editing the file is necessary to accomplish the goal."
|
|
9
|
+
),
|
|
10
|
+
"parameters": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"file_path": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "The path to the file to view.",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
"required": ["file_path"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# Normalized tool name for lookup
|
|
24
|
+
NORM_NAME = "view"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def execute_view(coder, file_path):
|
|
28
|
+
"""
|
|
29
|
+
Explicitly add a file to context as read-only.
|
|
30
|
+
|
|
31
|
+
This gives the LLM explicit control over what files to view,
|
|
32
|
+
rather than relying on indirect mentions.
|
|
33
|
+
"""
|
|
34
|
+
try:
|
|
35
|
+
# Use the coder's helper, marking it as an explicit view request
|
|
36
|
+
return coder._add_file_to_context(file_path, explicit=True)
|
|
37
|
+
except Exception as e:
|
|
38
|
+
coder.io.tool_error(f"Error viewing file: {str(e)}")
|
|
39
|
+
return f"Error: {str(e)}"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def process_response(coder, params):
|
|
43
|
+
"""
|
|
44
|
+
Process the View tool response.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
coder: The Coder instance
|
|
48
|
+
params: Dictionary of parameters
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
str: Result message
|
|
52
|
+
"""
|
|
53
|
+
file_path = params.get("file_path")
|
|
54
|
+
if file_path is not None:
|
|
55
|
+
return execute_view(coder, file_path)
|
|
56
|
+
else:
|
|
57
|
+
return "Error: Missing 'file_path' parameter for View"
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import fnmatch
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
schema = {
|
|
5
|
+
"type": "function",
|
|
6
|
+
"function": {
|
|
7
|
+
"name": "ViewFilesMatching",
|
|
8
|
+
"description": "View files containing a specific pattern.",
|
|
9
|
+
"parameters": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"pattern": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "The pattern to search for in file contents.",
|
|
15
|
+
},
|
|
16
|
+
"file_pattern": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "An optional glob pattern to filter which files are searched.",
|
|
19
|
+
},
|
|
20
|
+
"regex": {
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"description": (
|
|
23
|
+
"Whether the pattern is a regular expression. Defaults to False."
|
|
24
|
+
),
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
"required": ["pattern"],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Normalized tool name for lookup
|
|
33
|
+
NORM_NAME = "viewfilesmatching"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def execute_view_files_matching(coder, pattern, file_pattern=None, regex=False):
|
|
37
|
+
"""
|
|
38
|
+
Search for pattern (literal string or regex) in files and return matching files as text.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
coder: The Coder instance.
|
|
42
|
+
pattern (str): The pattern to search for.
|
|
43
|
+
Treated as a literal string by default.
|
|
44
|
+
file_pattern (str, optional): Glob pattern to filter which files are searched.
|
|
45
|
+
Defaults to None (search all files).
|
|
46
|
+
regex (bool, optional): If True, treat pattern as a regular expression.
|
|
47
|
+
Defaults to False.
|
|
48
|
+
|
|
49
|
+
This tool lets the LLM search for content within files, mimicking
|
|
50
|
+
how a developer would use grep or regex search to find relevant code.
|
|
51
|
+
"""
|
|
52
|
+
try:
|
|
53
|
+
# Get list of files to search
|
|
54
|
+
if file_pattern:
|
|
55
|
+
# Use glob pattern to filter files
|
|
56
|
+
all_files = coder.get_all_relative_files()
|
|
57
|
+
files_to_search = []
|
|
58
|
+
for file in all_files:
|
|
59
|
+
if fnmatch.fnmatch(file, file_pattern):
|
|
60
|
+
files_to_search.append(file)
|
|
61
|
+
|
|
62
|
+
if not files_to_search:
|
|
63
|
+
return f"No files matching '{file_pattern}' to search for pattern '{pattern}'"
|
|
64
|
+
else:
|
|
65
|
+
# Search all files if no pattern provided
|
|
66
|
+
files_to_search = coder.get_all_relative_files()
|
|
67
|
+
|
|
68
|
+
# Search for pattern in files
|
|
69
|
+
matches = {}
|
|
70
|
+
for file in files_to_search:
|
|
71
|
+
abs_path = coder.abs_root_path(file)
|
|
72
|
+
try:
|
|
73
|
+
with open(abs_path, "r", encoding="utf-8") as f:
|
|
74
|
+
content = f.read()
|
|
75
|
+
match_count = 0
|
|
76
|
+
if regex:
|
|
77
|
+
try:
|
|
78
|
+
matches_found = re.findall(pattern, content)
|
|
79
|
+
match_count = len(matches_found)
|
|
80
|
+
except re.error as e:
|
|
81
|
+
# Handle invalid regex patterns gracefully
|
|
82
|
+
coder.io.tool_error(f"Invalid regex pattern '{pattern}': {e}")
|
|
83
|
+
# Skip this file for this search if regex is invalid
|
|
84
|
+
continue
|
|
85
|
+
else:
|
|
86
|
+
# Exact string matching
|
|
87
|
+
match_count = content.count(pattern)
|
|
88
|
+
|
|
89
|
+
if match_count > 0:
|
|
90
|
+
matches[file] = match_count
|
|
91
|
+
except Exception:
|
|
92
|
+
# Skip files that can't be read (binary, etc.)
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
# Return formatted text instead of adding to context
|
|
96
|
+
if matches:
|
|
97
|
+
# Sort by number of matches (most matches first)
|
|
98
|
+
sorted_matches = sorted(matches.items(), key=lambda x: x[1], reverse=True)
|
|
99
|
+
match_list = [f"{file} ({count} matches)" for file, count in sorted_matches]
|
|
100
|
+
|
|
101
|
+
if len(matches) > 10:
|
|
102
|
+
result = (
|
|
103
|
+
f"Found '{pattern}' in {len(matches)} files: {', '.join(match_list[:10])} and"
|
|
104
|
+
f" {len(matches) - 10} more"
|
|
105
|
+
)
|
|
106
|
+
coder.io.tool_output(f"🔍 Found '{pattern}' in {len(matches)} files")
|
|
107
|
+
else:
|
|
108
|
+
result = f"Found '{pattern}' in {len(matches)} files: {', '.join(match_list)}"
|
|
109
|
+
coder.io.tool_output(
|
|
110
|
+
f"🔍 Found '{pattern}' in:"
|
|
111
|
+
f" {', '.join(match_list[:5])}{' and more' if len(matches) > 5 else ''}"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
return result
|
|
115
|
+
else:
|
|
116
|
+
coder.io.tool_output(f"⚠️ Pattern '{pattern}' not found in any files")
|
|
117
|
+
return "Pattern not found in any files"
|
|
118
|
+
except Exception as e:
|
|
119
|
+
coder.io.tool_error(f"Error in ViewFilesMatching: {str(e)}")
|
|
120
|
+
return f"Error: {str(e)}"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def process_response(coder, params):
|
|
124
|
+
"""
|
|
125
|
+
Process the ViewFilesMatching tool response.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
coder: The Coder instance
|
|
129
|
+
params: Dictionary of parameters
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
str: Result message
|
|
133
|
+
"""
|
|
134
|
+
pattern = params.get("pattern")
|
|
135
|
+
file_pattern = params.get("file_pattern")
|
|
136
|
+
regex = params.get("regex", False)
|
|
137
|
+
|
|
138
|
+
if pattern is not None:
|
|
139
|
+
return execute_view_files_matching(coder, pattern, file_pattern, regex)
|
|
140
|
+
else:
|
|
141
|
+
return "Error: Missing 'pattern' parameter for ViewFilesMatching"
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
schema = {
|
|
2
|
+
"type": "function",
|
|
3
|
+
"function": {
|
|
4
|
+
"name": "ViewFilesWithSymbol",
|
|
5
|
+
"description": "View files that contain a specific symbol (e.g., class, function).",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"symbol": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "The symbol to search for.",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
"required": ["symbol"],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Normalized tool name for lookup
|
|
20
|
+
NORM_NAME = "viewfileswithsymbol"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _execute_view_files_with_symbol(coder, symbol):
|
|
24
|
+
"""
|
|
25
|
+
Find files containing a symbol using RepoMap and return them as text.
|
|
26
|
+
Checks files already in context first.
|
|
27
|
+
"""
|
|
28
|
+
if not coder.repo_map:
|
|
29
|
+
coder.io.tool_output("⚠️ Repo map not available, cannot use ViewFilesWithSymbol tool.")
|
|
30
|
+
return "Repo map not available"
|
|
31
|
+
|
|
32
|
+
if not symbol:
|
|
33
|
+
return "Error: Missing 'symbol' parameter for ViewFilesWithSymbol"
|
|
34
|
+
|
|
35
|
+
# 1. Check files already in context
|
|
36
|
+
files_in_context = list(coder.abs_fnames) + list(coder.abs_read_only_fnames)
|
|
37
|
+
found_in_context = []
|
|
38
|
+
for abs_fname in files_in_context:
|
|
39
|
+
rel_fname = coder.get_rel_fname(abs_fname)
|
|
40
|
+
try:
|
|
41
|
+
# Use get_tags for consistency with RepoMap usage elsewhere for now.
|
|
42
|
+
tags = coder.repo_map.get_tags(abs_fname, rel_fname)
|
|
43
|
+
for tag in tags:
|
|
44
|
+
if tag.name == symbol:
|
|
45
|
+
found_in_context.append(rel_fname)
|
|
46
|
+
break # Found in this file, move to next
|
|
47
|
+
except Exception as e:
|
|
48
|
+
coder.io.tool_warning(
|
|
49
|
+
f"Could not get symbols for {rel_fname} while checking context: {e}"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if found_in_context:
|
|
53
|
+
# Symbol found in already loaded files. Report this and stop.
|
|
54
|
+
file_list = ", ".join(sorted(list(set(found_in_context))))
|
|
55
|
+
coder.io.tool_output(f"Symbol '{symbol}' found in already loaded file(s): {file_list}")
|
|
56
|
+
return f"Symbol '{symbol}' found in already loaded file(s): {file_list}"
|
|
57
|
+
|
|
58
|
+
# 2. If not found in context, search the repository using RepoMap
|
|
59
|
+
coder.io.tool_output(f"🔎 Searching for symbol '{symbol}' in repository...")
|
|
60
|
+
try:
|
|
61
|
+
found_files = set()
|
|
62
|
+
current_context_files = coder.abs_fnames | coder.abs_read_only_fnames
|
|
63
|
+
files_to_search = set(coder.get_all_abs_files()) - current_context_files
|
|
64
|
+
|
|
65
|
+
rel_fname_to_abs = {}
|
|
66
|
+
all_tags = []
|
|
67
|
+
|
|
68
|
+
for fname in files_to_search:
|
|
69
|
+
rel_fname = coder.get_rel_fname(fname)
|
|
70
|
+
rel_fname_to_abs[rel_fname] = fname
|
|
71
|
+
try:
|
|
72
|
+
tags = coder.repo_map.get_tags(fname, rel_fname)
|
|
73
|
+
all_tags.extend(tags)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
coder.io.tool_warning(f"Could not get tags for {rel_fname}: {e}")
|
|
76
|
+
|
|
77
|
+
# Find matching symbols
|
|
78
|
+
for tag in all_tags:
|
|
79
|
+
if tag.name == symbol:
|
|
80
|
+
# Use absolute path directly if available, otherwise resolve from relative path
|
|
81
|
+
abs_fname = rel_fname_to_abs.get(tag.rel_fname) or coder.abs_root_path(tag.fname)
|
|
82
|
+
if abs_fname in files_to_search: # Ensure we only add files we intended to search
|
|
83
|
+
found_files.add(coder.get_rel_fname(abs_fname))
|
|
84
|
+
|
|
85
|
+
# Return formatted text instead of adding to context
|
|
86
|
+
if found_files:
|
|
87
|
+
found_files_list = sorted(list(found_files))
|
|
88
|
+
if len(found_files) > 10:
|
|
89
|
+
result = (
|
|
90
|
+
f"Found symbol '{symbol}' in {len(found_files)} files:"
|
|
91
|
+
f" {', '.join(found_files_list[:10])} and {len(found_files) - 10} more"
|
|
92
|
+
)
|
|
93
|
+
coder.io.tool_output(f"🔎 Found '{symbol}' in {len(found_files)} files")
|
|
94
|
+
else:
|
|
95
|
+
result = (
|
|
96
|
+
f"Found symbol '{symbol}' in {len(found_files)} files:"
|
|
97
|
+
f" {', '.join(found_files_list)}"
|
|
98
|
+
)
|
|
99
|
+
coder.io.tool_output(
|
|
100
|
+
f"🔎 Found '{symbol}' in files:"
|
|
101
|
+
f" {', '.join(found_files_list[:5])}{' and more' if len(found_files) > 5 else ''}"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return result
|
|
105
|
+
else:
|
|
106
|
+
coder.io.tool_output(f"⚠️ Symbol '{symbol}' not found in searchable files")
|
|
107
|
+
return f"Symbol '{symbol}' not found in searchable files"
|
|
108
|
+
|
|
109
|
+
except Exception as e:
|
|
110
|
+
coder.io.tool_error(f"Error in ViewFilesWithSymbol: {str(e)}")
|
|
111
|
+
return f"Error: {str(e)}"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def process_response(coder, params):
|
|
115
|
+
"""
|
|
116
|
+
Process the ViewFilesWithSymbol tool response.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
coder: The Coder instance
|
|
120
|
+
params: Dictionary of parameters
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
str: Result message
|
|
124
|
+
"""
|
|
125
|
+
symbol = params.get("symbol")
|
|
126
|
+
if symbol is not None:
|
|
127
|
+
return _execute_view_files_with_symbol(coder, symbol)
|
|
128
|
+
else:
|
|
129
|
+
return "Error: Missing 'symbol' parameter for ViewFilesWithSymbol"
|
aider/urls.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
website = "https://aider.chat/"
|
|
2
|
+
add_all_files = "https://aider.chat/docs/faq.html#how-can-i-add-all-the-files-to-the-chat"
|
|
3
|
+
edit_errors = "https://aider.chat/docs/troubleshooting/edit-errors.html"
|
|
4
|
+
git = "https://aider.chat/docs/git.html"
|
|
5
|
+
enable_playwright = "https://aider.chat/docs/install/optional.html#enable-playwright"
|
|
6
|
+
favicon = "https://aider.chat/assets/icons/favicon-32x32.png"
|
|
7
|
+
model_warnings = "https://aider.chat/docs/llms/warnings.html"
|
|
8
|
+
token_limits = "https://aider.chat/docs/troubleshooting/token-limits.html"
|
|
9
|
+
llms = "https://aider.chat/docs/llms.html"
|
|
10
|
+
large_repos = "https://aider.chat/docs/faq.html#can-i-use-aider-in-a-large-mono-repo"
|
|
11
|
+
github_issues = "https://github.com/dwash96/aider-ce/issues/new"
|
|
12
|
+
git_index_version = "https://github.com/Aider-AI/aider/issues/211"
|
|
13
|
+
install_properly = "https://aider.chat/docs/troubleshooting/imports.html"
|
|
14
|
+
analytics = "https://aider.chat/docs/more/analytics.html"
|
|
15
|
+
release_notes = "https://aider.chat/HISTORY.html#release-notes"
|
|
16
|
+
edit_formats = "https://aider.chat/docs/more/edit-formats.html"
|
|
17
|
+
models_and_keys = "https://aider.chat/docs/troubleshooting/models-and-keys.html"
|