aider-ce 0.87.2.dev9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aider-ce might be problematic. Click here for more details.

Files changed (264) 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 +1014 -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/architect_coder.py +48 -0
  10. aider/coders/architect_prompts.py +40 -0
  11. aider/coders/ask_coder.py +9 -0
  12. aider/coders/ask_prompts.py +35 -0
  13. aider/coders/base_coder.py +3013 -0
  14. aider/coders/base_prompts.py +87 -0
  15. aider/coders/chat_chunks.py +64 -0
  16. aider/coders/context_coder.py +53 -0
  17. aider/coders/context_prompts.py +75 -0
  18. aider/coders/editblock_coder.py +657 -0
  19. aider/coders/editblock_fenced_coder.py +10 -0
  20. aider/coders/editblock_fenced_prompts.py +143 -0
  21. aider/coders/editblock_func_coder.py +141 -0
  22. aider/coders/editblock_func_prompts.py +27 -0
  23. aider/coders/editblock_prompts.py +177 -0
  24. aider/coders/editor_diff_fenced_coder.py +9 -0
  25. aider/coders/editor_diff_fenced_prompts.py +11 -0
  26. aider/coders/editor_editblock_coder.py +9 -0
  27. aider/coders/editor_editblock_prompts.py +21 -0
  28. aider/coders/editor_whole_coder.py +9 -0
  29. aider/coders/editor_whole_prompts.py +12 -0
  30. aider/coders/help_coder.py +16 -0
  31. aider/coders/help_prompts.py +46 -0
  32. aider/coders/navigator_coder.py +2711 -0
  33. aider/coders/navigator_legacy_prompts.py +338 -0
  34. aider/coders/navigator_prompts.py +530 -0
  35. aider/coders/patch_coder.py +706 -0
  36. aider/coders/patch_prompts.py +161 -0
  37. aider/coders/search_replace.py +757 -0
  38. aider/coders/shell.py +37 -0
  39. aider/coders/single_wholefile_func_coder.py +102 -0
  40. aider/coders/single_wholefile_func_prompts.py +27 -0
  41. aider/coders/udiff_coder.py +429 -0
  42. aider/coders/udiff_prompts.py +117 -0
  43. aider/coders/udiff_simple.py +14 -0
  44. aider/coders/udiff_simple_prompts.py +25 -0
  45. aider/coders/wholefile_coder.py +144 -0
  46. aider/coders/wholefile_func_coder.py +134 -0
  47. aider/coders/wholefile_func_prompts.py +27 -0
  48. aider/coders/wholefile_prompts.py +70 -0
  49. aider/commands.py +1946 -0
  50. aider/copypaste.py +72 -0
  51. aider/deprecated.py +126 -0
  52. aider/diffs.py +128 -0
  53. aider/dump.py +29 -0
  54. aider/editor.py +147 -0
  55. aider/exceptions.py +107 -0
  56. aider/format_settings.py +26 -0
  57. aider/gui.py +545 -0
  58. aider/help.py +163 -0
  59. aider/help_pats.py +19 -0
  60. aider/history.py +178 -0
  61. aider/io.py +1257 -0
  62. aider/linter.py +304 -0
  63. aider/llm.py +47 -0
  64. aider/main.py +1297 -0
  65. aider/mcp/__init__.py +94 -0
  66. aider/mcp/server.py +119 -0
  67. aider/mdstream.py +243 -0
  68. aider/models.py +1344 -0
  69. aider/onboarding.py +428 -0
  70. aider/openrouter.py +129 -0
  71. aider/prompts.py +56 -0
  72. aider/queries/tree-sitter-language-pack/README.md +7 -0
  73. aider/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
  74. aider/queries/tree-sitter-language-pack/c-tags.scm +9 -0
  75. aider/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
  76. aider/queries/tree-sitter-language-pack/clojure-tags.scm +7 -0
  77. aider/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
  78. aider/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
  79. aider/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
  80. aider/queries/tree-sitter-language-pack/d-tags.scm +26 -0
  81. aider/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
  82. aider/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
  83. aider/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
  84. aider/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
  85. aider/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
  86. aider/queries/tree-sitter-language-pack/go-tags.scm +42 -0
  87. aider/queries/tree-sitter-language-pack/java-tags.scm +20 -0
  88. aider/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
  89. aider/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
  90. aider/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
  91. aider/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
  92. aider/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
  93. aider/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
  94. aider/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
  95. aider/queries/tree-sitter-language-pack/python-tags.scm +14 -0
  96. aider/queries/tree-sitter-language-pack/r-tags.scm +21 -0
  97. aider/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
  98. aider/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
  99. aider/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
  100. aider/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
  101. aider/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
  102. aider/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
  103. aider/queries/tree-sitter-languages/README.md +23 -0
  104. aider/queries/tree-sitter-languages/c-tags.scm +9 -0
  105. aider/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
  106. aider/queries/tree-sitter-languages/cpp-tags.scm +15 -0
  107. aider/queries/tree-sitter-languages/dart-tags.scm +91 -0
  108. aider/queries/tree-sitter-languages/elisp-tags.scm +8 -0
  109. aider/queries/tree-sitter-languages/elixir-tags.scm +54 -0
  110. aider/queries/tree-sitter-languages/elm-tags.scm +19 -0
  111. aider/queries/tree-sitter-languages/go-tags.scm +30 -0
  112. aider/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  113. aider/queries/tree-sitter-languages/java-tags.scm +20 -0
  114. aider/queries/tree-sitter-languages/javascript-tags.scm +88 -0
  115. aider/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
  116. aider/queries/tree-sitter-languages/matlab-tags.scm +10 -0
  117. aider/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  118. aider/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
  119. aider/queries/tree-sitter-languages/php-tags.scm +26 -0
  120. aider/queries/tree-sitter-languages/python-tags.scm +12 -0
  121. aider/queries/tree-sitter-languages/ql-tags.scm +26 -0
  122. aider/queries/tree-sitter-languages/ruby-tags.scm +64 -0
  123. aider/queries/tree-sitter-languages/rust-tags.scm +60 -0
  124. aider/queries/tree-sitter-languages/scala-tags.scm +65 -0
  125. aider/queries/tree-sitter-languages/typescript-tags.scm +41 -0
  126. aider/reasoning_tags.py +82 -0
  127. aider/repo.py +621 -0
  128. aider/repomap.py +988 -0
  129. aider/report.py +200 -0
  130. aider/resources/__init__.py +3 -0
  131. aider/resources/model-metadata.json +699 -0
  132. aider/resources/model-settings.yml +2046 -0
  133. aider/run_cmd.py +132 -0
  134. aider/scrape.py +284 -0
  135. aider/sendchat.py +61 -0
  136. aider/special.py +203 -0
  137. aider/tools/__init__.py +26 -0
  138. aider/tools/command.py +58 -0
  139. aider/tools/command_interactive.py +53 -0
  140. aider/tools/delete_block.py +120 -0
  141. aider/tools/delete_line.py +112 -0
  142. aider/tools/delete_lines.py +137 -0
  143. aider/tools/extract_lines.py +276 -0
  144. aider/tools/grep.py +171 -0
  145. aider/tools/indent_lines.py +155 -0
  146. aider/tools/insert_block.py +211 -0
  147. aider/tools/list_changes.py +51 -0
  148. aider/tools/ls.py +49 -0
  149. aider/tools/make_editable.py +46 -0
  150. aider/tools/make_readonly.py +29 -0
  151. aider/tools/remove.py +48 -0
  152. aider/tools/replace_all.py +77 -0
  153. aider/tools/replace_line.py +125 -0
  154. aider/tools/replace_lines.py +160 -0
  155. aider/tools/replace_text.py +125 -0
  156. aider/tools/show_numbered_context.py +101 -0
  157. aider/tools/tool_utils.py +313 -0
  158. aider/tools/undo_change.py +60 -0
  159. aider/tools/view.py +13 -0
  160. aider/tools/view_files_at_glob.py +65 -0
  161. aider/tools/view_files_matching.py +103 -0
  162. aider/tools/view_files_with_symbol.py +121 -0
  163. aider/urls.py +17 -0
  164. aider/utils.py +454 -0
  165. aider/versioncheck.py +113 -0
  166. aider/voice.py +187 -0
  167. aider/waiting.py +221 -0
  168. aider/watch.py +318 -0
  169. aider/watch_prompts.py +12 -0
  170. aider/website/Gemfile +8 -0
  171. aider/website/_includes/blame.md +162 -0
  172. aider/website/_includes/get-started.md +22 -0
  173. aider/website/_includes/help-tip.md +5 -0
  174. aider/website/_includes/help.md +24 -0
  175. aider/website/_includes/install.md +5 -0
  176. aider/website/_includes/keys.md +4 -0
  177. aider/website/_includes/model-warnings.md +67 -0
  178. aider/website/_includes/multi-line.md +22 -0
  179. aider/website/_includes/python-m-aider.md +5 -0
  180. aider/website/_includes/recording.css +228 -0
  181. aider/website/_includes/recording.md +34 -0
  182. aider/website/_includes/replit-pipx.md +9 -0
  183. aider/website/_includes/works-best.md +1 -0
  184. aider/website/_sass/custom/custom.scss +103 -0
  185. aider/website/docs/config/adv-model-settings.md +2260 -0
  186. aider/website/docs/config/aider_conf.md +548 -0
  187. aider/website/docs/config/api-keys.md +90 -0
  188. aider/website/docs/config/dotenv.md +493 -0
  189. aider/website/docs/config/editor.md +127 -0
  190. aider/website/docs/config/mcp.md +95 -0
  191. aider/website/docs/config/model-aliases.md +104 -0
  192. aider/website/docs/config/options.md +890 -0
  193. aider/website/docs/config/reasoning.md +210 -0
  194. aider/website/docs/config.md +44 -0
  195. aider/website/docs/faq.md +384 -0
  196. aider/website/docs/git.md +76 -0
  197. aider/website/docs/index.md +47 -0
  198. aider/website/docs/install/codespaces.md +39 -0
  199. aider/website/docs/install/docker.md +57 -0
  200. aider/website/docs/install/optional.md +100 -0
  201. aider/website/docs/install/replit.md +8 -0
  202. aider/website/docs/install.md +115 -0
  203. aider/website/docs/languages.md +264 -0
  204. aider/website/docs/legal/contributor-agreement.md +111 -0
  205. aider/website/docs/legal/privacy.md +104 -0
  206. aider/website/docs/llms/anthropic.md +77 -0
  207. aider/website/docs/llms/azure.md +48 -0
  208. aider/website/docs/llms/bedrock.md +132 -0
  209. aider/website/docs/llms/cohere.md +34 -0
  210. aider/website/docs/llms/deepseek.md +32 -0
  211. aider/website/docs/llms/gemini.md +49 -0
  212. aider/website/docs/llms/github.md +111 -0
  213. aider/website/docs/llms/groq.md +36 -0
  214. aider/website/docs/llms/lm-studio.md +39 -0
  215. aider/website/docs/llms/ollama.md +75 -0
  216. aider/website/docs/llms/openai-compat.md +39 -0
  217. aider/website/docs/llms/openai.md +58 -0
  218. aider/website/docs/llms/openrouter.md +78 -0
  219. aider/website/docs/llms/other.md +111 -0
  220. aider/website/docs/llms/vertex.md +50 -0
  221. aider/website/docs/llms/warnings.md +10 -0
  222. aider/website/docs/llms/xai.md +53 -0
  223. aider/website/docs/llms.md +54 -0
  224. aider/website/docs/more/analytics.md +127 -0
  225. aider/website/docs/more/edit-formats.md +116 -0
  226. aider/website/docs/more/infinite-output.md +159 -0
  227. aider/website/docs/more-info.md +8 -0
  228. aider/website/docs/recordings/auto-accept-architect.md +31 -0
  229. aider/website/docs/recordings/dont-drop-original-read-files.md +35 -0
  230. aider/website/docs/recordings/index.md +21 -0
  231. aider/website/docs/recordings/model-accepts-settings.md +69 -0
  232. aider/website/docs/recordings/tree-sitter-language-pack.md +80 -0
  233. aider/website/docs/repomap.md +112 -0
  234. aider/website/docs/scripting.md +100 -0
  235. aider/website/docs/troubleshooting/aider-not-found.md +24 -0
  236. aider/website/docs/troubleshooting/edit-errors.md +76 -0
  237. aider/website/docs/troubleshooting/imports.md +62 -0
  238. aider/website/docs/troubleshooting/models-and-keys.md +54 -0
  239. aider/website/docs/troubleshooting/support.md +79 -0
  240. aider/website/docs/troubleshooting/token-limits.md +96 -0
  241. aider/website/docs/troubleshooting/warnings.md +12 -0
  242. aider/website/docs/troubleshooting.md +11 -0
  243. aider/website/docs/usage/browser.md +57 -0
  244. aider/website/docs/usage/caching.md +49 -0
  245. aider/website/docs/usage/commands.md +133 -0
  246. aider/website/docs/usage/conventions.md +119 -0
  247. aider/website/docs/usage/copypaste.md +121 -0
  248. aider/website/docs/usage/images-urls.md +48 -0
  249. aider/website/docs/usage/lint-test.md +118 -0
  250. aider/website/docs/usage/modes.md +211 -0
  251. aider/website/docs/usage/not-code.md +179 -0
  252. aider/website/docs/usage/notifications.md +87 -0
  253. aider/website/docs/usage/tips.md +79 -0
  254. aider/website/docs/usage/tutorials.md +30 -0
  255. aider/website/docs/usage/voice.md +121 -0
  256. aider/website/docs/usage/watch.md +294 -0
  257. aider/website/docs/usage.md +102 -0
  258. aider/website/share/index.md +101 -0
  259. aider_ce-0.87.2.dev9.dist-info/METADATA +543 -0
  260. aider_ce-0.87.2.dev9.dist-info/RECORD +264 -0
  261. aider_ce-0.87.2.dev9.dist-info/WHEEL +5 -0
  262. aider_ce-0.87.2.dev9.dist-info/entry_points.txt +3 -0
  263. aider_ce-0.87.2.dev9.dist-info/licenses/LICENSE.txt +202 -0
  264. aider_ce-0.87.2.dev9.dist-info/top_level.txt +1 -0
aider/watch.py ADDED
@@ -0,0 +1,318 @@
1
+ import re
2
+ import threading
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ from grep_ast import TreeContext
7
+ from pathspec import PathSpec
8
+ from pathspec.patterns import GitWildMatchPattern
9
+ from watchfiles import watch
10
+
11
+ from aider.dump import dump # noqa
12
+ from aider.watch_prompts import watch_ask_prompt, watch_code_prompt
13
+
14
+
15
+ def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
16
+ """Load and parse multiple .gitignore files into a single PathSpec"""
17
+ if not gitignore_paths:
18
+ return None
19
+
20
+ patterns = [
21
+ ".aider*",
22
+ ".git",
23
+ # Common editor backup/temp files
24
+ "*~", # Emacs/vim backup
25
+ "*.bak", # Generic backup
26
+ "*.swp", # Vim swap
27
+ "*.swo", # Vim swap
28
+ "\\#*\\#", # Emacs auto-save
29
+ ".#*", # Emacs lock files
30
+ "*.tmp", # Generic temp files
31
+ "*.temp", # Generic temp files
32
+ "*.orig", # Merge conflict originals
33
+ "*.pyc", # Python bytecode
34
+ "__pycache__/", # Python cache dir
35
+ ".DS_Store", # macOS metadata
36
+ "Thumbs.db", # Windows thumbnail cache
37
+ "*.svg",
38
+ "*.pdf",
39
+ # IDE files
40
+ ".idea/", # JetBrains IDEs
41
+ ".vscode/", # VS Code
42
+ "*.sublime-*", # Sublime Text
43
+ ".project", # Eclipse
44
+ ".settings/", # Eclipse
45
+ "*.code-workspace", # VS Code workspace
46
+ # Environment files
47
+ ".env", # Environment variables
48
+ ".venv/", # Python virtual environments
49
+ "node_modules/", # Node.js dependencies
50
+ "vendor/", # Various dependencies
51
+ # Logs and caches
52
+ "*.log", # Log files
53
+ ".cache/", # Cache directories
54
+ ".pytest_cache/", # Python test cache
55
+ "coverage/", # Code coverage reports
56
+ ] # Always ignore
57
+ for path in gitignore_paths:
58
+ if path.exists():
59
+ with open(path) as f:
60
+ patterns.extend(f.readlines())
61
+
62
+ return PathSpec.from_lines(GitWildMatchPattern, patterns) if patterns else None
63
+
64
+
65
+ class FileWatcher:
66
+ """Watches source files for changes and AI comments"""
67
+
68
+ # Compiled regex pattern for AI comments
69
+ ai_comment_pattern = re.compile(
70
+ r"(?:#|//|--|;+) *(ai\b.*|ai\b.*|.*\bai[?!]?) *$", re.IGNORECASE
71
+ )
72
+
73
+ def __init__(self, coder, gitignores=None, verbose=False, analytics=None, root=None):
74
+ self.coder = coder
75
+ self.io = coder.io
76
+ self.root = Path(root) if root else Path(coder.root)
77
+ self.verbose = verbose
78
+ self.analytics = analytics
79
+ self.stop_event = None
80
+ self.watcher_thread = None
81
+ self.changed_files = set()
82
+ self.gitignores = gitignores
83
+
84
+ self.gitignore_spec = load_gitignores(
85
+ [Path(g) for g in self.gitignores] if self.gitignores else []
86
+ )
87
+
88
+ coder.io.file_watcher = self
89
+
90
+ def filter_func(self, change_type, path):
91
+ """Filter function for the file watcher"""
92
+ path_obj = Path(path)
93
+ path_abs = path_obj.absolute()
94
+
95
+ if not path_abs.is_relative_to(self.root.absolute()):
96
+ return False
97
+
98
+ rel_path = path_abs.relative_to(self.root)
99
+ if self.verbose:
100
+ print("Changed", rel_path)
101
+
102
+ if self.gitignore_spec and self.gitignore_spec.match_file(
103
+ rel_path.as_posix() + ("/" if path_abs.is_dir() else "")
104
+ ):
105
+ return False
106
+
107
+ # Check file size before reading content
108
+ if path_abs.is_file() and path_abs.stat().st_size > 1 * 1024 * 1024: # 1MB limit
109
+ return False
110
+
111
+ if self.verbose:
112
+ print("Checking", rel_path)
113
+
114
+ # Check if file contains AI markers
115
+ try:
116
+ comments, _, _ = self.get_ai_comments(str(path_abs))
117
+ return bool(comments)
118
+ except Exception:
119
+ return
120
+
121
+ def get_roots_to_watch(self):
122
+ """Determine which root paths to watch based on gitignore rules"""
123
+ if self.gitignore_spec:
124
+ roots = [
125
+ str(path)
126
+ for path in self.root.iterdir()
127
+ if not self.gitignore_spec.match_file(
128
+ path.relative_to(self.root).as_posix() + ("/" if path.is_dir() else "")
129
+ )
130
+ ]
131
+ # Fallback to watching root if all top-level items are filtered out
132
+ return roots if roots else [str(self.root)]
133
+ return [str(self.root)]
134
+
135
+ def handle_changes(self, changes):
136
+ """Process the detected changes and update state"""
137
+ if not changes:
138
+ return False
139
+
140
+ changed_files = {str(Path(change[1])) for change in changes}
141
+ self.changed_files.update(changed_files)
142
+ self.io.interrupt_input()
143
+ return True
144
+
145
+ def watch_files(self):
146
+ """Watch for file changes and process them"""
147
+ try:
148
+ roots_to_watch = self.get_roots_to_watch()
149
+
150
+ for changes in watch(
151
+ *roots_to_watch,
152
+ watch_filter=self.filter_func,
153
+ stop_event=self.stop_event,
154
+ ignore_permission_denied=True,
155
+ ):
156
+ if self.handle_changes(changes):
157
+ return
158
+
159
+ except Exception as e:
160
+ if self.verbose:
161
+ dump(f"File watcher error: {e}")
162
+ raise e
163
+
164
+ def start(self):
165
+ """Start watching for file changes"""
166
+ self.stop_event = threading.Event()
167
+ self.changed_files = set()
168
+
169
+ self.watcher_thread = threading.Thread(target=self.watch_files, daemon=True)
170
+ self.watcher_thread.start()
171
+
172
+ def stop(self):
173
+ """Stop watching for file changes"""
174
+ if self.stop_event:
175
+ self.stop_event.set()
176
+ if self.watcher_thread:
177
+ self.watcher_thread.join()
178
+ self.watcher_thread = None
179
+ self.stop_event = None
180
+
181
+ def process_changes(self):
182
+ """Get any detected file changes"""
183
+
184
+ has_action = None
185
+ added = False
186
+ for fname in self.changed_files:
187
+ _, _, action = self.get_ai_comments(fname)
188
+ if action in ("!", "?"):
189
+ has_action = action
190
+
191
+ if fname in self.coder.abs_fnames:
192
+ continue
193
+ if self.analytics:
194
+ self.analytics.event("ai-comments file-add")
195
+ self.coder.abs_fnames.add(fname)
196
+ rel_fname = self.coder.get_rel_fname(fname)
197
+ if not added:
198
+ self.io.tool_output()
199
+ added = True
200
+ self.io.tool_output(f"Added {rel_fname} to the chat")
201
+
202
+ if not has_action:
203
+ if added:
204
+ self.io.tool_output(
205
+ "End your comment with AI! to request changes or AI? to ask questions"
206
+ )
207
+ return ""
208
+
209
+ if self.analytics:
210
+ self.analytics.event("ai-comments execute")
211
+ self.io.tool_output("Processing your request...")
212
+
213
+ if has_action == "!":
214
+ res = watch_code_prompt
215
+ elif has_action == "?":
216
+ res = watch_ask_prompt
217
+
218
+ # Refresh all AI comments from tracked files
219
+ for fname in self.coder.abs_fnames:
220
+ line_nums, comments, _action = self.get_ai_comments(fname)
221
+ if not line_nums:
222
+ continue
223
+
224
+ code = self.io.read_text(fname)
225
+ if not code:
226
+ continue
227
+
228
+ rel_fname = self.coder.get_rel_fname(fname)
229
+ res += f"\n{rel_fname}:\n"
230
+
231
+ # Convert comment line numbers to line indices (0-based)
232
+ lois = [ln - 1 for ln, _ in zip(line_nums, comments) if ln > 0]
233
+
234
+ try:
235
+ context = TreeContext(
236
+ rel_fname,
237
+ code,
238
+ color=False,
239
+ line_number=False,
240
+ child_context=False,
241
+ last_line=False,
242
+ margin=0,
243
+ mark_lois=True,
244
+ loi_pad=3,
245
+ show_top_of_file_parent_scope=False,
246
+ )
247
+ context.lines_of_interest = set()
248
+ context.add_lines_of_interest(lois)
249
+ context.add_context()
250
+ res += context.format()
251
+ except ValueError:
252
+ for ln, comment in zip(line_nums, comments):
253
+ res += f" Line {ln}: {comment}\n"
254
+
255
+ return res
256
+
257
+ def get_ai_comments(self, filepath):
258
+ """Extract AI comment line numbers, comments and action status from a file"""
259
+ line_nums = []
260
+ comments = []
261
+ has_action = None # None, "!" or "?"
262
+ content = self.io.read_text(filepath, silent=True)
263
+ if not content:
264
+ return None, None, None
265
+
266
+ for i, line in enumerate(content.splitlines(), 1):
267
+ if match := self.ai_comment_pattern.search(line):
268
+ comment = match.group(0).strip()
269
+ if comment:
270
+ line_nums.append(i)
271
+ comments.append(comment)
272
+ comment = comment.lower()
273
+ comment = comment.lstrip("/#-;") # Added semicolon for Lisp comments
274
+ comment = comment.strip()
275
+ if comment.startswith("ai!") or comment.endswith("ai!"):
276
+ has_action = "!"
277
+ elif comment.startswith("ai?") or comment.endswith("ai?"):
278
+ has_action = "?"
279
+ if not line_nums:
280
+ return None, None, None
281
+ return line_nums, comments, has_action
282
+
283
+
284
+ def main():
285
+ """Example usage of the file watcher"""
286
+ import argparse
287
+
288
+ parser = argparse.ArgumentParser(description="Watch source files for changes")
289
+ parser.add_argument("directory", help="Directory to watch")
290
+ parser.add_argument(
291
+ "--gitignore",
292
+ action="append",
293
+ help="Path to .gitignore file (can be specified multiple times)",
294
+ )
295
+ args = parser.parse_args()
296
+
297
+ directory = args.directory
298
+ print(f"Watching source files in {directory}...")
299
+
300
+ # Example ignore function that ignores files with "test" in the name
301
+ def ignore_test_files(path):
302
+ return "test" in path.name.lower()
303
+
304
+ watcher = FileWatcher(directory, gitignores=args.gitignore)
305
+ try:
306
+ watcher.start()
307
+ while True:
308
+ if changes := watcher.get_changes():
309
+ for file in sorted(changes.keys()):
310
+ print(file)
311
+ watcher.changed_files = None
312
+ except KeyboardInterrupt:
313
+ print("\nStopped watching files")
314
+ watcher.stop()
315
+
316
+
317
+ if __name__ == "__main__":
318
+ main()
aider/watch_prompts.py ADDED
@@ -0,0 +1,12 @@
1
+ watch_code_prompt = """
2
+ I've written your instructions in comments in the code and marked them with "ai"
3
+ You can see the "AI" comments shown below (marked with █).
4
+ Find them in the code files I've shared with you, and follow their instructions.
5
+
6
+ After completing those instructions, also be sure to remove all the "AI" comments from the code too.
7
+ """
8
+
9
+ watch_ask_prompt = """/ask
10
+ Find the "AI" comments below (marked with █) in the code files I've shared with you.
11
+ They contain my questions that I need you to answer and other instructions for you.
12
+ """
aider/website/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+ gem 'jekyll'
3
+ gem "just-the-docs", "0.8.2"
4
+ gem 'jekyll-redirect-from'
5
+ gem 'jekyll-sitemap'
6
+ gem "webrick"
7
+ gem 'github-pages', group: :jekyll_plugins
8
+ gem "html-proofer"
@@ -0,0 +1,162 @@
1
+ <div class="chart-container">
2
+ <canvas id="blameChart" style="margin-top: 20px"></canvas>
3
+ </div>
4
+ <div class="chart-container">
5
+ <canvas id="linesChart" style="margin-top: 20px"></canvas>
6
+ </div>
7
+
8
+ <style>
9
+ .chart-container {
10
+ position: relative;
11
+ width: 100%;
12
+ height: 300px;
13
+ }
14
+ </style>
15
+
16
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
17
+ <script src="https://cdn.jsdelivr.net/npm/moment"></script>
18
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>
19
+ <script>
20
+ document.addEventListener('DOMContentLoaded', function () {
21
+ var blameCtx = document.getElementById('blameChart').getContext('2d');
22
+ var linesCtx = document.getElementById('linesChart').getContext('2d');
23
+
24
+ var labels = [{% for row in site.data.blame %}'{{ row.end_tag }}',{% endfor %}];
25
+
26
+ var blameData = {
27
+ labels: labels,
28
+ datasets: [{
29
+ label: 'Aider\'s percent of new code by release',
30
+ data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.aider_percentage }}, lines: {{ row.aider_total }}, end_date: '{{ row.end_date }}' },{% endfor %}],
31
+ backgroundColor: 'rgba(54, 162, 235, 0.8)',
32
+ borderColor: 'rgba(54, 162, 235, 1)',
33
+ borderWidth: 1
34
+ }]
35
+ };
36
+
37
+ var linesData = {
38
+ labels: labels,
39
+ datasets: [{
40
+ label: 'Aider',
41
+ data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.aider_total }} },{% endfor %}],
42
+ backgroundColor: 'rgba(54, 162, 235, 0.8)',
43
+ borderColor: 'rgba(54, 162, 235, 1)',
44
+ borderWidth: 1
45
+ },
46
+ {
47
+ label: 'Human',
48
+ data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.total_lines | minus: row.aider_total }} },{% endfor %}],
49
+ backgroundColor: 'rgba(200, 200, 200, 0.8)',
50
+ borderColor: 'rgba(200, 200, 200, 1)',
51
+ borderWidth: 1
52
+ }]
53
+ };
54
+
55
+ var blameChart = new Chart(blameCtx, {
56
+ type: 'bar',
57
+ data: blameData,
58
+ options: {
59
+ maintainAspectRatio: false,
60
+ scales: {
61
+ x: {
62
+ type: 'category',
63
+ title: {
64
+ display: true,
65
+ text: 'Version'
66
+ },
67
+ ticks: {
68
+ maxRotation: 45,
69
+ minRotation: 45
70
+ }
71
+ },
72
+ y: {
73
+ title: {
74
+ display: true,
75
+ text: 'Percent of new code'
76
+ },
77
+ beginAtZero: true
78
+ }
79
+ },
80
+ plugins: {
81
+ legend: {
82
+ display: false
83
+ },
84
+ tooltip: {
85
+ callbacks: {
86
+ label: function(context) {
87
+ var label = 'Aider\'s contribution';
88
+ var value = context.parsed.y || 0;
89
+ var lines = context.raw.lines || 0;
90
+ return `${label}: ${Math.round(value)}% (${lines} lines)`;
91
+ },
92
+ afterLabel: function(context) {
93
+ let date = context.raw.end_date || 'n/a';
94
+ return `Date: ` + date;
95
+ }
96
+ }
97
+ },
98
+ title: {
99
+ display: true,
100
+ text: 'Percent of new code written by aider, by release',
101
+ font: {
102
+ size: 16
103
+ }
104
+ }
105
+ }
106
+ }
107
+ });
108
+
109
+ var linesChart = new Chart(linesCtx, {
110
+ type: 'bar',
111
+ data: linesData,
112
+ options: {
113
+ maintainAspectRatio: false,
114
+ scales: {
115
+ x: {
116
+ type: 'category',
117
+ stacked: true,
118
+ title: {
119
+ display: true,
120
+ text: 'Version'
121
+ },
122
+ ticks: {
123
+ maxRotation: 45,
124
+ minRotation: 45
125
+ }
126
+ },
127
+ y: {
128
+ stacked: true,
129
+ title: {
130
+ display: true,
131
+ text: 'Lines of new code'
132
+ },
133
+ beginAtZero: true
134
+ }
135
+ },
136
+ plugins: {
137
+ legend: {
138
+ display: true,
139
+ position: 'chartArea',
140
+ reverse: true
141
+ },
142
+ tooltip: {
143
+ callbacks: {
144
+ label: function(context) {
145
+ var label = context.dataset.label;
146
+ var value = context.parsed.y || 0;
147
+ return `${label}: ${value}`;
148
+ }
149
+ }
150
+ },
151
+ title: {
152
+ display: true,
153
+ text: 'Lines of new code, by release',
154
+ font: {
155
+ size: 16
156
+ }
157
+ }
158
+ }
159
+ }
160
+ });
161
+ });
162
+ </script>
@@ -0,0 +1,22 @@
1
+
2
+ If you already have python 3.8-3.13 installed, you can get started quickly like this.
3
+
4
+ First, install aider:
5
+
6
+ {% include install.md %}
7
+
8
+ Start working with aider on your codebase:
9
+
10
+ ```bash
11
+ # Change directory into your codebase
12
+ cd /to/your/project
13
+
14
+ # DeepSeek
15
+ aider --model deepseek --api-key deepseek=<key>
16
+
17
+ # Claude 3.7 Sonnet
18
+ aider --model sonnet --api-key anthropic=<key>
19
+
20
+ # o3-mini
21
+ aider --model o3-mini --api-key openai=<key>
22
+ ```
@@ -0,0 +1,5 @@
1
+ {: .tip }
2
+ Use `/help <question>` to
3
+ [ask for help about using aider](/docs/troubleshooting/support.html),
4
+ customizing settings, troubleshooting, using LLMs, etc.
5
+
@@ -0,0 +1,24 @@
1
+ If you need more help, please check our
2
+ [GitHub issues](https://github.com/Aider-AI/aider/issues)
3
+ and file a new issue if your problem isn't discussed.
4
+ Or drop into our
5
+ [Discord](https://discord.gg/Y7X7bhMQFV)
6
+ to chat with us.
7
+
8
+ When reporting problems, it is very helpful if you can provide:
9
+
10
+ - Aider version
11
+ - LLM model you are using
12
+
13
+ Including the "announcement" lines that
14
+ aider prints at startup
15
+ is an easy way to share this helpful info.
16
+
17
+ ```
18
+ Aider v0.37.1-dev
19
+ Models: gpt-4o with diff edit format, weak model gpt-3.5-turbo
20
+ Git repo: .git with 243 files
21
+ Repo-map: using 1024 tokens
22
+ ```
23
+
24
+ {% include help-tip.md %}
@@ -0,0 +1,5 @@
1
+
2
+ ```bash
3
+ python -m pip install aider-install
4
+ aider-install
5
+ ```
@@ -0,0 +1,4 @@
1
+ {: .tip :}
2
+ See the
3
+ [API key configuration docs](/docs/config/api-keys.html)
4
+ for information on how to configure and store your API keys.
@@ -0,0 +1,67 @@
1
+
2
+ ## Unknown context window size and token costs
3
+
4
+ ```
5
+ Model foobar: Unknown context window size and costs, using sane defaults.
6
+ ```
7
+
8
+ If you specify a model that aider has never heard of, you will get
9
+ this warning.
10
+ This means aider doesn't know the context window size and token costs
11
+ for that model.
12
+ Aider will use an unlimited context window and assume the model is free,
13
+ so this is not usually a significant problem.
14
+
15
+ See the docs on
16
+ [configuring advanced model settings](/docs/config/adv-model-settings.html)
17
+ for details on how to remove this warning.
18
+
19
+ {: .tip }
20
+ You can probably ignore the unknown context window size and token costs warning.
21
+
22
+ ## Did you mean?
23
+
24
+ If aider isn't familiar with the model you've specified,
25
+ it will suggest similarly named models.
26
+ This helps
27
+ in the case where you made a typo or mistake when specifying the model name.
28
+
29
+ ```
30
+ Model gpt-5o: Unknown context window size and costs, using sane defaults.
31
+ Did you mean one of these?
32
+ - gpt-4o
33
+ ```
34
+
35
+ ## Missing environment variables
36
+
37
+ You need to set the listed environment variables.
38
+ Otherwise you will get error messages when you start chatting with the model.
39
+
40
+ ```
41
+ Model azure/gpt-4-turbo: Missing these environment variables:
42
+ - AZURE_API_BASE
43
+ - AZURE_API_VERSION
44
+ - AZURE_API_KEY
45
+ ```
46
+
47
+ {: .tip }
48
+ On Windows,
49
+ if you just set these environment variables using `setx` you may need to restart your terminal or
50
+ command prompt for the changes to take effect.
51
+
52
+
53
+ ## Unknown which environment variables are required
54
+
55
+ ```
56
+ Model gpt-5: Unknown which environment variables are required.
57
+ ```
58
+
59
+ Aider is unable verify the environment because it doesn't know
60
+ which variables are required for the model.
61
+ If required variables are missing,
62
+ you may get errors when you attempt to chat with the model.
63
+ You can look in the [aider's LLM documentation](/docs/llms.html)
64
+ or the
65
+ [litellm documentation](https://docs.litellm.ai/docs/providers)
66
+ to see if the required variables are listed there.
67
+
@@ -0,0 +1,22 @@
1
+ You can send long, multi-line messages in the chat in a few ways:
2
+ - Paste a multi-line message directly into the chat.
3
+ - Enter `{` alone on the first line to start a multiline message and `}` alone on the last line to end it.
4
+ - Or, start with `{tag` (where "tag" is any sequence of letters/numbers) and end with `tag}`. This is useful when you need to include closing braces `}` in your message.
5
+ - Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
6
+ - Use `/paste` to paste text from the clipboard into the chat.
7
+ - Use the `/editor` command (or press `Ctrl-X Ctrl-E` if your terminal allows) to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
8
+ - Use multiline-mode, which swaps the function of Meta-Enter and Enter, so that Enter inserts a newline, and Meta-Enter submits your command. To enable multiline mode:
9
+ - Use the `/multiline-mode` command to toggle it during a session.
10
+ - Use the `--multiline` switch.
11
+
12
+ Example with a tag:
13
+ ```
14
+ {python
15
+ def hello():
16
+ print("Hello}") # Note: contains a brace
17
+ python}
18
+ ```
19
+
20
+ {: .note }
21
+ People often ask for SHIFT-ENTER to be a soft-newline.
22
+ Unfortunately there is no portable way to detect that keystroke in terminals.
@@ -0,0 +1,5 @@
1
+ {: .tip }
2
+ In some environments you may get "aider command not found" errors.
3
+ You can try `python -m aider` or
4
+ [see here for more info](/docs/troubleshooting/aider-not-found.html).
5
+