aider-ce 0.87.13.dev3__py3-none-any.whl → 0.88.1__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.
Potentially problematic release.
This version of aider-ce might be problematic. Click here for more details.
- aider/__init__.py +1 -1
- aider/_version.py +2 -2
- aider/args.py +6 -0
- aider/coders/architect_coder.py +3 -3
- aider/coders/base_coder.py +511 -190
- aider/coders/context_coder.py +1 -1
- aider/coders/editblock_func_coder.py +2 -2
- aider/coders/navigator_coder.py +451 -649
- aider/coders/navigator_legacy_prompts.py +49 -284
- aider/coders/navigator_prompts.py +46 -473
- aider/coders/search_replace.py +0 -0
- aider/coders/wholefile_func_coder.py +2 -2
- aider/commands.py +56 -44
- aider/exceptions.py +1 -0
- aider/history.py +14 -12
- aider/io.py +354 -117
- aider/llm.py +12 -4
- aider/main.py +32 -29
- aider/mcp/__init__.py +65 -2
- aider/mcp/server.py +37 -11
- aider/models.py +45 -20
- aider/onboarding.py +5 -5
- aider/repo.py +7 -7
- aider/resources/model-metadata.json +8 -8
- aider/scrape.py +2 -2
- aider/sendchat.py +185 -15
- aider/tools/__init__.py +44 -23
- aider/tools/command.py +18 -0
- aider/tools/command_interactive.py +18 -0
- aider/tools/delete_block.py +23 -0
- aider/tools/delete_line.py +19 -1
- aider/tools/delete_lines.py +20 -1
- aider/tools/extract_lines.py +25 -2
- aider/tools/git.py +142 -0
- aider/tools/grep.py +47 -2
- aider/tools/indent_lines.py +25 -0
- aider/tools/insert_block.py +26 -0
- aider/tools/list_changes.py +15 -0
- aider/tools/ls.py +24 -1
- aider/tools/make_editable.py +18 -0
- aider/tools/make_readonly.py +19 -0
- aider/tools/remove.py +22 -0
- aider/tools/replace_all.py +21 -0
- aider/tools/replace_line.py +20 -1
- aider/tools/replace_lines.py +21 -1
- aider/tools/replace_text.py +22 -0
- aider/tools/show_numbered_context.py +18 -0
- aider/tools/undo_change.py +15 -0
- aider/tools/update_todo_list.py +131 -0
- aider/tools/view.py +23 -0
- aider/tools/view_files_at_glob.py +32 -27
- aider/tools/view_files_matching.py +51 -37
- aider/tools/view_files_with_symbol.py +41 -54
- aider/tools/view_todo_list.py +57 -0
- aider/waiting.py +20 -203
- {aider_ce-0.87.13.dev3.dist-info → aider_ce-0.88.1.dist-info}/METADATA +21 -5
- {aider_ce-0.87.13.dev3.dist-info → aider_ce-0.88.1.dist-info}/RECORD +60 -57
- {aider_ce-0.87.13.dev3.dist-info → aider_ce-0.88.1.dist-info}/WHEEL +0 -0
- {aider_ce-0.87.13.dev3.dist-info → aider_ce-0.88.1.dist-info}/entry_points.txt +0 -0
- {aider_ce-0.87.13.dev3.dist-info → aider_ce-0.88.1.dist-info}/licenses/LICENSE.txt +0 -0
- {aider_ce-0.87.13.dev3.dist-info → aider_ce-0.88.1.dist-info}/top_level.txt +0 -0
aider/tools/git.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from aider.repo import ANY_GIT_ERROR
|
|
2
|
+
|
|
3
|
+
git_diff_schema = {
|
|
4
|
+
"type": "function",
|
|
5
|
+
"function": {
|
|
6
|
+
"name": "git_diff",
|
|
7
|
+
"description": (
|
|
8
|
+
"Show the diff between the current working directory and a git branch or commit."
|
|
9
|
+
),
|
|
10
|
+
"parameters": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"branch": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "The branch or commit hash to diff against. Defaults to HEAD.",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
"required": [],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _execute_git_diff(coder, branch=None):
|
|
25
|
+
"""
|
|
26
|
+
Show the diff between the current working directory and a git branch or commit.
|
|
27
|
+
"""
|
|
28
|
+
if not coder.repo:
|
|
29
|
+
return "Not in a git repository."
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
if branch:
|
|
33
|
+
diff = coder.repo.diff_commits(False, branch, "HEAD")
|
|
34
|
+
else:
|
|
35
|
+
diff = coder.repo.diff_commits(False, "HEAD", None)
|
|
36
|
+
|
|
37
|
+
if not diff:
|
|
38
|
+
return "No differences found."
|
|
39
|
+
return diff
|
|
40
|
+
except ANY_GIT_ERROR as e:
|
|
41
|
+
coder.io.tool_error(f"Error running git diff: {e}")
|
|
42
|
+
return f"Error running git diff: {e}"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
git_log_schema = {
|
|
46
|
+
"type": "function",
|
|
47
|
+
"function": {
|
|
48
|
+
"name": "git_log",
|
|
49
|
+
"description": "Show the git log.",
|
|
50
|
+
"parameters": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"limit": {
|
|
54
|
+
"type": "integer",
|
|
55
|
+
"description": "The maximum number of commits to show. Defaults to 10.",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
"required": [],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _execute_git_log(coder, limit=10):
|
|
65
|
+
"""
|
|
66
|
+
Show the git log.
|
|
67
|
+
"""
|
|
68
|
+
if not coder.repo:
|
|
69
|
+
return "Not in a git repository."
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
commits = list(coder.repo.repo.iter_commits(max_count=limit))
|
|
73
|
+
log_output = []
|
|
74
|
+
for commit in commits:
|
|
75
|
+
short_hash = commit.hexsha[:8]
|
|
76
|
+
message = commit.message.strip().split("\n")[0]
|
|
77
|
+
log_output.append(f"{short_hash} {message}")
|
|
78
|
+
return "\n".join(log_output)
|
|
79
|
+
except ANY_GIT_ERROR as e:
|
|
80
|
+
coder.io.tool_error(f"Error running git log: {e}")
|
|
81
|
+
return f"Error running git log: {e}"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
git_show_schema = {
|
|
85
|
+
"type": "function",
|
|
86
|
+
"function": {
|
|
87
|
+
"name": "git_show",
|
|
88
|
+
"description": "Show various types of objects (blobs, trees, tags, and commits).",
|
|
89
|
+
"parameters": {
|
|
90
|
+
"type": "object",
|
|
91
|
+
"properties": {
|
|
92
|
+
"object": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "The object to show. Defaults to HEAD.",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
"required": [],
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _execute_git_show(coder, object="HEAD"):
|
|
104
|
+
"""
|
|
105
|
+
Show various types of objects (blobs, trees, tags, and commits).
|
|
106
|
+
"""
|
|
107
|
+
if not coder.repo:
|
|
108
|
+
return "Not in a git repository."
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
return coder.repo.repo.git.show(object)
|
|
112
|
+
except ANY_GIT_ERROR as e:
|
|
113
|
+
coder.io.tool_error(f"Error running git show: {e}")
|
|
114
|
+
return f"Error running git show: {e}"
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
git_status_schema = {
|
|
118
|
+
"type": "function",
|
|
119
|
+
"function": {
|
|
120
|
+
"name": "git_status",
|
|
121
|
+
"description": "Show the working tree status.",
|
|
122
|
+
"parameters": {
|
|
123
|
+
"type": "object",
|
|
124
|
+
"properties": {},
|
|
125
|
+
"required": [],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _execute_git_status(coder):
|
|
132
|
+
"""
|
|
133
|
+
Show the working tree status.
|
|
134
|
+
"""
|
|
135
|
+
if not coder.repo:
|
|
136
|
+
return "Not in a git repository."
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
return coder.repo.repo.git.status()
|
|
140
|
+
except ANY_GIT_ERROR as e:
|
|
141
|
+
coder.io.tool_error(f"Error running git status: {e}")
|
|
142
|
+
return f"Error running git status: {e}"
|
aider/tools/grep.py
CHANGED
|
@@ -1,9 +1,54 @@
|
|
|
1
|
-
import shlex
|
|
2
1
|
import shutil
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
|
|
4
|
+
import oslex
|
|
5
|
+
|
|
5
6
|
from aider.run_cmd import run_cmd_subprocess
|
|
6
7
|
|
|
8
|
+
grep_schema = {
|
|
9
|
+
"type": "function",
|
|
10
|
+
"function": {
|
|
11
|
+
"name": "Grep",
|
|
12
|
+
"description": "Search for a pattern in files.",
|
|
13
|
+
"parameters": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"pattern": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The pattern to search for.",
|
|
19
|
+
},
|
|
20
|
+
"file_pattern": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Glob pattern for files to search. Defaults to '*'.",
|
|
23
|
+
},
|
|
24
|
+
"directory": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Directory to search in. Defaults to '.'.",
|
|
27
|
+
},
|
|
28
|
+
"use_regex": {
|
|
29
|
+
"type": "boolean",
|
|
30
|
+
"description": "Whether to use regex. Defaults to False.",
|
|
31
|
+
},
|
|
32
|
+
"case_insensitive": {
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"description": (
|
|
35
|
+
"Whether to perform a case-insensitive search. Defaults to False."
|
|
36
|
+
),
|
|
37
|
+
},
|
|
38
|
+
"context_before": {
|
|
39
|
+
"type": "integer",
|
|
40
|
+
"description": "Number of lines to show before a match. Defaults to 5.",
|
|
41
|
+
},
|
|
42
|
+
"context_after": {
|
|
43
|
+
"type": "integer",
|
|
44
|
+
"description": "Number of lines to show after a match. Defaults to 5.",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
"required": ["pattern"],
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
|
|
7
52
|
|
|
8
53
|
def _find_search_tool():
|
|
9
54
|
"""Find the best available command-line search tool (rg, ag, grep)."""
|
|
@@ -117,7 +162,7 @@ def _execute_grep(
|
|
|
117
162
|
cmd_args.extend([pattern, str(search_dir_path)])
|
|
118
163
|
|
|
119
164
|
# Convert list to command string for run_cmd_subprocess
|
|
120
|
-
command_string =
|
|
165
|
+
command_string = oslex.join(cmd_args)
|
|
121
166
|
|
|
122
167
|
coder.io.tool_output(f"⚙️ Executing {tool_name}: {command_string}")
|
|
123
168
|
|
aider/tools/indent_lines.py
CHANGED
|
@@ -10,6 +10,29 @@ from .tool_utils import (
|
|
|
10
10
|
validate_file_for_edit,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
+
indent_lines_schema = {
|
|
14
|
+
"type": "function",
|
|
15
|
+
"function": {
|
|
16
|
+
"name": "IndentLines",
|
|
17
|
+
"description": "Indent a block of lines in a file.",
|
|
18
|
+
"parameters": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"file_path": {"type": "string"},
|
|
22
|
+
"start_pattern": {"type": "string"},
|
|
23
|
+
"end_pattern": {"type": "string"},
|
|
24
|
+
"line_count": {"type": "integer"},
|
|
25
|
+
"indent_levels": {"type": "integer", "default": 1},
|
|
26
|
+
"near_context": {"type": "string"},
|
|
27
|
+
"occurrence": {"type": "integer", "default": 1},
|
|
28
|
+
"change_id": {"type": "string"},
|
|
29
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
30
|
+
},
|
|
31
|
+
"required": ["file_path", "start_pattern"],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
|
|
13
36
|
|
|
14
37
|
def _execute_indent_lines(
|
|
15
38
|
coder,
|
|
@@ -138,6 +161,8 @@ def _execute_indent_lines(
|
|
|
138
161
|
change_id,
|
|
139
162
|
)
|
|
140
163
|
|
|
164
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
165
|
+
|
|
141
166
|
# 8. Format and return result
|
|
142
167
|
action_past = "Indented" if indent_levels > 0 else "Unindented"
|
|
143
168
|
success_message = (
|
aider/tools/insert_block.py
CHANGED
|
@@ -12,6 +12,30 @@ from .tool_utils import (
|
|
|
12
12
|
validate_file_for_edit,
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
+
insert_block_schema = {
|
|
16
|
+
"type": "function",
|
|
17
|
+
"function": {
|
|
18
|
+
"name": "InsertBlock",
|
|
19
|
+
"description": "Insert a block of content into a file.",
|
|
20
|
+
"parameters": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"properties": {
|
|
23
|
+
"file_path": {"type": "string"},
|
|
24
|
+
"content": {"type": "string"},
|
|
25
|
+
"after_pattern": {"type": "string"},
|
|
26
|
+
"before_pattern": {"type": "string"},
|
|
27
|
+
"occurrence": {"type": "integer", "default": 1},
|
|
28
|
+
"change_id": {"type": "string"},
|
|
29
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
30
|
+
"position": {"type": "string", "enum": ["top", "bottom"]},
|
|
31
|
+
"auto_indent": {"type": "boolean", "default": True},
|
|
32
|
+
"use_regex": {"type": "boolean", "default": False},
|
|
33
|
+
},
|
|
34
|
+
"required": ["file_path", "content"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
15
39
|
|
|
16
40
|
def _execute_insert_block(
|
|
17
41
|
coder,
|
|
@@ -187,6 +211,8 @@ def _execute_insert_block(
|
|
|
187
211
|
change_id,
|
|
188
212
|
)
|
|
189
213
|
|
|
214
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
215
|
+
|
|
190
216
|
# 9. Format and return result
|
|
191
217
|
if position:
|
|
192
218
|
success_message = f"Inserted block {pattern_type} {file_path}"
|
aider/tools/list_changes.py
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import traceback
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
|
|
4
|
+
list_changes_schema = {
|
|
5
|
+
"type": "function",
|
|
6
|
+
"function": {
|
|
7
|
+
"name": "ListChanges",
|
|
8
|
+
"description": "List recent changes made.",
|
|
9
|
+
"parameters": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"file_path": {"type": "string"},
|
|
13
|
+
"limit": {"type": "integer", "default": 10},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
4
19
|
|
|
5
20
|
def _execute_list_changes(coder, file_path=None, limit=10):
|
|
6
21
|
"""
|
aider/tools/ls.py
CHANGED
|
@@ -1,7 +1,30 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
|
+
ls_schema = {
|
|
4
|
+
"type": "function",
|
|
5
|
+
"function": {
|
|
6
|
+
"name": "Ls",
|
|
7
|
+
"description": "List files in a directory.",
|
|
8
|
+
"parameters": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"directory": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "The directory to list.",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
"required": ["directory"],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}
|
|
3
20
|
|
|
4
|
-
|
|
21
|
+
|
|
22
|
+
def execute_ls(coder, dir_path=None, directory=None):
|
|
23
|
+
# Handle both positional and keyword arguments for backward compatibility
|
|
24
|
+
if dir_path is None and directory is not None:
|
|
25
|
+
dir_path = directory
|
|
26
|
+
elif dir_path is None:
|
|
27
|
+
return "Error: Missing directory parameter"
|
|
5
28
|
"""
|
|
6
29
|
List files in directory and optionally add some to context.
|
|
7
30
|
|
aider/tools/make_editable.py
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
|
+
make_editable_schema = {
|
|
4
|
+
"type": "function",
|
|
5
|
+
"function": {
|
|
6
|
+
"name": "MakeEditable",
|
|
7
|
+
"description": "Make a read-only file editable.",
|
|
8
|
+
"parameters": {
|
|
9
|
+
"type": "object",
|
|
10
|
+
"properties": {
|
|
11
|
+
"file_path": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "The path to the file to make editable.",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
"required": ["file_path"],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
|
|
3
21
|
|
|
4
22
|
# Keep the underscore prefix as this function is primarily for internal coder use
|
|
5
23
|
def _execute_make_editable(coder, file_path):
|
aider/tools/make_readonly.py
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
make_readonly_schema = {
|
|
2
|
+
"type": "function",
|
|
3
|
+
"function": {
|
|
4
|
+
"name": "MakeReadonly",
|
|
5
|
+
"description": "Make an editable file read-only.",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"file_path": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "The path to the file to make read-only.",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
"required": ["file_path"],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
1
20
|
def _execute_make_readonly(coder, file_path):
|
|
2
21
|
"""
|
|
3
22
|
Convert an editable file to a read-only file.
|
aider/tools/remove.py
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
import time
|
|
2
2
|
|
|
3
|
+
remove_schema = {
|
|
4
|
+
"type": "function",
|
|
5
|
+
"function": {
|
|
6
|
+
"name": "Remove",
|
|
7
|
+
"description": (
|
|
8
|
+
"Remove a file from the chat context. Should be used proactively to keep con"
|
|
9
|
+
"Should be used after editing a file when all edits are done "
|
|
10
|
+
"and the file is no longer necessary in context."
|
|
11
|
+
),
|
|
12
|
+
"parameters": {
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"file_path": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "The path to the file to remove.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
"required": ["file_path"],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
|
|
3
25
|
|
|
4
26
|
def _execute_remove(coder, file_path):
|
|
5
27
|
"""
|
aider/tools/replace_all.py
CHANGED
|
@@ -7,6 +7,25 @@ from .tool_utils import (
|
|
|
7
7
|
validate_file_for_edit,
|
|
8
8
|
)
|
|
9
9
|
|
|
10
|
+
replace_all_schema = {
|
|
11
|
+
"type": "function",
|
|
12
|
+
"function": {
|
|
13
|
+
"name": "ReplaceAll",
|
|
14
|
+
"description": "Replace all occurrences of text in a file.",
|
|
15
|
+
"parameters": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"file_path": {"type": "string"},
|
|
19
|
+
"find_text": {"type": "string"},
|
|
20
|
+
"replace_text": {"type": "string"},
|
|
21
|
+
"change_id": {"type": "string"},
|
|
22
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
23
|
+
},
|
|
24
|
+
"required": ["file_path", "find_text", "replace_text"],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
10
29
|
|
|
11
30
|
def _execute_replace_all(coder, file_path, find_text, replace_text, change_id=None, dry_run=False):
|
|
12
31
|
"""
|
|
@@ -63,6 +82,8 @@ def _execute_replace_all(coder, file_path, find_text, replace_text, change_id=No
|
|
|
63
82
|
change_id,
|
|
64
83
|
)
|
|
65
84
|
|
|
85
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
86
|
+
|
|
66
87
|
# 7. Format and return result
|
|
67
88
|
success_message = f"Replaced {count} occurrences in {file_path}"
|
|
68
89
|
return format_tool_result(
|
aider/tools/replace_line.py
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import traceback
|
|
3
3
|
|
|
4
|
+
replace_line_schema = {
|
|
5
|
+
"type": "function",
|
|
6
|
+
"function": {
|
|
7
|
+
"name": "ReplaceLine",
|
|
8
|
+
"description": "Replace a single line in a file.",
|
|
9
|
+
"parameters": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"file_path": {"type": "string"},
|
|
13
|
+
"line_number": {"type": "integer"},
|
|
14
|
+
"new_content": {"type": "string"},
|
|
15
|
+
"change_id": {"type": "string"},
|
|
16
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
17
|
+
},
|
|
18
|
+
"required": ["file_path", "line_number", "new_content"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
4
23
|
|
|
5
24
|
def _execute_replace_line(
|
|
6
25
|
coder, file_path, line_number, new_content, change_id=None, dry_run=False
|
|
@@ -112,7 +131,7 @@ def _execute_replace_line(
|
|
|
112
131
|
coder.io.tool_error(f"Error tracking change for ReplaceLine: {track_e}")
|
|
113
132
|
change_id = "TRACKING_FAILED"
|
|
114
133
|
|
|
115
|
-
coder.
|
|
134
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
116
135
|
|
|
117
136
|
# Improve feedback
|
|
118
137
|
coder.io.tool_output(
|
aider/tools/replace_lines.py
CHANGED
|
@@ -8,6 +8,26 @@ from .tool_utils import (
|
|
|
8
8
|
handle_tool_error,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
+
replace_lines_schema = {
|
|
12
|
+
"type": "function",
|
|
13
|
+
"function": {
|
|
14
|
+
"name": "ReplaceLines",
|
|
15
|
+
"description": "Replace a range of lines in a file.",
|
|
16
|
+
"parameters": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"file_path": {"type": "string"},
|
|
20
|
+
"start_line": {"type": "integer"},
|
|
21
|
+
"end_line": {"type": "integer"},
|
|
22
|
+
"new_content": {"type": "string"},
|
|
23
|
+
"change_id": {"type": "string"},
|
|
24
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
25
|
+
},
|
|
26
|
+
"required": ["file_path", "start_line", "end_line", "new_content"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
|
|
11
31
|
|
|
12
32
|
def _execute_replace_lines(
|
|
13
33
|
coder, file_path, start_line, end_line, new_content, change_id=None, dry_run=False
|
|
@@ -139,7 +159,7 @@ def _execute_replace_lines(
|
|
|
139
159
|
change_id,
|
|
140
160
|
)
|
|
141
161
|
|
|
142
|
-
coder.
|
|
162
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
143
163
|
replaced_count = end_line - start_line + 1
|
|
144
164
|
new_count = len(new_lines)
|
|
145
165
|
|
aider/tools/replace_text.py
CHANGED
|
@@ -7,6 +7,27 @@ from .tool_utils import (
|
|
|
7
7
|
validate_file_for_edit,
|
|
8
8
|
)
|
|
9
9
|
|
|
10
|
+
replace_text_schema = {
|
|
11
|
+
"type": "function",
|
|
12
|
+
"function": {
|
|
13
|
+
"name": "ReplaceText",
|
|
14
|
+
"description": "Replace text in a file.",
|
|
15
|
+
"parameters": {
|
|
16
|
+
"type": "object",
|
|
17
|
+
"properties": {
|
|
18
|
+
"file_path": {"type": "string"},
|
|
19
|
+
"find_text": {"type": "string"},
|
|
20
|
+
"replace_text": {"type": "string"},
|
|
21
|
+
"near_context": {"type": "string"},
|
|
22
|
+
"occurrence": {"type": "integer", "default": 1},
|
|
23
|
+
"change_id": {"type": "string"},
|
|
24
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
25
|
+
},
|
|
26
|
+
"required": ["file_path", "find_text", "replace_text"],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
|
|
10
31
|
|
|
11
32
|
def _execute_replace_text(
|
|
12
33
|
coder,
|
|
@@ -111,6 +132,7 @@ def _execute_replace_text(
|
|
|
111
132
|
change_id,
|
|
112
133
|
)
|
|
113
134
|
|
|
135
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
114
136
|
# 8. Format and return result
|
|
115
137
|
success_message = f"Replaced {occurrence_str} in {file_path}"
|
|
116
138
|
return format_tool_result(
|
|
@@ -2,6 +2,24 @@ import os
|
|
|
2
2
|
|
|
3
3
|
from .tool_utils import ToolError, handle_tool_error, resolve_paths
|
|
4
4
|
|
|
5
|
+
show_numbered_context_schema = {
|
|
6
|
+
"type": "function",
|
|
7
|
+
"function": {
|
|
8
|
+
"name": "ShowNumberedContext",
|
|
9
|
+
"description": "Show numbered lines of context around a pattern or line number.",
|
|
10
|
+
"parameters": {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"file_path": {"type": "string"},
|
|
14
|
+
"pattern": {"type": "string"},
|
|
15
|
+
"line_number": {"type": "integer"},
|
|
16
|
+
"context_lines": {"type": "integer", "default": 3},
|
|
17
|
+
},
|
|
18
|
+
"required": ["file_path"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
5
23
|
|
|
6
24
|
def execute_show_numbered_context(
|
|
7
25
|
coder, file_path, pattern=None, line_number=None, context_lines=3
|
aider/tools/undo_change.py
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import traceback
|
|
2
2
|
|
|
3
|
+
undo_change_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
|
+
|
|
3
18
|
|
|
4
19
|
def _execute_undo_change(coder, change_id=None, file_path=None):
|
|
5
20
|
"""
|