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.
Files changed (113) hide show
  1. aider/__init__.py +1 -1
  2. aider/_version.py +2 -2
  3. aider/args.py +63 -43
  4. aider/coders/agent_coder.py +331 -79
  5. aider/coders/agent_prompts.py +3 -15
  6. aider/coders/architect_coder.py +21 -5
  7. aider/coders/base_coder.py +661 -413
  8. aider/coders/base_prompts.py +6 -3
  9. aider/coders/chat_chunks.py +39 -17
  10. aider/commands.py +79 -15
  11. aider/diffs.py +10 -9
  12. aider/exceptions.py +1 -1
  13. aider/helpers/coroutines.py +8 -0
  14. aider/helpers/requests.py +45 -0
  15. aider/history.py +5 -0
  16. aider/io.py +179 -25
  17. aider/main.py +86 -35
  18. aider/models.py +16 -8
  19. aider/queries/tree-sitter-language-pack/c-tags.scm +3 -0
  20. aider/queries/tree-sitter-language-pack/clojure-tags.scm +5 -0
  21. aider/queries/tree-sitter-language-pack/commonlisp-tags.scm +5 -0
  22. aider/queries/tree-sitter-language-pack/cpp-tags.scm +3 -0
  23. aider/queries/tree-sitter-language-pack/csharp-tags.scm +6 -0
  24. aider/queries/tree-sitter-language-pack/dart-tags.scm +5 -0
  25. aider/queries/tree-sitter-language-pack/elixir-tags.scm +5 -0
  26. aider/queries/tree-sitter-language-pack/elm-tags.scm +3 -0
  27. aider/queries/tree-sitter-language-pack/go-tags.scm +7 -0
  28. aider/queries/tree-sitter-language-pack/java-tags.scm +6 -0
  29. aider/queries/tree-sitter-language-pack/javascript-tags.scm +8 -0
  30. aider/queries/tree-sitter-language-pack/lua-tags.scm +5 -0
  31. aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +3 -0
  32. aider/queries/tree-sitter-language-pack/python-tags.scm +10 -0
  33. aider/queries/tree-sitter-language-pack/r-tags.scm +6 -0
  34. aider/queries/tree-sitter-language-pack/ruby-tags.scm +5 -0
  35. aider/queries/tree-sitter-language-pack/rust-tags.scm +3 -0
  36. aider/queries/tree-sitter-language-pack/solidity-tags.scm +1 -1
  37. aider/queries/tree-sitter-language-pack/swift-tags.scm +4 -1
  38. aider/queries/tree-sitter-languages/c-tags.scm +3 -0
  39. aider/queries/tree-sitter-languages/c_sharp-tags.scm +6 -0
  40. aider/queries/tree-sitter-languages/cpp-tags.scm +3 -0
  41. aider/queries/tree-sitter-languages/dart-tags.scm +2 -1
  42. aider/queries/tree-sitter-languages/elixir-tags.scm +5 -0
  43. aider/queries/tree-sitter-languages/elm-tags.scm +3 -0
  44. aider/queries/tree-sitter-languages/fortran-tags.scm +3 -0
  45. aider/queries/tree-sitter-languages/go-tags.scm +6 -0
  46. aider/queries/tree-sitter-languages/haskell-tags.scm +2 -0
  47. aider/queries/tree-sitter-languages/java-tags.scm +6 -0
  48. aider/queries/tree-sitter-languages/javascript-tags.scm +8 -0
  49. aider/queries/tree-sitter-languages/julia-tags.scm +2 -2
  50. aider/queries/tree-sitter-languages/kotlin-tags.scm +3 -0
  51. aider/queries/tree-sitter-languages/ocaml_interface-tags.scm +6 -0
  52. aider/queries/tree-sitter-languages/php-tags.scm +6 -0
  53. aider/queries/tree-sitter-languages/python-tags.scm +10 -0
  54. aider/queries/tree-sitter-languages/ruby-tags.scm +5 -0
  55. aider/queries/tree-sitter-languages/rust-tags.scm +3 -0
  56. aider/queries/tree-sitter-languages/scala-tags.scm +2 -3
  57. aider/queries/tree-sitter-languages/typescript-tags.scm +3 -0
  58. aider/queries/tree-sitter-languages/zig-tags.scm +20 -3
  59. aider/repomap.py +71 -11
  60. aider/resources/model-metadata.json +27335 -635
  61. aider/resources/model-settings.yml +190 -0
  62. aider/scrape.py +2 -0
  63. aider/tools/__init__.py +2 -0
  64. aider/tools/command.py +84 -94
  65. aider/tools/command_interactive.py +95 -110
  66. aider/tools/delete_block.py +131 -159
  67. aider/tools/delete_line.py +97 -132
  68. aider/tools/delete_lines.py +120 -160
  69. aider/tools/extract_lines.py +288 -312
  70. aider/tools/finished.py +30 -43
  71. aider/tools/git_branch.py +107 -109
  72. aider/tools/git_diff.py +44 -56
  73. aider/tools/git_log.py +39 -53
  74. aider/tools/git_remote.py +37 -51
  75. aider/tools/git_show.py +33 -47
  76. aider/tools/git_status.py +30 -44
  77. aider/tools/grep.py +214 -242
  78. aider/tools/indent_lines.py +175 -201
  79. aider/tools/insert_block.py +220 -253
  80. aider/tools/list_changes.py +65 -80
  81. aider/tools/ls.py +64 -80
  82. aider/tools/make_editable.py +57 -73
  83. aider/tools/make_readonly.py +50 -66
  84. aider/tools/remove.py +64 -80
  85. aider/tools/replace_all.py +96 -109
  86. aider/tools/replace_line.py +118 -156
  87. aider/tools/replace_lines.py +160 -197
  88. aider/tools/replace_text.py +159 -160
  89. aider/tools/show_numbered_context.py +115 -141
  90. aider/tools/thinking.py +52 -0
  91. aider/tools/undo_change.py +78 -91
  92. aider/tools/update_todo_list.py +130 -138
  93. aider/tools/utils/base_tool.py +64 -0
  94. aider/tools/utils/output.py +118 -0
  95. aider/tools/view.py +38 -54
  96. aider/tools/view_files_matching.py +131 -134
  97. aider/tools/view_files_with_symbol.py +108 -120
  98. aider/urls.py +1 -1
  99. aider/versioncheck.py +4 -3
  100. aider/website/docs/config/adv-model-settings.md +237 -0
  101. aider/website/docs/config/agent-mode.md +36 -3
  102. aider/website/docs/config/model-aliases.md +2 -1
  103. aider/website/docs/faq.md +6 -11
  104. aider/website/docs/languages.md +2 -2
  105. aider/website/docs/more/infinite-output.md +27 -0
  106. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/METADATA +112 -70
  107. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/RECORD +112 -107
  108. aider_ce-0.88.38.dist-info/entry_points.txt +6 -0
  109. aider_ce-0.88.20.dist-info/entry_points.txt +0 -2
  110. /aider/tools/{tool_utils.py → utils/helpers.py} +0 -0
  111. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/WHEEL +0 -0
  112. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/licenses/LICENSE.txt +0 -0
  113. {aider_ce-0.88.20.dist-info → aider_ce-0.88.38.dist-info}/top_level.txt +0 -0
@@ -2,121 +2,106 @@
2
2
  import asyncio
3
3
 
4
4
  from aider.run_cmd import run_cmd
5
-
6
- schema = {
7
- "type": "function",
8
- "function": {
9
- "name": "CommandInteractive",
10
- "description": "Execute a shell command interactively.",
11
- "parameters": {
12
- "type": "object",
13
- "properties": {
14
- "command_string": {
15
- "type": "string",
16
- "description": "The interactive shell command to execute.",
5
+ from aider.tools.utils.base_tool import BaseTool
6
+
7
+
8
+ class Tool(BaseTool):
9
+ NORM_NAME = "commandinteractive"
10
+ SCHEMA = {
11
+ "type": "function",
12
+ "function": {
13
+ "name": "CommandInteractive",
14
+ "description": "Execute a shell command interactively.",
15
+ "parameters": {
16
+ "type": "object",
17
+ "properties": {
18
+ "command_string": {
19
+ "type": "string",
20
+ "description": "The interactive shell command to execute.",
21
+ },
17
22
  },
23
+ "required": ["command_string"],
18
24
  },
19
- "required": ["command_string"],
20
25
  },
21
- },
22
- }
23
-
24
- # Normalized tool name for lookup
25
- NORM_NAME = "commandinteractive"
26
-
27
-
28
- async def _execute_command_interactive(coder, command_string):
29
- """
30
- Execute an interactive shell command using run_cmd (which uses pexpect/PTY).
31
- """
32
- try:
33
- confirmed = (
34
- True
35
- if coder.skip_cli_confirmations
36
- else await coder.io.confirm_ask(
37
- "Allow execution of this command?",
38
- subject=command_string,
39
- explicit_yes_required=True, # Require explicit 'yes' or 'always'
40
- allow_never=True, # Enable the 'Always' option
41
- group_response="Command Interactive Tool",
26
+ }
27
+
28
+ @classmethod
29
+ async def execute(cls, coder, command_string):
30
+ """
31
+ Execute an interactive shell command using run_cmd (which uses pexpect/PTY).
32
+ """
33
+ try:
34
+ if command_string and getattr(coder.args, "command_prefix", None):
35
+ command_prefix = getattr(coder.args, "command_prefix", None)
36
+ command_string = f"{command_prefix} {command_string}"
37
+
38
+ confirmed = (
39
+ True
40
+ if coder.skip_cli_confirmations
41
+ else await coder.io.confirm_ask(
42
+ "Allow execution of this command?",
43
+ subject=command_string,
44
+ explicit_yes_required=True, # Require explicit 'yes' or 'always'
45
+ allow_never=True, # Enable the 'Always' option
46
+ group_response="Command Interactive Tool",
47
+ )
42
48
  )
43
- )
44
-
45
- if not confirmed:
46
- # This happens if the user explicitly says 'no' this time.
47
- # If 'Always' was chosen previously, confirm_ask returns True directly.
48
- coder.io.tool_output(f"Skipped execution of shell command: {command_string}")
49
- return "Shell command execution skipped by user."
50
-
51
- coder.io.tool_output(f"⚙️ Starting interactive shell command: {command_string}")
52
- coder.io.tool_output(">>> You may need to interact with the command below <<<")
53
- coder.io.tool_output(" \n")
54
-
55
- await coder.io.cancel_input_task()
56
- await asyncio.sleep(1)
57
-
58
- # Use run_cmd which handles PTY logic
59
- exit_status, combined_output = run_cmd(
60
- command_string,
61
- verbose=coder.verbose, # Pass verbose flag
62
- error_print=coder.io.tool_error, # Use io for error printing
63
- cwd=coder.root, # Execute in the project root
64
- )
65
-
66
- await asyncio.sleep(1)
67
49
 
68
- coder.io.tool_output(" \n")
69
- coder.io.tool_output(" \n")
70
- coder.io.tool_output(">>> Interactive command finished <<<")
71
-
72
- await coder.io.recreate_input()
73
-
74
- # Format the output for the result message, include more content
75
- output_content = combined_output or ""
76
- # Use the existing token threshold constant as the character limit for truncation
77
- output_limit = coder.large_file_token_threshold
78
- if len(output_content) > output_limit:
79
- # Truncate and add a clear message using the constant value
80
- output_content = (
81
- output_content[:output_limit]
82
- + f"\n... (output truncated at {output_limit} characters, based on"
83
- " large_file_token_threshold)"
50
+ if not confirmed:
51
+ # This happens if the user explicitly says 'no' this time.
52
+ # If 'Always' was chosen previously, confirm_ask returns True directly.
53
+ coder.io.tool_output(f"Skipped execution of shell command: {command_string}")
54
+ return "Shell command execution skipped by user."
55
+
56
+ coder.io.tool_output(f"⚙️ Starting interactive shell command: {command_string}")
57
+ coder.io.tool_output(">>> You may need to interact with the command below <<<")
58
+ coder.io.tool_output(" \n")
59
+
60
+ await coder.io.stop_input_task()
61
+ await asyncio.sleep(1)
62
+
63
+ # Use run_cmd which handles PTY logic
64
+ exit_status, combined_output = run_cmd(
65
+ command_string,
66
+ verbose=coder.verbose, # Pass verbose flag
67
+ error_print=coder.io.tool_error, # Use io for error printing
68
+ cwd=coder.root, # Execute in the project root
84
69
  )
85
70
 
86
- if exit_status == 0:
87
- return (
88
- "Interactive command finished successfully (exit code 0)."
89
- f" Output:\n{output_content}"
71
+ await asyncio.sleep(1)
72
+
73
+ coder.io.tool_output(" \n")
74
+ coder.io.tool_output(" \n")
75
+ coder.io.tool_output(">>> Interactive command finished <<<")
76
+
77
+ # Format the output for the result message, include more content
78
+ output_content = combined_output or ""
79
+ # Use the existing token threshold constant as the character limit for truncation
80
+ output_limit = coder.large_file_token_threshold
81
+ if len(output_content) > output_limit:
82
+ # Truncate and add a clear message using the constant value
83
+ output_content = (
84
+ output_content[:output_limit]
85
+ + f"\n... (output truncated at {output_limit} characters, based on"
86
+ " large_file_token_threshold)"
87
+ )
88
+
89
+ if exit_status == 0:
90
+ return (
91
+ "Interactive command finished successfully (exit code 0)."
92
+ f" Output:\n{output_content}"
93
+ )
94
+ else:
95
+ return (
96
+ f"Interactive command finished with exit code {exit_status}."
97
+ f" Output:\n{output_content}"
98
+ )
99
+
100
+ except Exception as e:
101
+ coder.io.tool_error(
102
+ f"Error executing interactive shell command '{command_string}': {str(e)}"
90
103
  )
91
- else:
92
- return (
93
- f"Interactive command finished with exit code {exit_status}."
94
- f" Output:\n{output_content}"
95
- )
96
-
97
- except Exception as e:
98
- coder.io.tool_error(
99
- f"Error executing interactive shell command '{command_string}': {str(e)}"
100
- )
101
- # Optionally include traceback for debugging if verbose
102
- # if coder.verbose:
103
- # coder.io.tool_error(traceback.format_exc())
104
- return f"Error executing interactive command: {str(e)}"
105
-
106
-
107
- async def process_response(coder, params):
108
- """
109
- Process the CommandInteractive tool response.
110
-
111
- Args:
112
- coder: The Coder instance
113
- params: Dictionary of parameters
114
-
115
- Returns:
116
- str: Result message
117
- """
118
- command_string = params.get("command_string")
119
- if command_string is not None:
120
- return await _execute_command_interactive(coder, command_string)
121
- else:
122
- return "Error: Missing 'command_string' parameter for CommandInteractive"
104
+ # Optionally include traceback for debugging if verbose
105
+ # if coder.verbose:
106
+ # coder.io.tool_error(traceback.format_exc())
107
+ return f"Error executing interactive command: {str(e)}"
@@ -1,4 +1,5 @@
1
- from .tool_utils import (
1
+ from aider.tools.utils.base_tool import BaseTool
2
+ from aider.tools.utils.helpers import (
2
3
  ToolError,
3
4
  apply_change,
4
5
  determine_line_range,
@@ -10,173 +11,144 @@ from .tool_utils import (
10
11
  validate_file_for_edit,
11
12
  )
12
13
 
13
- schema = {
14
- "type": "function",
15
- "function": {
16
- "name": "DeleteBlock",
17
- "description": "Delete a block of lines from 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
- "near_context": {"type": "string"},
26
- "occurrence": {"type": "integer", "default": 1},
27
- "change_id": {"type": "string"},
28
- "dry_run": {"type": "boolean", "default": False},
14
+
15
+ class Tool(BaseTool):
16
+ NORM_NAME = "deleteblock"
17
+ SCHEMA = {
18
+ "type": "function",
19
+ "function": {
20
+ "name": "DeleteBlock",
21
+ "description": "Delete a block of lines from a file.",
22
+ "parameters": {
23
+ "type": "object",
24
+ "properties": {
25
+ "file_path": {"type": "string"},
26
+ "start_pattern": {"type": "string"},
27
+ "end_pattern": {"type": "string"},
28
+ "line_count": {"type": "integer"},
29
+ "near_context": {"type": "string"},
30
+ "occurrence": {"type": "integer", "default": 1},
31
+ "change_id": {"type": "string"},
32
+ "dry_run": {"type": "boolean", "default": False},
33
+ },
34
+ "required": ["file_path", "start_pattern"],
29
35
  },
30
- "required": ["file_path", "start_pattern"],
31
36
  },
32
- },
33
- }
34
-
35
- # Normalized tool name for lookup
36
- NORM_NAME = "deleteblock"
37
-
38
-
39
- def _execute_delete_block(
40
- coder,
41
- file_path,
42
- start_pattern,
43
- end_pattern=None,
44
- line_count=None,
45
- near_context=None,
46
- occurrence=1,
47
- change_id=None,
48
- dry_run=False,
49
- ):
50
- """
51
- Delete a block of text between start_pattern and end_pattern (inclusive).
52
- Uses utility functions for validation, finding lines, and applying changes.
53
- """
54
- tool_name = "DeleteBlock"
55
- try:
56
- # 1. Validate file and get content
57
- abs_path, rel_path, original_content = validate_file_for_edit(coder, file_path)
58
- lines = original_content.splitlines()
59
-
60
- # 2. Find the start line
61
- pattern_desc = f"Start pattern '{start_pattern}'"
62
- if near_context:
63
- pattern_desc += f" near context '{near_context}'"
64
- start_pattern_indices = find_pattern_indices(lines, start_pattern, near_context)
65
- start_line_idx = select_occurrence_index(start_pattern_indices, occurrence, pattern_desc)
66
-
67
- # 3. Determine the end line, passing pattern_desc for better error messages
68
- start_line, end_line = determine_line_range(
69
- coder=coder,
70
- file_path=rel_path,
71
- lines=lines,
72
- start_pattern_line_index=start_line_idx,
73
- end_pattern=end_pattern,
74
- line_count=line_count,
75
- target_symbol=None, # DeleteBlock uses patterns, not symbols
76
- pattern_desc=pattern_desc,
77
- )
78
-
79
- # 4. Prepare the deletion
80
- deleted_lines = lines[start_line : end_line + 1]
81
- new_lines = lines[:start_line] + lines[end_line + 1 :]
82
- new_content = "\n".join(new_lines)
37
+ }
38
+
39
+ @classmethod
40
+ def execute(
41
+ cls,
42
+ coder,
43
+ file_path,
44
+ start_pattern,
45
+ end_pattern=None,
46
+ line_count=None,
47
+ near_context=None,
48
+ occurrence=1,
49
+ change_id=None,
50
+ dry_run=False,
51
+ ):
52
+ """
53
+ Delete a block of text between start_pattern and end_pattern (inclusive).
54
+ Uses utility functions for validation, finding lines, and applying changes.
55
+ """
56
+ tool_name = "DeleteBlock"
57
+ try:
58
+ # 1. Validate file and get content
59
+ abs_path, rel_path, original_content = validate_file_for_edit(coder, file_path)
60
+ lines = original_content.splitlines()
61
+
62
+ # 2. Find the start line
63
+ pattern_desc = f"Start pattern '{start_pattern}'"
64
+ if near_context:
65
+ pattern_desc += f" near context '{near_context}'"
66
+ start_pattern_indices = find_pattern_indices(lines, start_pattern, near_context)
67
+ start_line_idx = select_occurrence_index(
68
+ start_pattern_indices, occurrence, pattern_desc
69
+ )
83
70
 
84
- if original_content == new_content:
85
- coder.io.tool_warning("No changes made: deletion would not change file")
86
- return "Warning: No changes made (deletion would not change file)"
71
+ # 3. Determine the end line, passing pattern_desc for better error messages
72
+ start_line, end_line = determine_line_range(
73
+ coder=coder,
74
+ file_path=rel_path,
75
+ lines=lines,
76
+ start_pattern_line_index=start_line_idx,
77
+ end_pattern=end_pattern,
78
+ line_count=line_count,
79
+ target_symbol=None, # DeleteBlock uses patterns, not symbols
80
+ pattern_desc=pattern_desc,
81
+ )
87
82
 
88
- # 5. Generate diff for feedback
89
- diff_snippet = generate_unified_diff_snippet(original_content, new_content, rel_path)
90
- num_deleted = end_line - start_line + 1
91
- num_occurrences = len(start_pattern_indices)
92
- occurrence_str = f"occurrence {occurrence} of " if num_occurrences > 1 else ""
83
+ # 4. Prepare the deletion
84
+ deleted_lines = lines[start_line : end_line + 1]
85
+ new_lines = lines[:start_line] + lines[end_line + 1 :]
86
+ new_content = "\n".join(new_lines)
87
+
88
+ if original_content == new_content:
89
+ coder.io.tool_warning("No changes made: deletion would not change file")
90
+ return "Warning: No changes made (deletion would not change file)"
91
+
92
+ # 5. Generate diff for feedback
93
+ diff_snippet = generate_unified_diff_snippet(original_content, new_content, rel_path)
94
+ num_deleted = end_line - start_line + 1
95
+ num_occurrences = len(start_pattern_indices)
96
+ occurrence_str = f"occurrence {occurrence} of " if num_occurrences > 1 else ""
97
+
98
+ # 6. Handle dry run
99
+ if dry_run:
100
+ dry_run_message = (
101
+ f"Dry run: Would delete {num_deleted} lines ({start_line + 1}-{end_line + 1})"
102
+ f" based on {occurrence_str}start pattern '{start_pattern}' in {file_path}."
103
+ )
104
+ return format_tool_result(
105
+ coder,
106
+ tool_name,
107
+ "",
108
+ dry_run=True,
109
+ dry_run_message=dry_run_message,
110
+ diff_snippet=diff_snippet,
111
+ )
112
+
113
+ # 7. Apply Change (Not dry run)
114
+ metadata = {
115
+ "start_line": start_line + 1,
116
+ "end_line": end_line + 1,
117
+ "start_pattern": start_pattern,
118
+ "end_pattern": end_pattern,
119
+ "line_count": line_count,
120
+ "near_context": near_context,
121
+ "occurrence": occurrence,
122
+ "deleted_content": "\n".join(deleted_lines),
123
+ }
124
+ final_change_id = apply_change(
125
+ coder,
126
+ abs_path,
127
+ rel_path,
128
+ original_content,
129
+ new_content,
130
+ "deleteblock",
131
+ metadata,
132
+ change_id,
133
+ )
93
134
 
94
- # 6. Handle dry run
95
- if dry_run:
96
- dry_run_message = (
97
- f"Dry run: Would delete {num_deleted} lines ({start_line + 1}-{end_line + 1}) based"
98
- f" on {occurrence_str}start pattern '{start_pattern}' in {file_path}."
135
+ coder.files_edited_by_tools.add(rel_path)
136
+ # 8. Format and return result, adding line range to success message
137
+ success_message = (
138
+ f"Deleted {num_deleted} lines ({start_line + 1}-{end_line + 1}) (from"
139
+ f" {occurrence_str}start pattern) in {file_path}"
99
140
  )
100
141
  return format_tool_result(
101
142
  coder,
102
143
  tool_name,
103
- "",
104
- dry_run=True,
105
- dry_run_message=dry_run_message,
144
+ success_message,
145
+ change_id=final_change_id,
106
146
  diff_snippet=diff_snippet,
107
147
  )
108
148
 
109
- # 7. Apply Change (Not dry run)
110
- metadata = {
111
- "start_line": start_line + 1,
112
- "end_line": end_line + 1,
113
- "start_pattern": start_pattern,
114
- "end_pattern": end_pattern,
115
- "line_count": line_count,
116
- "near_context": near_context,
117
- "occurrence": occurrence,
118
- "deleted_content": "\n".join(deleted_lines),
119
- }
120
- final_change_id = apply_change(
121
- coder,
122
- abs_path,
123
- rel_path,
124
- original_content,
125
- new_content,
126
- "deleteblock",
127
- metadata,
128
- change_id,
129
- )
130
-
131
- coder.files_edited_by_tools.add(rel_path)
132
- # 8. Format and return result, adding line range to success message
133
- success_message = (
134
- f"Deleted {num_deleted} lines ({start_line + 1}-{end_line + 1}) (from"
135
- f" {occurrence_str}start pattern) in {file_path}"
136
- )
137
- return format_tool_result(
138
- coder, tool_name, success_message, change_id=final_change_id, diff_snippet=diff_snippet
139
- )
140
-
141
- except ToolError as e:
142
- # Handle errors raised by utility functions (expected errors)
143
- return handle_tool_error(coder, tool_name, e, add_traceback=False)
144
- except Exception as e:
145
- # Handle unexpected errors
146
- return handle_tool_error(coder, tool_name, e)
147
-
148
-
149
- def process_response(coder, params):
150
- """
151
- Process the DeleteBlock tool response.
152
-
153
- Args:
154
- coder: The Coder instance
155
- params: Dictionary of parameters
156
-
157
- Returns:
158
- str: Result message
159
- """
160
- file_path = params.get("file_path")
161
- start_pattern = params.get("start_pattern")
162
- end_pattern = params.get("end_pattern")
163
- line_count = params.get("line_count")
164
- near_context = params.get("near_context")
165
- occurrence = params.get("occurrence", 1)
166
- change_id = params.get("change_id")
167
- dry_run = params.get("dry_run", False)
168
-
169
- if file_path is not None and start_pattern is not None:
170
- return _execute_delete_block(
171
- coder,
172
- file_path,
173
- start_pattern,
174
- end_pattern,
175
- line_count,
176
- near_context,
177
- occurrence,
178
- change_id,
179
- dry_run,
180
- )
181
- else:
182
- return "Error: Missing required parameters for DeleteBlock (file_path, start_pattern)"
149
+ except ToolError as e:
150
+ # Handle errors raised by utility functions (expected errors)
151
+ return handle_tool_error(coder, tool_name, e, add_traceback=False)
152
+ except Exception as e:
153
+ # Handle unexpected errors
154
+ return handle_tool_error(coder, tool_name, e)