aider-ce 0.88.20__py3-none-any.whl → 0.88.38__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 +1 -1
- aider/_version.py +2 -2
- aider/args.py +63 -43
- aider/coders/agent_coder.py +331 -79
- aider/coders/agent_prompts.py +3 -15
- aider/coders/architect_coder.py +21 -5
- aider/coders/base_coder.py +661 -413
- aider/coders/base_prompts.py +6 -3
- aider/coders/chat_chunks.py +39 -17
- aider/commands.py +79 -15
- aider/diffs.py +10 -9
- aider/exceptions.py +1 -1
- aider/helpers/coroutines.py +8 -0
- aider/helpers/requests.py +45 -0
- aider/history.py +5 -0
- aider/io.py +179 -25
- aider/main.py +86 -35
- aider/models.py +16 -8
- aider/queries/tree-sitter-language-pack/c-tags.scm +3 -0
- aider/queries/tree-sitter-language-pack/clojure-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/commonlisp-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/cpp-tags.scm +3 -0
- aider/queries/tree-sitter-language-pack/csharp-tags.scm +6 -0
- aider/queries/tree-sitter-language-pack/dart-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/elixir-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/elm-tags.scm +3 -0
- aider/queries/tree-sitter-language-pack/go-tags.scm +7 -0
- aider/queries/tree-sitter-language-pack/java-tags.scm +6 -0
- aider/queries/tree-sitter-language-pack/javascript-tags.scm +8 -0
- aider/queries/tree-sitter-language-pack/lua-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +3 -0
- aider/queries/tree-sitter-language-pack/python-tags.scm +10 -0
- aider/queries/tree-sitter-language-pack/r-tags.scm +6 -0
- aider/queries/tree-sitter-language-pack/ruby-tags.scm +5 -0
- aider/queries/tree-sitter-language-pack/rust-tags.scm +3 -0
- aider/queries/tree-sitter-language-pack/solidity-tags.scm +1 -1
- aider/queries/tree-sitter-language-pack/swift-tags.scm +4 -1
- aider/queries/tree-sitter-languages/c-tags.scm +3 -0
- aider/queries/tree-sitter-languages/c_sharp-tags.scm +6 -0
- aider/queries/tree-sitter-languages/cpp-tags.scm +3 -0
- aider/queries/tree-sitter-languages/dart-tags.scm +2 -1
- aider/queries/tree-sitter-languages/elixir-tags.scm +5 -0
- aider/queries/tree-sitter-languages/elm-tags.scm +3 -0
- aider/queries/tree-sitter-languages/fortran-tags.scm +3 -0
- aider/queries/tree-sitter-languages/go-tags.scm +6 -0
- aider/queries/tree-sitter-languages/haskell-tags.scm +2 -0
- aider/queries/tree-sitter-languages/java-tags.scm +6 -0
- aider/queries/tree-sitter-languages/javascript-tags.scm +8 -0
- aider/queries/tree-sitter-languages/julia-tags.scm +2 -2
- aider/queries/tree-sitter-languages/kotlin-tags.scm +3 -0
- aider/queries/tree-sitter-languages/ocaml_interface-tags.scm +6 -0
- aider/queries/tree-sitter-languages/php-tags.scm +6 -0
- aider/queries/tree-sitter-languages/python-tags.scm +10 -0
- aider/queries/tree-sitter-languages/ruby-tags.scm +5 -0
- aider/queries/tree-sitter-languages/rust-tags.scm +3 -0
- aider/queries/tree-sitter-languages/scala-tags.scm +2 -3
- aider/queries/tree-sitter-languages/typescript-tags.scm +3 -0
- aider/queries/tree-sitter-languages/zig-tags.scm +20 -3
- aider/repomap.py +71 -11
- aider/resources/model-metadata.json +27335 -635
- aider/resources/model-settings.yml +190 -0
- aider/scrape.py +2 -0
- aider/tools/__init__.py +2 -0
- aider/tools/command.py +84 -94
- aider/tools/command_interactive.py +95 -110
- aider/tools/delete_block.py +131 -159
- aider/tools/delete_line.py +97 -132
- aider/tools/delete_lines.py +120 -160
- aider/tools/extract_lines.py +288 -312
- aider/tools/finished.py +30 -43
- aider/tools/git_branch.py +107 -109
- aider/tools/git_diff.py +44 -56
- aider/tools/git_log.py +39 -53
- aider/tools/git_remote.py +37 -51
- aider/tools/git_show.py +33 -47
- aider/tools/git_status.py +30 -44
- aider/tools/grep.py +214 -242
- aider/tools/indent_lines.py +175 -201
- aider/tools/insert_block.py +220 -253
- aider/tools/list_changes.py +65 -80
- aider/tools/ls.py +64 -80
- aider/tools/make_editable.py +57 -73
- aider/tools/make_readonly.py +50 -66
- aider/tools/remove.py +64 -80
- aider/tools/replace_all.py +96 -109
- aider/tools/replace_line.py +118 -156
- aider/tools/replace_lines.py +160 -197
- aider/tools/replace_text.py +159 -160
- aider/tools/show_numbered_context.py +115 -141
- aider/tools/thinking.py +52 -0
- aider/tools/undo_change.py +78 -91
- aider/tools/update_todo_list.py +130 -138
- aider/tools/utils/base_tool.py +64 -0
- aider/tools/utils/output.py +118 -0
- aider/tools/view.py +38 -54
- aider/tools/view_files_matching.py +131 -134
- aider/tools/view_files_with_symbol.py +108 -120
- aider/urls.py +1 -1
- aider/versioncheck.py +4 -3
- aider/website/docs/config/adv-model-settings.md +237 -0
- aider/website/docs/config/agent-mode.md +36 -3
- aider/website/docs/config/model-aliases.md +2 -1
- aider/website/docs/faq.md +6 -11
- aider/website/docs/languages.md +2 -2
- aider/website/docs/more/infinite-output.md +27 -0
- {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/METADATA +112 -70
- {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/RECORD +112 -107
- aider_ce-0.88.38.dist-info/entry_points.txt +6 -0
- aider_ce-0.88.20.dist-info/entry_points.txt +0 -2
- /aider/tools/{tool_utils.py → utils/helpers.py} +0 -0
- {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/WHEEL +0 -0
- {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/licenses/LICENSE.txt +0 -0
- {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/top_level.txt +0 -0
aider/tools/ls.py
CHANGED
|
@@ -1,93 +1,77 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
from aider.tools.utils.base_tool import BaseTool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Tool(BaseTool):
|
|
7
|
+
NORM_NAME = "ls"
|
|
8
|
+
SCHEMA = {
|
|
9
|
+
"type": "function",
|
|
10
|
+
"function": {
|
|
11
|
+
"name": "Ls",
|
|
12
|
+
"description": "List files in a directory.",
|
|
13
|
+
"parameters": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"directory": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The directory to list.",
|
|
19
|
+
},
|
|
14
20
|
},
|
|
21
|
+
"required": ["directory"],
|
|
15
22
|
},
|
|
16
|
-
"required": ["directory"],
|
|
17
23
|
},
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
# Normalized tool name for lookup
|
|
22
|
-
NORM_NAME = "ls"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def execute_ls(coder, dir_path=None, directory=None):
|
|
26
|
-
# Handle both positional and keyword arguments for backward compatibility
|
|
27
|
-
if dir_path is None and directory is not None:
|
|
28
|
-
dir_path = directory
|
|
29
|
-
elif dir_path is None:
|
|
30
|
-
return "Error: Missing directory parameter"
|
|
31
|
-
"""
|
|
32
|
-
List files in directory and optionally add some to context.
|
|
24
|
+
}
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
26
|
+
@classmethod
|
|
27
|
+
def execute(cls, coder, dir_path=None, directory=None):
|
|
28
|
+
# Handle both positional and keyword arguments for backward compatibility
|
|
29
|
+
if dir_path is None and directory is not None:
|
|
30
|
+
dir_path = directory
|
|
31
|
+
elif dir_path is None:
|
|
32
|
+
return "Error: Missing directory parameter"
|
|
33
|
+
"""
|
|
34
|
+
List files in directory and optionally add some to context.
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
# Check if path exists
|
|
48
|
-
if not os.path.exists(abs_dir):
|
|
49
|
-
coder.io.tool_output(f"⚠️ Directory '{dir_path}' not found")
|
|
50
|
-
return "Directory not found"
|
|
51
|
-
|
|
52
|
-
# Get directory contents
|
|
53
|
-
contents = []
|
|
36
|
+
This provides information about the structure of the codebase,
|
|
37
|
+
similar to how a developer would explore directories.
|
|
38
|
+
"""
|
|
54
39
|
try:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
rel_path = os.path.join(rel_dir, entry.name)
|
|
59
|
-
contents.append(rel_path)
|
|
60
|
-
except NotADirectoryError:
|
|
61
|
-
# If it's a file, just return the file
|
|
62
|
-
contents = [rel_dir]
|
|
63
|
-
|
|
64
|
-
if contents:
|
|
65
|
-
coder.io.tool_output(f"📋 Listed {len(contents)} file(s) in '{dir_path}'")
|
|
66
|
-
if len(contents) > 10:
|
|
67
|
-
return f"Found {len(contents)} files: {', '.join(contents[:10])}..."
|
|
40
|
+
# Make the path relative to root if it's absolute
|
|
41
|
+
if dir_path.startswith("/"):
|
|
42
|
+
rel_dir = os.path.relpath(dir_path, coder.root)
|
|
68
43
|
else:
|
|
69
|
-
|
|
70
|
-
else:
|
|
71
|
-
coder.io.tool_output(f"📋 No files found in '{dir_path}'")
|
|
72
|
-
return "No files found in directory"
|
|
73
|
-
except Exception as e:
|
|
74
|
-
coder.io.tool_error(f"Error in ls: {str(e)}")
|
|
75
|
-
return f"Error: {str(e)}"
|
|
44
|
+
rel_dir = dir_path
|
|
76
45
|
|
|
46
|
+
# Get absolute path
|
|
47
|
+
abs_dir = coder.abs_root_path(rel_dir)
|
|
77
48
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
49
|
+
# Check if path exists
|
|
50
|
+
if not os.path.exists(abs_dir):
|
|
51
|
+
coder.io.tool_output(f"⚠️ Directory '{dir_path}' not found")
|
|
52
|
+
return "Directory not found"
|
|
81
53
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
54
|
+
# Get directory contents
|
|
55
|
+
contents = []
|
|
56
|
+
try:
|
|
57
|
+
with os.scandir(abs_dir) as entries:
|
|
58
|
+
for entry in entries:
|
|
59
|
+
if entry.is_file() and not entry.name.startswith("."):
|
|
60
|
+
rel_path = os.path.join(rel_dir, entry.name)
|
|
61
|
+
contents.append(rel_path)
|
|
62
|
+
except NotADirectoryError:
|
|
63
|
+
# If it's a file, just return the file
|
|
64
|
+
contents = [rel_dir]
|
|
85
65
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
66
|
+
if contents:
|
|
67
|
+
coder.io.tool_output(f"📋 Listed {len(contents)} file(s) in '{dir_path}'")
|
|
68
|
+
if len(contents) > 10:
|
|
69
|
+
return f"Found {len(contents)} files: {', '.join(contents[:10])}..."
|
|
70
|
+
else:
|
|
71
|
+
return f"Found {len(contents)} files: {', '.join(contents)}"
|
|
72
|
+
else:
|
|
73
|
+
coder.io.tool_output(f"📋 No files found in '{dir_path}'")
|
|
74
|
+
return "No files found in directory"
|
|
75
|
+
except Exception as e:
|
|
76
|
+
coder.io.tool_error(f"Error in ls: {str(e)}")
|
|
77
|
+
return f"Error: {str(e)}"
|
aider/tools/make_editable.py
CHANGED
|
@@ -1,85 +1,69 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
from aider.tools.utils.base_tool import BaseTool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Tool(BaseTool):
|
|
7
|
+
NORM_NAME = "makeeditable"
|
|
8
|
+
SCHEMA = {
|
|
9
|
+
"type": "function",
|
|
10
|
+
"function": {
|
|
11
|
+
"name": "MakeEditable",
|
|
12
|
+
"description": "Make a read-only file editable.",
|
|
13
|
+
"parameters": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"file_path": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "The path to the file to make editable.",
|
|
19
|
+
},
|
|
14
20
|
},
|
|
21
|
+
"required": ["file_path"],
|
|
15
22
|
},
|
|
16
|
-
"required": ["file_path"],
|
|
17
23
|
},
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
# Normalized tool name for lookup
|
|
22
|
-
NORM_NAME = "makeeditable"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# Keep the underscore prefix as this function is primarily for internal coder use
|
|
26
|
-
def _execute_make_editable(coder, file_path):
|
|
27
|
-
"""
|
|
28
|
-
Convert a read-only file to an editable file.
|
|
29
|
-
|
|
30
|
-
This allows the LLM to upgrade a file from read-only to editable
|
|
31
|
-
when it determines it needs to make changes to that file.
|
|
32
|
-
"""
|
|
33
|
-
try:
|
|
34
|
-
# Get absolute path
|
|
35
|
-
abs_path = coder.abs_root_path(file_path)
|
|
36
|
-
|
|
37
|
-
# Check if file is already editable
|
|
38
|
-
if abs_path in coder.abs_fnames:
|
|
39
|
-
coder.io.tool_output(f"📝 File '{file_path}' is already editable")
|
|
40
|
-
return "File is already editable"
|
|
41
|
-
|
|
42
|
-
# Check if file exists on disk
|
|
43
|
-
if not os.path.isfile(abs_path):
|
|
44
|
-
coder.io.tool_output(f"⚠️ File '{file_path}' not found")
|
|
45
|
-
return "Error: File not found"
|
|
24
|
+
}
|
|
46
25
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
26
|
+
# Keep the underscore prefix as this function is primarily for internal coder use
|
|
27
|
+
@classmethod
|
|
28
|
+
def execute(cls, coder, file_path):
|
|
29
|
+
"""
|
|
30
|
+
Convert a read-only file to an editable file.
|
|
52
31
|
|
|
53
|
-
|
|
54
|
-
|
|
32
|
+
This allows the LLM to upgrade a file from read-only to editable
|
|
33
|
+
when it determines it needs to make changes to that file.
|
|
34
|
+
"""
|
|
35
|
+
try:
|
|
36
|
+
# Get absolute path
|
|
37
|
+
abs_path = coder.abs_root_path(file_path)
|
|
55
38
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
# File was not previously in context at all
|
|
61
|
-
coder.io.tool_output(f"📝 Added '{file_path}' directly to editable context")
|
|
62
|
-
# Track if added during exploration? Maybe not needed for direct MakeEditable.
|
|
63
|
-
# coder.files_added_in_exploration.add(rel_path) # Consider if needed
|
|
64
|
-
return "File is now editable (added directly)"
|
|
65
|
-
except Exception as e:
|
|
66
|
-
coder.io.tool_error(f"Error in MakeEditable for '{file_path}': {str(e)}")
|
|
67
|
-
return f"Error: {str(e)}"
|
|
39
|
+
# Check if file is already editable
|
|
40
|
+
if abs_path in coder.abs_fnames:
|
|
41
|
+
coder.io.tool_output(f"📝 File '{file_path}' is already editable")
|
|
42
|
+
return "File is already editable"
|
|
68
43
|
|
|
44
|
+
# Check if file exists on disk
|
|
45
|
+
if not os.path.isfile(abs_path):
|
|
46
|
+
coder.io.tool_output(f"⚠️ File '{file_path}' not found")
|
|
47
|
+
return "Error: File not found"
|
|
69
48
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
# File exists, is not editable, might be read-only or not in context yet
|
|
50
|
+
was_read_only = False
|
|
51
|
+
if abs_path in coder.abs_read_only_fnames:
|
|
52
|
+
coder.abs_read_only_fnames.remove(abs_path)
|
|
53
|
+
was_read_only = True
|
|
73
54
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
params: Dictionary of parameters
|
|
55
|
+
# Add to editable files
|
|
56
|
+
coder.abs_fnames.add(abs_path)
|
|
77
57
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
58
|
+
if was_read_only:
|
|
59
|
+
coder.io.tool_output(f"📝 Moved '{file_path}' from read-only to editable")
|
|
60
|
+
return "File is now editable (moved from read-only)"
|
|
61
|
+
else:
|
|
62
|
+
# File was not previously in context at all
|
|
63
|
+
coder.io.tool_output(f"📝 Added '{file_path}' directly to editable context")
|
|
64
|
+
# Track if added during exploration? Maybe not needed for direct MakeEditable.
|
|
65
|
+
# coder.files_added_in_exploration.add(rel_path) # Consider if needed
|
|
66
|
+
return "File is now editable (added directly)"
|
|
67
|
+
except Exception as e:
|
|
68
|
+
coder.io.tool_error(f"Error in MakeEditable for '{file_path}': {str(e)}")
|
|
69
|
+
return f"Error: {str(e)}"
|
aider/tools/make_readonly.py
CHANGED
|
@@ -1,69 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
from aider.tools.utils.base_tool import BaseTool
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Tool(BaseTool):
|
|
5
|
+
NORM_NAME = "makereadonly"
|
|
6
|
+
SCHEMA = {
|
|
7
|
+
"type": "function",
|
|
8
|
+
"function": {
|
|
9
|
+
"name": "MakeReadonly",
|
|
10
|
+
"description": "Make an editable file read-only.",
|
|
11
|
+
"parameters": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"properties": {
|
|
14
|
+
"file_path": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "The path to the file to make read-only.",
|
|
17
|
+
},
|
|
12
18
|
},
|
|
19
|
+
"required": ["file_path"],
|
|
13
20
|
},
|
|
14
|
-
"required": ["file_path"],
|
|
15
21
|
},
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return "File is now read-only"
|
|
49
|
-
except Exception as e:
|
|
50
|
-
coder.io.tool_error(f"Error making file read-only: {str(e)}")
|
|
51
|
-
return f"Error: {str(e)}"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def process_response(coder, params):
|
|
55
|
-
"""
|
|
56
|
-
Process the MakeReadonly tool response.
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
coder: The Coder instance
|
|
60
|
-
params: Dictionary of parameters
|
|
61
|
-
|
|
62
|
-
Returns:
|
|
63
|
-
str: Result message
|
|
64
|
-
"""
|
|
65
|
-
file_path = params.get("file_path")
|
|
66
|
-
if file_path is not None:
|
|
67
|
-
return _execute_make_readonly(coder, file_path)
|
|
68
|
-
else:
|
|
69
|
-
return "Error: Missing 'file_path' parameter for MakeReadonly"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def execute(cls, coder, file_path):
|
|
26
|
+
"""
|
|
27
|
+
Convert an editable file to a read-only file.
|
|
28
|
+
|
|
29
|
+
This allows the LLM to downgrade a file from editable to read-only
|
|
30
|
+
when it determines it no longer needs to make changes to that file.
|
|
31
|
+
"""
|
|
32
|
+
try:
|
|
33
|
+
# Get absolute path
|
|
34
|
+
abs_path = coder.abs_root_path(file_path)
|
|
35
|
+
|
|
36
|
+
# Check if file is in editable context
|
|
37
|
+
if abs_path not in coder.abs_fnames:
|
|
38
|
+
if abs_path in coder.abs_read_only_fnames:
|
|
39
|
+
coder.io.tool_output(f"📚 File '{file_path}' is already read-only")
|
|
40
|
+
return "File is already read-only"
|
|
41
|
+
else:
|
|
42
|
+
coder.io.tool_output(f"⚠️ File '{file_path}' not in context")
|
|
43
|
+
return "File not in context"
|
|
44
|
+
|
|
45
|
+
# Move from editable to read-only
|
|
46
|
+
coder.abs_fnames.remove(abs_path)
|
|
47
|
+
coder.abs_read_only_fnames.add(abs_path)
|
|
48
|
+
|
|
49
|
+
coder.io.tool_output(f"📚 Made '{file_path}' read-only")
|
|
50
|
+
return "File is now read-only"
|
|
51
|
+
except Exception as e:
|
|
52
|
+
coder.io.tool_error(f"Error making file read-only: {str(e)}")
|
|
53
|
+
return f"Error: {str(e)}"
|
aider/tools/remove.py
CHANGED
|
@@ -1,91 +1,75 @@
|
|
|
1
1
|
import time
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
from aider.tools.utils.base_tool import BaseTool
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Tool(BaseTool):
|
|
7
|
+
NORM_NAME = "remove"
|
|
8
|
+
SCHEMA = {
|
|
9
|
+
"type": "function",
|
|
10
|
+
"function": {
|
|
11
|
+
"name": "Remove",
|
|
12
|
+
"description": (
|
|
13
|
+
"Remove a file from the chat context. Should be used proactively to keep con"
|
|
14
|
+
"Should be used after editing a file when all edits are done "
|
|
15
|
+
"and the file is no longer necessary in context."
|
|
16
|
+
),
|
|
17
|
+
"parameters": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"properties": {
|
|
20
|
+
"file_path": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "The path to the file to remove.",
|
|
23
|
+
},
|
|
18
24
|
},
|
|
25
|
+
"required": ["file_path"],
|
|
19
26
|
},
|
|
20
|
-
"required": ["file_path"],
|
|
21
27
|
},
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
# Normalized tool name for lookup
|
|
26
|
-
NORM_NAME = "remove"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _execute_remove(coder, file_path):
|
|
30
|
-
"""
|
|
31
|
-
Explicitly remove a file from context.
|
|
32
|
-
|
|
33
|
-
This allows the LLM to clean up its context when files are no
|
|
34
|
-
longer needed, keeping the context focused and efficient.
|
|
35
|
-
"""
|
|
36
|
-
try:
|
|
37
|
-
# Get absolute path
|
|
38
|
-
abs_path = coder.abs_root_path(file_path)
|
|
39
|
-
rel_path = coder.get_rel_fname(abs_path)
|
|
40
|
-
|
|
41
|
-
# Check if file is in context (either editable or read-only)
|
|
42
|
-
removed = False
|
|
43
|
-
if abs_path in coder.abs_fnames:
|
|
44
|
-
# Don't remove if it's the last editable file and there are no read-only files
|
|
45
|
-
if len(coder.abs_fnames) <= 1 and not coder.abs_read_only_fnames:
|
|
46
|
-
coder.io.tool_output(
|
|
47
|
-
f"⚠️ Cannot remove '{file_path}' - it's the only file in context"
|
|
48
|
-
)
|
|
49
|
-
return "Cannot remove - last file in context"
|
|
50
|
-
coder.abs_fnames.remove(abs_path)
|
|
51
|
-
removed = True
|
|
52
|
-
elif abs_path in coder.abs_read_only_fnames:
|
|
53
|
-
# Don't remove if it's the last read-only file and there are no editable files
|
|
54
|
-
if len(coder.abs_read_only_fnames) <= 1 and not coder.abs_fnames:
|
|
55
|
-
coder.io.tool_output(
|
|
56
|
-
f"⚠️ Cannot remove '{file_path}' - it's the only file in context"
|
|
57
|
-
)
|
|
58
|
-
return "Cannot remove - last file in context"
|
|
59
|
-
coder.abs_read_only_fnames.remove(abs_path)
|
|
60
|
-
removed = True
|
|
61
|
-
|
|
62
|
-
if not removed:
|
|
63
|
-
coder.io.tool_output(f"⚠️ File '{file_path}' not in context")
|
|
64
|
-
return "File not in context"
|
|
28
|
+
}
|
|
65
29
|
|
|
66
|
-
|
|
67
|
-
|
|
30
|
+
@classmethod
|
|
31
|
+
def execute(cls, coder, file_path):
|
|
32
|
+
"""
|
|
33
|
+
Explicitly remove a file from context.
|
|
68
34
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
35
|
+
This allows the LLM to clean up its context when files are no
|
|
36
|
+
longer needed, keeping the context focused and efficient.
|
|
37
|
+
"""
|
|
38
|
+
try:
|
|
39
|
+
# Get absolute path
|
|
40
|
+
abs_path = coder.abs_root_path(file_path)
|
|
41
|
+
rel_path = coder.get_rel_fname(abs_path)
|
|
74
42
|
|
|
43
|
+
# Check if file is in context (either editable or read-only)
|
|
44
|
+
removed = False
|
|
45
|
+
if abs_path in coder.abs_fnames:
|
|
46
|
+
# Don't remove if it's the last editable file and there are no read-only files
|
|
47
|
+
if len(coder.abs_fnames) <= 1 and not coder.abs_read_only_fnames:
|
|
48
|
+
coder.io.tool_output(
|
|
49
|
+
f"⚠️ Cannot remove '{file_path}' - it's the only file in context"
|
|
50
|
+
)
|
|
51
|
+
return "Cannot remove - last file in context"
|
|
52
|
+
coder.abs_fnames.remove(abs_path)
|
|
53
|
+
removed = True
|
|
54
|
+
elif abs_path in coder.abs_read_only_fnames:
|
|
55
|
+
# Don't remove if it's the last read-only file and there are no editable files
|
|
56
|
+
if len(coder.abs_read_only_fnames) <= 1 and not coder.abs_fnames:
|
|
57
|
+
coder.io.tool_output(
|
|
58
|
+
f"⚠️ Cannot remove '{file_path}' - it's the only file in context"
|
|
59
|
+
)
|
|
60
|
+
return "Cannot remove - last file in context"
|
|
61
|
+
coder.abs_read_only_fnames.remove(abs_path)
|
|
62
|
+
removed = True
|
|
75
63
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
if not removed:
|
|
65
|
+
coder.io.tool_output(f"⚠️ File '{file_path}' not in context")
|
|
66
|
+
return "File not in context"
|
|
79
67
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
params: Dictionary of parameters
|
|
68
|
+
# Track in recently removed
|
|
69
|
+
coder.recently_removed[rel_path] = {"removed_at": time.time()}
|
|
83
70
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return _execute_remove(coder, file_path)
|
|
90
|
-
else:
|
|
91
|
-
return "Error: Missing 'file_path' parameter for Remove"
|
|
71
|
+
coder.io.tool_output(f"🗑️ Explicitly removed '{file_path}' from context")
|
|
72
|
+
return "Removed file from context"
|
|
73
|
+
except Exception as e:
|
|
74
|
+
coder.io.tool_error(f"Error removing file: {str(e)}")
|
|
75
|
+
return f"Error: {str(e)}"
|