Compare commits

...

282 Commits

Author SHA1 Message Date
Paul Gauthier
5c848d59b2 set version to 0.69.2.dev 2024-12-16 12:36:28 -08:00
Paul Gauthier
b1c04dece9 version bump to 0.69.1 2024-12-16 12:34:51 -08:00
Paul Gauthier
b87c7987bb copy 2024-12-16 12:29:10 -08:00
Paul Gauthier
0bef52ae7d fix: Only show AI comment help once per file add 2024-12-16 12:27:19 -08:00
Paul Gauthier (aider)
9ae04cf1ec style: Format tool output message 2024-12-16 12:13:35 -08:00
Paul Gauthier (aider)
0f7c4a8d4f feat: Add help message for first-time AI usage 2024-12-16 12:13:32 -08:00
Paul Gauthier
07353207c0 feat: Output "Use AI!" if no action triggered 2024-12-16 12:13:31 -08:00
Paul Gauthier
d89be83414 copy 2024-12-16 12:10:34 -08:00
Paul Gauthier
01382527f5 cleanup cog of toml 2024-12-16 12:08:08 -08:00
Paul Gauthier
dece2193fc Switch to MANIFEST.in to exclude aider/website/assets/ and other from whl build file 2024-12-16 12:07:02 -08:00
Paul Gauthier
d298f864fa works? 2024-12-16 11:55:24 -08:00
Paul Gauthier (aider)
ff37d8c691 feat: Add include-package-data to pyproject.toml 2024-12-16 08:28:10 -08:00
Paul Gauthier
f7f305a564 fix: Update include pattern for assets 2024-12-16 08:28:09 -08:00
Paul Gauthier (aider)
86f38e11cd feat: Add MANIFEST.in to exclude website assets 2024-12-16 08:27:02 -08:00
Paul Gauthier
0b60c48253 fixed gemini metadata keys 2024-12-15 16:00:40 -08:00
Paul Gauthier
024b9840f0 copy 2024-12-15 09:34:51 -08:00
Paul Gauthier
2f4f59d82f copy 2024-12-15 09:29:21 -08:00
Paul Gauthier
830d5ee763 copy 2024-12-15 09:27:22 -08:00
Paul Gauthier
5bc63f7a33 copy 2024-12-15 09:25:29 -08:00
Paul Gauthier
b54f970e12 copy 2024-12-15 09:16:42 -08:00
Paul Gauthier
0cc8c54152 copy 2024-12-15 09:01:13 -08:00
Paul Gauthier
241e1e27d0 copy 2024-12-15 08:50:28 -08:00
Paul Gauthier
0145e86202 Merge branch 'main' of github.com:Aider-AI/aider 2024-12-15 08:48:12 -08:00
Paul Gauthier
4d50e1e373 copy 2024-12-15 08:46:44 -08:00
Paul Gauthier
4b6ae34800 updated keys config docs 2024-12-15 08:46:20 -08:00
Paul Gauthier
2feb85e831 api keys 2024-12-15 08:40:02 -08:00
Paul Gauthier
a67ac81265 updated install instructions 2024-12-15 08:39:53 -08:00
paul-gauthier
dab536c9e8 Merge pull request #2633 from you-n-g/patch-1 2024-12-15 07:04:51 -08:00
you-n-g
64cf298521 docs: Update watch.md 2024-12-15 13:35:14 +08:00
Paul Gauthier
10b5aaa6a5 copy 2024-12-14 20:52:20 -08:00
Paul Gauthier
8c79e5ccfb copy 2024-12-14 20:09:51 -08:00
Paul Gauthier
2ef536a342 copy 2024-12-14 17:42:22 -08:00
Paul Gauthier
85b1303460 fix: Remove always-true condition for Windows env var message 2024-12-14 09:50:26 -08:00
Paul Gauthier
60aca3a241 Merge branch 'no-git' 2024-12-14 09:49:41 -08:00
Paul Gauthier
db98381a86 refactor: Move git check after env loading 2024-12-14 09:44:42 -08:00
Paul Gauthier
f62ef34715 fix: Handle missing git module gracefully 2024-12-14 09:42:54 -08:00
Paul Gauthier
f95a6c1a5a recommend aider-install 2024-12-14 09:42:32 -08:00
Paul Gauthier
65555b5dd0 copy 2024-12-13 13:43:15 -08:00
Paul Gauthier
9f6331a35e copy 2024-12-13 13:34:18 -08:00
Paul Gauthier (aider)
8c10cb6230 style: Fix linting issues in my_models.py 2024-12-13 13:22:59 -08:00
Paul Gauthier (aider)
c8894bcead feat: Conditionally add redacted model note to script 2024-12-13 13:22:55 -08:00
Paul Gauthier
edc602c33a copy 2024-12-13 12:55:33 -08:00
Paul Gauthier (aider)
abfb2ca810 fix: Correct import path for my_models in faq.md 2024-12-13 12:49:01 -08:00
Paul Gauthier (aider)
9967efe45a fix: Correct import path in cog block for model stats 2024-12-13 12:48:29 -08:00
Paul Gauthier
e77d80bda5 docs: Add FAQ about LLMs used to build aider 2024-12-13 12:48:28 -08:00
Paul Gauthier (aider)
a691d1750a style: Apply linter formatting 2024-12-13 12:34:34 -08:00
Paul Gauthier (aider)
834e2f9304 refactor: Separate data, text, and HTML formatting into functions 2024-12-13 12:34:31 -08:00
Paul Gauthier (aider)
66e5e9c1ce feat: Add percentage column to model token usage summary 2024-12-13 12:33:14 -08:00
Paul Gauthier (aider)
2d5f613984 feat: Process only last 1000 lines of analytics file 2024-12-13 12:32:28 -08:00
Paul Gauthier (aider)
868e7a278f feat: Sort model token usage by count descending 2024-12-13 12:31:38 -08:00
Paul Gauthier
f953d17889 chore: Make my_models.py executable 2024-12-13 12:31:37 -08:00
Paul Gauthier (aider)
3473969aae fix: Remove unused os import in my_models.py 2024-12-13 12:31:09 -08:00
Paul Gauthier (aider)
ec11ae7c40 style: Fix linting issues in my_models.py 2024-12-13 12:31:03 -08:00
Paul Gauthier (aider)
8217ee1bbb feat: Add script to analyze model token usage 2024-12-13 12:30:59 -08:00
Paul Gauthier
1ad3ee0aec feat: Add my_models.py script 2024-12-13 12:30:59 -08:00
Paul Gauthier (aider)
b3e9a2fede feat: Allow version arg for blame script, default to v0.1.0 2024-12-13 11:49:15 -08:00
Paul Gauthier
2f5d6bf909 feat: Take version as optional arg for blame script 2024-12-13 11:49:14 -08:00
Paul Gauthier
cd79f479e9 copy 2024-12-13 11:48:14 -08:00
Paul Gauthier
12c0f675ce copy 2024-12-13 11:46:44 -08:00
Paul Gauthier
29471b8019 set version to 0.69.1.dev 2024-12-13 11:42:00 -08:00
Paul Gauthier
cad661f0c8 version bump to 0.69.0 2024-12-13 11:40:25 -08:00
Paul Gauthier
261d770482 Merge branch 'main' of github.com:Aider-AI/aider 2024-12-13 11:39:41 -08:00
Paul Gauthier
a75c9c74fd copy 2024-12-13 11:39:37 -08:00
paul-gauthier
8b5bdf9a16 Merge pull request #2623 from damms005/patch-1
Update conventions.md to fix url
2024-12-13 10:42:54 -08:00
Damilola Emmanuel Olowookere
e35eba2d51 Update conventions.md to fix url 2024-12-13 18:36:10 +00:00
Paul Gauthier (aider)
df8c88cef4 style: Fix line length in issues.py 2024-12-13 08:46:57 -08:00
Paul Gauthier (aider)
844e12769c feat: Handle "bug" label like "enhancement" for closing 2024-12-13 08:46:53 -08:00
Paul Gauthier (aider)
b982626ac4 style: Fix line length in comment 2024-12-13 08:46:02 -08:00
Paul Gauthier (aider)
517b2b42a6 fix: Fix long lines in closing comment 2024-12-13 08:45:58 -08:00
Paul Gauthier (aider)
6778c33628 style: Apply linter fixes 2024-12-13 08:45:47 -08:00
Paul Gauthier (aider)
bc0b11e1ef feat: Add fixed enhancement issue closing 2024-12-13 08:45:43 -08:00
Paul Gauthier
6b0d4b9c93 copy 2024-12-13 08:23:42 -08:00
Paul Gauthier
7d4e4f029e copy 2024-12-13 08:13:36 -08:00
Paul Gauthier
1fbdb629ff add gemini-2.0-flash-exp metadata 2024-12-13 08:12:06 -08:00
Paul Gauthier
a437237947 copy 2024-12-13 07:37:15 -08:00
Paul Gauthier
910637c549 5% analytics 2024-12-13 06:51:50 -08:00
Paul Gauthier
e8974a3e69 copy 2024-12-12 19:08:21 -08:00
Paul Gauthier
6c98310f7f copy 2024-12-12 19:08:16 -08:00
Paul Gauthier
72aed0d26d fix: Disable complete_while_typing in prompt_session 2024-12-12 12:27:14 -08:00
Paul Gauthier
e10ef8b9e0 feat: Add instructions to /copy-context command 2024-12-12 12:08:29 -08:00
Paul Gauthier
39fa8ba831 copy 2024-12-12 07:54:54 -08:00
Paul Gauthier (aider)
8ee8279044 fix: Correct emacs auto-save gitignore pattern 2024-12-11 20:44:02 -08:00
Paul Gauthier (aider)
c3f85c3bb2 test: Fix gitignore pattern matching and add ai comment test 2024-12-11 20:43:07 -08:00
Paul Gauthier (aider)
ad59c4cbf3 test: Add comprehensive gitignore pattern tests 2024-12-11 20:43:03 -08:00
Paul Gauthier
26bc981981 chore: Add comment about testing gitignore patterns 2024-12-11 20:43:02 -08:00
Paul Gauthier
514c34b242 copy 2024-12-11 20:41:24 -08:00
Paul Gauthier (aider)
6f266c0090 fix: Skip test fixture watch files in blame script 2024-12-11 20:38:11 -08:00
Paul Gauthier
baa7352ca6 chore: Skip test fixture files in blame script 2024-12-11 20:38:11 -08:00
Paul Gauthier (aider)
fdb1c8d99a chore: Remove comment about skipping test files 2024-12-11 20:37:29 -08:00
Paul Gauthier
79f5dba094 chore: Skip test fixture files in blame script 2024-12-11 20:37:28 -08:00
Paul Gauthier
2134965f16 initial 2024-12-11 20:34:00 -08:00
Paul Gauthier
77b7a59a27 copy 2024-12-11 20:33:30 -08:00
Paul Gauthier
365e7126d0 refactor: Remove is_source_file function and check in FileWatcher 2024-12-11 20:30:47 -08:00
Paul Gauthier (aider)
d3daf9d159 feat: Add IDE, env, log, and cache patterns to ignore list 2024-12-11 20:30:17 -08:00
Paul Gauthier
8d59a519a6 chore: Add comment about gitignore patterns 2024-12-11 20:29:28 -08:00
Paul Gauthier (aider)
239262f360 style: Format gitignore patterns for readability 2024-12-11 20:28:07 -08:00
Paul Gauthier (aider)
9eb938fd6f feat: Expand gitignore patterns to include editor temp files 2024-12-11 20:28:03 -08:00
Paul Gauthier
3fcbf1a43f feat: Add text editor temp files to gitignore 2024-12-11 20:28:02 -08:00
Paul Gauthier
2b7ee271df copy 2024-12-11 20:24:08 -08:00
Paul Gauthier
11512c6281 feat: Add support for ! and ? action comments 2024-12-11 20:23:29 -08:00
Paul Gauthier (aider)
b16ba547ab test: Add assertion for line count in test_ai_comment_pattern 2024-12-11 20:21:50 -08:00
Paul Gauthier (aider)
e5b8899b4c fix: Remove extra comment in test_watch.py 2024-12-11 20:21:46 -08:00
Paul Gauthier (aider)
fee3e9e63b feat: Add test for watch_question.js fixture 2024-12-11 20:21:42 -08:00
Paul Gauthier
57a24d30b5 test: Add test for watch_question.js ai comments 2024-12-11 20:21:41 -08:00
Paul Gauthier (aider)
5a83610fb1 refactor: Update ai comment action handling to support '?' 2024-12-11 20:16:10 -08:00
Paul Gauthier
96086f12c6 fix: Correct ai comment regex to match ai? and ai! 2024-12-11 20:16:09 -08:00
Paul Gauthier
a6ee3ce07f cleanup 2024-12-11 20:12:26 -08:00
Paul Gauthier (aider)
5f36ddd425 test: Fix multiline mode tests and add toggle test 2024-12-11 20:10:30 -08:00
Paul Gauthier (aider)
bec67074e0 feat: Add tests for multiline input mode 2024-12-11 20:10:26 -08:00
Paul Gauthier (aider)
895c92cdae fix: Remove unused import buffer_has_focus 2024-12-11 20:05:04 -08:00
Paul Gauthier
7406a5bc26 refactor: Move is_searching filter to top level 2024-12-11 20:05:01 -08:00
Paul Gauthier (aider)
ef97714404 fix: Reorder imports to satisfy linter 2024-12-11 20:00:00 -08:00
Paul Gauthier (aider)
6d6daee511 fix: Use correct filter for custom enter keybinding 2024-12-11 19:59:56 -08:00
Paul Gauthier (aider)
32cd1c2a65 fix: Fix Ctrl-R reverse search enter key selection 2024-12-11 19:55:08 -08:00
Paul Gauthier
abad920a8a feat: Add gemini-2.0-flash-exp model settings 2024-12-11 19:47:44 -08:00
Paul Gauthier
e1ab49e100 copy 2024-12-11 19:43:31 -08:00
Paul Gauthier
df300e89a2 refac prompt out 2024-12-11 19:42:01 -08:00
Paul Gauthier
9a278bed21 feat: Add gemini flash model alias 2024-12-11 16:00:31 -08:00
Paul Gauthier
4a7fc084ce refactor: move watch prompt text to separate module 2024-12-11 15:07:30 -08:00
Paul Gauthier
2649e736fb chore: update model name in leaderboard to include date 2024-12-11 15:00:18 -08:00
Paul Gauthier
42ac891e28 docs: add bash syntax highlighting to code blocks in docs 2024-12-11 14:49:22 -08:00
Paul Gauthier
4dc3b9072e feat: increase retry timeout for benchmarking 2024-12-11 14:26:28 -08:00
Paul Gauthier
ae3235b099 feat: add Gemini 2.0 Flash model leaderboard entry 2024-12-11 13:55:52 -08:00
Paul Gauthier
7cc5e0d577 docs: add Yi Lightning model test results to leaderboard 2024-12-11 13:54:39 -08:00
Paul Gauthier
f6b956dc8e refactor: simplify voice command and improve installation docs 2024-12-11 13:52:33 -08:00
Paul Gauthier (aider)
fcb2bacd1e style: format benchmark.py with black 2024-12-11 13:09:52 -08:00
Paul Gauthier (aider)
a9401e921e feat: add sleep option between tests in single-threaded mode 2024-12-11 13:09:45 -08:00
Paul Gauthier
02e7e315b2 copy 2024-12-11 12:54:50 -08:00
Paul Gauthier
def72a64e0 copy 2024-12-11 12:45:56 -08:00
Paul Gauthier
46e7672197 copy 2024-12-11 12:42:19 -08:00
Paul Gauthier
2f8a5ce935 copy 2024-12-11 12:40:13 -08:00
Paul Gauthier (aider)
730e5bd831 fix: add error handling for clipboard operations in copy_context command 2024-12-11 12:10:12 -08:00
Paul Gauthier
b7984a05af copy 2024-12-11 09:51:51 -08:00
Paul Gauthier
5d4af67186 Merge branch 'main' of github.com:Aider-AI/aider 2024-12-11 07:21:18 -08:00
paul-gauthier
370e08cf4d Merge pull request #2601 from miradnanali/multiline-mode
Implement /multiline-mode, swaps Enter & Meta-Enter
2024-12-11 07:21:09 -08:00
Mir Adnan ALI
aaf7e3f943 Implement multiline-mode, swaps Enter & Meta-Enter 2024-12-11 09:09:58 -05:00
Paul Gauthier
fbde0936e7 revert 2024-12-10 11:20:25 -08:00
Paul Gauthier (aider)
af48f7bab4 fix: update artifact upload path to match Jekyll build directory 2024-12-10 11:12:23 -08:00
Paul Gauthier
61def89878 ci: downgrade upload-pages-artifact action to v3 2024-12-10 11:07:42 -08:00
Paul Gauthier (aider)
88e86cee77 chore: upgrade upload-pages-artifact action to v4 2024-12-10 11:04:46 -08:00
Paul Gauthier
acc1625406 Merge branch 'main' of github.com:Aider-AI/aider 2024-12-10 11:03:20 -08:00
Paul Gauthier
502f448053 copy 2024-12-10 09:59:56 -08:00
paul-gauthier
55b081884c Merge pull request #2592 from JeongJuhyeon/patch-1
Add '?' to set of punctuations to strip for file mentions
2024-12-10 08:41:38 -08:00
Paul Gauthier
fd67171908 copy 2024-12-10 08:21:28 -08:00
Paul Gauthier
16a53aa641 set version to 0.68.1.dev 2024-12-10 08:19:44 -08:00
Paul Gauthier
4aec676950 version bump to 0.68.0 2024-12-10 08:18:06 -08:00
Paul Gauthier
d8fff0e90a copy 2024-12-10 08:01:18 -08:00
Paul Gauthier
57ad6cc3ea Update shell cmd prompt: no multi-line, run from project root 2024-12-10 07:59:24 -08:00
Paul Gauthier
2b46a8b9c9 copy 2024-12-10 07:39:58 -08:00
Paul Gauthier
4d1a2e8c53 copy 2024-12-10 07:19:00 -08:00
Paul Gauthier
58b1409bd2 copy 2024-12-10 07:02:26 -08:00
Paul Gauthier
a2525dbf56 docs: remove deprecated label from DeepSeek model names 2024-12-10 06:59:58 -08:00
Paul Gauthier
36eb2a31b5 docs: add DeepSeek-V2.5-1210 model leaderboard results 2024-12-10 06:57:18 -08:00
Paul Gauthier
0483bfc9cb docs: add Gemini whole file edit experiment results to leaderboard 2024-12-10 06:47:41 -08:00
JeongJuhyeon
3f63a64254 Add '?' to set of punctuations to strip for file mentions 2024-12-10 22:10:00 +09:00
Paul Gauthier
16332b285f copy 2024-12-09 20:27:38 -08:00
Paul Gauthier
f7371f6faf copy 2024-12-09 20:27:32 -08:00
Paul Gauthier
92d29805f1 copy 2024-12-09 20:06:36 -08:00
Paul Gauthier
4a37d07acb fix: skip context copy when using placeholder input 2024-12-09 18:46:44 -08:00
Paul Gauthier
bb4c61e9cc copy 2024-12-09 15:38:40 -08:00
Paul Gauthier
f4e5515c82 docs: clarify read-only command description and behavior 2024-12-09 15:37:48 -08:00
Paul Gauthier (aider)
141a2df19c test: add test for bulk conversion to read-only mode 2024-12-09 15:36:03 -08:00
Paul Gauthier (aider)
e2385b4922 feat: add bulk conversion to read-only mode when no files specified 2024-12-09 15:34:59 -08:00
Paul Gauthier
9974fb50f7 feat: add auto-conversion of /added files to read-only mode 2024-12-09 15:34:57 -08:00
Paul Gauthier
c5d51d62c4 feat: add architect command and improve coder class documentation 2024-12-09 15:30:01 -08:00
Paul Gauthier
4fcbf28f91 Restore interactive shell #2415 2024-12-09 15:23:39 -08:00
Paul Gauthier
f678b664ff refactor: Move website files list to global scope 2024-12-09 15:01:12 -08:00
Paul Gauthier (aider)
4206920a7d style: fix whitespace in blame.py 2024-12-09 15:00:47 -08:00
Paul Gauthier (aider)
ad2e5ead54 refactor: extract website files into dedicated list 2024-12-09 15:00:41 -08:00
Paul Gauthier
eb72719117 chore: add website file to blame script and improve comments 2024-12-09 15:00:40 -08:00
Paul Gauthier (aider)
20b46afbf2 style: update cookie consent box colors to dark grey 2024-12-09 14:41:12 -08:00
Paul Gauthier (aider)
1925e4a7f4 feat: add cookie persistence config to consent banner 2024-12-09 14:39:19 -08:00
Paul Gauthier (aider)
1a12322354 feat: add GDPR-compliant cookie consent for PostHog analytics 2024-12-09 14:33:54 -08:00
Paul Gauthier
73f3f4ec7e feat: add analytics events for copy-paste mode and AI comments 2024-12-09 10:47:30 -08:00
Paul Gauthier (aider)
a8c42f453a style: format FileWatcher instantiation for better readability 2024-12-09 10:32:08 -08:00
Paul Gauthier (aider)
79dd0c5ba6 feat: add analytics events for file watching and AI comments 2024-12-09 10:31:59 -08:00
Paul Gauthier
89bc3b6b16 feat: add analytics event hooks to file watcher 2024-12-09 10:31:57 -08:00
Paul Gauthier (aider)
a997dd6c49 fix: use LiteLLMExceptions class instead of undefined litellm_ex 2024-12-09 07:46:09 -08:00
Paul Gauthier (aider)
6aa80d2a4c feat: handle cost calculation differently for context window vs other errors 2024-12-09 07:45:50 -08:00
Paul Gauthier
f009e8fb14 add pip as a req 2024-12-09 06:51:06 -08:00
Paul Gauthier
a8dde17155 add posthog 2024-12-09 06:50:58 -08:00
Paul Gauthier
cbcbff341b style: format voice.py and suppress syntax warnings 2024-12-08 18:14:30 -08:00
Paul Gauthier (aider)
e50992bb93 style: remove unused shutil import 2024-12-08 18:12:36 -08:00
Paul Gauthier
fa6c3068c0 refactor: simplify pip install command by using sys.executable directly 2024-12-08 18:12:30 -08:00
Paul Gauthier
dd9bdca572 copy 2024-12-08 14:44:51 -08:00
Paul Gauthier
3f7dffe47d copy 2024-12-08 14:30:31 -08:00
Paul Gauthier
c7fde14458 copy 2024-12-08 12:05:41 -08:00
Paul Gauthier
57f4186cad refactor: optimize analytics event tracking with system info as super properties 2024-12-08 11:49:12 -08:00
Paul Gauthier
fa5a6021b1 copy 2024-12-08 11:49:01 -08:00
Paul Gauthier
42ae279b91 fix: update test cases to use Model wrapper class 2024-12-07 15:09:04 -08:00
Paul Gauthier
a74cdbfc28 test: update test_sendchat to use Model class and fix assertion 2024-12-07 15:07:39 -08:00
Paul Gauthier (aider)
a56fa567dd test: update print call count assertions in sendchat tests 2024-12-07 13:44:08 -08:00
Paul Gauthier (aider)
c9c2d5ab6f test: update test assertions to check model objects instead of names 2024-12-07 13:38:57 -08:00
Paul Gauthier (aider)
ccf460c1f7 refactor: update simple_send_with_retries to use model object and handle temperature 2024-12-07 13:37:14 -08:00
Paul Gauthier
2325f542b8 copy 2024-12-07 13:04:06 -08:00
Paul Gauthier (aider)
63fdf3f3f6 style: format git blame command arguments for better readability 2024-12-07 11:54:14 -08:00
Paul Gauthier (aider)
efa83bdf34 feat: add git blame move/copy detection for better attribution 2024-12-07 11:54:10 -08:00
Paul Gauthier
5705bda818 style: Update settings section headings to use lowercase 2024-12-07 11:51:19 -08:00
Paul Gauthier
20042334ff refactor: reorganize command line arguments and improve help messages 2024-12-07 11:45:20 -08:00
Paul Gauthier (aider)
7ae9569816 docs: update deprecated OpenAI args help text to suggest --set-env 2024-12-07 11:23:05 -08:00
Paul Gauthier
cacba526b3 refactor: reorganize API key and environment settings arguments 2024-12-07 11:23:03 -08:00
Paul Gauthier
50f203cc8a cleanup 2024-12-07 11:07:59 -08:00
Paul Gauthier
3efcd154f3 refactor: consolidate API key and environment variable handling 2024-12-07 10:55:29 -08:00
Paul Gauthier (aider)
bdb08d7c78 style: format long lines in main.py 2024-12-07 10:52:27 -08:00
Paul Gauthier (aider)
f3874dd40a feat: add deprecation warnings for legacy API key arguments 2024-12-07 10:52:21 -08:00
Paul Gauthier
935c39e341 refactor: move API key handling earlier in startup sequence 2024-12-07 10:52:19 -08:00
Paul Gauthier (aider)
7ddcc30e8d style: format test_main.py line breaks 2024-12-07 08:23:58 -08:00
Paul Gauthier (aider)
13ff038e58 feat: add --api-key flag to set provider API keys as env vars 2024-12-07 08:23:50 -08:00
Paul Gauthier
1d4918dfbf refactor: Remove analytics event for invalid env var format 2024-12-07 08:11:10 -08:00
Paul Gauthier (aider)
ba14ab96da refactor: update env format test to check return value instead of SystemExit 2024-12-07 08:09:56 -08:00
Paul Gauthier
054e0820b7 refactor: Move --set-env processing after IO initialization 2024-12-07 08:09:52 -08:00
Paul Gauthier (aider)
af3d8dd6a7 style: format test_main.py with black 2024-12-07 08:08:40 -08:00
Paul Gauthier (aider)
e10d06cb47 test: add test coverage for --set-env functionality 2024-12-07 08:08:35 -08:00
Paul Gauthier (aider)
87a1469c1e style: fix string quote consistency in env setting split 2024-12-07 08:07:28 -08:00
Paul Gauthier (aider)
2492f1635c refactor: remove --set-env argument processing from main function 2024-12-07 08:07:23 -08:00
Paul Gauthier (aider)
b3305e6e19 refactor: move env var processing after IO initialization 2024-12-07 08:07:14 -08:00
Paul Gauthier (aider)
491d3e6606 style: fix string quote consistency in env setting split 2024-12-07 08:06:04 -08:00
Paul Gauthier (aider)
e41bf67f73 feat: add --set-env flag to set environment variables from command line 2024-12-07 08:05:57 -08:00
Paul Gauthier
66b99c4fa0 bumped deps to pickup litellm that supports OPENAI_ORGANIZATION 2024-12-07 07:57:29 -08:00
Paul Gauthier (aider)
f2f2645fe6 style: fix linting issues in watch.py 2024-12-07 07:54:24 -08:00
Paul Gauthier (aider)
4c77d0509a feat: add shell dotfile extensions to source file detection 2024-12-07 07:54:20 -08:00
Paul Gauthier
33d77f4355 feat: add shell script file extensions to source file detection 2024-12-07 07:54:18 -08:00
Paul Gauthier
ecf8617246 copy 2024-12-06 17:41:34 -08:00
Paul Gauthier
bec216d72a feat: add experimental Gemini model settings 2024-12-06 17:41:11 -08:00
Paul Gauthier (aider)
374e8c3307 feat: add video file exclusions to linkchecker 2024-12-06 15:12:12 -08:00
Paul Gauthier
b5eff8a9dd copy 2024-12-06 14:52:50 -08:00
Paul Gauthier (aider)
d53002a494 feat: add legend to chart showing diff and whole format patterns 2024-12-06 14:46:43 -08:00
Paul Gauthier (aider)
04662f0875 feat: add y-axis label to leaderboard charts 2024-12-06 14:45:25 -08:00
Paul Gauthier
aec92c7c17 refactor: update highlighted model name to 1206 2024-12-06 14:45:23 -08:00
Paul Gauthier (aider)
f7a7976923 feat: add red striped pattern for highlighted model with whole edit format 2024-12-06 14:43:05 -08:00
Paul Gauthier
1b50d4507f feat: update highlighted model to Qwen in leaderboard 2024-12-06 14:43:02 -08:00
Paul Gauthier (aider)
045cf887df feat: add pattern background for whole edit format bars in chart 2024-12-06 14:39:05 -08:00
Paul Gauthier (aider)
277d7c0e04 perf: cache diagonal pattern and optimize label access in chart rendering 2024-12-06 14:36:34 -08:00
Paul Gauthier (aider)
0e2c703e77 fix: add chart render call to ensure pattern reappears after row selection 2024-12-06 14:33:31 -08:00
Paul Gauthier (aider)
62b3f38f00 feat: add Patternomaly script tags for chart patterns 2024-12-06 14:31:52 -08:00
Paul Gauthier (aider)
422658293d fix: remove redundant pattern initialization and add Patternomaly script 2024-12-06 14:31:29 -08:00
Paul Gauthier (aider)
74cfd05642 feat: add edit format field and striped pattern for whole edits 2024-12-06 14:29:36 -08:00
Paul Gauthier (aider)
80586f1de3 feat: add line breaks for long x-axis labels in leaderboard chart 2024-12-06 14:22:54 -08:00
Paul Gauthier
a933177ac0 copy 2024-12-06 14:19:00 -08:00
Paul Gauthier
ade2db696b add emini-exp-1206 2024-12-06 14:14:07 -08:00
Paul Gauthier
cf266037ff copy 2024-12-06 14:10:11 -08:00
Paul Gauthier
5f14277fbf Remove -i when running shell commands, as it tosses local env 2024-12-06 13:56:57 -08:00
Paul Gauthier
b677349ec9 copy 2024-12-06 13:55:53 -08:00
Paul Gauthier
7f72d2a703 reraise EOFError to fix control-d 2024-12-06 13:55:41 -08:00
Paul Gauthier
779983cb85 feat: add missing dependency hints for Gemini and Bedrock 2024-12-06 13:43:49 -08:00
Paul Gauthier
f2d2ab51b1 copy 2024-12-06 13:27:26 -08:00
Paul Gauthier
0a54f8c4a7 copy 2024-12-06 12:25:45 -08:00
Paul Gauthier
881527ddd0 handle and test for trailing whitespace after ai 2024-12-06 12:23:27 -08:00
Paul Gauthier
cca4f894a8 style: fix indentation and remove redundant comment 2024-12-06 12:20:23 -08:00
Paul Gauthier (aider)
20dae33be5 fix: remove duplicate TreeContext parameters causing syntax error 2024-12-06 12:15:59 -08:00
Paul Gauthier (aider)
fd301c519d feat: add error handling for TreeContext with fallback to raw comments 2024-12-06 12:15:46 -08:00
Paul Gauthier
a96d87814b fix: handle ValueError in TreeContext by including raw comments 2024-12-06 12:15:45 -08:00
Paul Gauthier
2a3eefc5be copy 2024-12-06 12:09:20 -08:00
Paul Gauthier
c5dc10e3cd copy 2024-12-06 11:24:26 -08:00
Paul Gauthier
c251a93609 fix --test to automatically fix errors 2024-12-06 11:23:15 -08:00
Paul Gauthier
2df509effd added llama 3.3 70b 2024-12-06 10:47:40 -08:00
Paul Gauthier
53e0d670b3 copy 2024-12-06 09:45:41 -08:00
Paul Gauthier
ccd19d2c96 copy 2024-12-06 09:24:13 -08:00
Paul Gauthier
b69f084db9 copy 2024-12-06 09:10:35 -08:00
Paul Gauthier
9639395937 feat: improve AI comment handling and documentation 2024-12-06 08:46:52 -08:00
Paul Gauthier
117b7afd81 copy 2024-12-06 07:17:21 -08:00
Paul Gauthier
009c4dc8db copy 2024-12-06 07:02:06 -08:00
Paul Gauthier
0fdf3fc851 Merge branch 'copypaste' 2024-12-06 07:01:40 -08:00
Paul Gauthier
ffc2d91cef copy 2024-12-06 06:44:23 -08:00
Paul Gauthier
6efdf8a7f4 refactor: rename copypaste flag to copy-paste and update help text 2024-12-05 20:43:14 -08:00
Paul Gauthier
623770e24b refactor: move clipboard context functionality to commands.py 2024-12-05 20:41:40 -08:00
Paul Gauthier (aider)
402940a215 fix: store clipboard watcher instance in coder object 2024-12-05 20:36:04 -08:00
Paul Gauthier (aider)
7fea85cdcd style: reorder imports alphabetically 2024-12-05 20:35:51 -08:00
Paul Gauthier (aider)
93b3b7a184 feat: set auto-copy-context based on copypaste argument 2024-12-05 20:35:46 -08:00
Paul Gauthier
8f2a84629a refactor: move ClipboardWatcher import to top level 2024-12-05 20:35:44 -08:00
Paul Gauthier (aider)
7a1c1982f0 feat: implement auto copy context functionality 2024-12-05 20:35:04 -08:00
Paul Gauthier
75d8982b23 feat: add auto copy context feature with empty implementation 2024-12-05 20:35:02 -08:00
Paul Gauthier (aider)
87dbb56d7e style: fix trailing comma in system prompt dictionary 2024-12-05 18:57:50 -08:00
Paul Gauthier (aider)
aa217a3a43 fix: handle system reminder message construction properly 2024-12-05 18:57:47 -08:00
Paul Gauthier (aider)
22fc961dc0 fix: add empty list check before accessing last chat chunk 2024-12-05 18:57:24 -08:00
Paul Gauthier (aider)
8f57186945 style: remove trailing whitespace in editor_editblock_coder.py 2024-12-05 18:55:54 -08:00
Paul Gauthier (aider)
f8277c55a8 feat: add format_chat_markdown method to EditorEditBlockCoder 2024-12-05 18:55:50 -08:00
Paul Gauthier (aider)
6163713e34 style: fix linting issues in clipboard watcher initialization 2024-12-05 18:44:57 -08:00
Paul Gauthier (aider)
d2d5887936 feat: add clipboard watcher with --copypaste flag 2024-12-05 18:44:50 -08:00
Paul Gauthier (aider)
2a1065efc1 style: fix linting issues in copypaste.py 2024-12-05 18:43:16 -08:00
Paul Gauthier (aider)
6f36a97c4a feat: add clipboard watcher to monitor and update IO placeholder 2024-12-05 18:43:12 -08:00
Paul Gauthier
eeed79009a feat: add copypaste module for code manipulation 2024-12-05 18:43:09 -08:00
98 changed files with 4649 additions and 2872 deletions

View File

@@ -84,4 +84,4 @@ jobs:
- name: Run linkchecker
run: |
linkchecker https://aider.chat
linkchecker --ignore-url='.+\.(mp4|mov|avi)' https://aider.chat

View File

@@ -1,5 +1,42 @@
# Release history
### Aider v0.69.0
- [Watch files](https://aider.chat/docs/usage/watch.html) improvements:
- Use `# ... AI?` comments to trigger aider and ask questions about your code.
- Now watches *all* files, not just certain source files.
- Use `# AI comments`, `// AI comments`, or `-- AI comments` to give aider instructions in any text file.
- Full support for Gemini Flash 2.0 Exp:
- `aider --model flash` or `aider --model gemini/gemini-2.0-flash-exp`
- [New `--multiline` flag and `/multiline-mode` command](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) makes ENTER a soft newline and META-ENTER send the message, by @miradnanali.
- `/copy-context <instructions>` now takes optional "instructions" when [copying code context to the clipboard](https://aider.chat/docs/usage/copypaste.html#copy-aiders-code-context-to-your-clipboard-paste-into-the-web-ui).
- Improved clipboard error handling with helpful requirements install info.
- Ask 5% of users if they want to opt-in to analytics.
- `/voice` now lets you edit the transcribed text before sending.
- Disabled auto-complete in Y/N prompts.
- Aider wrote 68% of the code in this release.
### Aider v0.68.0
- [Aider works with LLM web chat UIs](https://aider.chat/docs/usage/copypaste.html).
- New `--copy-paste` mode.
- New `/copy-context` command.
- [Set API keys and other environment variables for all providers from command line or yaml conf file](https://aider.chat/docs/config/aider_conf.html#storing-llm-keys).
- New `--api-key provider=key` setting.
- New `--set-env VAR=value` setting.
- Added bash and zsh support to `--watch-files`.
- Better error messages when missing dependencies for Gemini and Bedrock models.
- Control-D now properly exits the program.
- Don't count token costs when API provider returns a hard error.
- Bugfix so watch files works with files that don't have tree-sitter support.
- Bugfix so o1 models can be used as weak model.
- Updated shell command prompt.
- Added docstrings for all Coders.
- Reorganized command line arguments with improved help messages and grouping.
- Use the exact `sys.python` for self-upgrades.
- Added experimental Gemini models.
- Aider wrote 71% of the code in this release.
### Aider v0.67.0
- [Use aider in your IDE or editor](https://aider.chat/docs/usage/watch.html).
@@ -13,7 +50,7 @@
- Spinner now falls back to ASCII art if fancy symbols throw unicode errors.
- `--read` now expands `~` home dirs.
- Enabled exception capture in analytics.
- Aider wrote 61% of the code in this release.
- [Aider wrote 61% of the code in this release.](https://aider.chat/HISTORY.html)
### Aider v0.66.0

14
MANIFEST.in Normal file
View File

@@ -0,0 +1,14 @@
# This needs to sync with aider/help_pats.py
global-exclude .DS_Store
recursive-exclude aider/website/examples *
recursive-exclude aider/website/_posts *
exclude aider/website/HISTORY.md
exclude aider/website/docs/benchmarks*.md
exclude aider/website/docs/ctags.md
exclude aider/website/docs/unified-diffs.md
exclude aider/website/docs/leaderboards/index.md
recursive-exclude aider/website/assets *
recursive-exclude aider/website *.js
recursive-exclude aider/website *.html
recursive-exclude aider/website *.yml

View File

@@ -43,28 +43,27 @@ VIDEO END -->
cog.out(open("aider/website/_includes/get-started.md").read())
]]]-->
You can get started quickly like this:
You can get started quickly like this, with python 3.8-3.13:
```
python -m pip install -U aider-chat
```bash
python -m pip install aider-install
aider-install
# Change directory into a git repo
# Change directory into your code base
cd /to/your/git/repo
# Work with Claude 3.5 Sonnet on your repo
export ANTHROPIC_API_KEY=your-key-goes-here
aider
aider --model sonnet --anthropic-api-key your-key-goes-here
# Work with GPT-4o on your repo
export OPENAI_API_KEY=your-key-goes-here
aider
aider --model gpt-4o --openai-api-key your-key-goes-here
```
<!--[[[end]]]-->
See the
[installation instructions](https://aider.chat/docs/install.html)
and other
[documentation](https://aider.chat/docs/usage.html)
and
[usage documentation](https://aider.chat/docs/usage.html)
for more details.
## Features

View File

@@ -1,6 +1,6 @@
from packaging import version
__version__ = "0.67.1.dev"
__version__ = "0.69.2.dev"
safe_version = __version__
try:

View File

@@ -56,6 +56,7 @@ class Analytics:
host=posthog_host,
on_error=self.posthog_error,
enable_exception_autocapture=True,
super_properties=self.get_system_info(), # Add system info to all events
)
def disable(self, permanently):
@@ -83,7 +84,7 @@ class Analytics:
if not self.user_id:
return False
PERCENT = 2.5
PERCENT = 5
return self.is_uuid_in_percentage(self.user_id, PERCENT)
def is_uuid_in_percentage(self, uuid_str, percent):
@@ -164,6 +165,7 @@ class Analytics:
"os_platform": platform.system(),
"os_release": platform.release(),
"machine": platform.machine(),
"aider_version": __version__,
}
def _redact_model_name(self, model):
@@ -179,6 +181,7 @@ class Analytics:
def posthog_error(self):
"""disable posthog if we get an error"""
print("X" * 100)
# https://github.com/PostHog/posthog-python/blob/9e1bb8c58afaa229da24c4fb576c08bb88a75752/posthog/consumer.py#L86
# https://github.com/Aider-AI/aider/issues/2532
self.ph = None
@@ -195,7 +198,6 @@ class Analytics:
properties["editor_model"] = self._redact_model_name(main_model.editor_model)
properties.update(kwargs)
properties.update(self.get_system_info()) # Add system info to all events
# Handle numeric values
for key, value in properties.items():
@@ -204,8 +206,6 @@ class Analytics:
else:
properties[key] = str(value)
properties["aider_version"] = __version__
if self.mp:
try:
self.mp.track(self.user_id, event_name, dict(properties))

View File

@@ -28,22 +28,10 @@ def get_parser(default_config_files, git_root):
config_file_parser_class=configargparse.YAMLConfigFileParser,
auto_env_var_prefix="AIDER_",
)
group = parser.add_argument_group("Main")
group = parser.add_argument_group("Main model")
group.add_argument(
"files", metavar="FILE", nargs="*", help="files to edit with an LLM (optional)"
)
group.add_argument(
"--openai-api-key",
metavar="OPENAI_API_KEY",
env_var="OPENAI_API_KEY",
help="Specify the OpenAI API key",
)
group.add_argument(
"--anthropic-api-key",
metavar="ANTHROPIC_API_KEY",
env_var="ANTHROPIC_API_KEY",
help="Specify the Anthropic API key",
)
group.add_argument(
"--model",
metavar="MODEL",
@@ -144,43 +132,59 @@ def get_parser(default_config_files, git_root):
)
##########
group = parser.add_argument_group("Model Settings")
group = parser.add_argument_group("API Keys and settings")
group.add_argument(
"--openai-api-key",
help="Specify the OpenAI API key",
)
group.add_argument(
"--anthropic-api-key",
help="Specify the Anthropic API key",
)
group.add_argument(
"--openai-api-base",
help="Specify the api base url",
)
group.add_argument(
"--openai-api-type",
help="(deprecated, use --set-env OPENAI_API_TYPE=<value>)",
)
group.add_argument(
"--openai-api-version",
help="(deprecated, use --set-env OPENAI_API_VERSION=<value>)",
)
group.add_argument(
"--openai-api-deployment-id",
help="(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)",
)
group.add_argument(
"--openai-organization-id",
help="(deprecated, use --set-env OPENAI_ORGANIZATION=<value>)",
)
group.add_argument(
"--set-env",
action="append",
metavar="ENV_VAR_NAME=value",
help="Set an environment variable (to control API settings, can be used multiple times)",
default=[],
)
group.add_argument(
"--api-key",
action="append",
metavar="PROVIDER=KEY",
help=(
"Set an API key for a provider (eg: --api-key provider=<key> sets"
" PROVIDER_API_KEY=<key>)"
),
default=[],
)
group = parser.add_argument_group("Model settings")
group.add_argument(
"--list-models",
"--models",
metavar="MODEL",
help="List known models which match the (partial) MODEL name",
)
group.add_argument(
"--openai-api-base",
metavar="OPENAI_API_BASE",
env_var="OPENAI_API_BASE",
help="Specify the api base url",
)
group.add_argument(
"--openai-api-type",
metavar="OPENAI_API_TYPE",
env_var="OPENAI_API_TYPE",
help="Specify the api_type",
)
group.add_argument(
"--openai-api-version",
metavar="OPENAI_API_VERSION",
env_var="OPENAI_API_VERSION",
help="Specify the api_version",
)
group.add_argument(
"--openai-api-deployment-id",
metavar="OPENAI_API_DEPLOYMENT_ID",
env_var="OPENAI_API_DEPLOYMENT_ID",
help="Specify the deployment_id",
)
group.add_argument(
"--openai-organization-id",
metavar="OPENAI_ORGANIZATION_ID",
env_var="OPENAI_ORGANIZATION_ID",
help="Specify the OpenAI organization ID",
)
group.add_argument(
"--model-settings-file",
metavar="MODEL_SETTINGS_FILE",
@@ -261,17 +265,9 @@ def get_parser(default_config_files, git_root):
" If unspecified, defaults to the model's max_chat_history_tokens."
),
)
# This is a duplicate of the argument in the preparser and is a no-op by this time of
# argument parsing, but it's here so that the help is displayed as expected.
group.add_argument(
"--env-file",
metavar="ENV_FILE",
default=default_env_file(git_root),
help="Specify the .env file to load (default: .env in git root)",
)
##########
group = parser.add_argument_group("Cache Settings")
group = parser.add_argument_group("Cache settings")
group.add_argument(
"--cache-prompts",
action=argparse.BooleanOptionalAction,
@@ -286,7 +282,7 @@ def get_parser(default_config_files, git_root):
)
##########
group = parser.add_argument_group("Repomap Settings")
group = parser.add_argument_group("Repomap settings")
group.add_argument(
"--map-tokens",
type=int,
@@ -343,7 +339,7 @@ def get_parser(default_config_files, git_root):
)
##########
group = parser.add_argument_group("Output Settings")
group = parser.add_argument_group("Output settings")
group.add_argument(
"--dark-mode",
action="store_true",
@@ -442,7 +438,7 @@ def get_parser(default_config_files, git_root):
)
##########
group = parser.add_argument_group("Git Settings")
group = parser.add_argument_group("Git settings")
group.add_argument(
"--git",
action=argparse.BooleanOptionalAction,
@@ -595,37 +591,8 @@ def get_parser(default_config_files, git_root):
default=False,
)
group = parser.add_argument_group("Other Settings")
group.add_argument(
"--file",
action="append",
metavar="FILE",
help="specify a file to edit (can be used multiple times)",
)
group.add_argument(
"--read",
action="append",
metavar="FILE",
help="specify a read-only file (can be used multiple times)",
)
group.add_argument(
"--vim",
action="store_true",
help="Use VI editing mode in the terminal (default: False)",
default=False,
)
group.add_argument(
"--chat-language",
metavar="CHAT_LANGUAGE",
default=None,
help="Specify the language to use in the chat (default: None, uses system settings)",
)
group.add_argument(
"--version",
action="version",
version=f"%(prog)s {__version__}",
help="Show the version number and exit",
)
#########
group = parser.add_argument_group("Upgrading")
group.add_argument(
"--just-check-update",
action="store_true",
@@ -658,47 +625,14 @@ def get_parser(default_config_files, git_root):
default=False,
)
group.add_argument(
"--apply",
metavar="FILE",
help="Apply the changes from the given file instead of running the chat (debug)",
)
group.add_argument(
"--apply-clipboard-edits",
action="store_true",
help="Apply clipboard contents as edits using the main model's editor format",
default=False,
)
group.add_argument(
"--yes-always",
action="store_true",
help="Always say yes to every confirmation",
default=None,
)
group.add_argument(
"-v",
"--verbose",
action="store_true",
help="Enable verbose output",
default=False,
)
group.add_argument(
"--show-repo-map",
action="store_true",
help="Print the repo map and exit (debug)",
default=False,
)
group.add_argument(
"--show-prompts",
action="store_true",
help="Print the system prompts and exit (debug)",
default=False,
)
group.add_argument(
"--exit",
action="store_true",
help="Do all startup activities then exit before accepting user input (debug)",
default=False,
"--version",
action="version",
version=f"%(prog)s {__version__}",
help="Show the version number and exit",
)
##########
group = parser.add_argument_group("Modes")
group.add_argument(
"--message",
"--msg",
@@ -717,6 +651,110 @@ def get_parser(default_config_files, git_root):
" (disables chat mode)"
),
)
group.add_argument(
"--gui",
"--browser",
action=argparse.BooleanOptionalAction,
help="Run aider in your browser (default: False)",
default=False,
)
group.add_argument(
"--copy-paste",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable automatic copy/paste of chat between aider and web UI (default: False)",
)
group.add_argument(
"--apply",
metavar="FILE",
help="Apply the changes from the given file instead of running the chat (debug)",
)
group.add_argument(
"--apply-clipboard-edits",
action="store_true",
help="Apply clipboard contents as edits using the main model's editor format",
default=False,
)
group.add_argument(
"--exit",
action="store_true",
help="Do all startup activities then exit before accepting user input (debug)",
default=False,
)
group.add_argument(
"--show-repo-map",
action="store_true",
help="Print the repo map and exit (debug)",
default=False,
)
group.add_argument(
"--show-prompts",
action="store_true",
help="Print the system prompts and exit (debug)",
default=False,
)
##########
group = parser.add_argument_group("Voice settings")
group.add_argument(
"--voice-format",
metavar="VOICE_FORMAT",
default="wav",
choices=["wav", "mp3", "webm"],
help="Audio format for voice recording (default: wav). webm and mp3 require ffmpeg",
)
group.add_argument(
"--voice-language",
metavar="VOICE_LANGUAGE",
default="en",
help="Specify the language for voice using ISO 639-1 code (default: auto)",
)
group.add_argument(
"--voice-input-device",
metavar="VOICE_INPUT_DEVICE",
default=None,
help="Specify the input device name for voice recording",
)
######
group = parser.add_argument_group("Other settings")
group.add_argument(
"--file",
action="append",
metavar="FILE",
help="specify a file to edit (can be used multiple times)",
)
group.add_argument(
"--read",
action="append",
metavar="FILE",
help="specify a read-only file (can be used multiple times)",
)
group.add_argument(
"--vim",
action="store_true",
help="Use VI editing mode in the terminal (default: False)",
default=False,
)
group.add_argument(
"--chat-language",
metavar="CHAT_LANGUAGE",
default=None,
help="Specify the language to use in the chat (default: None, uses system settings)",
)
group.add_argument(
"--yes-always",
action="store_true",
help="Always say yes to every confirmation",
default=None,
)
group.add_argument(
"-v",
"--verbose",
action="store_true",
help="Enable verbose output",
default=False,
)
group.add_argument(
"--load",
metavar="LOAD_FILE",
@@ -737,12 +775,13 @@ def get_parser(default_config_files, git_root):
" or home directory)"
),
)
# This is a duplicate of the argument in the preparser and is a no-op by this time of
# argument parsing, but it's here so that the help is displayed as expected.
group.add_argument(
"--gui",
"--browser",
action=argparse.BooleanOptionalAction,
help="Run aider in your browser (default: False)",
default=False,
"--env-file",
metavar="ENV_FILE",
default=default_env_file(git_root),
help="Specify the .env file to load (default: .env in git root)",
)
group.add_argument(
"--suggest-shell-commands",
@@ -756,6 +795,12 @@ def get_parser(default_config_files, git_root):
default=True,
help="Enable/disable fancy input with history and completion (default: True)",
)
group.add_argument(
"--multiline",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable multi-line input mode with Meta-Enter to submit (default: False)",
)
group.add_argument(
"--detect-urls",
action=argparse.BooleanOptionalAction,
@@ -767,28 +812,6 @@ def get_parser(default_config_files, git_root):
help="Specify which editor to use for the /editor command",
)
##########
group = parser.add_argument_group("Voice Settings")
group.add_argument(
"--voice-format",
metavar="VOICE_FORMAT",
default="wav",
choices=["wav", "mp3", "webm"],
help="Audio format for voice recording (default: wav). webm and mp3 require ffmpeg",
)
group.add_argument(
"--voice-language",
metavar="VOICE_LANGUAGE",
default="en",
help="Specify the language for voice using ISO 639-1 code (default: auto)",
)
group.add_argument(
"--voice-input-device",
metavar="VOICE_INPUT_DEVICE",
default=None,
help="Specify the input device name for voice recording",
)
return parser

View File

@@ -248,6 +248,9 @@ class Coder:
if self.done_messages:
lines.append("Restored previous conversation history.")
if self.io.multiline_mode:
lines.append("Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text")
return lines
def __init__(
@@ -286,6 +289,7 @@ class Coder:
detect_urls=True,
ignore_mentions=None,
file_watcher=None,
auto_copy_context=False,
):
# Fill in a dummy Analytics if needed, but it is never .enable()'d
self.analytics = analytics if analytics is not None else Analytics()
@@ -297,6 +301,8 @@ class Coder:
self.rejected_urls = set()
self.abs_root_path_cache = {}
self.auto_copy_context = auto_copy_context
self.ignore_mentions = ignore_mentions
if not self.ignore_mentions:
self.ignore_mentions = set()
@@ -792,9 +798,10 @@ class Coder:
self.io.user_input(with_message)
self.run_one(with_message, preproc)
return self.partial_response_content
while True:
try:
if not self.io.placeholder:
self.copy_context()
user_message = self.get_input()
self.run_one(user_message, preproc)
self.show_undo_hint()
@@ -803,6 +810,10 @@ class Coder:
except EOFError:
return
def copy_context(self):
if self.auto_copy_context:
self.commands.cmd_copy_context()
def get_input(self):
inchat_files = self.get_inchat_relative_files()
read_only_files = [self.get_rel_fname(fname) for fname in self.abs_read_only_fnames]
@@ -1114,7 +1125,10 @@ class Coder:
# add the reminder anyway
total_tokens = 0
final = chunks.cur[-1]
if chunks.cur:
final = chunks.cur[-1]
else:
final = None
max_input_tokens = self.main_model.info.get("max_input_tokens") or 0
# Add the reminder prompt if we still have room to include it.
@@ -1125,7 +1139,7 @@ class Coder:
):
if self.main_model.reminder == "sys":
chunks.reminder = reminder_message
elif self.main_model.reminder == "user" and final["role"] == "user":
elif self.main_model.reminder == "user" and final and final["role"] == "user":
# stuff it into the user message
new_content = (
final["content"]
@@ -1460,7 +1474,7 @@ class Coder:
words = set(word for word in content.split())
# drop sentence punctuation from the end
words = set(word.rstrip(",.!;:") for word in words)
words = set(word.rstrip(",.!;:?") for word in words)
# strip away all kinds of quotes
quotes = "".join(['"', "'", "`"])
@@ -1549,6 +1563,16 @@ class Coder:
yield from self.show_send_output_stream(completion)
else:
self.show_send_output(completion)
# Calculate costs for successful responses
self.calculate_and_show_tokens_and_cost(messages, completion)
except LiteLLMExceptions().exceptions_tuple() as err:
ex_info = LiteLLMExceptions().get_ex_info(err)
if ex_info.name == "ContextWindowExceededError":
# Still calculate costs for context window errors
self.calculate_and_show_tokens_and_cost(messages, completion)
raise
except KeyboardInterrupt as kbi:
self.keyboard_interrupt()
raise kbi
@@ -1566,8 +1590,6 @@ class Coder:
if args:
self.io.ai_output(json.dumps(args, indent=4))
self.calculate_and_show_tokens_and_cost(messages, completion)
def show_send_output(self, completion):
if self.verbose:
print(completion)

View File

@@ -35,7 +35,9 @@ ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
Just suggest shell commands this way, not example code.
Only suggest complete shell commands that are ready to execute, without placeholders.
Only suggest at most a few shell commands at a time, not more than 1-3.
Only suggest at most a few shell commands at a time, not more than 1-3, one per line.
Do not suggest multi-line shell commands.
All shell commands will run from the root directory of the user's project.
Use the appropriate shell based on the user's system info:
{platform}

View File

@@ -3,5 +3,6 @@ from .editor_editblock_prompts import EditorEditBlockPrompts
class EditorEditBlockCoder(EditBlockCoder):
"A coder that uses search/replace blocks, focused purely on editing files."
edit_format = "editor-diff"
gpt_prompts = EditorEditBlockPrompts()

View File

@@ -3,5 +3,6 @@ from .wholefile_coder import WholeFileCoder
class EditorWholeFileCoder(WholeFileCoder):
"A coder that operates on entire files, focused purely on editing files."
edit_format = "editor-whole"
gpt_prompts = EditorWholeFilePrompts()

View File

@@ -3,7 +3,11 @@
import sys
from pathlib import Path
import git
try:
import git
except ImportError:
git = None
from diff_match_patch import diff_match_patch
from tqdm import tqdm

View File

@@ -103,6 +103,13 @@ class Commands:
("help", "Get help about using aider (usage, config, troubleshoot)."),
("ask", "Ask questions about your code without making any changes."),
("code", "Ask for changes to your code (using the best edit format)."),
(
"architect",
(
"Work with an architect model to design code changes, and an editor to make"
" them."
),
),
]
)
@@ -1118,36 +1125,14 @@ class Commands:
)
return
history_iter = self.io.get_input_history()
history = []
size = 0
for line in history_iter:
if line.startswith("/"):
continue
if line in history:
continue
if size + len(line) > 1024:
break
size += len(line)
history.append(line)
history.reverse()
history = "\n".join(history)
try:
text = self.voice.record_and_transcribe(history, language=self.voice_language)
text = self.voice.record_and_transcribe(None, language=self.voice_language)
except litellm.OpenAIError as err:
self.io.tool_error(f"Unable to use OpenAI whisper model: {err}")
return
if text:
self.io.add_to_input_history(text)
self.io.print()
self.io.user_input(text, log_only=False)
self.io.print()
return text
self.io.placeholder = text
def cmd_paste(self, args):
"""Paste image/text from the clipboard into the chat.\
@@ -1200,9 +1185,14 @@ class Commands:
self.io.tool_error(f"Error processing clipboard content: {e}")
def cmd_read_only(self, args):
"Add files to the chat that are for reference, not to be edited"
"Add files to the chat that are for reference only, or turn added files to read-only"
if not args.strip():
self.io.tool_error("Please provide filenames or directories to read.")
# Convert all files in chat to read-only
for fname in list(self.coder.abs_fnames):
self.coder.abs_fnames.remove(fname)
self.coder.abs_read_only_fnames.add(fname)
rel_fname = self.coder.get_rel_fname(fname)
self.io.tool_output(f"Converted {rel_fname} to read-only")
return
filenames = parse_quoted_filenames(args)
@@ -1351,6 +1341,10 @@ class Commands:
except Exception as e:
self.io.tool_error(f"Error saving commands to file: {e}")
def cmd_multiline_mode(self, args):
"Toggle multiline mode (swaps behavior of Enter and Meta+Enter)"
self.io.toggle_multiline_mode()
def cmd_copy(self, args):
"Copy the last assistant message to the clipboard"
all_messages = self.coder.done_messages + self.coder.cur_messages
@@ -1399,6 +1393,50 @@ class Commands:
if user_input.strip():
self.io.set_placeholder(user_input.rstrip())
def cmd_copy_context(self, args=None):
"""Copy the current chat context as markdown, suitable to paste into a web UI"""
chunks = self.coder.format_chat_chunks()
markdown = ""
# Only include specified chunks in order
for messages in [chunks.repo, chunks.readonly_files, chunks.chat_files]:
for msg in messages:
# Only include user messages
if msg["role"] != "user":
continue
content = msg["content"]
# Handle image/multipart content
if isinstance(content, list):
for part in content:
if part.get("type") == "text":
markdown += part["text"] + "\n\n"
else:
markdown += content + "\n\n"
args = args or ""
markdown += f"""
Just tell me how to edit the files to make the changes.
Don't give me back entire files.
Just show me the edits I need to make.
{args}
"""
try:
pyperclip.copy(markdown)
self.io.tool_output("Copied code context to clipboard.")
except pyperclip.PyperclipException as e:
self.io.tool_error(f"Failed to copy to clipboard: {str(e)}")
self.io.tool_output(
"You may need to install xclip or xsel on Linux, or pbcopy on macOS."
)
except Exception as e:
self.io.tool_error(f"An unexpected error occurred while copying to clipboard: {str(e)}")
def expand_subdir(file_path):
if file_path.is_file():

72
aider/copypaste.py Normal file
View File

@@ -0,0 +1,72 @@
import threading
import time
import pyperclip
class ClipboardWatcher:
"""Watches clipboard for changes and updates IO placeholder"""
def __init__(self, io, verbose=False):
self.io = io
self.verbose = verbose
self.stop_event = None
self.watcher_thread = None
self.last_clipboard = None
self.io.clipboard_watcher = self
def start(self):
"""Start watching clipboard for changes"""
self.stop_event = threading.Event()
self.last_clipboard = pyperclip.paste()
def watch_clipboard():
while not self.stop_event.is_set():
try:
current = pyperclip.paste()
if current != self.last_clipboard:
self.last_clipboard = current
self.io.interrupt_input()
self.io.placeholder = current
if len(current.splitlines()) > 1:
self.io.placeholder = "\n" + self.io.placeholder + "\n"
time.sleep(0.5)
except Exception as e:
if self.verbose:
from aider.dump import dump
dump(f"Clipboard watcher error: {e}")
continue
self.watcher_thread = threading.Thread(target=watch_clipboard, daemon=True)
self.watcher_thread.start()
def stop(self):
"""Stop watching clipboard for changes"""
if self.stop_event:
self.stop_event.set()
if self.watcher_thread:
self.watcher_thread.join()
self.watcher_thread = None
self.stop_event = None
def main():
"""Example usage of the clipboard watcher"""
from aider.io import InputOutput
io = InputOutput()
watcher = ClipboardWatcher(io, verbose=True)
try:
watcher.start()
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\nStopped watching clipboard")
watcher.stop()
if __name__ == "__main__":
main()

View File

@@ -78,4 +78,13 @@ class LiteLLMExceptions:
def get_ex_info(self, ex):
"""Return the ExInfo for a given exception instance"""
import litellm
if ex.__class__ is litellm.APIConnectionError:
if "google.auth" in str(ex):
return ExInfo(
"APIConnectionError", False, "You need to: pip install google-generativeai"
)
if "boto3" in str(ex):
return ExInfo("APIConnectionError", False, "You need to: pip install boto3")
return self.exceptions.get(ex.__class__, ExInfo(None, None, None))

View File

@@ -1,4 +1,7 @@
# This needs to sync with MANIFEST.in
exclude_website_pats = [
"**/.DS_Store",
"examples/**",
"_posts/**",
"HISTORY.md",
@@ -7,5 +10,4 @@ exclude_website_pats = [
"docs/unified-diffs.md",
"docs/leaderboards/index.md",
"assets/**",
"**/.DS_Store",
]

View File

@@ -108,9 +108,7 @@ class ChatSummary:
for model in self.models:
try:
summary = simple_send_with_retries(
model.name, summarize_messages, extra_params=model.extra_params
)
summary = simple_send_with_retries(model, summarize_messages)
if summary is not None:
summary = prompts.summary_prefix + summary
return [dict(role="user", content=summary)]

View File

@@ -12,7 +12,7 @@ from pathlib import Path
from prompt_toolkit.completion import Completer, Completion, ThreadedCompleter
from prompt_toolkit.cursor_shapes import ModalCursorShapeConfig
from prompt_toolkit.enums import EditingMode
from prompt_toolkit.filters import Condition
from prompt_toolkit.filters import Condition, is_searching
from prompt_toolkit.history import FileHistory
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.keys import Keys
@@ -176,6 +176,7 @@ class AutoCompleter(Completer):
class InputOutput:
num_error_outputs = 0
num_user_asks = 0
clipboard_watcher = None
def __init__(
self,
@@ -201,11 +202,13 @@ class InputOutput:
editingmode=EditingMode.EMACS,
fancy_input=True,
file_watcher=None,
multiline_mode=False,
):
self.placeholder = None
self.interrupted = False
self.never_prompts = set()
self.editingmode = editingmode
self.multiline_mode = multiline_mode
no_color = os.environ.get("NO_COLOR")
if no_color is not None and no_color != "":
pretty = False
@@ -411,6 +414,8 @@ class InputOutput:
show = self.format_files_for_input(rel_fnames, rel_read_only_fnames)
if edit_format:
show += edit_format
if self.multiline_mode:
show += (" " if edit_format else "") + "multi"
show += "> "
inp = ""
@@ -455,9 +460,25 @@ class InputOutput:
"Navigate forward through history"
event.current_buffer.history_forward()
@kb.add("escape", "c-m", eager=True)
@kb.add("enter", eager=True, filter=~is_searching)
def _(event):
event.current_buffer.insert_text("\n")
"Handle Enter key press"
if self.multiline_mode:
# In multiline mode, Enter adds a newline
event.current_buffer.insert_text("\n")
else:
# In normal mode, Enter submits
event.current_buffer.validate_and_handle()
@kb.add("escape", "enter", eager=True, filter=~is_searching) # This is Alt+Enter
def _(event):
"Handle Alt+Enter key press"
if self.multiline_mode:
# In multiline mode, Alt+Enter submits
event.current_buffer.validate_and_handle()
else:
# In normal mode, Alt+Enter adds a newline
event.current_buffer.insert_text("\n")
while True:
if multiline_input:
@@ -470,8 +491,11 @@ class InputOutput:
self.placeholder = None
self.interrupted = False
if not multiline_input and self.file_watcher:
self.file_watcher.start()
if not multiline_input:
if self.file_watcher:
self.file_watcher.start()
if self.clipboard_watcher:
self.clipboard_watcher.start()
line = self.prompt_session.prompt(
show,
@@ -487,11 +511,13 @@ class InputOutput:
# Check if we were interrupted by a file change
if self.interrupted:
cmd = self.file_watcher.process_changes()
return cmd
line = line or ""
if self.file_watcher:
cmd = self.file_watcher.process_changes()
return cmd
except EOFError:
return ""
raise
except Exception as err:
import traceback
@@ -504,6 +530,8 @@ class InputOutput:
finally:
if self.file_watcher:
self.file_watcher.stop()
if self.clipboard_watcher:
self.clipboard_watcher.stop()
if line.strip("\r\n") and not multiline_input:
stripped = line.strip("\r\n")
@@ -621,6 +649,9 @@ class InputOutput:
group=None,
allow_never=False,
):
# Temporarily disable multiline mode for yes/no prompts
orig_multiline = self.multiline_mode
self.multiline_mode = False
self.num_user_asks += 1
question_id = (question, subject)
@@ -678,6 +709,7 @@ class InputOutput:
res = self.prompt_session.prompt(
question,
style=style,
complete_while_typing=False,
)
else:
res = input(question)
@@ -718,9 +750,15 @@ class InputOutput:
hist = f"{question.strip()} {res}"
self.append_chat_history(hist, linebreak=True, blockquote=True)
# Restore original multiline mode
self.multiline_mode = orig_multiline
return is_yes
def prompt_ask(self, question, default="", subject=None):
# Temporarily disable multiline mode for prompts
orig_multiline = self.multiline_mode
self.multiline_mode = False
self.num_user_asks += 1
if subject:
@@ -744,6 +782,9 @@ class InputOutput:
if self.yes in (True, False):
self.tool_output(hist)
# Restore original multiline mode
self.multiline_mode = orig_multiline
return res
def _tool_message(self, message="", strip=True, color=None):
@@ -813,6 +854,18 @@ class InputOutput:
def print(self, message=""):
print(message)
def toggle_multiline_mode(self):
"""Toggle between normal and multiline input modes"""
self.multiline_mode = not self.multiline_mode
if self.multiline_mode:
self.tool_output(
"Multiline mode: Enabled. Enter inserts newline, Alt-Enter submits text"
)
else:
self.tool_output(
"Multiline mode: Disabled. Alt-Enter inserts newline, Enter submits text"
)
def append_chat_history(self, text, linebreak=False, blockquote=False, strip=True):
if blockquote:
if strip:

View File

@@ -9,7 +9,11 @@ import webbrowser
from dataclasses import fields
from pathlib import Path
import git
try:
import git
except ImportError:
git = None
import importlib_resources
from dotenv import load_dotenv
from prompt_toolkit.enums import EditingMode
@@ -20,6 +24,7 @@ from aider.args import get_parser
from aider.coders import Coder
from aider.coders.base_coder import UnknownEditFormat
from aider.commands import Commands, SwitchCoder
from aider.copypaste import ClipboardWatcher
from aider.format_settings import format_settings, scrub_sensitive_info
from aider.history import ChatSummary
from aider.io import InputOutput
@@ -92,6 +97,9 @@ def make_new_repo(git_root, io):
def setup_git(git_root, io):
if git is None:
return
try:
cwd = Path.cwd()
except OSError:
@@ -409,7 +417,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if argv is None:
argv = sys.argv[1:]
if force_git_root:
if git is None:
git_root = None
elif force_git_root:
git_root = force_git_root
else:
git_root = get_git_root()
@@ -456,6 +466,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
# Parse again to include any arguments that might have been defined in .env
args = parser.parse_args(argv)
if git is None:
args.git = False
if args.analytics_disable:
analytics = Analytics(permanently_disable=True)
print("Analytics have been permanently disabled.")
@@ -514,6 +527,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
llm_history_file=args.llm_history_file,
editingmode=editing_mode,
fancy_input=args.fancy_input,
multiline_mode=args.multiline,
)
io = get_io(args.pretty)
@@ -525,6 +539,50 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io = get_io(False)
io.tool_warning("Terminal does not support pretty output (UnicodeDecodeError)")
# Process any environment variables set via --set-env
if args.set_env:
for env_setting in args.set_env:
try:
name, value = env_setting.split("=", 1)
os.environ[name.strip()] = value.strip()
except ValueError:
io.tool_error(f"Invalid --set-env format: {env_setting}")
io.tool_output("Format should be: ENV_VAR_NAME=value")
return 1
# Process any API keys set via --api-key
if args.api_key:
for api_setting in args.api_key:
try:
provider, key = api_setting.split("=", 1)
env_var = f"{provider.strip().upper()}_API_KEY"
os.environ[env_var] = key.strip()
except ValueError:
io.tool_error(f"Invalid --api-key format: {api_setting}")
io.tool_output("Format should be: provider=key")
return 1
if args.anthropic_api_key:
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
if args.openai_api_key:
os.environ["OPENAI_API_KEY"] = args.openai_api_key
if args.openai_api_base:
os.environ["OPENAI_API_BASE"] = args.openai_api_base
if args.openai_api_version:
io.tool_warning(
"--openai-api-version is deprecated, use --set-env OPENAI_API_VERSION=<value>"
)
os.environ["OPENAI_API_VERSION"] = args.openai_api_version
if args.openai_api_type:
io.tool_warning("--openai-api-type is deprecated, use --set-env OPENAI_API_TYPE=<value>")
os.environ["OPENAI_API_TYPE"] = args.openai_api_type
if args.openai_organization_id:
io.tool_warning(
"--openai-organization-id is deprecated, use --set-env OPENAI_ORGANIZATION=<value>"
)
os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id
analytics = Analytics(logfile=args.analytics_log, permanently_disable=args.analytics_disable)
if args.analytics is not False:
if analytics.need_to_ask(args.analytics):
@@ -600,7 +658,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
# We can't know the git repo for sure until after parsing the args.
# If we guessed wrong, reparse because that changes things like
# the location of the config.yml and history files.
if args.git and not force_git_root:
if args.git and not force_git_root and git is not None:
right_repo_root = guessed_wrong_repo(io, git_root, fnames, git_dname)
if right_repo_root:
analytics.event("exit", reason="Recursing with correct repo")
@@ -645,20 +703,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
is_first_run = is_first_run_of_new_version(io, verbose=args.verbose)
check_and_load_imports(io, is_first_run, verbose=args.verbose)
if args.anthropic_api_key:
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
if args.openai_api_key:
os.environ["OPENAI_API_KEY"] = args.openai_api_key
if args.openai_api_base:
os.environ["OPENAI_API_BASE"] = args.openai_api_base
if args.openai_api_version:
os.environ["OPENAI_API_VERSION"] = args.openai_api_version
if args.openai_api_type:
os.environ["OPENAI_API_TYPE"] = args.openai_api_type
if args.openai_organization_id:
os.environ["OPENAI_ORGANIZATION"] = args.openai_organization_id
register_models(git_root, args.model_settings_file, io, verbose=args.verbose)
register_litellm_models(git_root, args.model_metadata_file, io, verbose=args.verbose)
@@ -687,6 +731,10 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
editor_edit_format=args.editor_edit_format,
)
if args.copy_paste and args.edit_format is None:
if main_model.edit_format in ("diff", "whole"):
main_model.edit_format = "editor-" + main_model.edit_format
if args.verbose:
io.tool_output("Model metadata:")
io.tool_output(json.dumps(main_model.info, indent=4))
@@ -800,6 +848,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
suggest_shell_commands=args.suggest_shell_commands,
chat_language=args.chat_language,
detect_urls=args.detect_urls,
auto_copy_context=args.copy_paste,
)
except UnknownEditFormat as err:
io.tool_error(str(err))
@@ -822,9 +871,15 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
ignores.append(args.aiderignore)
if args.watch_files:
file_watcher = FileWatcher(coder, gitignores=ignores, verbose=args.verbose)
file_watcher = FileWatcher(
coder, gitignores=ignores, verbose=args.verbose, analytics=analytics
)
coder.file_watcher = file_watcher
if args.copy_paste:
analytics.event("copy-paste mode")
ClipboardWatcher(coder.io, verbose=args.verbose)
coder.show_announcements()
if args.show_prompts:
@@ -844,9 +899,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io.tool_error("No --test-cmd provided.")
analytics.event("exit", reason="No test command provided")
return 1
test_errors = coder.commands.cmd_test(args.test_cmd)
if test_errors:
coder.run(test_errors)
coder.commands.cmd_test(args.test_cmd)
if io.placeholder:
coder.run(io.placeholder)
if args.commit:
if args.dry_run:

View File

@@ -76,6 +76,7 @@ MODEL_ALIASES = {
"3": "gpt-3.5-turbo",
# Other models
"deepseek": "deepseek/deepseek-coder",
"flash": "gemini/gemini-2.0-flash-exp",
}
@@ -583,6 +584,21 @@ MODEL_SETTINGS = [
"diff-fenced",
use_repo_map=True,
),
ModelSettings(
"gemini/gemini-exp-1206",
"diff",
use_repo_map=True,
),
ModelSettings(
"gemini/gemini-exp-1114",
"diff",
use_repo_map=True,
),
ModelSettings(
"gemini/gemini-exp-1121",
"diff",
use_repo_map=True,
),
ModelSettings(
"vertex_ai/gemini-pro-experimental",
"diff-fenced",
@@ -594,6 +610,12 @@ MODEL_SETTINGS = [
use_repo_map=False,
send_undo_reply=False,
),
ModelSettings(
"gemini/gemini-2.0-flash-exp",
"diff",
use_repo_map=True,
send_undo_reply=False,
),
ModelSettings(
"deepseek/deepseek-chat",
"diff",
@@ -1210,10 +1232,10 @@ def sanity_check_model(io, model):
status = "Set" if value else "Not set"
io.tool_output(f"- {key}: {status}")
if platform.system() == "Windows" or True:
if platform.system() == "Windows":
io.tool_output(
"If you just set these environment variables using `setx` you may need to restart"
" your terminal or command prompt for the changes to take effect."
"Note: You may need to restart your terminal or command prompt for `setx` to take"
" effect."
)
elif not model.keys_in_environment:

View File

@@ -2,7 +2,17 @@ import os
import time
from pathlib import Path, PurePosixPath
import git
try:
import git
ANY_GIT_ERROR = [
git.exc.ODBError,
git.exc.GitError,
]
except ImportError:
git = None
ANY_GIT_ERROR = []
import pathspec
from aider import prompts, utils
@@ -10,15 +20,14 @@ from aider.sendchat import simple_send_with_retries
from .dump import dump # noqa: F401
ANY_GIT_ERROR = (
git.exc.ODBError,
git.exc.GitError,
ANY_GIT_ERROR += [
OSError,
IndexError,
BufferError,
TypeError,
ValueError,
)
]
ANY_GIT_ERROR = tuple(ANY_GIT_ERROR)
class GitRepo:
@@ -192,9 +201,7 @@ class GitRepo:
max_tokens = model.info.get("max_input_tokens") or 0
if max_tokens and num_tokens > max_tokens:
continue
commit_message = simple_send_with_retries(
model.name, messages, extra_params=model.extra_params
)
commit_message = simple_send_with_retries(model, messages)
if commit_message:
break

View File

@@ -0,0 +1,38 @@
{
"vertex_ai-language-models/gemini-2.0-flash-exp": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
"max_output_tokens": 8192,
"max_images_per_prompt": 3000,
"max_videos_per_prompt": 10,
"max_video_length": 1,
"max_audio_length_hours": 8.4,
"max_audio_per_prompt": 1,
"max_pdf_size_mb": 30,
"litellm_provider": "vertex_ai-language-models",
"mode": "chat",
"supports_system_messages": true,
"supports_function_calling": true,
"supports_vision": true,
"supports_response_schema": true,
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2"
},
"gemini/gemini-2.0-flash-exp": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
"max_output_tokens": 8192,
"max_images_per_prompt": 3000,
"max_videos_per_prompt": 10,
"max_video_length": 1,
"max_audio_length_hours": 8.4,
"max_audio_per_prompt": 1,
"max_pdf_size_mb": 30,
"litellm_provider": "gemini",
"mode": "chat",
"supports_system_messages": true,
"supports_function_calling": true,
"supports_vision": true,
"supports_response_schema": true,
"source": "https://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2"
},
}

View File

@@ -56,18 +56,19 @@ def send_completion(
return hash_object, res
def simple_send_with_retries(model_name, messages, extra_params=None):
def simple_send_with_retries(model, messages):
litellm_ex = LiteLLMExceptions()
retry_delay = 0.125
while True:
try:
kwargs = {
"model_name": model_name,
"model_name": model.name,
"messages": messages,
"functions": None,
"stream": False,
"extra_params": extra_params,
"temperature": None if not model.use_temperature else 0,
"extra_params": model.extra_params,
}
_hash, response = send_completion(**kwargs)

View File

@@ -2,15 +2,12 @@ import itertools
import os
import platform
import shlex
import shutil
import subprocess
import sys
import tempfile
import time
from pathlib import Path
import git
from aider.dump import dump # noqa: F401
IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".webp", ".pdf"}
@@ -74,6 +71,8 @@ class GitTemporaryDirectory(ChdirTemporaryDirectory):
def make_repo(path=None):
import git
if not path:
path = "."
repo = git.Repo.init(path)
@@ -194,25 +193,9 @@ def split_chat_history_markdown(text, include_tool=False):
return messages
# Copied from pip, MIT license
# https://github.com/pypa/pip/blob/b989e6ef04810bbd4033a3683020bd4ddcbdb627/src/pip/_internal/utils/entrypoints.py#L73
def get_best_invocation_for_this_python() -> str:
"""Try to figure out the best way to invoke the current Python."""
exe = sys.executable
exe_name = os.path.basename(exe)
# Try to use the basename, if it's the first executable.
found_executable = shutil.which(exe_name)
if found_executable and os.path.samefile(found_executable, exe):
return exe_name
# Use the full executable name, because we couldn't find something simpler.
return exe
def get_pip_install(args):
cmd = [
get_best_invocation_for_this_python(),
sys.executable,
"-m",
"pip",
"install",

View File

@@ -14,6 +14,8 @@ from .dump import dump # noqa: F401
warnings.filterwarnings(
"ignore", message="Couldn't find ffmpeg or avconv - defaulting to ffmpeg, but may not work"
)
warnings.filterwarnings("ignore", category=SyntaxWarning)
from pydub import AudioSegment # noqa
@@ -43,7 +45,6 @@ class Voice:
self.sd = sd
devices = sd.query_devices()
if device_name:
@@ -55,7 +56,10 @@ class Voice:
break
if device_id is None:
available_inputs = [d["name"] for d in devices if d["max_input_channels"] > 0]
raise ValueError(f"Device '{device_name}' not found. Available input devices: {available_inputs}")
raise ValueError(
f"Device '{device_name}' not found. Available input devices:"
f" {available_inputs}"
)
print(f"Using input device: {device_name} (ID: {device_id})")
@@ -125,7 +129,9 @@ class Voice:
self.start_time = time.time()
try:
with self.sd.InputStream(samplerate=sample_rate, channels=1, callback=self.callback, device=self.device_id):
with self.sd.InputStream(
samplerate=sample_rate, channels=1, callback=self.callback, device=self.device_id
):
prompt(self.get_prompt, refresh_interval=0.1)
except self.sd.PortAudioError as err:
raise SoundDeviceError(f"Error accessing audio input device: {err}")

View File

@@ -9,49 +9,7 @@ from pathspec.patterns import GitWildMatchPattern
from watchfiles import watch
from aider.dump import dump # noqa
def is_source_file(path: Path) -> bool:
"""
Check if a file is a source file that uses # or // style comments.
This includes Python, JavaScript, TypeScript, C, C++, etc.
"""
COMMENT_STYLE_EXTENSIONS = {
# # style comments
".py",
".r",
".rb",
".pl",
".pm",
".sh",
".bash",
".yaml",
".yml",
# // style comments
".js",
".ts",
".jsx",
".tsx",
".cpp",
".c",
".h",
".hpp",
".java",
".swift",
".kt",
".cs",
".go",
".rs",
".php",
# -- style comments
".sql",
".hs", # Haskell
".lua",
".elm",
".vhd", # VHDL
".vhdl",
}
return path.suffix.lower() in COMMENT_STYLE_EXTENSIONS
from aider.watch_prompts import watch_ask_prompt, watch_code_prompt
def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
@@ -59,7 +17,41 @@ def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
if not gitignore_paths:
return None
patterns = [".aider*", ".git"] # Always ignore
patterns = [
".aider*",
".git",
# Common editor backup/temp files
"*~", # Emacs/vim backup
"*.bak", # Generic backup
"*.swp", # Vim swap
"*.swo", # Vim swap
"\\#*\\#", # Emacs auto-save
".#*", # Emacs lock files
"*.tmp", # Generic temp files
"*.temp", # Generic temp files
"*.orig", # Merge conflict originals
"*.pyc", # Python bytecode
"__pycache__/", # Python cache dir
".DS_Store", # macOS metadata
"Thumbs.db", # Windows thumbnail cache
# IDE files
".idea/", # JetBrains IDEs
".vscode/", # VS Code
"*.sublime-*", # Sublime Text
".project", # Eclipse
".settings/", # Eclipse
"*.code-workspace", # VS Code workspace
# Environment files
".env", # Environment variables
".venv/", # Python virtual environments
"node_modules/", # Node.js dependencies
"vendor/", # Various dependencies
# Logs and caches
"*.log", # Log files
".cache/", # Cache directories
".pytest_cache/", # Python test cache
"coverage/", # Code coverage reports
] # Always ignore
for path in gitignore_paths:
if path.exists():
with open(path) as f:
@@ -72,13 +64,14 @@ class FileWatcher:
"""Watches source files for changes and AI comments"""
# Compiled regex pattern for AI comments
ai_comment_pattern = re.compile(r"(?:#|//|--) *(ai\b.*|ai\b.*|.*\bai!?)$", re.IGNORECASE)
ai_comment_pattern = re.compile(r"(?:#|//|--) *(ai\b.*|ai\b.*|.*\bai[?!]?) *$", re.IGNORECASE)
def __init__(self, coder, gitignores=None, verbose=False):
def __init__(self, coder, gitignores=None, verbose=False, analytics=None):
self.coder = coder
self.io = coder.io
self.root = Path(coder.root)
self.verbose = verbose
self.analytics = analytics
self.stop_event = None
self.watcher_thread = None
self.changed_files = set()
@@ -105,9 +98,6 @@ class FileWatcher:
if self.gitignore_spec and self.gitignore_spec.match_file(str(rel_path)):
return False
if not is_source_file(path_obj):
return False
if self.verbose:
dump("ok", rel_path)
@@ -154,33 +144,43 @@ class FileWatcher:
def process_changes(self):
"""Get any detected file changes"""
has_bangs = False
has_action = None
added = False
for fname in self.changed_files:
_, _, has_bang = self.get_ai_comments(fname)
has_bangs |= has_bang
_, _, action = self.get_ai_comments(fname)
if action in ("!", "?"):
has_action = action
if fname in self.coder.abs_fnames:
continue
if self.analytics:
self.analytics.event("ai-comments file-add")
self.coder.abs_fnames.add(fname)
rel_fname = self.coder.get_rel_fname(fname)
if not added:
self.io.tool_output()
added = True
self.io.tool_output(f"Added {rel_fname} to the chat")
self.io.tool_output()
if not has_bangs:
if not has_action:
if added:
self.io.tool_output(
"End your comment with AI! to request changes or AI? to ask questions"
)
return ""
if self.analytics:
self.analytics.event("ai-comments execute")
self.io.tool_output("Processing your request...")
res = """The "AI" comments below can be found in the code files I've shared with you.
They contain your instructions.
Make the requested changes.
Be sure to remove all these "AI" comments from the code!
"""
if has_action == "!":
res = watch_code_prompt
elif has_action == "?":
res = watch_ask_prompt
# Refresh all AI comments from tracked files
for fname in self.coder.abs_fnames:
line_nums, comments, _has_bang = self.get_ai_comments(fname)
line_nums, comments, _action = self.get_ai_comments(fname)
if not line_nums:
continue
@@ -194,30 +194,34 @@ Be sure to remove all these "AI" comments from the code!
# Convert comment line numbers to line indices (0-based)
lois = [ln - 1 for ln, _ in zip(line_nums, comments) if ln > 0]
context = TreeContext(
rel_fname,
code,
color=False,
line_number=False,
child_context=False,
last_line=False,
margin=0,
mark_lois=False,
loi_pad=3,
show_top_of_file_parent_scope=False,
)
context.lines_of_interest = set()
context.add_lines_of_interest(lois)
context.add_context()
res += context.format()
try:
context = TreeContext(
rel_fname,
code,
color=False,
line_number=False,
child_context=False,
last_line=False,
margin=0,
mark_lois=True,
loi_pad=3,
show_top_of_file_parent_scope=False,
)
context.lines_of_interest = set()
context.add_lines_of_interest(lois)
context.add_context()
res += context.format()
except ValueError:
for ln, comment in zip(line_nums, comments):
res += f" Line {ln}: {comment}\n"
return res
def get_ai_comments(self, filepath):
"""Extract AI comment line numbers, comments and bang status from a file"""
"""Extract AI comment line numbers, comments and action status from a file"""
line_nums = []
comments = []
has_bang = False
has_action = None # None, "!" or "?"
content = self.io.read_text(filepath, silent=True)
for i, line in enumerate(content.splitlines(), 1):
if match := self.ai_comment_pattern.search(line):
@@ -229,10 +233,12 @@ Be sure to remove all these "AI" comments from the code!
comment = comment.lstrip("/#-")
comment = comment.strip()
if comment.startswith("ai!") or comment.endswith("ai!"):
has_bang = True
has_action = "!"
elif comment.startswith("ai?") or comment.endswith("ai?"):
has_action = "?"
if not line_nums:
return None, None, False
return line_nums, comments, has_bang
return None, None, None
return line_nums, comments, has_action
def main():

11
aider/watch_prompts.py Normal file
View File

@@ -0,0 +1,11 @@
watch_code_prompt = """
Find the "AI" comments below (marked with █) in the code files I've shared with you.
They contain your instructions.
Make the requested changes.
Be sure to remove all these "AI" comments from the code!
"""
watch_ask_prompt = """/ask
Find the "AI" comments below (marked with █) in the code files I've shared with you.
They contain your questions you need to answer and other instructions.
"""

View File

@@ -1,7 +1,6 @@
---
title: Release history
parent: More info
nav_order: 900
nav_order: 925
highlight_image: /assets/blame.jpg
description: Release notes and stats on aider writing its own code.
---
@@ -24,6 +23,43 @@ cog.out(text)
]]]-->
### Aider v0.69.0
- [Watch files](https://aider.chat/docs/usage/watch.html) improvements:
- Use `# ... AI?` comments to trigger aider and ask questions about your code.
- Now watches *all* files, not just certain source files.
- Use `# AI comments`, `// AI comments`, or `-- AI comments` to give aider instructions in any text file.
- Full support for Gemini Flash 2.0 Exp:
- `aider --model flash` or `aider --model gemini/gemini-2.0-flash-exp`
- [New `--multiline` flag and `/multiline-mode` command](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) makes ENTER a soft newline and META-ENTER send the message, by @miradnanali.
- `/copy-context <instructions>` now takes optional "instructions" when [copying code context to the clipboard](https://aider.chat/docs/usage/copypaste.html#copy-aiders-code-context-to-your-clipboard-paste-into-the-web-ui).
- Improved clipboard error handling with helpful requirements install info.
- Ask 5% of users if they want to opt-in to analytics.
- `/voice` now lets you edit the transcribed text before sending.
- Disabled auto-complete in Y/N prompts.
- Aider wrote 68% of the code in this release.
### Aider v0.68.0
- [Aider works with LLM web chat UIs](https://aider.chat/docs/usage/copypaste.html).
- New `--copy-paste` mode.
- New `/copy-context` command.
- [Set API keys and other environment variables for all providers from command line or yaml conf file](https://aider.chat/docs/config/aider_conf.html#storing-llm-keys).
- New `--api-key provider=key` setting.
- New `--set-env VAR=value` setting.
- Added bash and zsh support to `--watch-files`.
- Better error messages when missing dependencies for Gemini and Bedrock models.
- Control-D now properly exits the program.
- Don't count token costs when API provider returns a hard error.
- Bugfix so watch files works with files that don't have tree-sitter support.
- Bugfix so o1 models can be used as weak model.
- Updated shell command prompt.
- Added docstrings for all Coders.
- Reorganized command line arguments with improved help messages and grouping.
- Use the exact `sys.python` for self-upgrades.
- Added experimental Gemini models.
- Aider wrote 71% of the code in this release.
### Aider v0.67.0
- [Use aider in your IDE or editor](https://aider.chat/docs/usage/watch.html).
@@ -37,7 +73,7 @@ cog.out(text)
- Spinner now falls back to ASCII art if fancy symbols throw unicode errors.
- `--read` now expands `~` home dirs.
- Enabled exception capture in analytics.
- Aider wrote 61% of the code in this release.
- [Aider wrote 61% of the code in this release.](https://aider.chat/HISTORY.html)
### Aider v0.66.0

File diff suppressed because it is too large Load Diff

View File

@@ -644,7 +644,7 @@
- dirname: 2024-07-19-08-57-13--openrouter-deepseek-chat-v2-0628
test_cases: 133
model: DeepSeek Chat V2 0628 (deprecated)
model: DeepSeek Chat V2 0628
edit_format: diff
commit_hash: 96ff06e-dirty
pass_rate_1: 60.9
@@ -716,7 +716,7 @@
- dirname: 2024-07-24-07-10-58--deepseek-coder2-0724-diff-direct
test_cases: 133
model: DeepSeek Coder V2 0724 (deprecated)
model: DeepSeek Coder V2 0724
edit_format: diff
commit_hash: 89965bf
pass_rate_1: 57.9
@@ -1232,7 +1232,7 @@
- dirname: 2024-09-24-16-33-23--gemini-1.5-flash-002-whole
test_cases: 133
model: gemini-1.5-flash-002
model: gemini-1.5-flash-002 (0924)
edit_format: whole
commit_hash: 3edcd71
pass_rate_1: 37.6
@@ -2042,4 +2042,142 @@
date: 2024-12-04
versions: 0.66.1.dev
seconds_per_case: 8.7
total_cost: 0.0000
- dirname: 2024-12-06-18-27-47--llama33-diff
test_cases: 133
model: llama-3.3-70b-instruct
edit_format: diff
commit_hash: 53e0d67
pass_rate_1: 42.1
pass_rate_2: 59.4
percent_cases_well_formed: 88.7
error_outputs: 33
num_malformed_responses: 33
num_with_malformed_responses: 15
user_asks: 3
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model openrouter/meta-llama/llama-3.3-70b-instruct
date: 2024-12-06
versions: 0.67.1.dev
seconds_per_case: 20.2
total_cost: 0.0000
- dirname: 2024-12-06-21-35-50--gemini-exp-1206-diff
test_cases: 133
model: gemini-exp-1206 (diff)
edit_format: diff
commit_hash: f2d2ab5
pass_rate_1: 55.6
pass_rate_2: 69.2
percent_cases_well_formed: 84.2
error_outputs: 68
num_malformed_responses: 68
num_with_malformed_responses: 21
user_asks: 5
lazy_comments: 0
syntax_errors: 2
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model gemini/gemini-exp-1206
date: 2024-12-06
versions: 0.67.1.dev
seconds_per_case: 32.1
total_cost: 0.0000
- dirname: 2024-12-08-21-39-06--gemini-exp-1206-whole
test_cases: 133
model: gemini-exp-1206 (whole)
edit_format: whole
commit_hash: f2d2ab5
pass_rate_1: 60.9
pass_rate_2: 80.5
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 1
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model gemini/gemini-exp-1206
date: 2024-12-08
versions: 0.67.1.dev
seconds_per_case: 64.2
total_cost: 0.0000
- dirname: 2024-12-10-14-45-21--deepseek-1210-diff
test_cases: 133
model: DeepSeek-V2.5-1210
edit_format: diff
commit_hash: 16332b2
pass_rate_1: 58.6
pass_rate_2: 72.2
percent_cases_well_formed: 99.2
error_outputs: 1
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model deepseek/deepseek-chat
date: 2024-12-10
versions: 0.67.1.dev
seconds_per_case: 32.7
total_cost: 0.1106
- dirname: 2024-12-11-00-37-08--yi-test
test_cases: 133
model: yi-lightning
edit_format: whole
commit_hash: e909a3d-dirty
pass_rate_1: 49.6
pass_rate_2: 65.4
percent_cases_well_formed: 97.0
error_outputs: 304
num_malformed_responses: 5
num_with_malformed_responses: 4
user_asks: 34
lazy_comments: 2
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model openai/yi-lightning
date: 2024-12-11
versions: 0.67.1.dev
seconds_per_case: 57.8
total_cost: 0.0000
- dirname: 2024-12-11-21-07-00--gemini-2-flash-diff
test_cases: 133
model: gemini-2.0-flash-exp
edit_format: diff
commit_hash: fcb2bac-dirty, 02e7e31-dirty
pass_rate_1: 56.4
pass_rate_2: 69.9
percent_cases_well_formed: 97.0
error_outputs: 10
num_malformed_responses: 6
num_with_malformed_responses: 4
user_asks: 8
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 2
test_timeouts: 1
command: aider --model gemini/gemini-2.0-flash-exp
date: 2024-12-11
versions: 0.68.1.dev
seconds_per_case: 7.3
total_cost: 0.0000

View File

@@ -1,13 +1,21 @@
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('editChart').getContext('2d');
const HIGHTLIGHT_MODEL = 'no no no no';
const blueDiagonalPattern = pattern.draw('diagonal', 'rgba(54, 162, 235, 0.2)');
const redDiagonalPattern = pattern.draw('diagonal', 'rgba(255, 99, 132, 0.2)');
let displayedData = [];
const HIGHTLIGHT_MODEL = 'no no no';
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: function(context) {
const label = context.chart.data.labels[context.dataIndex] || '';
const row = allData[context.dataIndex];
if (row && row.edit_format === 'whole') {
return diagonalPattern;
}
const label = leaderboardData.labels[context.dataIndex] || '';
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)';
},
borderColor: function(context) {
@@ -23,7 +31,8 @@ document.addEventListener('DOMContentLoaded', function () {
allData.push({
model: '{{ row.model }}',
pass_rate_2: {{ row.pass_rate_2 }},
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
percent_cases_well_formed: {{ row.percent_cases_well_formed }},
edit_format: '{{ row.edit_format }}'
});
{% endfor %}
@@ -31,6 +40,7 @@ document.addEventListener('DOMContentLoaded', function () {
var selectedRows = document.querySelectorAll('tr.selected');
var showAll = selectedRows.length === 0;
displayedData = [];
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
@@ -40,14 +50,30 @@ document.addEventListener('DOMContentLoaded', function () {
rowElement.classList.remove('selected');
}
if (showAll || rowElement.classList.contains('selected')) {
displayedData.push(row);
leaderboardData.labels.push(row.model);
leaderboardData.datasets[0].data.push(row.pass_rate_2);
}
});
leaderboardChart.update();
leaderboardChart.render();
}
// Use displayedData in the backgroundColor callback instead of allData
leaderboardData.datasets[0].backgroundColor = function(context) {
const row = displayedData[context.dataIndex];
const label = leaderboardData.labels[context.dataIndex] || '';
if (label && label.includes(HIGHTLIGHT_MODEL)) {
if (row && row.edit_format === 'whole') return redDiagonalPattern;
else return 'rgba(255, 99, 132, 0.2)';
} else if (row && row.edit_format === 'whole') {
return blueDiagonalPattern;
} else {
return 'rgba(54, 162, 235, 0.2)';
}
};
var tableBody = document.querySelector('table tbody');
allData.forEach(function(row, index) {
var tr = tableBody.children[index];
@@ -63,9 +89,69 @@ document.addEventListener('DOMContentLoaded', function () {
type: 'bar',
data: leaderboardData,
options: {
plugins: {
legend: {
display: true,
labels: {
generateLabels: function(chart) {
return [
{
text: 'Diff-like format',
fillStyle: 'rgba(54, 162, 235, 0.2)',
strokeStyle: 'rgba(54, 162, 235, 1)',
lineWidth: 1
},
{
text: 'Whole format',
fillStyle: blueDiagonalPattern,
strokeStyle: 'rgba(54, 162, 235, 1)',
lineWidth: 1
}
];
}
}
}
},
scales: {
y: {
beginAtZero: true
beginAtZero: true,
title: {
display: true,
text: 'Percent completed correctly'
}
},
x: {
ticks: {
callback: function(value, index) {
const label = this.getLabelForValue(value);
if (label.length <= "claude-3-5-sonnet".length) {
return label;
}
// Find all possible split positions
const splitPositions = [];
for (let i = 0; i < label.length; i++) {
if (label[i] === '-' || label[i] === ' ') {
splitPositions.push(i);
}
}
if (splitPositions.length === 0) {
return label;
}
// Find split position closest to middle
const middle = label.length / 2;
const splitIndex = splitPositions.reduce((closest, current) => {
return Math.abs(current - middle) < Math.abs(closest - middle) ? current : closest;
});
return [
label.slice(0, splitIndex),
label.slice(splitIndex + 1)
];
}
}
}
}
}
@@ -79,6 +165,7 @@ document.addEventListener('DOMContentLoaded', function () {
var tableBody = document.querySelector('table:first-of-type tbody');
var rows = tableBody.getElementsByTagName('tr');
displayedData = [];
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
@@ -86,6 +173,7 @@ document.addEventListener('DOMContentLoaded', function () {
var rowText = rows[i].textContent;
if (searchWords.every(word => rowText.toLowerCase().includes(word))) {
rows[i].style.display = '';
displayedData.push(allData[i]);
leaderboardData.labels.push(allData[i].model);
leaderboardData.datasets[0].data.push(allData[i].pass_rate_2);
} else {

View File

@@ -1,6 +0,0 @@
{: .tip }
All API keys can be stored in a
[.env file](/docs/config/dotenv.html).
Only OpenAI and Anthropic keys can be stored in the
[YAML config file](/docs/config/aider_conf.html).

View File

@@ -1,17 +1,16 @@
You can get started quickly like this:
You can get started quickly like this, with python 3.8-3.13:
```
python -m pip install -U aider-chat
```bash
python -m pip install aider-install
aider-install
# Change directory into a git repo
# Change directory into your code base
cd /to/your/git/repo
# Work with Claude 3.5 Sonnet on your repo
export ANTHROPIC_API_KEY=your-key-goes-here
aider
aider --model sonnet --anthropic-api-key your-key-goes-here
# Work with GPT-4o on your repo
export OPENAI_API_KEY=your-key-goes-here
aider
aider --model gpt-4o --openai-api-key your-key-goes-here
```

View File

@@ -18,3 +18,63 @@
<link rel="mask-icon" href="{{ '/assets/icons/safari-pinned-tab.svg' | relative_url }}" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<!-- Cookie Consent -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.css" />
<script src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js" data-cfasync="false"></script>
<script>
window.addEventListener('load', function(){
window.cookieconsent.initialise({
palette: {
popup: {
background: "#333333",
text: "#ffffff"
},
button: {
background: "#ffffff",
text: "#333333"
}
},
type: "opt-in",
position: "bottom-left",
showLink: false,
dismissOnScroll: true,
cookie: {
name: 'cookieconsent_status',
path: '/',
domain: 'aider.chat',
expiryDays: 365
},
content: {
message: "This website uses analytics cookies to help us understand how you use the site.",
dismiss: "Decline",
allow: "Accept",
link: "Learn more",
href: "https://aider.chat/docs/legal/privacy.html"
},
onInitialise: function(status) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (didConsent) {
initPostHog();
}
},
onStatusChange: function(status, chosenBefore) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (didConsent) {
initPostHog();
}
}
})
});
// PostHog initialization function
function initPostHog() {
!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey getNextSurveyStep identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
posthog.init('phc_99T7muzafUMMZX15H8XePbMSreEUzahHbtWjy3l5Qbv', {
api_host:'https://us.i.posthog.com',
person_profiles: 'identified_only'
})
}
</script>

View File

@@ -0,0 +1,4 @@
{: .tip :}
See the
[API key configuration docs](/docs/config/api-keys.html)
for information on how to configure and store your API keys.

View File

@@ -5,7 +5,10 @@ You can send long, multi-line messages in the chat in a few ways:
- Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
- Use `/paste` to paste text from the clipboard into the chat.
- Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
- 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:
- Use the `/multiline-mode` command to toggle it during a session.
- Use the `--multiline` switch.
Example with a tag:
```
{python

View File

@@ -1,6 +1,6 @@
To use aider with pipx on replit, you can run these commands in the replit shell:
```
```bash
pip install pipx
pipx run aider-chat ...normal aider args...
```

View File

@@ -1,12 +0,0 @@
Aider has special support for providing
OpenAI and Anthropic API keys
via
[command line switches](/docs/config/options.html)
and
[yaml config file](/docs/config/aider_conf.html).
*All other LLM providers* must
have their keys and settings
specified in environment variables.
This can be done in your shell,
or by using a
[.env file](/docs/config/dotenv.html).

View File

@@ -1,7 +0,0 @@
{: .tip }
Using a Python
[virtual environment](https://docs.python.org/3/library/venv.html){:target="_blank"}
is recommended.
Or, you could
[use pipx to install aider](/docs/install/pipx.html)
once for your whole system.

View File

@@ -1,6 +1,6 @@
---
title: Aider has written 7% of its own code
excerpt: Aider has written 7% of its own code, via 600+ commits that inserted 4.8K and deleted 1.5K lines of code.
title: Aider has written 7% of its own code (outdated, now 70%)
excerpt: This article is quite out dated. Aider is currently writing about 70% of the new code in each release.
highlight_image: /assets/self-assembly.jpg
nav_exclude: true
---
@@ -8,13 +8,16 @@ nav_exclude: true
<p class="post-date">{{ page.date | date: "%B %d, %Y" }}</p>
{% endif %}
# Aider has written 7% of its own code
# Aider has written 7% of its own code (outdated, now 70%)
[![self assembly](/assets/self-assembly.jpg)](https://aider.chat/assets/self-assembly.jpg)
{: .note }
This article is quite out dated. For current statistics, see
[aider's release history](/HISTORY.html).
This article is quite old and outdated.
Aider is currently writing about 70% of the new code
in each release.
See
[aider's release history](/HISTORY.html) for the latest statistics.
The
[aider git repo](https://github.com/Aider-AI/aider)

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -14,14 +14,8 @@
## show this help message and exit
#help: xxx
#######
# Main:
## Specify the OpenAI API key
#openai-api-key: xxx
## Specify the Anthropic API key
#anthropic-api-key: xxx
#############
# Main model:
## Specify the model to use for the main chat
#model: xxx
@@ -59,27 +53,52 @@
## Use o1-preview model for the main chat
#o1-preview: false
#################
# Model Settings:
########################
# API Keys and settings:
## List known models which match the (partial) MODEL name
#list-models: xxx
## Specify the OpenAI API key
#openai-api-key: xxx
## Specify the Anthropic API key
#anthropic-api-key: xxx
## Specify the api base url
#openai-api-base: xxx
## Specify the api_type
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
#openai-api-type: xxx
## Specify the api_version
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
#openai-api-version: xxx
## Specify the deployment_id
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
#openai-api-deployment-id: xxx
## Specify the OpenAI organization ID
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
#openai-organization-id: xxx
## Set an environment variable (to control API settings, can be used multiple times)
#set-env: xxx
## Specify multiple values like this:
#set-env:
# - xxx
# - yyy
# - zzz
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
#api-key: xxx
## Specify multiple values like this:
#api-key:
# - xxx
# - yyy
# - zzz
#################
# Model settings:
## List known models which match the (partial) MODEL name
#list-models: xxx
## Specify a file with aider model settings for unknown models
#model-settings-file: .aider.model.settings.yml
@@ -121,11 +140,8 @@
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#max-chat-history-tokens: xxx
## Specify the .env file to load (default: .env in git root)
#env-file: .env
#################
# Cache Settings:
# Cache settings:
## Enable caching of prompts (default: False)
#cache-prompts: false
@@ -134,7 +150,7 @@
#cache-keepalive-pings: false
###################
# Repomap Settings:
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
#map-tokens: xxx
@@ -161,7 +177,7 @@
#llm-history-file: xxx
##################
# Output Settings:
# Output settings:
## Use colors suitable for a dark terminal background (default: False)
#dark-mode: false
@@ -209,7 +225,7 @@
#show-diffs: false
###############
# Git Settings:
# Git settings:
## Enable/disable looking for a git repo (default: True)
#git: true
@@ -294,8 +310,71 @@
## Permanently disable analytics
#analytics-disable: false
############
# Upgrading:
## Check for updates and return status in the exit code
#just-check-update: false
## Check for new aider versions on launch
#check-update: true
## Show release notes on first run of new version (default: None, ask user)
#show-release-notes: xxx
## Install the latest version from the main branch
#install-main-branch: false
## Upgrade aider to the latest version from PyPI
#upgrade: false
## Show the version number and exit
#version: xxx
########
# Modes:
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#message: xxx
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Run aider in your browser (default: False)
#gui: false
## Enable automatic copy/paste of chat between aider and web UI (default: False)
#copy-paste: false
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Do all startup activities then exit before accepting user input (debug)
#exit: false
## Print the repo map and exit (debug)
#show-repo-map: false
## Print the system prompts and exit (debug)
#show-prompts: false
#################
# Other Settings:
# Voice settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
#voice-format: wav
## Specify the language for voice using ISO 639-1 code (default: auto)
#voice-language: en
## Specify the input device name for voice recording
#voice-input-device: xxx
#################
# Other settings:
## specify a file to edit (can be used multiple times)
#file: xxx
@@ -319,51 +398,12 @@
## Specify the language to use in the chat (default: None, uses system settings)
#chat-language: xxx
## Show the version number and exit
#version: xxx
## Check for updates and return status in the exit code
#just-check-update: false
## Check for new aider versions on launch
#check-update: true
## Show release notes on first run of new version (default: None, ask user)
#show-release-notes: xxx
## Install the latest version from the main branch
#install-main-branch: false
## Upgrade aider to the latest version from PyPI
#upgrade: false
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Always say yes to every confirmation
#yes-always: false
## Enable verbose output
#verbose: false
## Print the repo map and exit (debug)
#show-repo-map: false
## Print the system prompts and exit (debug)
#show-prompts: false
## Do all startup activities then exit before accepting user input (debug)
#exit: false
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#message: xxx
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Load and execute /commands from a file on launch
#load: xxx
@@ -373,8 +413,8 @@
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx
## Run aider in your browser (default: False)
#gui: false
## Specify the .env file to load (default: .env in git root)
#env-file: .env
## Enable/disable suggesting shell commands (default: True)
#suggest-shell-commands: true
@@ -382,20 +422,11 @@
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
#multiline: false
## Enable/disable detection and offering to add URLs to chat (default: True)
#detect-urls: true
## Specify which editor to use for the /editor command
#editor: xxx
#################
# Voice Settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
#voice-format: wav
## Specify the language for voice using ISO 639-1 code (default: auto)
#voice-language: en
## Specify the input device name for voice recording
#voice-input-device: xxx

View File

@@ -18,14 +18,8 @@
##...
#######
# Main:
## Specify the OpenAI API key
#OPENAI_API_KEY=
## Specify the Anthropic API key
#ANTHROPIC_API_KEY=
#############
# Main model:
## Specify the model to use for the main chat
#AIDER_MODEL=
@@ -63,27 +57,42 @@
## Use o1-preview model for the main chat
#AIDER_O1_PREVIEW=
########################
# API Keys and settings:
## Specify the OpenAI API key
#AIDER_OPENAI_API_KEY=
## Specify the Anthropic API key
#AIDER_ANTHROPIC_API_KEY=
## Specify the api base url
#AIDER_OPENAI_API_BASE=
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
#AIDER_OPENAI_API_TYPE=
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
#AIDER_OPENAI_API_VERSION=
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
#AIDER_OPENAI_API_DEPLOYMENT_ID=
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
#AIDER_OPENAI_ORGANIZATION_ID=
## Set an environment variable (to control API settings, can be used multiple times)
#AIDER_SET_ENV=
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
#AIDER_API_KEY=
#################
# Model Settings:
# Model settings:
## List known models which match the (partial) MODEL name
#AIDER_LIST_MODELS=
## Specify the api base url
#OPENAI_API_BASE=
## Specify the api_type
#OPENAI_API_TYPE=
## Specify the api_version
#OPENAI_API_VERSION=
## Specify the deployment_id
#OPENAI_API_DEPLOYMENT_ID=
## Specify the OpenAI organization ID
#OPENAI_ORGANIZATION_ID=
## Specify a file with aider model settings for unknown models
#AIDER_MODEL_SETTINGS_FILE=.aider.model.settings.yml
@@ -120,11 +129,8 @@
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#AIDER_MAX_CHAT_HISTORY_TOKENS=
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env
#################
# Cache Settings:
# Cache settings:
## Enable caching of prompts (default: False)
#AIDER_CACHE_PROMPTS=false
@@ -133,7 +139,7 @@
#AIDER_CACHE_KEEPALIVE_PINGS=false
###################
# Repomap Settings:
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
#AIDER_MAP_TOKENS=
@@ -160,7 +166,7 @@
#AIDER_LLM_HISTORY_FILE=
##################
# Output Settings:
# Output settings:
## Use colors suitable for a dark terminal background (default: False)
#AIDER_DARK_MODE=false
@@ -208,7 +214,7 @@
#AIDER_SHOW_DIFFS=false
###############
# Git Settings:
# Git settings:
## Enable/disable looking for a git repo (default: True)
#AIDER_GIT=true
@@ -288,20 +294,8 @@
## Permanently disable analytics
#AIDER_ANALYTICS_DISABLE=false
#################
# Other Settings:
## specify a file to edit (can be used multiple times)
#AIDER_FILE=
## specify a read-only file (can be used multiple times)
#AIDER_READ=
## Use VI editing mode in the terminal (default: False)
#AIDER_VIM=false
## Specify the language to use in the chat (default: None, uses system settings)
#AIDER_CHAT_LANGUAGE=
############
# Upgrading:
## Check for updates and return status in the exit code
#AIDER_JUST_CHECK_UPDATE=false
@@ -318,26 +312,8 @@
## Upgrade aider to the latest version from PyPI
#AIDER_UPGRADE=false
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
## Enable verbose output
#AIDER_VERBOSE=false
## Print the repo map and exit (debug)
#AIDER_SHOW_REPO_MAP=false
## Print the system prompts and exit (debug)
#AIDER_SHOW_PROMPTS=false
## Do all startup activities then exit before accepting user input (debug)
#AIDER_EXIT=false
########
# Modes:
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#AIDER_MESSAGE=
@@ -345,29 +321,29 @@
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser (default: False)
#AIDER_GUI=false
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable automatic copy/paste of chat between aider and web UI (default: False)
#AIDER_COPY_PASTE=false
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Enable/disable detection and offering to add URLs to chat (default: True)
#AIDER_DETECT_URLS=true
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Specify which editor to use for the /editor command
#AIDER_EDITOR=
## Do all startup activities then exit before accepting user input (debug)
#AIDER_EXIT=false
## Print the repo map and exit (debug)
#AIDER_SHOW_REPO_MAP=false
## Print the system prompts and exit (debug)
#AIDER_SHOW_PROMPTS=false
#################
# Voice Settings:
# Voice settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
#AIDER_VOICE_FORMAT=wav
@@ -377,3 +353,48 @@
## Specify the input device name for voice recording
#AIDER_VOICE_INPUT_DEVICE=
#################
# Other settings:
## specify a file to edit (can be used multiple times)
#AIDER_FILE=
## specify a read-only file (can be used multiple times)
#AIDER_READ=
## Use VI editing mode in the terminal (default: False)
#AIDER_VIM=false
## Specify the language to use in the chat (default: None, uses system settings)
#AIDER_CHAT_LANGUAGE=
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
## Enable verbose output
#AIDER_VERBOSE=false
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
#AIDER_MULTILINE=false
## Enable/disable detection and offering to add URLs to chat (default: True)
#AIDER_DETECT_URLS=true
## Specify which editor to use for the /editor command
#AIDER_EDITOR=

View File

@@ -40,5 +40,5 @@ Using an `.env` file:
AIDER_DARK_MODE=true
```
{% include env-keys-tip.md %}
{% include keys.md %}

View File

@@ -46,14 +46,19 @@ The json file should be a dictionary with an entry for each model, as follows:
}
```
See
[litellm's model_prices_and_context_window.json file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json) for more examples.
Consider submitting a PR to that file to add missing models.
{: .tip }
Use a fully qualified model name with a `provider/` at the front
in the `.aider.model.metadata.json` file.
For example, use `deepseek/deepseek-chat`, not just `deepseek-chat`.
That prefix should match the `litellm_provider` field.
### Contribute model metadata
Aider relies on
[litellm's model_prices_and_context_window.json file](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json)
for model metadata.
Consider submitting a PR to that file to add missing models.
## Model settings
@@ -978,6 +983,54 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: false
name: gemini/gemini-exp-1206
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: false
name: gemini/gemini-exp-1114
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: false
name: gemini/gemini-exp-1121
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
@@ -1010,6 +1063,22 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: false
name: gemini/gemini-2.0-flash-exp
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: diff

View File

@@ -15,11 +15,7 @@ load whichever is found first.
- The root of your git repo.
- Your home directory.
## Storing LLM keys
{% include special-keys.md %}
{% include env-keys-tip.md %}
{% include keys.md %}
## A note on lists
@@ -70,14 +66,8 @@ cog.outl("```")
## show this help message and exit
#help: xxx
#######
# Main:
## Specify the OpenAI API key
#openai-api-key: xxx
## Specify the Anthropic API key
#anthropic-api-key: xxx
#############
# Main model:
## Specify the model to use for the main chat
#model: xxx
@@ -115,27 +105,52 @@ cog.outl("```")
## Use o1-preview model for the main chat
#o1-preview: false
#################
# Model Settings:
########################
# API Keys and settings:
## List known models which match the (partial) MODEL name
#list-models: xxx
## Specify the OpenAI API key
#openai-api-key: xxx
## Specify the Anthropic API key
#anthropic-api-key: xxx
## Specify the api base url
#openai-api-base: xxx
## Specify the api_type
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
#openai-api-type: xxx
## Specify the api_version
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
#openai-api-version: xxx
## Specify the deployment_id
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
#openai-api-deployment-id: xxx
## Specify the OpenAI organization ID
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
#openai-organization-id: xxx
## Set an environment variable (to control API settings, can be used multiple times)
#set-env: xxx
## Specify multiple values like this:
#set-env:
# - xxx
# - yyy
# - zzz
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
#api-key: xxx
## Specify multiple values like this:
#api-key:
# - xxx
# - yyy
# - zzz
#################
# Model settings:
## List known models which match the (partial) MODEL name
#list-models: xxx
## Specify a file with aider model settings for unknown models
#model-settings-file: .aider.model.settings.yml
@@ -177,11 +192,8 @@ cog.outl("```")
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#max-chat-history-tokens: xxx
## Specify the .env file to load (default: .env in git root)
#env-file: .env
#################
# Cache Settings:
# Cache settings:
## Enable caching of prompts (default: False)
#cache-prompts: false
@@ -190,7 +202,7 @@ cog.outl("```")
#cache-keepalive-pings: false
###################
# Repomap Settings:
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
#map-tokens: xxx
@@ -217,7 +229,7 @@ cog.outl("```")
#llm-history-file: xxx
##################
# Output Settings:
# Output settings:
## Use colors suitable for a dark terminal background (default: False)
#dark-mode: false
@@ -265,7 +277,7 @@ cog.outl("```")
#show-diffs: false
###############
# Git Settings:
# Git settings:
## Enable/disable looking for a git repo (default: True)
#git: true
@@ -350,8 +362,71 @@ cog.outl("```")
## Permanently disable analytics
#analytics-disable: false
############
# Upgrading:
## Check for updates and return status in the exit code
#just-check-update: false
## Check for new aider versions on launch
#check-update: true
## Show release notes on first run of new version (default: None, ask user)
#show-release-notes: xxx
## Install the latest version from the main branch
#install-main-branch: false
## Upgrade aider to the latest version from PyPI
#upgrade: false
## Show the version number and exit
#version: xxx
########
# Modes:
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#message: xxx
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Run aider in your browser (default: False)
#gui: false
## Enable automatic copy/paste of chat between aider and web UI (default: False)
#copy-paste: false
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Do all startup activities then exit before accepting user input (debug)
#exit: false
## Print the repo map and exit (debug)
#show-repo-map: false
## Print the system prompts and exit (debug)
#show-prompts: false
#################
# Other Settings:
# Voice settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
#voice-format: wav
## Specify the language for voice using ISO 639-1 code (default: auto)
#voice-language: en
## Specify the input device name for voice recording
#voice-input-device: xxx
#################
# Other settings:
## specify a file to edit (can be used multiple times)
#file: xxx
@@ -375,51 +450,12 @@ cog.outl("```")
## Specify the language to use in the chat (default: None, uses system settings)
#chat-language: xxx
## Show the version number and exit
#version: xxx
## Check for updates and return status in the exit code
#just-check-update: false
## Check for new aider versions on launch
#check-update: true
## Show release notes on first run of new version (default: None, ask user)
#show-release-notes: xxx
## Install the latest version from the main branch
#install-main-branch: false
## Upgrade aider to the latest version from PyPI
#upgrade: false
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Always say yes to every confirmation
#yes-always: false
## Enable verbose output
#verbose: false
## Print the repo map and exit (debug)
#show-repo-map: false
## Print the system prompts and exit (debug)
#show-prompts: false
## Do all startup activities then exit before accepting user input (debug)
#exit: false
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#message: xxx
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Load and execute /commands from a file on launch
#load: xxx
@@ -429,8 +465,8 @@ cog.outl("```")
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx
## Run aider in your browser (default: False)
#gui: false
## Specify the .env file to load (default: .env in git root)
#env-file: .env
## Enable/disable suggesting shell commands (default: True)
#suggest-shell-commands: true
@@ -438,22 +474,13 @@ cog.outl("```")
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
#multiline: false
## Enable/disable detection and offering to add URLs to chat (default: True)
#detect-urls: true
## Specify which editor to use for the /editor command
#editor: xxx
#################
# Voice Settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
#voice-format: wav
## Specify the language for voice using ISO 639-1 code (default: auto)
#voice-language: en
## Specify the input device name for voice recording
#voice-input-device: xxx
```
<!--[[[end]]]-->

View File

@@ -0,0 +1,68 @@
---
parent: Configuration
nav_order: 5
description: Setting API keys for API providers.
---
# API Keys
### OpenAI and Anthropic
Aider has special support for providing
OpenAI and Anthropic API keys
via dedicated switches and configuration options.
Settings keys for other providers works a bit differently, see below.
You can set OpenAI and Anthropic API keys via
[command line switches](/docs/config/options.html#api-keys-and-settings)
`--openai-api-key` and `--anthropic-api-key`.
You can also set those API keys via special entries in the
[yaml config file](/docs/config/aider_conf.html), like this:
```yaml
openai-api-key: <key>
anthropic-api-key: <key>
```
You can also store them in environment variables or a
[.env file](/docs/config/dotenv.html), which also works
for every API provider:
```
OPENAI_API_KEY=<key>
ANTHROPIC_API_KEY=<key>
```
All other LLM providers can use one of these other methods to set their API keys.
### API keys on the command line
{: .no_toc }
Use `--api-key provider=<key>` which has the effect of setting the environment variable `PROVIDER_API_KEY=<key>`. So `--api-key gemini=xxx` would set `GEMINI_API_KEY=xxx`.
### API keys in .aider.conf.yml
{: .no_toc }
You can also set API keys in the
[`.aider.conf.yml` file](/docs/config/aider_conf.html)
via the `api-key` entry:
```
api-key:
- gemini=foo # Sets env var GEMINI_API_KEY=foo
- openrouter=bar # Sets env var OPENROUTER_API_KEY=bar
- deepseek=baz # Sets env var DEEPSEEK_API_KEY=baz
```
### API keys in a .env file
{: .no_toc }
The [.env file](/docs/config/dotenv.html)
is a great place to set API keys and other provider API environment variables:
```bash
GEMINI_API_KEY=foo
OPENROUTER_API_KEY=bar
DEEPSEEK_API_KEY=baz
```

View File

@@ -1,6 +1,6 @@
---
parent: Configuration
nav_order: 900
nav_order: 20
description: Using a .env file to store LLM API keys for aider.
---
@@ -20,9 +20,7 @@ Aider will look for a `.env` file in these locations:
If the files above exist, they will be loaded in that order. Files loaded last will take priority.
## Storing LLM keys
{% include special-keys.md %}
{% include keys.md %}
## Sample .env file
@@ -60,14 +58,8 @@ cog.outl("```")
##...
#######
# Main:
## Specify the OpenAI API key
#OPENAI_API_KEY=
## Specify the Anthropic API key
#ANTHROPIC_API_KEY=
#############
# Main model:
## Specify the model to use for the main chat
#AIDER_MODEL=
@@ -105,27 +97,42 @@ cog.outl("```")
## Use o1-preview model for the main chat
#AIDER_O1_PREVIEW=
########################
# API Keys and settings:
## Specify the OpenAI API key
#AIDER_OPENAI_API_KEY=
## Specify the Anthropic API key
#AIDER_ANTHROPIC_API_KEY=
## Specify the api base url
#AIDER_OPENAI_API_BASE=
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
#AIDER_OPENAI_API_TYPE=
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
#AIDER_OPENAI_API_VERSION=
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
#AIDER_OPENAI_API_DEPLOYMENT_ID=
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
#AIDER_OPENAI_ORGANIZATION_ID=
## Set an environment variable (to control API settings, can be used multiple times)
#AIDER_SET_ENV=
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
#AIDER_API_KEY=
#################
# Model Settings:
# Model settings:
## List known models which match the (partial) MODEL name
#AIDER_LIST_MODELS=
## Specify the api base url
#OPENAI_API_BASE=
## Specify the api_type
#OPENAI_API_TYPE=
## Specify the api_version
#OPENAI_API_VERSION=
## Specify the deployment_id
#OPENAI_API_DEPLOYMENT_ID=
## Specify the OpenAI organization ID
#OPENAI_ORGANIZATION_ID=
## Specify a file with aider model settings for unknown models
#AIDER_MODEL_SETTINGS_FILE=.aider.model.settings.yml
@@ -162,11 +169,8 @@ cog.outl("```")
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#AIDER_MAX_CHAT_HISTORY_TOKENS=
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env
#################
# Cache Settings:
# Cache settings:
## Enable caching of prompts (default: False)
#AIDER_CACHE_PROMPTS=false
@@ -175,7 +179,7 @@ cog.outl("```")
#AIDER_CACHE_KEEPALIVE_PINGS=false
###################
# Repomap Settings:
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
#AIDER_MAP_TOKENS=
@@ -202,7 +206,7 @@ cog.outl("```")
#AIDER_LLM_HISTORY_FILE=
##################
# Output Settings:
# Output settings:
## Use colors suitable for a dark terminal background (default: False)
#AIDER_DARK_MODE=false
@@ -250,7 +254,7 @@ cog.outl("```")
#AIDER_SHOW_DIFFS=false
###############
# Git Settings:
# Git settings:
## Enable/disable looking for a git repo (default: True)
#AIDER_GIT=true
@@ -330,20 +334,8 @@ cog.outl("```")
## Permanently disable analytics
#AIDER_ANALYTICS_DISABLE=false
#################
# Other Settings:
## specify a file to edit (can be used multiple times)
#AIDER_FILE=
## specify a read-only file (can be used multiple times)
#AIDER_READ=
## Use VI editing mode in the terminal (default: False)
#AIDER_VIM=false
## Specify the language to use in the chat (default: None, uses system settings)
#AIDER_CHAT_LANGUAGE=
############
# Upgrading:
## Check for updates and return status in the exit code
#AIDER_JUST_CHECK_UPDATE=false
@@ -360,26 +352,8 @@ cog.outl("```")
## Upgrade aider to the latest version from PyPI
#AIDER_UPGRADE=false
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
## Enable verbose output
#AIDER_VERBOSE=false
## Print the repo map and exit (debug)
#AIDER_SHOW_REPO_MAP=false
## Print the system prompts and exit (debug)
#AIDER_SHOW_PROMPTS=false
## Do all startup activities then exit before accepting user input (debug)
#AIDER_EXIT=false
########
# Modes:
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#AIDER_MESSAGE=
@@ -387,29 +361,29 @@ cog.outl("```")
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser (default: False)
#AIDER_GUI=false
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable automatic copy/paste of chat between aider and web UI (default: False)
#AIDER_COPY_PASTE=false
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Enable/disable detection and offering to add URLs to chat (default: True)
#AIDER_DETECT_URLS=true
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Specify which editor to use for the /editor command
#AIDER_EDITOR=
## Do all startup activities then exit before accepting user input (debug)
#AIDER_EXIT=false
## Print the repo map and exit (debug)
#AIDER_SHOW_REPO_MAP=false
## Print the system prompts and exit (debug)
#AIDER_SHOW_PROMPTS=false
#################
# Voice Settings:
# Voice settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
#AIDER_VOICE_FORMAT=wav
@@ -419,5 +393,50 @@ cog.outl("```")
## Specify the input device name for voice recording
#AIDER_VOICE_INPUT_DEVICE=
#################
# Other settings:
## specify a file to edit (can be used multiple times)
#AIDER_FILE=
## specify a read-only file (can be used multiple times)
#AIDER_READ=
## Use VI editing mode in the terminal (default: False)
#AIDER_VIM=false
## Specify the language to use in the chat (default: None, uses system settings)
#AIDER_CHAT_LANGUAGE=
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
## Enable verbose output
#AIDER_VERBOSE=false
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
#AIDER_MULTILINE=false
## Enable/disable detection and offering to add URLs to chat (default: True)
#AIDER_DETECT_URLS=true
## Specify which editor to use for the /editor command
#AIDER_EDITOR=
```
<!--[[[end]]]-->

View File

@@ -1,6 +1,6 @@
---
parent: Configuration
nav_order: 15
nav_order: 100
description: How to configure a custom editor for aider's /editor command
---

View File

@@ -56,6 +56,7 @@ for alias, model in sorted(MODEL_ALIASES.items()):
- `4-turbo`: gpt-4-1106-preview
- `4o`: gpt-4o
- `deepseek`: deepseek/deepseek-coder
- `flash`: gemini/gemini-2.0-flash-exp
- `haiku`: claude-3-5-haiku-20241022
- `opus`: claude-3-opus-20240229
- `sonnet`: claude-3-5-sonnet-20241022

View File

@@ -13,10 +13,7 @@ or review them below.
- TOC
{:toc}
## LLM keys
{: .no_toc }
{% include special-keys.md %}
{% include keys.md %}
## Usage summary
@@ -25,18 +22,19 @@ from aider.args import get_md_help
cog.out(get_md_help())
]]]-->
```
usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--opus] [--sonnet] [--haiku] [--4] [--4o] [--mini]
[--4-turbo] [--35turbo] [--deepseek] [--o1-mini]
[--o1-preview] [--list-models] [--openai-api-base]
usage: aider [-h] [--model] [--opus] [--sonnet] [--haiku] [--4]
[--4o] [--mini] [--4-turbo] [--35turbo] [--deepseek]
[--o1-mini] [--o1-preview] [--openai-api-key]
[--anthropic-api-key] [--openai-api-base]
[--openai-api-type] [--openai-api-version]
[--openai-api-deployment-id] [--openai-organization-id]
[--set-env] [--api-key] [--list-models]
[--model-settings-file] [--model-metadata-file]
[--alias] [--verify-ssl | --no-verify-ssl] [--timeout]
[--edit-format] [--architect] [--weak-model]
[--editor-model] [--editor-edit-format]
[--show-model-warnings | --no-show-model-warnings]
[--max-chat-history-tokens] [--env-file]
[--max-chat-history-tokens]
[--cache-prompts | --no-cache-prompts]
[--cache-keepalive-pings] [--map-tokens]
[--map-refresh] [--map-multiplier-no-files]
@@ -64,20 +62,22 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--lint-cmd] [--auto-lint | --no-auto-lint]
[--test-cmd] [--auto-test | --no-auto-test] [--test]
[--analytics | --no-analytics] [--analytics-log]
[--analytics-disable] [--file] [--read] [--vim]
[--chat-language] [--version] [--just-check-update]
[--analytics-disable] [--just-check-update]
[--check-update | --no-check-update]
[--show-release-notes | --no-show-release-notes]
[--install-main-branch] [--upgrade] [--apply]
[--apply-clipboard-edits] [--yes-always] [-v]
[--show-repo-map] [--show-prompts] [--exit] [--message]
[--message-file] [--load] [--encoding] [-c]
[--install-main-branch] [--upgrade] [--version]
[--message] [--message-file]
[--gui | --no-gui | --browser | --no-browser]
[--copy-paste | --no-copy-paste] [--apply]
[--apply-clipboard-edits] [--exit] [--show-repo-map]
[--show-prompts] [--voice-format] [--voice-language]
[--voice-input-device] [--file] [--read] [--vim]
[--chat-language] [--yes-always] [-v] [--load]
[--encoding] [-c] [--env-file]
[--suggest-shell-commands | --no-suggest-shell-commands]
[--fancy-input | --no-fancy-input]
[--multiline | --no-multiline]
[--detect-urls | --no-detect-urls] [--editor]
[--voice-format] [--voice-language]
[--voice-input-device]
```
@@ -89,15 +89,7 @@ Aliases:
- `-h`
- `--help`
## Main:
### `--openai-api-key OPENAI_API_KEY`
Specify the OpenAI API key
Environment variable: `OPENAI_API_KEY`
### `--anthropic-api-key ANTHROPIC_API_KEY`
Specify the Anthropic API key
Environment variable: `ANTHROPIC_API_KEY`
## Main model:
### `--model MODEL`
Specify the model to use for the main chat
@@ -155,7 +147,47 @@ Environment variable: `AIDER_O1_MINI`
Use o1-preview model for the main chat
Environment variable: `AIDER_O1_PREVIEW`
## Model Settings:
## API Keys and settings:
### `--openai-api-key VALUE`
Specify the OpenAI API key
Environment variable: `AIDER_OPENAI_API_KEY`
### `--anthropic-api-key VALUE`
Specify the Anthropic API key
Environment variable: `AIDER_ANTHROPIC_API_KEY`
### `--openai-api-base VALUE`
Specify the api base url
Environment variable: `AIDER_OPENAI_API_BASE`
### `--openai-api-type VALUE`
(deprecated, use --set-env OPENAI_API_TYPE=<value>)
Environment variable: `AIDER_OPENAI_API_TYPE`
### `--openai-api-version VALUE`
(deprecated, use --set-env OPENAI_API_VERSION=<value>)
Environment variable: `AIDER_OPENAI_API_VERSION`
### `--openai-api-deployment-id VALUE`
(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
Environment variable: `AIDER_OPENAI_API_DEPLOYMENT_ID`
### `--openai-organization-id VALUE`
(deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
Environment variable: `AIDER_OPENAI_ORGANIZATION_ID`
### `--set-env ENV_VAR_NAME=value`
Set an environment variable (to control API settings, can be used multiple times)
Default: []
Environment variable: `AIDER_SET_ENV`
### `--api-key PROVIDER=KEY`
Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
Default: []
Environment variable: `AIDER_API_KEY`
## Model settings:
### `--list-models MODEL`
List known models which match the (partial) MODEL name
@@ -164,26 +196,6 @@ Aliases:
- `--list-models MODEL`
- `--models MODEL`
### `--openai-api-base OPENAI_API_BASE`
Specify the api base url
Environment variable: `OPENAI_API_BASE`
### `--openai-api-type OPENAI_API_TYPE`
Specify the api_type
Environment variable: `OPENAI_API_TYPE`
### `--openai-api-version OPENAI_API_VERSION`
Specify the api_version
Environment variable: `OPENAI_API_VERSION`
### `--openai-api-deployment-id OPENAI_API_DEPLOYMENT_ID`
Specify the deployment_id
Environment variable: `OPENAI_API_DEPLOYMENT_ID`
### `--openai-organization-id OPENAI_ORGANIZATION_ID`
Specify the OpenAI organization ID
Environment variable: `OPENAI_ORGANIZATION_ID`
### `--model-settings-file MODEL_SETTINGS_FILE`
Specify a file with aider model settings for unknown models
Default: .aider.model.settings.yml
@@ -245,12 +257,7 @@ Aliases:
Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
Environment variable: `AIDER_MAX_CHAT_HISTORY_TOKENS`
### `--env-file ENV_FILE`
Specify the .env file to load (default: .env in git root)
Default: .env
Environment variable: `AIDER_ENV_FILE`
## Cache Settings:
## Cache settings:
### `--cache-prompts`
Enable caching of prompts (default: False)
@@ -265,7 +272,7 @@ Number of times to ping at 5min intervals to keep prompt cache warm (default: 0)
Default: 0
Environment variable: `AIDER_CACHE_KEEPALIVE_PINGS`
## Repomap Settings:
## Repomap settings:
### `--map-tokens VALUE`
Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
@@ -305,7 +312,7 @@ Aliases:
Log the conversation with the LLM to this file (for example, .aider.llm.history)
Environment variable: `AIDER_LLM_HISTORY_FILE`
## Output Settings:
## Output settings:
### `--dark-mode`
Use colors suitable for a dark terminal background (default: False)
@@ -383,7 +390,7 @@ Show diffs when committing changes (default: False)
Default: False
Environment variable: `AIDER_SHOW_DIFFS`
## Git Settings:
## Git settings:
### `--git`
Enable/disable looking for a git repo (default: True)
@@ -545,27 +552,7 @@ Permanently disable analytics
Default: False
Environment variable: `AIDER_ANALYTICS_DISABLE`
## Other Settings:
### `--file FILE`
specify a file to edit (can be used multiple times)
Environment variable: `AIDER_FILE`
### `--read FILE`
specify a read-only file (can be used multiple times)
Environment variable: `AIDER_READ`
### `--vim`
Use VI editing mode in the terminal (default: False)
Default: False
Environment variable: `AIDER_VIM`
### `--chat-language CHAT_LANGUAGE`
Specify the language to use in the chat (default: None, uses system settings)
Environment variable: `AIDER_CHAT_LANGUAGE`
### `--version`
Show the version number and exit
## Upgrading:
### `--just-check-update`
Check for updates and return status in the exit code
@@ -600,41 +587,10 @@ Aliases:
- `--upgrade`
- `--update`
### `--apply FILE`
Apply the changes from the given file instead of running the chat (debug)
Environment variable: `AIDER_APPLY`
### `--version`
Show the version number and exit
### `--apply-clipboard-edits`
Apply clipboard contents as edits using the main model's editor format
Default: False
Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS`
### `--yes-always`
Always say yes to every confirmation
Environment variable: `AIDER_YES_ALWAYS`
### `--verbose`
Enable verbose output
Default: False
Environment variable: `AIDER_VERBOSE`
Aliases:
- `-v`
- `--verbose`
### `--show-repo-map`
Print the repo map and exit (debug)
Default: False
Environment variable: `AIDER_SHOW_REPO_MAP`
### `--show-prompts`
Print the system prompts and exit (debug)
Default: False
Environment variable: `AIDER_SHOW_PROMPTS`
### `--exit`
Do all startup activities then exit before accepting user input (debug)
Default: False
Environment variable: `AIDER_EXIT`
## Modes:
### `--message COMMAND`
Specify a single message to send the LLM, process reply then exit (disables chat mode)
@@ -651,6 +607,95 @@ Aliases:
- `--message-file MESSAGE_FILE`
- `-f MESSAGE_FILE`
### `--gui`
Run aider in your browser (default: False)
Default: False
Environment variable: `AIDER_GUI`
Aliases:
- `--gui`
- `--no-gui`
- `--browser`
- `--no-browser`
### `--copy-paste`
Enable automatic copy/paste of chat between aider and web UI (default: False)
Default: False
Environment variable: `AIDER_COPY_PASTE`
Aliases:
- `--copy-paste`
- `--no-copy-paste`
### `--apply FILE`
Apply the changes from the given file instead of running the chat (debug)
Environment variable: `AIDER_APPLY`
### `--apply-clipboard-edits`
Apply clipboard contents as edits using the main model's editor format
Default: False
Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS`
### `--exit`
Do all startup activities then exit before accepting user input (debug)
Default: False
Environment variable: `AIDER_EXIT`
### `--show-repo-map`
Print the repo map and exit (debug)
Default: False
Environment variable: `AIDER_SHOW_REPO_MAP`
### `--show-prompts`
Print the system prompts and exit (debug)
Default: False
Environment variable: `AIDER_SHOW_PROMPTS`
## Voice settings:
### `--voice-format VOICE_FORMAT`
Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
Default: wav
Environment variable: `AIDER_VOICE_FORMAT`
### `--voice-language VOICE_LANGUAGE`
Specify the language for voice using ISO 639-1 code (default: auto)
Default: en
Environment variable: `AIDER_VOICE_LANGUAGE`
### `--voice-input-device VOICE_INPUT_DEVICE`
Specify the input device name for voice recording
Environment variable: `AIDER_VOICE_INPUT_DEVICE`
## Other settings:
### `--file FILE`
specify a file to edit (can be used multiple times)
Environment variable: `AIDER_FILE`
### `--read FILE`
specify a read-only file (can be used multiple times)
Environment variable: `AIDER_READ`
### `--vim`
Use VI editing mode in the terminal (default: False)
Default: False
Environment variable: `AIDER_VIM`
### `--chat-language CHAT_LANGUAGE`
Specify the language to use in the chat (default: None, uses system settings)
Environment variable: `AIDER_CHAT_LANGUAGE`
### `--yes-always`
Always say yes to every confirmation
Environment variable: `AIDER_YES_ALWAYS`
### `--verbose`
Enable verbose output
Default: False
Environment variable: `AIDER_VERBOSE`
Aliases:
- `-v`
- `--verbose`
### `--load LOAD_FILE`
Load and execute /commands from a file on launch
Environment variable: `AIDER_LOAD`
@@ -666,15 +711,10 @@ Aliases:
- `-c CONFIG_FILE`
- `--config CONFIG_FILE`
### `--gui`
Run aider in your browser (default: False)
Default: False
Environment variable: `AIDER_GUI`
Aliases:
- `--gui`
- `--no-gui`
- `--browser`
- `--no-browser`
### `--env-file ENV_FILE`
Specify the .env file to load (default: .env in git root)
Default: .env
Environment variable: `AIDER_ENV_FILE`
### `--suggest-shell-commands`
Enable/disable suggesting shell commands (default: True)
@@ -692,6 +732,14 @@ Aliases:
- `--fancy-input`
- `--no-fancy-input`
### `--multiline`
Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
Default: False
Environment variable: `AIDER_MULTILINE`
Aliases:
- `--multiline`
- `--no-multiline`
### `--detect-urls`
Enable/disable detection and offering to add URLs to chat (default: True)
Default: True
@@ -703,20 +751,4 @@ Aliases:
### `--editor VALUE`
Specify which editor to use for the /editor command
Environment variable: `AIDER_EDITOR`
## Voice Settings:
### `--voice-format VOICE_FORMAT`
Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
Default: wav
Environment variable: `AIDER_VOICE_FORMAT`
### `--voice-language VOICE_LANGUAGE`
Specify the language for voice using ISO 639-1 code (default: auto)
Default: en
Environment variable: `AIDER_VOICE_LANGUAGE`
### `--voice-input-device VOICE_INPUT_DEVICE`
Specify the input device name for voice recording
Environment variable: `AIDER_VOICE_INPUT_DEVICE`
<!--[[[end]]]-->

View File

@@ -209,6 +209,47 @@ all the raw information being sent to/from the LLM in the conversation.
You can also refer to the
[instructions for installing a development version of aider](https://aider.chat/docs/install/optional.html#install-the-development-version-of-aider).
## What LLMs do you use to build aider?
Aider writes a lot of its own code, usually about 70% of the new code in each
release.
People often ask which LLMs I use with aider, when writing aider.
Below is a table showing the models I have used recently,
extracted from the
[public log](https://github.com/aider-ai/aider/blob/main/aider/website/assets/sample-analytics.jsonl)
of my
[aider analytics](https://aider.chat/docs/more/analytics.html).
<!--[[[cog
import sys
sys.path.append(".")
import scripts.my_models as my_models
stats = my_models.collect_model_stats()
html = my_models.format_html_table(stats)
cog.out(html)
]]]-->
<style>
table { border-collapse: collapse; width: 100%; }
th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
th { background-color: #f2f2f2; }
tr:hover { background-color: #f5f5f5; }
.right { text-align: right; }
</style>
<table>
<tr><th>Model Name</th><th class='right'>Total Tokens</th><th class='right'>Percent</th></tr>
<tr><td>claude-3-5-sonnet-20241022</td><td class='right'>1,630,102</td><td class='right'>88.9%</td></tr>
<tr><td>o1-preview</td><td class='right'>83,782</td><td class='right'>4.6%</td></tr>
<tr><td>gemini/REDACTED</td><td class='right'>82,572</td><td class='right'>4.5%</td></tr>
<tr><td>deepseek/deepseek-coder</td><td class='right'>24,628</td><td class='right'>1.3%</td></tr>
<tr><td>gpt-4o</td><td class='right'>9,243</td><td class='right'>0.5%</td></tr>
<tr><td>gpt-4o-mini</td><td class='right'>3,420</td><td class='right'>0.2%</td></tr>
<tr><td>mistral/REDACTED</td><td class='right'>620</td><td class='right'>0.0%</td></tr>
</table>
{: .note :}
Some models show as REDACTED, because they are new or unpopular models.
Aider's analytics only records the names of "well known" LLMs.
<!--[[[end]]]-->
## How are the "aider wrote xx% of code" stats computed?

View File

@@ -5,41 +5,84 @@ nav_order: 20
description: How to install and get started pair programming with aider.
---
# Quick start
# Installation
{: .no_toc }
## Get started quickly with aider-install
{% include get-started.md %}
Or see the
[full installation instructions](/docs/install/install.html)
for more details,
or the
[usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.
If needed,
aider-install will automatically install a separate version of python3.12 to use with aider.
There are some [optional install steps](/docs/install/optional.html) you could consider.
See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.
## Install with uv
A recommended way to install aider is with uv:
```bash
python -m pip install uv # If you need to install uv
uv tool install --python python3.12 aider-chat
```
You can use uv to install aider with your existing python versions 3.8-3.13.
If needed,
uv will automatically install a separate version of python3.12 to use with aider.
Also see the
[docs on other methods for installing uv itself](https://docs.astral.sh/uv/getting-started/installation/).
## Install with pipx
A recommended way to install aider is with pipx:
```bash
python -m pip install pipx # If you need to install pipx
pipx install aider-chat
```
You can use pipx to install aider with python versions 3.9-3.12.
Also see the
[docs on other methods for installing pipx itself](https://pipx.pypa.io/stable/installation/).
## Install with pip
You can directly install aider with pip, but one of the above
methods is usually safer.
If you do install with pip, you should consider
using a
[virtual environment](https://docs.python.org/3/library/venv.html)
to keep aider's dependencies separated.
You can use pip to install aider with python versions 3.9-3.12.
```bash
# Install aider
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
# To work with GPT-4o:
aider --4o --openai-api-key sk-xxx...
# To work with Claude 3.5 Sonnet:
aider --sonnet --anthropic-api-key sk-xxx...
```
{% include python-m-aider.md %}
<div class="video-container">
<video controls poster="/assets/install.jpg">
<source src="/assets/install.mp4" type="video/mp4">
<a href="/assets/install.mp4">Installing aider</a>
</video>
</div>
## Installing with package managers
<style>
.video-container {
position: relative;
padding-bottom: 76.2711864407%;
height: 0;
overflow: hidden;
}
.video-container video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
It's best to install aider using aider-install, uv or pipx as described above.
While aider is available in a number of system package managers,
they often install aider with incorrect dependencies.
## Next steps...
There are some [optional install steps](/docs/install/optional.html) you could consider.
See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.

View File

@@ -8,9 +8,9 @@ nav_order: 900
You can use aider in GitHub Codespaces via the built-in Terminal pane.
See below for an example,
but you can see the
but you can just follow the
[main install instructions](/docs/install.html)
for all the details.
inside your codespace terminal.
<div class="video-container">

View File

@@ -1,70 +0,0 @@
---
parent: Installation
nav_order: 10
---
# Installing aider
{: .no_toc }
- TOC
{:toc}
## Python version
Aider currently works with python 3.9-3.12.
## Install git
Make sure you have git installed.
Here are
[instructions for installing git in various environments](https://github.com/git-guides/install-git).
## Get your API key
To work with OpenAI's models like GPT-4o or GPT-3.5 you need a paid
[OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key).
Note that this is different than being a "ChatGPT Plus" subscriber.
To work with Anthropic's models like Claude 3.5 Sonnet you need a paid
[Anthropic API key](https://docs.anthropic.com/claude/reference/getting-started-with-the-api).
{% include venv-pipx.md %}
## Mac/Linux install
```
# Install aider
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
# To work with GPT-4o:
$ aider --4o --openai-api-key sk-xxx...
# To work with Claude 3.5 Sonnet:
$ aider --sonnet --anthropic-api-key sk-xxx...
```
## Windows install
```
# Install aider
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
# To work with GPT-4o:
$ aider --4o --openai-api-key sk-xxx...
# To work with Claude 3.5 Sonnet:
$ aider --sonnet --anthropic-api-key sk-xxx...
```
{% include python-m-aider.md %}
## Working with other LLMs
{% include works-best.md %}
## You are done!
There are some [optional install steps](/docs/install/optional.html) you could consider.
See the [usage instructions](https://aider.chat/docs/usage.html) to start coding with aider.

View File

@@ -11,10 +11,29 @@ The steps below are completely optional.
- TOC
{:toc}
## Install git
## Store your api keys
Aider works best if you have git installed.
Here are
[instructions for installing git in various environments](https://github.com/git-guides/install-git).
You can [store your api keys in a .env file](/docs/config/dotenv.html)
## Get your API key
To work with OpenAI's models like GPT-4o or o1-preview you need a paid
[OpenAI API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key).
Note that this is different than being a "ChatGPT Plus" subscriber.
To work with Anthropic's models like Claude 3.5 Sonnet you need a paid
[Anthropic API key](https://docs.anthropic.com/claude/reference/getting-started-with-the-api).
### Working with other LLMs
{% include works-best.md %}
### Store your api keys
You can [store your api keys in configuration or env files](/docs/config/api-keys.html)
and they will be loaded automatically whenever you run aider.
## Enable Playwright
@@ -55,13 +74,17 @@ Installing PortAudio is completely optional, but can usually be accomplished lik
- For Linux, do `sudo apt-get install libportaudio2`
- Some linux environments may also need `sudo apt install libasound2-plugins`
## Add aider to your editor
## Add aider to your IDE/editor
Other projects have integrated aider into some IDE/editors.
You can use
[aider's `--watch-files` mode](https://aider.chat/docs/usage/watch.html)
to integrate with any IDE or editor.
Other projects have made plugins for various IDE/editors.
It's not clear if they are tracking the latest
versions of aider,
so it may be best to just run the latest
aider in a terminal alongside your editor.
aider in a terminal alongside your editor and use `--watch-files`.
### NeoVim
@@ -71,9 +94,9 @@ aider in a terminal alongside your editor.
### VS Code
joshuavial also confirmed that aider works inside a VS Code terminal window.
Aider detects if it is running inside VSCode and turns off pretty/color output,
since the VSCode terminal doesn't seem to support it well.
You can run aider inside a VS Code terminal window.
There are a number of 3rd party
[aider plugins for VSCode](https://marketplace.visualstudio.com/search?term=aider%20-kodu&target=VSCode&category=All%20categories&sortBy=Relevance).
### Other editors
@@ -85,15 +108,8 @@ please let me know by opening a
## Install the development version of aider
If you want the very latest development version of aider
you can install directly from GitHub:
you can install it like this:
```
python -m pip install --upgrade git+https://github.com/Aider-AI/aider.git
aider --install-main-branch
```
If you've git cloned the aider repository already, you can install "live" from your local copy. This is mostly useful if you are developing aider and want your current modifications to take effect immediately.
```
python -m pip install -e .
```

View File

@@ -1,33 +0,0 @@
---
parent: Installation
nav_order: 100
---
# Install with pipx
If you are using aider to work on a python project, sometimes your project will require
specific versions of python packages which conflict with the versions that aider
requires.
If this happens, the `python -m pip install` command may return errors like these:
```
aider-chat 0.23.0 requires somepackage==X.Y.Z, but you have somepackage U.W.V which is incompatible.
```
You can avoid this problem by installing aider using `pipx`,
which will install it globally on your system
within its own python environment.
This way you can use aider to work on any python project,
even if that project has conflicting dependencies.
Install [pipx](https://pipx.pypa.io/stable/) then just do:
```
pipx install aider-chat
```
## pipx on replit
{% include replit-pipx.md %}

View File

@@ -0,0 +1,8 @@
---
parent: Installation
nav_order: 900
---
### Replit
{% include replit-pipx.md %}

View File

@@ -58,6 +58,7 @@ The model also has to successfully apply all its changes to the source file with
</table>
<canvas id="editChart" width="800" height="450" style="margin-top: 20px"></canvas>
<script src="https://unpkg.com/patternomaly/dist/patternomaly.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
{% include edit-leaderboard.js %}
@@ -113,6 +114,7 @@ Therefore, results are available for fewer models.
</table>
<canvas id="refacChart" width="800" height="450" style="margin-top: 20px"></canvas>
<script src="https://unpkg.com/patternomaly/dist/patternomaly.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
{% include refactor-leaderboard.js %}
@@ -181,6 +183,6 @@ mod_dates = [get_last_modified_date(file) for file in files]
latest_mod_date = max(mod_dates)
cog.out(f"{latest_mod_date.strftime('%B %d, %Y.')}")
]]]-->
December 04, 2024.
December 11, 2024.
<!--[[[end]]]-->
</p>

View File

@@ -69,7 +69,7 @@ We make reasonable efforts to protect your information by using physical and ele
### Childrens Privacy
We do not knowingly collect, maintain, or use personal information from children under 18 years of age, and no part of our Service(s) is directed to children. If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at [INSERT EMAIL ADDRESS].
We do not knowingly collect, maintain, or use personal information from children under 18 years of age, and no part of our Service(s) is directed to children. If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at privacy@aider.chat.
### International Visitors
@@ -98,7 +98,7 @@ if result.returncode == 0:
date = datetime.datetime.fromtimestamp(timestamp)
cog.out(f"{date.strftime('%B %d, %Y.')}")
]]]-->
October 31, 2024.
December 06, 2024.
<!--[[[end]]]-->
</p>

View File

@@ -50,7 +50,7 @@ pip install boto3
To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dependency to aider's virtual environment by running
```bash
pipx inject aider boto3
pipx inject aider-chat boto3
```

View File

@@ -5,15 +5,17 @@ nav_order: 300
# Gemini
Google currently offers
[*free* API access to the Gemini 1.5 Pro model](https://ai.google.dev/pricing).
This is the most capable free model to use with aider,
with code editing capability that's comparable to GPT-3.5.
You'll need a [Gemini API key](https://aistudio.google.com/app/u/2/apikey).
```
python -m pip install -U aider-chat
# You may need to install google-generativeai
pip install -U google-generativeai
# Or with pipx...
pipx inject aider-chat google-generativeai
export GEMINI_API_KEY=<key> # Mac/Linux
setx GEMINI_API_KEY <key> # Windows, restart shell after setx

View File

@@ -14,12 +14,11 @@ You may see an error message like this:
> aider: The term 'aider' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Below is the most fail safe way to install and run aider in these situations:
Below is the most fail safe way to run aider in these situations:
```
python -m pip install -U aider-chat
python -m aider
```
{% include venv-pipx.md %}
You should also consider
[installing aider using aider-install, uv or pipx](/docs/install.html).

View File

@@ -5,7 +5,7 @@ nav_order: 28
# Dependency versions
Aider expects to be installed via `pip` or `pipx`, which will install
Aider expects to be installed with the
correct versions of all of its required dependencies.
If you've been linked to this doc from a GitHub issue,
@@ -13,43 +13,38 @@ or if aider is reporting `ImportErrors`
it is likely that your
aider install is using incorrect dependencies.
## Install with pipx
## Avoid package conflicts
If you are using aider to work on a python project, sometimes your project will require
specific versions of python packages which conflict with the versions that aider
requires.
If this happens, you may see errors like these when running pip installs:
```
aider-chat 0.23.0 requires somepackage==X.Y.Z, but you have somepackage U.W.V which is incompatible.
```
## Install with aider-install, uv or pipx
If you are having dependency problems you should consider
[installing aider using pipx](/docs/install/pipx.html).
[installing aider using aider-install, uv or pipx](/docs/install.html).
This will ensure that aider is installed in its own python environment,
with the correct set of dependencies.
Try re-installing cleanly:
```
pipx uninstall aider-chat
pipx install aider-chat
```
## Package managers like Homebrew, AUR, ports
Package managers often install aider with the wrong dependencies, leading
to import errors and other problems.
The recommended way to
install aider is with
[pip](/docs/install/install.html).
Be sure to use the `--upgrade-strategy only-if-needed` switch so that the correct
versions of dependencies will be installed.
It is recommended to
[install aider using aider-install, uv or pipx](/docs/install.html).
```
python -m pip install -U --upgrade-strategy only-if-needed aider-chat
```
A very safe way is to
[install aider using pipx](/docs/install/pipx.html),
which will ensure it is installed in a stand alone virtual environment.
## Dependency versions matter
Aider pins its dependencies and is tested to work with those specific versions.
If you are installing aider with pip (rather than pipx),
If you are installing aider directly with pip
you should be careful about upgrading or downgrading the python packages that
aider uses.
@@ -64,9 +59,4 @@ and sometimes introduces bugs or backwards incompatible changes.
## Replit
You can `pip install -U aider-chat` on replit.
Or you can install aider with
pipx as follows:
{% include replit-pipx.md %}

View File

@@ -29,6 +29,7 @@ cog.out(get_help_md())
| **/code** | Ask for changes to your code |
| **/commit** | Commit edits to the repo made outside the chat (commit message optional) |
| **/copy** | Copy the last assistant message to the clipboard |
| **/copy-context** | Copy the current chat context as markdown, suitable to paste into a web UI |
| **/diff** | Display the diff of changes since the last message |
| **/drop** | Remove files from the chat session to free up context space |
| **/editor** | Open an editor to write a prompt |
@@ -42,9 +43,10 @@ cog.out(get_help_md())
| **/map-refresh** | Force a refresh of the repository map |
| **/model** | Switch to a new LLM |
| **/models** | Search the list of available models |
| **/multiline-mode** | Toggle multiline mode (swaps behavior of Enter and Meta+Enter) |
| **/paste** | Paste image/text from the clipboard into the chat. Optionally provide a name for the image. |
| **/quit** | Exit the application |
| **/read-only** | Add files to the chat that are for reference, not to be edited |
| **/read-only** | Add files to the chat that are for reference only, or turn added files to read-only |
| **/report** | Report a problem by opening a GitHub Issue |
| **/reset** | Drop all files and clear the chat history |
| **/run** | Run a shell command and optionally add the output to the chat (alias: !) |

View File

@@ -28,6 +28,11 @@ or `aider --read CONVENTIONS.md`.
This way it is marked as read-only, and cached if prompt caching
is enabled.
## Community contributed conventions
You can check the [aider conventions repository](https://github.com/Aider-AI/conventions)
to find or contribute conventions files.
## Always load conventions
You can also configure aider to always load your conventions file

View File

@@ -0,0 +1,121 @@
---
title: Copy/paste with web chat
#highlight_image: /assets/browser.jpg
parent: Usage
nav_order: 850
description: Aider works with LLM web chat UIs
---
# Copy/paste with web chat
<div class="video-container">
<video controls loop poster="/assets/copypaste.jpg">
<source src="/assets/copypaste.mp4" type="video/mp4">
<a href="/assets/copypaste.mp4">Aider browser UI demo video</a>
</video>
</div>
<style>
.video-container {
position: relative;
padding-bottom: 66.34%; /* 2160 / 3256 = 0.6634 */
height: 0;
overflow: hidden;
}
.video-container video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
## Working with an LLM web chat
[Aider can connect to most LLMs via API](https://aider.chat/docs/llms.html) and works best that way.
But there are times when you may want to work with an LLM via its web chat interface:
- Workplace policies may limit your LLM usage to a proprietary web chat system.
- The web chat LLM may have access to unique context or may have been specially fine tuned for your task.
- It may be cost prohibitive to use some models via API.
- There may not be an API available.
Aider has features for working with an LLM via its web chat interface.
This allows you to use the web chat LLM as the "big brain code architect"
while running aider with a smaller, cheaper LLM to actually make changes
to your local files.
For this "file editor" part of the process
you can run aider with many open source, free or very inexpensive LLMs.
For example, the demo video above shows aider using DeepSeek to apply the changes
that o1-preview is suggesting in the web chat.
### Copy aider's code context to your clipboard, paste into the web UI
The `/copy-context <instructions>` command can be used in chat to copy aider's code context to your clipboard.
It will include:
- All the files which have been added to the chat via `/add`.
- Any read only files which have been added via `/read`.
- Aider's [repository map](https://aider.chat/docs/repomap.html) that brings in code context related to the above files from elsewhere in your git repo.
- Some instructions to the LLM that ask it to output change instructions concisely.
- If you include `<instructions>`, they will be copied too.
You can paste the context into your browser, and start interacting with the LLM web chat to
ask for code changes.
### Paste the LLM's reply back into aider to edit your files
Once the LLM has replied, you can use the "copy response" button in the web UI to copy
the LLM's response.
Back in aider, you can run `/paste` and aider will edit your files
to implement the changes suggested by the LLM.
You can use a cheap, efficient model like GPT-4o Mini, DeepSeek or Qwen to do these edits.
This works best if you run aider with `--edit-format editor-diff` or `--edit-format editor-whole`.
### Copy/paste mode
Aider has a `--copy-paste` mode that streamlines this entire process:
- Whenever you `/add` or `/read` files, aider will automatically copy the entire, updated
code context to your clipboard.
You'll see "Copied code context to clipboard" whenever this happens.
- When you copy the LLM reply to your clipboard outside aider, aider will automatically notice
and load it into the aider chat.
Just press ENTER to send the message
and aider will apply the LLMs changes to your local files.
- Aider will automatically select the best edit format for this copy/paste functionality.
Depending on the LLM you have aider use, it will be either `editor-whole` or `editor-diff`.
## Terms of service
Be sure to review the Terms Of Service of any LLM web chat service you use with
these features.
These features are not intended to be used in violation of any service's Terms Of Service (TOS).
Aider's web chat features have been designed to be compliant with the
terms of service of most LLM web chats.
There are 4 copy/paste steps involved when coding with an LLM web chat:
1. Copy code and context from aider.
2. Paste the code and context into the LLM web chat.
3. Copy the reply from the LLM web chat.
4. Paste the LLM reply into aider.
Most LLM web chat TOS prohibit automating steps (2) and (3) where code
is copied from and pasted into the web chat.
Aider's `--copy-paste` mode leaves those as 100% manual steps for the user to complete.
It simply streamlines steps (1) and (4) that are interactions with aider,
and which should not be under the scope of an LLM web chat TOS.
If you are concerned that
the automatic interactions with aider in steps (1) and (4) may be problematic with respect to
your LLM web chat provider's TOS, you can forego `--copy-paste` mode.
Instead, manually use the `/copy-context` and `/paste` commands if that
will keep you in compliance.
Again, do not use these features in violation of any service's Terms Of Service.

View File

@@ -18,7 +18,7 @@ description: Aider can run in your browser, not just on the command line.
<style>
.video-container {
position: relative;
padding-bottom: 101.89%; /* 1080 / 1060 = 1.0189 */
padding-bottom: 102.7%; /1.027 */
height: 0;
overflow: hidden;
}
@@ -37,21 +37,29 @@ description: Aider can run in your browser, not just on the command line.
If you run aider with `--watch-files`, it will watch all files in your repo
and look for any AI coding instructions you add using your favorite IDE or text editor.
Specifically, aider looks for one-liner comments (# ... or // ...) that either start or end with `AI` or `AI!`, like these:
Specifically, aider looks for one-liner comments (# ... or // ...) that either start or end with `AI`, `AI!` or `AI?` like these:
```python
# Implement a snake game. AI!
# Make a snake game. AI!
# What is the purpose of this method AI?
```
Or in `//` comment languages...
```js
// Write a self-learning protein folding prediction engine. AI!
// Write a protein folding prediction engine. AI!
```
Aider will take note of all the comments that start or end with `AI`, but
a comment that includes `AI!` with an exclamation point is special.
That triggers aider to take action to collect *all* the AI comments and use them as instructions to make code changes.
Aider will take note of all the comments that start or end with `AI`.
Comments that include `AI!` with an exclamation point or `AI?` with a question
mark are special.
They triggers aider to take action to collect *all* the AI comments and use them
as your instructions.
- `AI!` triggers aider to make changes to your code.
- `AI?` triggers aider to answer your question.
See the demo video above that shows aider working with AI comments in VSCode.
## Example
@@ -74,8 +82,19 @@ function factorial(n) {
}
```
## Comment styles
Also see the demo video above that shows aider working with AI comments in VSCode.
Aider only watches for these types of **one-liner** comments:
```
# Python and bash style
// Javascript style
-- SQL style
```
Aider will look for those comment types in all files.
You can use them into any code file you're editing, even if they aren't the
correct comment syntax for that language.
## Multiple uses
@@ -99,7 +118,7 @@ app.get('/sqrt/:n', (req, res) => {
### Multiple comments
You can drop multiple `AI` comments without the `!`,
You can add multiple `AI` comments without the `!`,
before triggering aider with a final `AI!`.
Also keep in mind that you can spread the AI comments across
multiple files, if you want to coordinate changes in multiple places.
@@ -146,12 +165,33 @@ simply put an `#AI` comment in it and save the file.
You can undo/remove the comment immediately if you like, the file
will still be added to the aider chat.
## Also use aider chat in the terminal
### You can be lazy
It can be really helpful to get a change started with AI comments.
But sometimes you want to build on or refine those changes.
You can of course continue to do that with AI comments,
but it can sometimes be effective to switch over to the aider terminal chat.
The chat has the history of the AI comments you just made,
so you can continue on naturally from there.
The comments in the examples above all show AI
You can also use the normal aider chat in your terminal to work with
many of aider's more advanced features:
- Use `/undo` to revert changes you don't like. Although you may also be able to use your IDE's undo function to step back in the file history.
- Use [chat modes](https://aider.chat/docs/usage/modes.html) to ask questions or get help.
- Manage the chat context with `/tokens`, `/clear`, `/drop`, `/reset`.
Adding an AI comment will add the file to the chat.
Periodically, you may want remove extra context that is no longer needed.
- [Fix lint and test errors](https://aider.chat/docs/usage/lint-test.html).
- Run shell commands.
- Etc.
## You can be lazy
The examples above all show AI
comments with full sentences, proper capitalization, punctuation, etc.
This was done for clarity, but is not needed in practice.
This was done to help explain how AI comments work, but is not needed in practice.
Most LLMs are perfectly capable of dealing with ambiguity and
inferring implied intent.
@@ -211,3 +251,45 @@ def factorial(n):
As you use aider with your chosen LLM, you can develop a sense for how
explicit you need to make your AI comments.
## Behind the scenes
Aider sends your AI comments to the LLM with the
[repo map](https://aider.chat/docs/repomap.html)
and all the other code context you've added to the chat.
It also pulls out and highlights the AI comments with specific context, showing the LLM
exactly how they fit into the code base.
```
The "AI" comments below marked with █ can be found in the code files I've shared with you.
They contain your instructions.
Make the requested changes.
Be sure to remove all these "AI" comments from the code!
todo_app.py:
⋮...
│class TodoList:
⋮...
│ def __init__(self):
│ """Initialize an empty todo list"""
⋮...
│ def list_tasks(self):
│ """Display all tasks"""
█ # Implement this. AI!
│def main():
│ todo = TodoList()
⋮...
```
--------
#### Credits
*This feature was inspired by
the way [Override](https://github.com/oi-overide) watches for file changes
to find prompts embedded within `//> a specific set of delimiters <//`.*

View File

@@ -70,28 +70,27 @@ Aider works best with GPT-4o & Claude 3.5 Sonnet and can
cog.out(open("aider/website/_includes/get-started.md").read())
-->
You can get started quickly like this:
You can get started quickly like this, with python 3.8-3.13:
```
python -m pip install -U aider-chat
```bash
python -m pip install aider-install
aider-install
# Change directory into a git repo
# Change directory into your code base
cd /to/your/git/repo
# Work with Claude 3.5 Sonnet on your repo
export ANTHROPIC_API_KEY=your-key-goes-here
aider
aider --model sonnet --anthropic-api-key your-key-goes-here
# Work with GPT-4o on your repo
export OPENAI_API_KEY=your-key-goes-here
aider
aider --model gpt-4o --openai-api-key your-key-goes-here
```
<!-- NOOP -->
See the
[installation instructions](https://aider.chat/docs/install.html)
and other
[documentation](https://aider.chat/docs/usage.html)
and
[usage documentation](https://aider.chat/docs/usage.html)
for more details.
## Features

View File

@@ -24,8 +24,8 @@ from dotenv import load_dotenv
from plots import plot_refactoring
from rich.console import Console
from aider import models
from aider.coders import Coder
from aider import models, sendchat
from aider.coders import Coder, base_coder
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
@@ -158,6 +158,9 @@ def main(
dirnames: Optional[List[str]] = typer.Argument(None, help="Directory names"),
graphs: bool = typer.Option(False, "--graphs", help="Generate graphs"),
model: str = typer.Option("gpt-3.5-turbo", "--model", "-m", help="Model name"),
sleep: float = typer.Option(
0, "--sleep", help="Sleep seconds between tests when single threaded"
),
edit_format: str = typer.Option(None, "--edit-format", "-e", help="Edit format"),
editor_model: str = typer.Option(None, "--editor-model", help="Editor model name"),
editor_edit_format: str = typer.Option(None, "--editor-edit-format", help="Editor edit format"),
@@ -267,6 +270,11 @@ def main(
if num_tests > 0:
test_dnames = test_dnames[:num_tests]
# Don't give up when benchmarking
LONG_TIMEOUT = 24 * 60 * 60
sendchat.RETRY_TIMEOUT = LONG_TIMEOUT
base_coder.RETRY_TIMEOUT = LONG_TIMEOUT
if threads == 1:
all_results = []
for testname in test_dnames:
@@ -285,10 +293,13 @@ def main(
editor_model,
editor_edit_format,
num_ctx,
sleep,
)
all_results.append(results)
summarize_results(dirname)
if sleep:
time.sleep(sleep)
else:
run_test_threaded = lox.thread(threads)(run_test)
for testname in test_dnames:
@@ -565,6 +576,7 @@ def run_test_real(
editor_model,
editor_edit_format,
num_ctx=None,
sleep=0,
):
if not os.path.isdir(testdir):
print("Not a dir:", testdir)

View File

@@ -1,7 +1,3 @@
# [[[cog
# from aider.help_pats import exclude_website_pats
# ]]]
# [[[end]]]
[project]
name = "aider-chat"
@@ -38,29 +34,11 @@ help = { file = "requirements/requirements-help.txt" }
browser = { file = "requirements/requirements-browser.txt" }
playwright = { file = "requirements/requirements-playwright.txt" }
[tool.setuptools]
include-package-data = true
[tool.setuptools.packages.find]
include = ["aider*", "aider.website"]
[tool.setuptools.package-data]
"aider" = ["queries/*.scm"]
"aider.website" = ["**/*.md"]
[tool.setuptools.exclude-package-data]
"aider.website" = [
# [[[cog
# cog.out("\n".join(f' "{pat}",' for pat in exclude_website_pats))
# ]]]
"examples/**",
"_posts/**",
"HISTORY.md",
"docs/benchmarks*md",
"docs/ctags.md",
"docs/unified-diffs.md",
"docs/leaderboards/index.md",
"assets/**",
"**/.DS_Store",
# [[[end]]]
]
include = ["aider"]
[build-system]
requires = ["setuptools>=68", "setuptools_scm[toml]>=8"]

View File

@@ -2,17 +2,17 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --output-file=requirements.txt requirements/requirements.in
# pip-compile --allow-unsafe --output-file=requirements.txt requirements/requirements.in
#
aiohappyeyeballs==2.4.4
# via aiohttp
aiohttp==3.11.9
aiohttp==3.11.10
# via litellm
aiosignal==1.3.1
# via aiohttp
annotated-types==0.7.0
# via pydantic
anyio==4.6.2.post1
anyio==4.7.0
# via
# httpx
# openai
@@ -73,7 +73,7 @@ httpx==0.27.2
# via
# litellm
# openai
huggingface-hub==0.26.3
huggingface-hub==0.26.5
# via tokenizers
idna==3.10
# via
@@ -99,7 +99,7 @@ jsonschema==4.23.0
# litellm
jsonschema-specifications==2024.10.1
# via jsonschema
litellm==1.53.5
litellm==1.53.9
# via -r requirements/requirements.in
markdown-it-py==3.0.0
# via rich
@@ -123,7 +123,7 @@ numpy==1.26.4
# via
# -r requirements/requirements.in
# scipy
openai==1.56.2
openai==1.57.0
# via litellm
packaging==24.2
# via
@@ -234,6 +234,7 @@ tree-sitter-languages==1.10.2
# via grep-ast
typing-extensions==4.12.2
# via
# anyio
# huggingface-hub
# openai
# pydantic
@@ -250,3 +251,7 @@ yarl==1.18.3
# via aiohttp
zipp==3.21.0
# via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
pip==24.3.1
# via -r requirements/requirements.in

View File

@@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
# pip-compile --allow-unsafe --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
#
altair==5.5.0
# via streamlit
@@ -92,7 +92,7 @@ mdurl==0.1.2
# -c requirements.txt
# -c requirements/requirements-dev.txt
# markdown-it-py
narwhals==1.15.2
narwhals==1.16.0
# via altair
numpy==1.26.4
# via

View File

@@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --constraint=requirements.txt --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in
# pip-compile --allow-unsafe --constraint=requirements.txt --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in
#
alabaster==1.0.0
# via sphinx
@@ -51,7 +51,7 @@ filelock==3.16.1
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# virtualenv
fonttools==4.55.1
fonttools==4.55.2
# via matplotlib
identify==2.6.3
# via pre-commit
@@ -224,5 +224,10 @@ wheel==0.45.1
# via pip-tools
# The following packages are considered to be unsafe in a requirements file:
# pip
# setuptools
pip==24.3.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# pip-tools
setuptools==75.6.0
# via pip-tools

View File

@@ -2,14 +2,14 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --output-file=requirements/requirements-help.txt requirements/requirements-help.in
# pip-compile --allow-unsafe --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --output-file=requirements/requirements-help.txt requirements/requirements-help.in
#
aiohappyeyeballs==2.4.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# aiohttp
aiohttp==3.11.9
aiohttp==3.11.10
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -25,7 +25,7 @@ annotated-types==0.7.0
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# pydantic
anyio==4.6.2.post1
anyio==4.7.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -103,7 +103,7 @@ httpx==0.27.2
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# llama-index-core
huggingface-hub[inference]==0.26.3
huggingface-hub[inference]==0.26.5
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -284,6 +284,7 @@ typing-extensions==4.12.2
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/requirements-dev.txt
# anyio
# huggingface-hub
# llama-index-core
# pydantic

View File

@@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-browser.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-playwright.txt requirements/requirements-playwright.in
# pip-compile --allow-unsafe --constraint=requirements.txt --constraint=requirements/requirements-browser.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-playwright.txt requirements/requirements-playwright.in
#
greenlet==3.0.3
# via

View File

@@ -29,6 +29,7 @@ pexpect
json5
psutil
watchfiles
pip
# The proper dependency is networkx[default], but this brings
# in matplotlib and a bunch of other deps

0
scripts/__init__.py Normal file
View File

View File

@@ -12,6 +12,12 @@ import semver
import yaml
from tqdm import tqdm
website_files = [
"aider/website/share/index.md",
"aider/website/_includes/head_custom.html",
"aider/website/docs/leaderboards/index.md",
]
def blame(start_tag, end_tag=None):
commits = get_all_commit_hashes_between_tags(start_tag, end_tag)
@@ -26,10 +32,10 @@ def blame(start_tag, end_tag=None):
for f in files
if f.endswith((".js", ".py", ".scm", ".sh", "Dockerfile", "Gemfile"))
or (f.startswith(".github/workflows/") and f.endswith(".yml"))
or f == "aider/website/share/index.md"
or f == "aider/website/docs/leaderboards/index.md"
or f in website_files
]
files = [f for f in files if not f.endswith("prompts.py")]
files = [f for f in files if not f.startswith("tests/fixtures/watch")]
all_file_counts = {}
grand_total = defaultdict(int)
@@ -203,9 +209,23 @@ def main():
def get_counts_for_file(start_tag, end_tag, authors, fname):
try:
if end_tag:
text = run(["git", "blame", f"{start_tag}..{end_tag}", "--", fname])
text = run(
[
"git",
"blame",
"-M",
"-C",
"-C",
"--abbrev=9",
f"{start_tag}..{end_tag}",
"--",
fname,
]
)
else:
text = run(["git", "blame", f"{start_tag}..HEAD", "--", fname])
text = run(
["git", "blame", "-M", "-C", "-C", "--abbrev=9", f"{start_tag}..HEAD", "--", fname]
)
if not text:
return None
text = text.splitlines()

View File

@@ -0,0 +1,16 @@
history_prompt = """
Update the history with changes shown in the diffs.
Describe actual user-facing changes, not every single commit that was made implementing them.
Only add new items not already listed.
Do NOT edit or update existing history entries.
Do NOT add duplicate entries for changes that have existing history entries.
End each bullet with a period.
Be sure to attribute changes to the proper .x version.
Changes in the .x-dev version should be listed under a "### main branch" heading
Also, add this as the last bullet under the "### main branch" section:
{aider_line}
""" # noqa

View File

@@ -46,6 +46,20 @@ CLOSE_STALE_COMMENT = (
+ BOT_SUFFIX
)
CLOSE_FIXED_ENHANCEMENT_COMMENT = (
"""I'm closing this enhancement request since it has been marked as 'fixed' for over """
"""3 weeks. The requested feature should now be available in recent versions of aider.\n\n"""
"""If you find that this enhancement is still needed, please feel free to reopen this """
"""issue or create a new one.""" + BOT_SUFFIX
)
CLOSE_FIXED_BUG_COMMENT = (
"""I'm closing this bug report since it has been marked as 'fixed' for over """
"""3 weeks. This issue should be resolved in recent versions of aider.\n\n"""
"""If you find that this bug is still present, please feel free to reopen this """
"""issue or create a new one with steps to reproduce.""" + BOT_SUFFIX
)
# GitHub API configuration
GITHUB_API_URL = "https://api.github.com"
REPO_OWNER = "Aider-AI"
@@ -306,6 +320,68 @@ def handle_stale_closing(all_issues, auto_yes):
print(f" Closed issue #{issue['number']}")
def handle_fixed_issues(all_issues, auto_yes):
print("\nChecking for fixed enhancement and bug issues to close...")
for issue in all_issues:
# Skip if not open or doesn't have fixed label
labels = [label["name"] for label in issue["labels"]]
if issue["state"] != "open" or "fixed" not in labels:
continue
# Check if it's an enhancement or bug
is_enhancement = "enhancement" in labels
is_bug = "bug" in labels
if not (is_enhancement or is_bug):
continue
# Find when the fixed label was added
timeline_url = (
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/timeline"
)
response = requests.get(timeline_url, headers=headers)
response.raise_for_status()
events = response.json()
# Find the most recent fixed label addition
fixed_events = [
event
for event in events
if event.get("event") == "labeled" and event.get("label", {}).get("name") == "fixed"
]
if not fixed_events:
continue
latest_fixed = datetime.strptime(fixed_events[-1]["created_at"], "%Y-%m-%dT%H:%M:%SZ")
days_fixed = (datetime.now() - latest_fixed).days
if days_fixed >= 21:
issue_type = "enhancement" if is_enhancement else "bug"
print(f"\nFixed {issue_type} ready for closing #{issue['number']}: {issue['title']}")
print(f" Has been marked fixed for {days_fixed} days")
if not auto_yes:
confirm = input("Close this issue? (y/n): ")
if confirm.lower() != "y":
print("Skipping this issue.")
continue
# Add closing comment
comment_url = (
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
)
comment = CLOSE_FIXED_ENHANCEMENT_COMMENT if is_enhancement else CLOSE_FIXED_BUG_COMMENT
response = requests.post(comment_url, headers=headers, json={"body": comment})
response.raise_for_status()
# Close the issue
url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}"
response = requests.patch(url, headers=headers, json={"state": "closed"})
response.raise_for_status()
print(f" Closed issue #{issue['number']}")
def handle_duplicate_issues(all_issues, auto_yes):
open_issues = [issue for issue in all_issues if issue["state"] == "open"]
grouped_open_issues = group_issues_by_subject(open_issues)
@@ -363,6 +439,7 @@ def main():
handle_stale_issues(all_issues, args.yes)
handle_stale_closing(all_issues, args.yes)
handle_duplicate_issues(all_issues, args.yes)
handle_fixed_issues(all_issues, args.yes)
if __name__ == "__main__":

95
scripts/my_models.py Executable file
View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python3
import json
from collections import defaultdict, deque
from pathlib import Path
def collect_model_stats(n_lines=1000):
"""Collect model usage statistics from the analytics file."""
analytics_path = Path.home() / ".aider" / "analytics.jsonl"
model_stats = defaultdict(int)
with open(analytics_path) as f:
lines = deque(f, n_lines)
for line in lines:
try:
event = json.loads(line)
if event["event"] == "message_send":
properties = event["properties"]
main_model = properties.get("main_model")
total_tokens = properties.get("total_tokens", 0)
if main_model:
model_stats[main_model] += total_tokens
except json.JSONDecodeError:
continue
return model_stats
def format_text_table(model_stats):
"""Format model statistics as a text table."""
total_tokens = sum(model_stats.values())
lines = []
lines.append("\nModel Token Usage Summary:")
lines.append("-" * 80)
lines.append(f"{'Model Name':<40} {'Total Tokens':>15} {'Percent':>10}")
lines.append("-" * 80)
for model, tokens in sorted(model_stats.items(), key=lambda x: x[1], reverse=True):
percentage = (tokens / total_tokens) * 100 if total_tokens > 0 else 0
lines.append(f"{model:<40} {tokens:>15,} {percentage:>9.1f}%")
lines.append("-" * 80)
lines.append(f"{'TOTAL':<40} {total_tokens:>15,} {100:>9.1f}%")
return "\n".join(lines)
def format_html_table(model_stats):
"""Format model statistics as an HTML table."""
total_tokens = sum(model_stats.values())
html = [
"<style>",
"table { border-collapse: collapse; width: 100%; }",
"th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }",
"th { background-color: #f2f2f2; }",
"tr:hover { background-color: #f5f5f5; }",
".right { text-align: right; }",
"</style>",
"<table>",
(
"<tr><th>Model Name</th><th class='right'>Total Tokens</th><th"
" class='right'>Percent</th></tr>"
),
]
for model, tokens in sorted(model_stats.items(), key=lambda x: x[1], reverse=True):
percentage = (tokens / total_tokens) * 100 if total_tokens > 0 else 0
html.append(
f"<tr><td>{model}</td>"
f"<td class='right'>{tokens:,}</td>"
f"<td class='right'>{percentage:.1f}%</td></tr>"
)
html.append("</table>")
# Add note about redacted models if any are present
if any("REDACTED" in model for model in model_stats.keys()):
html.extend(
[
"",
"{: .note :}",
"Some models show as REDACTED, because they are new or unpopular models.",
'Aider\'s analytics only records the names of "well known" LLMs.',
]
)
return "\n".join(html)
if __name__ == "__main__":
stats = collect_model_stats()
print(format_text_table(stats))

View File

@@ -5,6 +5,7 @@ set -e
# First compile the base requirements
pip-compile \
--allow-unsafe \
requirements/requirements.in \
--output-file=requirements.txt \
$1
@@ -15,6 +16,7 @@ CONSTRAINTS="--constraint=requirements.txt"
for SUFFIX in "${SUFFIXES[@]}"; do
pip-compile \
--allow-unsafe \
requirements/requirements-${SUFFIX}.in \
--output-file=requirements/requirements-${SUFFIX}.txt \
${CONSTRAINTS} \

View File

@@ -3,4 +3,6 @@
# exit when any command fails
set -e
./scripts/blame.py v0.1.0 --all --output aider/website/_data/blame.yml
# Use first argument as version if provided, otherwise default to v0.1.0
VERSION=${1:-v0.1.0}
./scripts/blame.py "$VERSION" --all --output aider/website/_data/blame.yml

View File

@@ -20,6 +20,7 @@ cog $ARG \
aider/website/HISTORY.md \
aider/website/docs/usage/commands.md \
aider/website/docs/languages.md \
aider/website/docs/faq.md \
aider/website/docs/config/dotenv.md \
aider/website/docs/config/options.md \
aider/website/docs/config/aider_conf.md \

View File

@@ -5,6 +5,8 @@ import re
import subprocess
import tempfile
from history_prompts import history_prompt
from aider import __version__
@@ -76,20 +78,7 @@ def main():
aider_line = blame_result.stdout.strip().split("\n")[-1] # Get last line with percentage
# Construct and run the aider command
message = f"""
Update the history with changes shown in the diffs.
Describe actual user-facing changes, not every single commit that was made implementing them.
Only add new items not already listed.
Do NOT edit or update existing history entries.
Do NOT add duplicate entries for changes that have existing history entries.
Be sure to attribute changes to the proper .x version.
Changes in the .x-dev version should be listed under a "### main branch" heading
Also, add this as the last bullet under the "### main branch" section:
{aider_line}
""" # noqa
message = history_prompt.format(aider_line=aider_line)
cmd = ["aider", hist_path, "--read", diff_path, "--msg", message, "--no-auto-commit"]
subprocess.run(cmd)

View File

@@ -10,15 +10,6 @@ import sys
from packaging import version
def check_cog_pyproject():
result = subprocess.run(["cog", "--check", "pyproject.toml"], capture_output=True, text=True)
if result.returncode != 0:
print("Error: cog --check pyproject.toml failed, updating.")
subprocess.run(["cog", "-r", "pyproject.toml"])
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description="Bump version")
parser.add_argument("new_version", help="New version in x.y.z format")
@@ -82,7 +73,6 @@ def main():
dry_run = args.dry_run
# Perform checks before proceeding
check_cog_pyproject()
check_branch()
check_working_directory_clean()
check_main_branch_up_to_date()

View File

@@ -1468,6 +1468,39 @@ class TestCommands(TestCase):
commands.cmd_drop("test_file.txt")
self.assertEqual(len(coder.abs_read_only_fnames), 0)
def test_cmd_read_only_bulk_conversion(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create and add some test files
test_files = ["test1.txt", "test2.txt", "test3.txt"]
for fname in test_files:
Path(fname).write_text(f"Content of {fname}")
commands.cmd_add(fname)
# Verify files are in editable mode
self.assertEqual(len(coder.abs_fnames), 3)
self.assertEqual(len(coder.abs_read_only_fnames), 0)
# Convert all files to read-only mode
commands.cmd_read_only("")
# Verify all files were moved to read-only
self.assertEqual(len(coder.abs_fnames), 0)
self.assertEqual(len(coder.abs_read_only_fnames), 3)
# Check specific files
for fname in test_files:
abs_path = Path(repo_dir) / fname
self.assertTrue(
any(
os.path.samefile(str(abs_path), ro_fname)
for ro_fname in coder.abs_read_only_fnames
)
)
def test_cmd_read_only_with_multiple_files(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=False)

View File

@@ -91,9 +91,9 @@ class TestChatSummary(TestCase):
# Check that both models were tried
self.assertEqual(mock_send.call_count, 2)
# Check that the calls were made with the correct model names
self.assertEqual(mock_send.call_args_list[0][0][0], "gpt-4")
self.assertEqual(mock_send.call_args_list[1][0][0], "gpt-3.5-turbo")
# Check that the calls were made with the correct models
self.assertEqual(mock_send.call_args_list[0][0][0], mock_model1)
self.assertEqual(mock_send.call_args_list[1][0][0], mock_model2)
# Check that we got a summary from the second model
self.assertEqual(

View File

@@ -220,6 +220,7 @@ class TestInputOutput(unittest.TestCase):
@patch("builtins.input", side_effect=["d"])
def test_confirm_ask_allow_never(self, mock_input):
"""Test the 'don't ask again' functionality in confirm_ask"""
io = InputOutput(pretty=False, fancy_input=False)
# First call: user selects "Don't ask again"
@@ -259,5 +260,24 @@ class TestInputOutput(unittest.TestCase):
self.assertNotIn(("Do you want to proceed?", None), io.never_prompts)
class TestInputOutputMultilineMode(unittest.TestCase):
def setUp(self):
self.io = InputOutput(fancy_input=True)
self.io.prompt_session = MagicMock()
def test_toggle_multiline_mode(self):
"""Test that toggling multiline mode works correctly"""
# Start in single-line mode
self.io.multiline_mode = False
# Toggle to multiline mode
self.io.toggle_multiline_mode()
self.assertTrue(self.io.multiline_mode)
# Toggle back to single-line mode
self.io.toggle_multiline_mode()
self.assertFalse(self.io.multiline_mode)
if __name__ == "__main__":
unittest.main()

View File

@@ -672,6 +672,59 @@ class TestMain(TestCase):
# Verify that environment variables from pytest.ini are properly set
self.assertEqual(os.environ.get("AIDER_ANALYTICS"), "false")
def test_set_env_single(self):
# Test setting a single environment variable
with GitTemporaryDirectory():
main(["--set-env", "TEST_VAR=test_value", "--exit", "--yes"])
self.assertEqual(os.environ.get("TEST_VAR"), "test_value")
def test_set_env_multiple(self):
# Test setting multiple environment variables
with GitTemporaryDirectory():
main(
[
"--set-env",
"TEST_VAR1=value1",
"--set-env",
"TEST_VAR2=value2",
"--exit",
"--yes",
]
)
self.assertEqual(os.environ.get("TEST_VAR1"), "value1")
self.assertEqual(os.environ.get("TEST_VAR2"), "value2")
def test_set_env_with_spaces(self):
# Test setting env var with spaces in value
with GitTemporaryDirectory():
main(["--set-env", "TEST_VAR=test value with spaces", "--exit", "--yes"])
self.assertEqual(os.environ.get("TEST_VAR"), "test value with spaces")
def test_set_env_invalid_format(self):
# Test invalid format handling
with GitTemporaryDirectory():
result = main(["--set-env", "INVALID_FORMAT", "--exit", "--yes"])
self.assertEqual(result, 1)
def test_api_key_single(self):
# Test setting a single API key
with GitTemporaryDirectory():
main(["--api-key", "anthropic=test-key", "--exit", "--yes"])
self.assertEqual(os.environ.get("ANTHROPIC_API_KEY"), "test-key")
def test_api_key_multiple(self):
# Test setting multiple API keys
with GitTemporaryDirectory():
main(["--api-key", "anthropic=key1", "--api-key", "openai=key2", "--exit", "--yes"])
self.assertEqual(os.environ.get("ANTHROPIC_API_KEY"), "key1")
self.assertEqual(os.environ.get("OPENAI_API_KEY"), "key2")
def test_api_key_invalid_format(self):
# Test invalid format handling
with GitTemporaryDirectory():
result = main(["--api-key", "INVALID_FORMAT", "--exit", "--yes"])
self.assertEqual(result, 1)
def test_invalid_edit_format(self):
with GitTemporaryDirectory():
with patch("aider.io.InputOutput.offer_url") as mock_offer_url:

View File

@@ -125,9 +125,9 @@ class TestRepo(unittest.TestCase):
# Check that simple_send_with_retries was called twice
self.assertEqual(mock_send.call_count, 2)
# Check that it was called with the correct model names
self.assertEqual(mock_send.call_args_list[0][0][0], model1.name)
self.assertEqual(mock_send.call_args_list[1][0][0], model2.name)
# Check that it was called with the correct models
self.assertEqual(mock_send.call_args_list[0][0][0], model1)
self.assertEqual(mock_send.call_args_list[1][0][0], model2)
# Check that the content of the messages is the same for both calls
self.assertEqual(mock_send.call_args_list[0][0][1], mock_send.call_args_list[1][0][1])

View File

@@ -3,6 +3,7 @@ from unittest.mock import MagicMock, patch
from aider.exceptions import LiteLLMExceptions
from aider.llm import litellm
from aider.models import Model
from aider.sendchat import send_completion, simple_send_with_retries
@@ -37,7 +38,7 @@ class TestSendChat(unittest.TestCase):
]
# Call the simple_send_with_retries method
simple_send_with_retries("model", ["message"])
simple_send_with_retries(Model(self.mock_model), self.mock_messages)
assert mock_print.call_count == 3
@patch("litellm.completion")
@@ -74,7 +75,7 @@ class TestSendChat(unittest.TestCase):
mock_completion.return_value.choices = None
# Should return None on AttributeError
result = simple_send_with_retries(self.mock_model, self.mock_messages)
result = simple_send_with_retries(Model(self.mock_model), self.mock_messages)
assert result is None
@patch("litellm.completion")
@@ -88,6 +89,7 @@ class TestSendChat(unittest.TestCase):
message="Invalid request", llm_provider="test_provider", model="test_model"
)
result = simple_send_with_retries(self.mock_model, self.mock_messages)
result = simple_send_with_retries(Model(self.mock_model), self.mock_messages)
assert result is None
# Should only print the error message
assert mock_print.call_count == 1

View File

@@ -4,6 +4,63 @@ from aider.io import InputOutput
from aider.watch import FileWatcher
def test_gitignore_patterns():
"""Test that gitignore patterns are properly loaded and matched"""
from pathlib import Path
from aider.watch import load_gitignores
# Create a temporary gitignore file with test patterns
tmp_gitignore = Path("test.gitignore")
tmp_gitignore.write_text("custom_pattern\n*.custom")
gitignores = [tmp_gitignore]
spec = load_gitignores(gitignores)
# Test built-in patterns
assert spec.match_file(".aider.conf")
assert spec.match_file(".git/config")
assert spec.match_file("file~") # Emacs/vim backup
assert spec.match_file("file.bak")
assert spec.match_file("file.swp")
assert spec.match_file("file.swo")
assert spec.match_file("#temp#") # Emacs auto-save
assert spec.match_file(".#lock") # Emacs lock
assert spec.match_file("temp.tmp")
assert spec.match_file("temp.temp")
assert spec.match_file("conflict.orig")
assert spec.match_file("script.pyc")
assert spec.match_file("__pycache__/module.pyc")
assert spec.match_file(".DS_Store")
assert spec.match_file("Thumbs.db")
assert spec.match_file(".idea/workspace.xml")
assert spec.match_file(".vscode/settings.json")
assert spec.match_file("project.sublime-workspace")
assert spec.match_file(".project")
assert spec.match_file(".settings/config.json")
assert spec.match_file("workspace.code-workspace")
assert spec.match_file(".env")
assert spec.match_file(".venv/bin/python")
assert spec.match_file("node_modules/package/index.js")
assert spec.match_file("vendor/lib/module.py")
assert spec.match_file("debug.log")
assert spec.match_file(".cache/files")
assert spec.match_file(".pytest_cache/v/cache")
assert spec.match_file("coverage/lcov.info")
# Test custom patterns from gitignore file
assert spec.match_file("custom_pattern")
assert spec.match_file("file.custom")
# Test non-matching patterns
assert not spec.match_file("regular_file.txt")
assert not spec.match_file("src/main.py")
assert not spec.match_file("docs/index.html")
# Cleanup
tmp_gitignore.unlink()
def test_ai_comment_pattern():
# Create minimal IO and Coder instances for testing
class MinimalCoder:
@@ -32,13 +89,27 @@ def test_ai_comment_pattern():
f"Expected {py_expected} unique AI comments in Python fixture, found"
f" {len(unique_py_comments)}"
)
assert py_has_bang, "Expected at least one bang (!) comment in Python fixture"
assert py_has_bang == "!", "Expected at least one bang (!) comment in Python fixture"
# Test JavaScript fixture
js_path = fixtures_dir / "watch.js"
js_lines, js_comments, js_has_bang = watcher.get_ai_comments(str(js_path))
js_expected = 14
js_expected = 16
assert (
len(js_lines) == js_expected
), f"Expected {js_expected} AI comments in JavaScript fixture, found {len(js_lines)}"
assert js_has_bang, "Expected at least one bang (!) comment in JavaScript fixture"
assert js_has_bang == "!", "Expected at least one bang (!) comment in JavaScript fixture"
# Test watch_question.js fixture
question_js_path = fixtures_dir / "watch_question.js"
question_js_lines, question_js_comments, question_js_has_bang = watcher.get_ai_comments(
str(question_js_path)
)
question_js_expected = 6
assert len(question_js_lines) == question_js_expected, (
f"Expected {question_js_expected} AI comments in watch_question.js fixture, found"
f" {len(question_js_lines)}"
)
assert (
question_js_has_bang == "?"
), "Expected at least one bang (!) comment in watch_question.js fixture"

View File

@@ -33,3 +33,6 @@ class Example {
return 1;
}
}
// trailing whitespace ai
// trailing whitespace ai!
// 15-16

11
tests/fixtures/watch_question.js vendored Normal file
View File

@@ -0,0 +1,11 @@
// Regular AI comment
//ai do 1 something
//AI make 2 this better
//ai! urgent 3 change needed
//AI! another 4 urgent one
// ai with 5 space
// with questions AI?
// this is not an ai comment
// aider is not an ai! comment