aider-ce 0.88.20__py3-none-any.whl

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