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/delete_line.py
CHANGED
|
@@ -1,155 +1,120 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
from .tool_utils import (
|
|
1
|
+
from aider.tools.utils.base_tool import BaseTool
|
|
2
|
+
from aider.tools.utils.helpers import (
|
|
4
3
|
ToolError,
|
|
5
4
|
apply_change,
|
|
6
5
|
format_tool_result,
|
|
7
6
|
generate_unified_diff_snippet,
|
|
8
7
|
handle_tool_error,
|
|
8
|
+
validate_file_for_edit,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
11
|
+
|
|
12
|
+
class Tool(BaseTool):
|
|
13
|
+
NORM_NAME = "deleteline"
|
|
14
|
+
SCHEMA = {
|
|
15
|
+
"type": "function",
|
|
16
|
+
"function": {
|
|
17
|
+
"name": "DeleteLine",
|
|
18
|
+
"description": "Delete a single line from a file.",
|
|
19
|
+
"parameters": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"properties": {
|
|
22
|
+
"file_path": {"type": "string"},
|
|
23
|
+
"line_number": {"type": "integer"},
|
|
24
|
+
"change_id": {"type": "string"},
|
|
25
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
26
|
+
},
|
|
27
|
+
"required": ["file_path", "line_number"],
|
|
23
28
|
},
|
|
24
|
-
"required": ["file_path", "line_number"],
|
|
25
29
|
},
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
# Normalized tool name for lookup
|
|
30
|
-
NORM_NAME = "deleteline"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _execute_delete_line(coder, file_path, line_number, change_id=None, dry_run=False):
|
|
34
|
-
"""
|
|
35
|
-
Delete a specific line number (1-based).
|
|
30
|
+
}
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- change_id: Optional ID for tracking the change
|
|
42
|
-
- dry_run: If True, simulate the change without modifying the file
|
|
32
|
+
@classmethod
|
|
33
|
+
def execute(cls, coder, file_path, line_number, change_id=None, dry_run=False):
|
|
34
|
+
"""
|
|
35
|
+
Delete a specific line number (1-based).
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
Parameters:
|
|
38
|
+
- coder: The Coder instance
|
|
39
|
+
- file_path: Path to the file to modify
|
|
40
|
+
- line_number: The 1-based line number to delete
|
|
41
|
+
- change_id: Optional ID for tracking the change
|
|
42
|
+
- dry_run: If True, simulate the change without modifying the file
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# Get absolute file path
|
|
50
|
-
abs_path = coder.abs_root_path(file_path)
|
|
51
|
-
rel_path = coder.get_rel_fname(abs_path)
|
|
44
|
+
Returns a result message.
|
|
45
|
+
"""
|
|
52
46
|
|
|
53
|
-
|
|
54
|
-
if not os.path.isfile(abs_path):
|
|
55
|
-
raise ToolError(f"File '{file_path}' not found")
|
|
56
|
-
|
|
57
|
-
# Check if file is in editable context
|
|
58
|
-
if abs_path not in coder.abs_fnames:
|
|
59
|
-
if abs_path in coder.abs_read_only_fnames:
|
|
60
|
-
raise ToolError(f"File '{file_path}' is read-only. Use MakeEditable first.")
|
|
61
|
-
else:
|
|
62
|
-
raise ToolError(f"File '{file_path}' not in context")
|
|
63
|
-
|
|
64
|
-
# Reread file content immediately before modification
|
|
65
|
-
file_content = coder.io.read_text(abs_path)
|
|
66
|
-
if file_content is None:
|
|
67
|
-
raise ToolError(f"Could not read file '{file_path}'")
|
|
68
|
-
|
|
69
|
-
lines = file_content.splitlines()
|
|
70
|
-
original_content = file_content
|
|
71
|
-
|
|
72
|
-
# Validate line number
|
|
47
|
+
tool_name = "DeleteLine"
|
|
73
48
|
try:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
49
|
+
# 1. Validate file and get content
|
|
50
|
+
abs_path, rel_path, original_content = validate_file_for_edit(coder, file_path)
|
|
51
|
+
lines = original_content.splitlines()
|
|
52
|
+
|
|
53
|
+
# Validate line number
|
|
54
|
+
try:
|
|
55
|
+
line_num_int = int(line_number)
|
|
56
|
+
if line_num_int < 1 or line_num_int > len(lines):
|
|
57
|
+
raise ToolError(f"Line number {line_num_int} is out of range (1-{len(lines)})")
|
|
58
|
+
line_idx = line_num_int - 1 # Convert to 0-based index
|
|
59
|
+
except ValueError:
|
|
60
|
+
raise ToolError(f"Invalid line_number value: '{line_number}'. Must be an integer.")
|
|
61
|
+
|
|
62
|
+
# Prepare the deletion
|
|
63
|
+
deleted_line = lines[line_idx]
|
|
64
|
+
new_lines = lines[:line_idx] + lines[line_idx + 1 :]
|
|
65
|
+
new_content = "\n".join(new_lines)
|
|
66
|
+
|
|
67
|
+
if original_content == new_content:
|
|
68
|
+
coder.io.tool_warning(
|
|
69
|
+
f"No changes made: deleting line {line_num_int} would not change file"
|
|
70
|
+
)
|
|
71
|
+
return (
|
|
72
|
+
f"Warning: No changes made (deleting line {line_num_int} would not change file)"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Generate diff snippet
|
|
76
|
+
diff_snippet = generate_unified_diff_snippet(original_content, new_content, rel_path)
|
|
77
|
+
|
|
78
|
+
# Handle dry run
|
|
79
|
+
if dry_run:
|
|
80
|
+
dry_run_message = f"Dry run: Would delete line {line_num_int} in {file_path}"
|
|
81
|
+
return format_tool_result(
|
|
82
|
+
coder,
|
|
83
|
+
tool_name,
|
|
84
|
+
"",
|
|
85
|
+
dry_run=True,
|
|
86
|
+
dry_run_message=dry_run_message,
|
|
87
|
+
diff_snippet=diff_snippet,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# --- Apply Change (Not dry run) ---
|
|
91
|
+
metadata = {"line_number": line_num_int, "deleted_content": deleted_line}
|
|
92
|
+
final_change_id = apply_change(
|
|
93
|
+
coder,
|
|
94
|
+
abs_path,
|
|
95
|
+
rel_path,
|
|
96
|
+
original_content,
|
|
97
|
+
new_content,
|
|
98
|
+
"deleteline",
|
|
99
|
+
metadata,
|
|
100
|
+
change_id,
|
|
89
101
|
)
|
|
90
|
-
return f"Warning: No changes made (deleting line {line_num_int} would not change file)"
|
|
91
102
|
|
|
92
|
-
|
|
93
|
-
diff_snippet = generate_unified_diff_snippet(original_content, new_content, rel_path)
|
|
103
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
94
104
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
dry_run_message = f"Dry run: Would delete line {line_num_int} in {file_path}"
|
|
105
|
+
# Format and return result
|
|
106
|
+
success_message = f"Deleted line {line_num_int} in {file_path}"
|
|
98
107
|
return format_tool_result(
|
|
99
108
|
coder,
|
|
100
109
|
tool_name,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
dry_run_message=dry_run_message,
|
|
110
|
+
success_message,
|
|
111
|
+
change_id=final_change_id,
|
|
104
112
|
diff_snippet=diff_snippet,
|
|
105
113
|
)
|
|
106
114
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
original_content,
|
|
114
|
-
new_content,
|
|
115
|
-
"deleteline",
|
|
116
|
-
metadata,
|
|
117
|
-
change_id,
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
coder.files_edited_by_tools.add(rel_path)
|
|
121
|
-
|
|
122
|
-
# Format and return result
|
|
123
|
-
success_message = f"Deleted line {line_num_int} in {file_path}"
|
|
124
|
-
return format_tool_result(
|
|
125
|
-
coder, tool_name, success_message, change_id=final_change_id, diff_snippet=diff_snippet
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
except ToolError as e:
|
|
129
|
-
# Handle errors raised by utility functions (expected errors)
|
|
130
|
-
return handle_tool_error(coder, tool_name, e, add_traceback=False)
|
|
131
|
-
except Exception as e:
|
|
132
|
-
# Handle unexpected errors
|
|
133
|
-
return handle_tool_error(coder, tool_name, e)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def process_response(coder, params):
|
|
137
|
-
"""
|
|
138
|
-
Process the DeleteLine tool response.
|
|
139
|
-
|
|
140
|
-
Args:
|
|
141
|
-
coder: The Coder instance
|
|
142
|
-
params: Dictionary of parameters
|
|
143
|
-
|
|
144
|
-
Returns:
|
|
145
|
-
str: Result message
|
|
146
|
-
"""
|
|
147
|
-
file_path = params.get("file_path")
|
|
148
|
-
line_number = params.get("line_number")
|
|
149
|
-
change_id = params.get("change_id")
|
|
150
|
-
dry_run = params.get("dry_run", False)
|
|
151
|
-
|
|
152
|
-
if file_path is not None and line_number is not None:
|
|
153
|
-
return _execute_delete_line(coder, file_path, line_number, change_id, dry_run)
|
|
154
|
-
else:
|
|
155
|
-
return "Error: Missing required parameters for DeleteLine (file_path, line_number)"
|
|
115
|
+
except ToolError as e:
|
|
116
|
+
# Handle errors raised by utility functions (expected errors)
|
|
117
|
+
return handle_tool_error(coder, tool_name, e, add_traceback=False)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
# Handle unexpected errors
|
|
120
|
+
return handle_tool_error(coder, tool_name, e)
|
aider/tools/delete_lines.py
CHANGED
|
@@ -1,184 +1,144 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
from .tool_utils import (
|
|
1
|
+
from aider.tools.utils.base_tool import BaseTool
|
|
2
|
+
from aider.tools.utils.helpers import (
|
|
4
3
|
ToolError,
|
|
5
4
|
apply_change,
|
|
6
5
|
format_tool_result,
|
|
7
6
|
generate_unified_diff_snippet,
|
|
8
7
|
handle_tool_error,
|
|
8
|
+
validate_file_for_edit,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
|
|
12
|
+
class Tool(BaseTool):
|
|
13
|
+
NORM_NAME = "deletelines"
|
|
14
|
+
SCHEMA = {
|
|
15
|
+
"type": "function",
|
|
16
|
+
"function": {
|
|
17
|
+
"name": "DeleteLines",
|
|
18
|
+
"description": "Delete a range of lines from a file.",
|
|
19
|
+
"parameters": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"properties": {
|
|
22
|
+
"file_path": {"type": "string"},
|
|
23
|
+
"start_line": {"type": "integer"},
|
|
24
|
+
"end_line": {"type": "integer"},
|
|
25
|
+
"change_id": {"type": "string"},
|
|
26
|
+
"dry_run": {"type": "boolean", "default": False},
|
|
27
|
+
},
|
|
28
|
+
"required": ["file_path", "start_line", "end_line"],
|
|
24
29
|
},
|
|
25
|
-
"required": ["file_path", "start_line", "end_line"],
|
|
26
30
|
},
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Returns a result message.
|
|
47
|
-
"""
|
|
48
|
-
tool_name = "DeleteLines"
|
|
49
|
-
try:
|
|
50
|
-
# Get absolute file path
|
|
51
|
-
abs_path = coder.abs_root_path(file_path)
|
|
52
|
-
rel_path = coder.get_rel_fname(abs_path)
|
|
53
|
-
|
|
54
|
-
# Check if file exists
|
|
55
|
-
if not os.path.isfile(abs_path):
|
|
56
|
-
raise ToolError(f"File '{file_path}' not found")
|
|
57
|
-
|
|
58
|
-
# Check if file is in editable context
|
|
59
|
-
if abs_path not in coder.abs_fnames:
|
|
60
|
-
if abs_path in coder.abs_read_only_fnames:
|
|
61
|
-
raise ToolError(f"File '{file_path}' is read-only. Use MakeEditable first.")
|
|
62
|
-
else:
|
|
63
|
-
raise ToolError(f"File '{file_path}' not in context")
|
|
64
|
-
|
|
65
|
-
# Reread file content immediately before modification
|
|
66
|
-
file_content = coder.io.read_text(abs_path)
|
|
67
|
-
if file_content is None:
|
|
68
|
-
raise ToolError(f"Could not read file '{file_path}'")
|
|
69
|
-
|
|
70
|
-
lines = file_content.splitlines()
|
|
71
|
-
original_content = file_content
|
|
72
|
-
|
|
73
|
-
# Validate line numbers
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def execute(cls, coder, file_path, start_line, end_line, change_id=None, dry_run=False):
|
|
35
|
+
"""
|
|
36
|
+
Delete a range of lines (1-based, inclusive).
|
|
37
|
+
|
|
38
|
+
Parameters:
|
|
39
|
+
- coder: The Coder instance
|
|
40
|
+
- file_path: Path to the file to modify
|
|
41
|
+
- start_line: The 1-based starting line number to delete
|
|
42
|
+
- end_line: The 1-based ending line number to delete
|
|
43
|
+
- change_id: Optional ID for tracking the change
|
|
44
|
+
- dry_run: If True, simulate the change without modifying the file
|
|
45
|
+
|
|
46
|
+
Returns a result message.
|
|
47
|
+
"""
|
|
48
|
+
tool_name = "DeleteLines"
|
|
74
49
|
try:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
50
|
+
# 1. Validate file and get content
|
|
51
|
+
abs_path, rel_path, original_content = validate_file_for_edit(coder, file_path)
|
|
52
|
+
lines = original_content.splitlines()
|
|
53
|
+
|
|
54
|
+
# Validate line numbers
|
|
55
|
+
try:
|
|
56
|
+
start_line_int = int(start_line)
|
|
57
|
+
end_line_int = int(end_line)
|
|
58
|
+
|
|
59
|
+
if start_line_int < 1 or start_line_int > len(lines):
|
|
60
|
+
raise ToolError(f"Start line {start_line_int} is out of range (1-{len(lines)})")
|
|
61
|
+
if end_line_int < 1 or end_line_int > len(lines):
|
|
62
|
+
raise ToolError(f"End line {end_line_int} is out of range (1-{len(lines)})")
|
|
63
|
+
if start_line_int > end_line_int:
|
|
64
|
+
raise ToolError(
|
|
65
|
+
f"Start line {start_line_int} cannot be after end line {end_line_int}"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
start_idx = start_line_int - 1 # Convert to 0-based index
|
|
69
|
+
end_idx = end_line_int - 1 # Convert to 0-based index
|
|
70
|
+
except ValueError:
|
|
83
71
|
raise ToolError(
|
|
84
|
-
f"
|
|
72
|
+
f"Invalid line numbers: '{start_line}', '{end_line}'. Must be integers."
|
|
85
73
|
)
|
|
86
74
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
f"Invalid line numbers: '{start_line}', '{end_line}'. Must be integers."
|
|
92
|
-
)
|
|
75
|
+
# Prepare the deletion
|
|
76
|
+
deleted_lines = lines[start_idx : end_idx + 1]
|
|
77
|
+
new_lines = lines[:start_idx] + lines[end_idx + 1 :]
|
|
78
|
+
new_content = "\n".join(new_lines)
|
|
93
79
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
if original_content == new_content:
|
|
81
|
+
coder.io.tool_warning(
|
|
82
|
+
f"No changes made: deleting lines {start_line_int}-{end_line_int} would not"
|
|
83
|
+
" change file"
|
|
84
|
+
)
|
|
85
|
+
return (
|
|
86
|
+
"Warning: No changes made (deleting lines"
|
|
87
|
+
f" {start_line_int}-{end_line_int} would not change file)"
|
|
88
|
+
)
|
|
98
89
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
f"No changes made: deleting lines {start_line_int}-{end_line_int} would not change"
|
|
102
|
-
" file"
|
|
103
|
-
)
|
|
104
|
-
return (
|
|
105
|
-
f"Warning: No changes made (deleting lines {start_line_int}-{end_line_int} would"
|
|
106
|
-
" not change file)"
|
|
107
|
-
)
|
|
90
|
+
# Generate diff snippet
|
|
91
|
+
diff_snippet = generate_unified_diff_snippet(original_content, new_content, rel_path)
|
|
108
92
|
|
|
109
|
-
|
|
110
|
-
|
|
93
|
+
# Handle dry run
|
|
94
|
+
if dry_run:
|
|
95
|
+
dry_run_message = (
|
|
96
|
+
f"Dry run: Would delete lines {start_line_int}-{end_line_int} in {file_path}"
|
|
97
|
+
)
|
|
98
|
+
return format_tool_result(
|
|
99
|
+
coder,
|
|
100
|
+
tool_name,
|
|
101
|
+
"",
|
|
102
|
+
dry_run=True,
|
|
103
|
+
dry_run_message=dry_run_message,
|
|
104
|
+
diff_snippet=diff_snippet,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# --- Apply Change (Not dry run) ---
|
|
108
|
+
metadata = {
|
|
109
|
+
"start_line": start_line_int,
|
|
110
|
+
"end_line": end_line_int,
|
|
111
|
+
"deleted_content": "\n".join(deleted_lines),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
final_change_id = apply_change(
|
|
115
|
+
coder,
|
|
116
|
+
abs_path,
|
|
117
|
+
rel_path,
|
|
118
|
+
original_content,
|
|
119
|
+
new_content,
|
|
120
|
+
"deletelines",
|
|
121
|
+
metadata,
|
|
122
|
+
change_id,
|
|
123
|
+
)
|
|
111
124
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
125
|
+
coder.files_edited_by_tools.add(rel_path)
|
|
126
|
+
num_deleted = end_idx - start_idx + 1
|
|
127
|
+
# Format and return result
|
|
128
|
+
success_message = (
|
|
129
|
+
f"Deleted {num_deleted} lines ({start_line_int}-{end_line_int}) in {file_path}"
|
|
116
130
|
)
|
|
117
131
|
return format_tool_result(
|
|
118
132
|
coder,
|
|
119
133
|
tool_name,
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
dry_run_message=dry_run_message,
|
|
134
|
+
success_message,
|
|
135
|
+
change_id=final_change_id,
|
|
123
136
|
diff_snippet=diff_snippet,
|
|
124
137
|
)
|
|
125
138
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
final_change_id = apply_change(
|
|
134
|
-
coder,
|
|
135
|
-
abs_path,
|
|
136
|
-
rel_path,
|
|
137
|
-
original_content,
|
|
138
|
-
new_content,
|
|
139
|
-
"deletelines",
|
|
140
|
-
metadata,
|
|
141
|
-
change_id,
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
coder.files_edited_by_tools.add(rel_path)
|
|
145
|
-
num_deleted = end_idx - start_idx + 1
|
|
146
|
-
# Format and return result
|
|
147
|
-
success_message = (
|
|
148
|
-
f"Deleted {num_deleted} lines ({start_line_int}-{end_line_int}) in {file_path}"
|
|
149
|
-
)
|
|
150
|
-
return format_tool_result(
|
|
151
|
-
coder, tool_name, success_message, change_id=final_change_id, diff_snippet=diff_snippet
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
except ToolError as e:
|
|
155
|
-
# Handle errors raised by utility functions (expected errors)
|
|
156
|
-
return handle_tool_error(coder, tool_name, e, add_traceback=False)
|
|
157
|
-
except Exception as e:
|
|
158
|
-
# Handle unexpected errors
|
|
159
|
-
return handle_tool_error(coder, tool_name, e)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
def process_response(coder, params):
|
|
163
|
-
"""
|
|
164
|
-
Process the DeleteLines tool response.
|
|
165
|
-
|
|
166
|
-
Args:
|
|
167
|
-
coder: The Coder instance
|
|
168
|
-
params: Dictionary of parameters
|
|
169
|
-
|
|
170
|
-
Returns:
|
|
171
|
-
str: Result message
|
|
172
|
-
"""
|
|
173
|
-
file_path = params.get("file_path")
|
|
174
|
-
start_line = params.get("start_line")
|
|
175
|
-
end_line = params.get("end_line")
|
|
176
|
-
change_id = params.get("change_id")
|
|
177
|
-
dry_run = params.get("dry_run", False)
|
|
178
|
-
|
|
179
|
-
if file_path is not None and start_line is not None and end_line is not None:
|
|
180
|
-
return _execute_delete_lines(coder, file_path, start_line, end_line, change_id, dry_run)
|
|
181
|
-
else:
|
|
182
|
-
return (
|
|
183
|
-
"Error: Missing required parameters for DeleteLines (file_path, start_line, end_line)"
|
|
184
|
-
)
|
|
139
|
+
except ToolError as e:
|
|
140
|
+
# Handle errors raised by utility functions (expected errors)
|
|
141
|
+
return handle_tool_error(coder, tool_name, e, add_traceback=False)
|
|
142
|
+
except Exception as e:
|
|
143
|
+
# Handle unexpected errors
|
|
144
|
+
return handle_tool_error(coder, tool_name, e)
|