Compare commits

...

315 Commits

Author SHA1 Message Date
Paul Gauthier
50c17bd5e4 set version to 0.72.4.dev 2025-01-25 08:15:36 -08:00
Paul Gauthier
1882c43389 version bump to 0.72.3 2025-01-25 08:13:57 -08:00
Paul Gauthier
d7027887cc copy 2025-01-25 08:13:38 -08:00
Paul Gauthier
7d8c9df252 copy 2025-01-25 08:08:44 -08:00
Paul Gauthier
b276d48ecf copy 2025-01-24 18:36:01 -08:00
Paul Gauthier
0c13734f7a copy 2025-01-24 15:50:04 -08:00
Paul Gauthier (aider)
de788266eb style: Format test_sendchat.py with consistent newlines 2025-01-24 09:19:21 -08:00
Paul Gauthier (aider)
eb879a743e test: add tests for ensure_alternating_roles function 2025-01-24 09:19:16 -08:00
Paul Gauthier (aider)
231bceeabb style: Fix whitespace in docstring 2025-01-24 09:14:55 -08:00
Paul Gauthier (aider)
387b7602cf style: Break long lines to comply with flake8 E501 2025-01-24 09:14:51 -08:00
Paul Gauthier
d8c14c04e3 refactor: standardize string quotes and improve model name handling 2025-01-24 09:14:37 -08:00
paul-gauthier
33f981d8f1 Merge pull request #2982 from miradnanali/ensure-alternating-roles-for-deepseek-reasoner
Ensure alternating roles for deepseek-reasoner
2025-01-24 09:11:58 -08:00
Paul Gauthier
6188b89ff0 copy 2025-01-24 09:06:59 -08:00
Paul Gauthier
2d424e078e copy 2025-01-24 09:05:53 -08:00
Paul Gauthier
ee5d72301a copy 2025-01-24 08:47:25 -08:00
Paul Gauthier
ddb02adbb4 copy 2025-01-24 08:35:29 -08:00
Paul Gauthier
b6b05f79a1 copy 2025-01-24 08:32:41 -08:00
Paul Gauthier
4a438e4799 copy 2025-01-24 08:29:40 -08:00
Paul Gauthier
31dc69da42 copy 2025-01-24 08:26:29 -08:00
Paul Gauthier (aider)
35dfd13ddd feat: make chart legend visibility configurable via show_legend assign 2025-01-24 08:24:01 -08:00
Paul Gauthier (aider)
b4535bd29b feat: hide legend in leaderboard chart 2025-01-24 08:23:28 -08:00
Paul Gauthier
5a30ec1806 docs: Add comment to hide legend in leaderboard script 2025-01-24 08:23:26 -08:00
Paul Gauthier
d7bb80468b copy 2025-01-24 08:22:13 -08:00
Mir Adnan ALI
92f6d31f33 Updated patch to avoid KeyError on malformed dict 2025-01-24 05:25:21 -05:00
Mir Adnan ALI
421bc93765 Ensure alternating roles for deepseek-reasoner 2025-01-24 03:58:08 -05:00
Paul Gauthier (aider)
9d6a692054 feat: Show "?" when total cost is 0 in table 2025-01-23 15:31:42 -08:00
Paul Gauthier (aider)
278c7bfc53 fix: Correct currency formatting in table cells using Liquid filters 2025-01-23 15:29:20 -08:00
Paul Gauthier (aider)
ad23c0e03e feat: format total_cost as $x.xx in table display 2025-01-23 15:28:33 -08:00
Paul Gauthier (aider)
ca8274dbe8 feat: Add total_cost column to results table 2025-01-23 15:28:00 -08:00
Paul Gauthier
1234fbf5f4 feat: Add new blog post for January 23, 2025 2025-01-23 15:27:58 -08:00
Paul Gauthier
e64ed4c27f copy 2025-01-23 11:35:11 -08:00
Paul Gauthier (aider)
a4b7236289 refactor: preserve original case in model name matching 2025-01-23 11:34:16 -08:00
Paul Gauthier
16c4374f7a refactor: lowercase model names for fuzzy matching while preserving original case 2025-01-23 11:34:14 -08:00
Paul Gauthier
05a77c7406 copy 2025-01-22 15:32:25 -08:00
Paul Gauthier
fceead7cbe copy 2025-01-22 15:16:02 -08:00
Paul Gauthier
3d81bdd281 copy 2025-01-22 15:08:56 -08:00
Paul Gauthier
56ab8de968 copy 2025-01-22 15:07:58 -08:00
Paul Gauthier
30b150dbfc refactor: Simplify test assertions and remove redundant checks 2025-01-22 10:17:21 -08:00
Paul Gauthier (aider)
40ee3b1b45 style: Reorder imports in test_coder.py 2025-01-22 10:05:02 -08:00
Paul Gauthier (aider)
c79217dd75 fix: Add missing imports for FinishReasonLength and sanity_check_messages 2025-01-22 10:04:58 -08:00
Paul Gauthier (aider)
075d4d4210 test: add tests for message integrity after interrupts and token limits 2025-01-22 10:03:51 -08:00
Paul Gauthier
216b679e4b set version to 0.72.3.dev 2025-01-22 10:01:02 -08:00
Paul Gauthier
c5fe81f4e6 version bump to 0.72.2 2025-01-22 09:59:23 -08:00
Paul Gauthier
0c464d0220 copy 2025-01-22 09:55:18 -08:00
Paul Gauthier
02f28d12e3 fix: Correct condition for adding assistant reply in Coder class 2025-01-22 09:53:32 -08:00
Paul Gauthier
13d24278f2 feat: Add assistant reply for token limit exhaustion in base_coder 2025-01-22 09:30:05 -08:00
Paul Gauthier
42ef4352f4 refactor: Handle KeyboardInterrupt with user-assistant message pair and add env check for sanity_check_messages 2025-01-22 09:03:09 -08:00
Paul Gauthier
843720a671 copy 2025-01-20 17:44:36 -08:00
Paul Gauthier
0884dd88d6 docs: Update usage documentation for config & text files 2025-01-20 17:44:17 -08:00
Paul Gauthier (aider)
4262fa8637 docs: add Jekyll front matter to not-code.md 2025-01-20 17:39:05 -08:00
Paul Gauthier (aider)
29a2db6552 docs: add examples for editing non-code files with aider 2025-01-20 17:35:42 -08:00
Paul Gauthier
06fa0c17a4 docs: Add usage documentation for non-code interactions 2025-01-20 17:35:40 -08:00
Paul Gauthier
cfdca6a894 copy 2025-01-20 17:28:54 -08:00
Paul Gauthier
2873f6c193 copy 2025-01-20 14:25:36 -08:00
Paul Gauthier
8b963ed63c set version to 0.72.2.dev 2025-01-20 14:24:39 -08:00
Paul Gauthier
adb951426a version bump to 0.72.1 2025-01-20 14:23:06 -08:00
Paul Gauthier
9ced96a1c9 copy 2025-01-20 14:23:00 -08:00
Paul Gauthier
7e155dc87b copy 2025-01-20 14:21:05 -08:00
Paul Gauthier
c5e2d80fc0 blame 2025-01-20 14:20:56 -08:00
Paul Gauthier
b0fa646de9 fix litellm_provider 2025-01-20 14:19:30 -08:00
Paul Gauthier
83f08cffee copy 2025-01-20 11:51:32 -08:00
Paul Gauthier
03652a0030 set version to 0.72.1.dev 2025-01-20 11:51:13 -08:00
Paul Gauthier
1c3e0ba656 version bump to 0.72.0 2025-01-20 11:48:46 -08:00
Paul Gauthier
48f80b947b copy 2025-01-20 11:43:38 -08:00
Paul Gauthier
d7873de4e8 Merge branch 'main' of github.com:Aider-AI/aider 2025-01-20 11:42:04 -08:00
Paul Gauthier
32d025bcf2 r1 leaderboard 2025-01-20 11:37:09 -08:00
Paul Gauthier
61ab5d1652 disable sanity check 2025-01-20 11:35:54 -08:00
Paul Gauthier
f5fd6833e2 copy 2025-01-20 11:30:21 -08:00
Paul Gauthier
163e6f56df re-enable summaries 2025-01-20 11:26:19 -08:00
Paul Gauthier
5650697475 no turn errors, with upd_cur_msgs fix and summarizer disabled 2025-01-20 11:10:43 -08:00
Paul Gauthier
2968087d37 more deepseek config 2025-01-20 10:09:48 -08:00
Paul Gauthier
e7ec80f58a Merge branch 'main' into deepseek-reasoner 2025-01-20 09:50:35 -08:00
Paul Gauthier
f0ba699463 copy 2025-01-20 09:49:48 -08:00
Paul Gauthier
06d5b14b86 sanity_check_messages 2025-01-20 09:43:01 -08:00
Paul Gauthier
dff544cd5d refactor: Split summarize method and add model metadata handling 2025-01-20 09:38:45 -08:00
Paul Gauthier (aider)
73bc0f6258 style: Remove trailing whitespace in sendchat.py 2025-01-20 08:35:24 -08:00
Paul Gauthier (aider)
7e5e180000 feat: verify last non-system message is from user in sanity_check_messages 2025-01-20 08:35:21 -08:00
Paul Gauthier (aider)
fc431df2b4 style: Add blank lines for better readability in sendchat.py 2025-01-20 08:34:44 -08:00
Paul Gauthier (aider)
bb61be630a feat: add message role validation function 2025-01-20 08:34:40 -08:00
Paul Gauthier
cdc9ec2854 refactor: Add comment for sanity_check_messages function in sendchat.py 2025-01-20 08:34:38 -08:00
Paul Gauthier
21d3703b69 feat: Add deepseek-reasoner model settings and enable caching for deepseek-chat 2025-01-20 08:14:12 -08:00
paul-gauthier
c395be252e Merge pull request #2895 from pauldw/pwalker/2025-01-17_add_tags_scm_for_kotlin 2025-01-19 09:49:44 -08:00
Paul Walker
293c350fb7 Add tags.scm for Kotlin 2025-01-17 21:18:55 -05:00
Paul Gauthier
a777f336e1 chore: Update polyglot leaderboard test results and metadata 2025-01-17 13:37:02 -08:00
Paul Gauthier
5b6c186125 copy 2025-01-17 13:35:36 -08:00
Paul Gauthier
6451d59deb bump deps 2025-01-16 12:29:12 -08:00
Paul Gauthier (aider)
c912b66a8f ci: Update GitHub Actions workflow to use github.event_name for build conditions 2025-01-16 11:52:34 -08:00
Paul Gauthier (aider)
d62c43bc95 ci: Fix GitHub Actions workflow syntax for secret conditions 2025-01-16 11:51:10 -08:00
Paul Gauthier (aider)
3b7b9b6ed1 ci: Update Docker build workflow to use DockerHub secret conditions 2025-01-16 11:48:59 -08:00
Paul Gauthier (aider)
9822a6ed5d feat: Modify Docker workflow to separate PR and push build steps 2025-01-16 11:47:29 -08:00
Paul Gauthier
a06f4dfad6 copy 2025-01-16 10:30:14 -08:00
Paul Gauthier
b92df87400 publish 2025-01-16 09:03:09 -08:00
Paul Gauthier
d7921c0111 chore: Update GitHub Actions workflow with artifact path and deploy pages version 2025-01-16 09:01:01 -08:00
Paul Gauthier (aider)
af09c3e62a chore: Update artifact upload path in GitHub Pages workflow 2025-01-16 08:57:51 -08:00
Paul Gauthier (aider)
0ed42f657d feat: Add build output listing step to debug artifact upload 2025-01-16 08:54:57 -08:00
Paul Gauthier (aider)
ed7fbabd1c ci: Update pull_request workflow triggers with consistent path ignores 2025-01-16 08:51:24 -08:00
Paul Gauthier (aider)
bd03563fcb ci: Ignore workflow file changes except for self-modification 2025-01-16 08:50:53 -08:00
Paul Gauthier (aider)
05ffc7f8d6 feat: Add trigger for pages.yml workflow file changes 2025-01-16 08:38:38 -08:00
Paul Gauthier (aider)
ebc475d278 feat: Update GitHub Pages artifact upload path 2025-01-16 08:38:19 -08:00
Paul Gauthier
2813437515 chore: Update GitHub Actions upload-pages-artifact to v3 2025-01-16 08:35:13 -08:00
Paul Gauthier
ea2e885505 Revert "chore: Update upload-pages-artifact action to v4"
This reverts commit a7fadc3a45.
2025-01-16 08:32:46 -08:00
Paul Gauthier (aider)
a7fadc3a45 chore: Update upload-pages-artifact action to v4 2025-01-16 08:28:18 -08:00
Paul Gauthier
8040a20f71 add uv article 2025-01-16 08:25:02 -08:00
Paul Gauthier
0e87854819 copy 2025-01-16 08:24:47 -08:00
Paul Gauthier
3bc6c641de copy 2025-01-16 08:24:31 -08:00
Paul Gauthier
4abb6e17ba Merge branch 'main' of github.com:Aider-AI/aider 2025-01-16 08:24:21 -08:00
Paul Gauthier
1986f08cf9 ci: Conditionally push Docker images only on non-pull request events 2025-01-16 08:24:02 -08:00
paul-gauthier
620ae5cf1d Merge pull request #2877 from golergka/docs/file-editing-troubleshooting-architect-mode 2025-01-15 15:55:10 -08:00
Max Yankov (aider)
590ee5a248 docs: Add architect mode section to edit errors troubleshooting guide 2025-01-15 20:50:53 -03:00
Paul Gauthier
a08326ab60 enable all java tests 2025-01-15 15:18:46 -08:00
Paul Gauthier
63cf99361d ensure no loading of any other files 2025-01-15 13:57:54 -08:00
Paul Gauthier
1e54ca82b8 refactor: encapsulate rsync logic in function and add continuous sync loop 2025-01-13 15:47:49 -08:00
Paul Gauthier
2ec576e110 use examples_as_sys_msg=True for 4o models 2025-01-13 15:46:36 -08:00
Paul Gauthier
4251e976b3 copy 2025-01-13 14:28:34 -08:00
Paul Gauthier
d831e2f3a4 copy 2025-01-13 14:26:24 -08:00
Paul Gauthier
21f20417d6 copy 2025-01-13 11:39:22 -08:00
Paul Gauthier
e1c914d9bb chore: Update polyglot leaderboard with new test results for Codestral 25.01 2025-01-13 11:21:34 -08:00
Paul Gauthier
4b03b0a93a Merge branch 'main' of github.com:Aider-AI/aider 2025-01-13 11:18:31 -08:00
Paul Gauthier
bbcde55a9e copy 2025-01-13 10:18:34 -08:00
Paul Gauthier (aider)
0cba898280 fix: Make line endings validation test order-independent 2025-01-13 09:38:36 -08:00
Paul Gauthier (aider)
b9edec069a fix: Update test to match error message format for line endings validation 2025-01-13 09:38:13 -08:00
paul-gauthier
939cb7958a Merge pull request #2857 from titusz/improve-read-errors
refactor: Reorder exception handling in file reading method
2025-01-13 09:37:38 -08:00
Paul Gauthier (aider)
ebb38c6518 style: Format test_io.py to comply with linter rules 2025-01-13 09:36:31 -08:00
Paul Gauthier (aider)
fa80d2f3cc test: add line endings validation tests for InputOutput 2025-01-13 09:36:26 -08:00
Paul Gauthier (aider)
869f37cd89 style: Format code for better readability in io.py 2025-01-13 09:35:07 -08:00
Paul Gauthier (aider)
c22202585d fix: validate line_endings parameter in InputOutput initialization 2025-01-13 09:35:01 -08:00
Titusz Pan
f28c912d5a refactor: Reorder exception handling in file reading method 2025-01-13 18:29:04 +01:00
paul-gauthier
a0e56c5282 Merge pull request #2856 from titusz/configurable-line-endings
feat: Add line endings configuration option for file writing - fixes #1102
2025-01-13 09:26:57 -08:00
Paul Gauthier
de7da1e806 copy 2025-01-13 09:12:56 -08:00
Paul Gauthier
add2f6f669 copy 2025-01-13 09:00:21 -08:00
Paul Gauthier
b06e765e68 copy 2025-01-13 08:58:26 -08:00
Titusz Pan
c3952cb985 feat: Add line endings configuration option for file writing 2025-01-13 17:51:02 +01:00
Paul Gauthier
ac26fc6d5f set version to 0.71.2.dev 2025-01-11 16:07:56 -08:00
Paul Gauthier
122088712d version bump to 0.71.1 2025-01-11 16:06:25 -08:00
Paul Gauthier
9fb09ce14d copy 2025-01-11 16:04:53 -08:00
Paul Gauthier (aider)
392fb21946 fix: ensure integer indices for list slicing in repomap.py 2025-01-11 15:49:58 -08:00
Paul Gauthier (aider)
e94b05851f style: Format test_io.py with consistent string quotes and spacing 2025-01-11 15:48:10 -08:00
Paul Gauthier (aider)
571a5962b7 test: update test to use invalid Unicode that triggers encoding error 2025-01-11 15:48:05 -08:00
Paul Gauthier (aider)
8b6863dc40 style: Format test_io.py with consistent quotes and spacing 2025-01-11 15:46:33 -08:00
Paul Gauthier (aider)
01af629399 test: add test for Unicode to ASCII fallback in tool messages 2025-01-11 15:46:28 -08:00
Paul Gauthier (aider)
4ece6d2a9b fix: handle Text objects properly in io.py for Windows Unicode encoding 2025-01-11 15:40:24 -08:00
Paul Gauthier
18d1d7af33 no chown for COPY 2025-01-11 07:46:23 -08:00
Paul Gauthier
5ada250a66 refactor: Add period to read-only file message in base_coder.py 2025-01-11 07:39:29 -08:00
Paul Gauthier (aider)
308c7ab670 feat: Add read-only file announcements to chat 2025-01-11 07:27:50 -08:00
Paul Gauthier
89d35e020a refactor: Add comment for read-only file message in base_coder.py 2025-01-11 07:27:49 -08:00
Paul Gauthier (aider)
6729570799 refactor: Simplify docker-build-test.yml to mirror release workflow with dev tags 2025-01-11 07:16:02 -08:00
Paul Gauthier (aider)
f72f5f6438 ci: Add dev tag publishing to Docker build test workflow 2025-01-11 07:12:56 -08:00
Paul Gauthier
a02e11e0bc Revert "ci: Add Docker image tests with --yes --exit args"
This reverts commit fdddfc6b1f.
2025-01-11 07:06:08 -08:00
Paul Gauthier
9ff15e1506 copy 2025-01-11 06:53:44 -08:00
Paul Gauthier (aider)
fdddfc6b1f ci: Add Docker image tests with --yes --exit args 2025-01-11 06:52:29 -08:00
Paul Gauthier (aider)
78ebb6295d fix: Restore site-packages permissions in Dockerfile for appuser access 2025-01-11 06:48:26 -08:00
Paul Gauthier
73c89e8c00 copy 2025-01-10 15:53:17 -08:00
Paul Gauthier (aider)
fcc499e401 refactor: normalize deepseek model names to deepseek-chat 2025-01-10 15:51:53 -08:00
Paul Gauthier
6e8efe22aa refactor: Combine deepseek/deepseek-coder into chat AI in model stats 2025-01-10 15:51:52 -08:00
Paul Gauthier
f9c5cb73a2 copy 2025-01-10 15:08:15 -08:00
Paul Gauthier
c939521f5f copy 2025-01-10 15:04:54 -08:00
Paul Gauthier
2640e05307 set version to 0.71.1.dev 2025-01-10 15:01:41 -08:00
Paul Gauthier
c1a371e3d3 version bump to 0.71.0 2025-01-10 15:00:02 -08:00
Paul Gauthier
5a4871155a copy 2025-01-10 14:54:42 -08:00
Paul Gauthier (aider)
d8e6dbf788 docs: clarify dual purpose of /ask, /code, and /architect commands 2025-01-10 14:51:25 -08:00
Paul Gauthier
7ea69ae4b4 refactor: Simplify map_tokens assignment logic in main.py 2025-01-10 14:49:16 -08:00
Paul Gauthier
d238ead451 copy 2025-01-10 14:44:00 -08:00
Paul Gauthier (aider)
e6b449f24d test: add tests for get_repo_map_tokens method 2025-01-10 14:39:50 -08:00
Paul Gauthier (aider)
41018d05a8 fix: remove unused max_tokens variable in get_repo_map_tokens 2025-01-10 14:38:22 -08:00
Paul Gauthier
d48008e13d refactor: Update repo map token handling and improve warning message 2025-01-10 14:38:12 -08:00
Paul Gauthier
a9cf438100 refactor: Update terminal detection message to include pretty output 2025-01-10 14:26:06 -08:00
Paul Gauthier (aider)
6c7a0d21d2 style: Remove trailing whitespace in io.py 2025-01-10 14:25:04 -08:00
Paul Gauthier (aider)
d887db4c18 fix: disable pretty output for dumb terminals 2025-01-10 14:24:59 -08:00
Paul Gauthier (aider)
e6be69ec6d test: add test case for TERM=dumb terminal handling 2025-01-10 14:24:27 -08:00
Paul Gauthier
c1ba7db8a1 refactor: Update placeholder text in cmd_run for better clarity 2025-01-10 14:23:42 -08:00
Paul Gauthier
dc5b5896a9 copy 2025-01-10 14:20:50 -08:00
Paul Gauthier
38678fafc1 refactor: Simplify fence pattern matching in base_coder.py 2025-01-10 14:20:02 -08:00
Paul Gauthier
7611211d1c copy 2025-01-10 14:19:51 -08:00
Paul Gauthier
0d9c2cd902 copy 2025-01-10 14:09:22 -08:00
Paul Gauthier (aider)
1a84c109fc feat: allow /ask, /code, /architect without args to switch modes 2025-01-10 14:07:24 -08:00
Paul Gauthier (aider)
cbedf3f8cc fix: Correct typo in variable name from model_metatdata_files to model_metadata_files 2025-01-10 14:04:54 -08:00
Paul Gauthier
50436e3106 docs: Update model usage statistics and dumb terminal message 2025-01-10 14:04:41 -08:00
Paul Gauthier (aider)
62498ec867 style: Reorder imports and fix whitespace in aider/io.py 2025-01-10 14:03:57 -08:00
Paul Gauthier (aider)
91b94bb16c feat: add dumb terminal detection and fallback handling 2025-01-10 14:03:53 -08:00
Paul Gauthier
c2bbdc503c copy 2025-01-10 13:33:00 -08:00
Paul Gauthier
babae0fa6e refactor: conditionally set stream based on main_model.streaming 2025-01-10 13:31:55 -08:00
Paul Gauthier
f047882ac1 refactor: Add InvalidGitRepositoryError to ANY_GIT_ERROR list 2025-01-09 15:01:36 -08:00
Paul Gauthier
b818d6a921 copy 2025-01-09 12:07:00 -08:00
Paul Gauthier
ba631c8451 copy 2025-01-09 12:03:17 -08:00
Paul Gauthier
2c963b389c include author in history updates 2025-01-09 12:03:05 -08:00
Paul Gauthier
8437fbc314 cleanup 2025-01-09 12:02:48 -08:00
Paul Gauthier (aider)
76404004a4 feat: include author info in git log output for history updates 2025-01-09 11:57:23 -08:00
Paul Gauthier
1b64514c2c copy 2025-01-09 11:44:40 -08:00
Paul Gauthier
6efea7d365 Merge branch 'main' of github.com:Aider-AI/aider 2025-01-09 11:44:19 -08:00
Paul Gauthier (aider)
e1a3b77d67 feat: add rootless container support with dedicated appuser 2025-01-09 11:26:06 -08:00
Paul Gauthier
cfc7ad5627 copy 2025-01-09 09:56:49 -08:00
paul-gauthier
b3cbf14ad6 Merge pull request #2809 from hydai/fix_missing_link 2025-01-09 06:39:40 -08:00
hydai
51cfbe6b00 docs: fix missing link
Signed-off-by: hydai <z54981220@gmail.com>
2025-01-09 18:46:14 +08:00
paul-gauthier
155f397d0b Merge pull request #2798 from schpet/improve-watch-description 2025-01-07 15:02:52 -08:00
Peter Schilling
4b53b8b6a1 2025-01-07 14:00:49 -08:00
Peter Schilling (aider)
dbea4a1787 aider: feat: Update watch.md description for IDE usage 2025-01-07 13:57:39 -08:00
Peter Schilling
5b6da85e68 docs: Update watch.md documentation description and comments 2025-01-07 13:57:38 -08:00
Paul Gauthier
61671e9d3f cleanup 2025-01-07 10:49:21 -08:00
Paul Gauthier
f94e05e04e Merge branch 'main' of github.com:Aider-AI/aider 2025-01-07 10:04:17 -08:00
Paul Gauthier
b5cad9a8cc copy 2025-01-07 09:58:20 -08:00
paul-gauthier
3a97d8cc82 Merge pull request #2795 from nims11/fix-discard
Fix files not being excluded in benchmark.py
2025-01-07 09:57:35 -08:00
Paul Gauthier
3c099465da refactor: Add AssertionError to ANY_GIT_ERROR tuple 2025-01-07 09:50:28 -08:00
Paul Gauthier (aider)
fcdb2591b6 fix: check prompt session is active before interrupting input 2025-01-07 09:46:48 -08:00
Paul Gauthier
b67a16e9af fix: Add AttributeError to ANY_GIT_ERROR tuple 2025-01-07 09:45:53 -08:00
Paul Gauthier (aider)
1d672616be fix: correct file export path in voice format conversion 2025-01-07 09:43:49 -08:00
Nimesh Ghelani
ed9d70903d Fix files not being excluded in benchmark.py
`.discard()` removes an item from the set. `.difference_update()` is the
correct call here.
2025-01-07 17:35:29 +00:00
Paul Gauthier
8a9bab8a46 copy 2025-01-07 09:33:00 -08:00
Paul Gauthier
fdc6a08eb4 copy 2025-01-07 09:28:34 -08:00
Paul Gauthier
154309912d delay renedering md when it gets slow 2025-01-07 06:57:38 -08:00
Paul Gauthier
a84fea86b8 copy 2025-01-07 06:57:20 -08:00
Paul Gauthier (aider)
609998bc18 style: Format floating-point division in mdstream.py 2025-01-07 06:51:59 -08:00
Paul Gauthier (aider)
891868b061 perf: adjust min_delay based on markdown render time for smoother updates 2025-01-07 06:51:56 -08:00
Paul Gauthier
3fc5cf8b9f refactor: Replace hardcoded min_delay with 1./20 for 20fps in MarkdownStream 2025-01-07 06:51:54 -08:00
Paul Gauthier (aider)
6048ed5bc1 style: Remove trailing whitespace from Lorem Ipsum text lines 2025-01-07 06:44:35 -08:00
Paul Gauthier (aider)
a1a007134c style: Break long Lorem Ipsum text into multiple lines to comply with line length limit 2025-01-07 06:44:10 -08:00
Paul Gauthier
d82f9fa432 refactor: Multiply _text by 10 in mdstream.py for testing 2025-01-07 06:44:09 -08:00
Paul Gauthier (aider)
c0074301a3 style: Remove extra blank line in mdstream.py 2025-01-07 06:42:52 -08:00
Paul Gauthier (aider)
9c2c05ad44 refactor: read io.py source file in mdstream.py main block 2025-01-07 06:42:48 -08:00
Paul Gauthier
fad230c02e refactor: Split markdown text into prefix and suffix variables 2025-01-07 06:42:46 -08:00
Paul Gauthier (aider)
ad3c95f273 style: Fix whitespace and formatting in mdstream.py 2025-01-07 06:11:58 -08:00
Paul Gauthier (aider)
684fdb6095 refactor: extract markdown rendering logic into helper method 2025-01-07 06:11:54 -08:00
Paul Gauthier
8e64f171b8 refactor: improve markdown streaming with stable/unstable line handling 2025-01-07 06:11:52 -08:00
Paul Gauthier (aider)
d616c3fed7 style: Remove trailing whitespace in MarkdownStream class docstring 2025-01-07 05:58:45 -08:00
Paul Gauthier (aider)
e07e6cd2a3 docs: Format docstring to comply with line length limits 2025-01-07 05:58:41 -08:00
Paul Gauthier (aider)
f1bd5cdb52 style: Fix whitespace and formatting in MarkdownStream class 2025-01-07 05:57:39 -08:00
Paul Gauthier (aider)
be82b6bed9 docs: add comments to explain MarkdownStream class and methods 2025-01-07 05:57:35 -08:00
Paul Gauthier
37ad4758a1 refactor: Move fname_path assignment inside try block in GitRepo.ignored_file_raw 2025-01-04 12:36:07 -08:00
Paul Gauthier (aider)
e4a238a05c style: Format code with consistent string quotes and remove trailing whitespace 2025-01-04 12:27:11 -08:00
Paul Gauthier (aider)
e5ca922ce8 fix: handle empty paths and dotfiles in get_ident_filename_matches 2025-01-04 12:27:04 -08:00
Paul Gauthier
6a1f4431d0 docs: Update HISTORY.md and FAQ.md with latest changes and model usage stats 2025-01-04 12:22:45 -08:00
Paul Gauthier (aider)
d67eda24d2 style: Remove trailing whitespace and format confirm_ask prompt 2025-01-04 12:09:53 -08:00
Paul Gauthier (aider)
bba0cc8dc5 feat: show token count in command output confirmation prompt 2025-01-04 12:09:48 -08:00
Paul Gauthier
884b52b710 refactor: Add comment for tokenizing command output in Commands class 2025-01-04 12:09:45 -08:00
Paul Gauthier
01ef2351b3 refactor: Use temporary variable for audio format to avoid state mutation 2025-01-04 12:08:05 -08:00
Paul Gauthier
de1d566e9e refactor: Simplify audio file handling and conversion logic 2025-01-04 12:06:07 -08:00
Paul Gauthier (aider)
19114a61ae style: Format print statement in voice.py for better readability 2025-01-04 12:04:13 -08:00
Paul Gauthier (aider)
36e5599ead feat: Add file size logging after audio conversion 2025-01-04 12:04:09 -08:00
Paul Gauthier (aider)
f5a82e575c style: Format print statement in voice.py for better readability 2025-01-04 12:03:32 -08:00
Paul Gauthier (aider)
1851de323d feat: add error handling and feedback for audio conversion 2025-01-04 12:03:25 -08:00
Paul Gauthier
f9408640a3 refactor: Simplify audio file size check and format conversion logic 2025-01-04 12:03:24 -08:00
Paul Gauthier (aider)
73837730fa feat: Add file size check and mp3 conversion for large audio files 2025-01-04 11:59:42 -08:00
Paul Gauthier
9b46991721 refactor: Add comment for handling large file uploads in voice.py 2025-01-04 11:59:40 -08:00
Paul Gauthier
606cd0368f refactor: remove redundant exception handling in GitRepo 2025-01-04 11:09:55 -08:00
Paul Gauthier
d9ef23ad99 Merge branch 'main' of github.com:Aider-AI/aider 2025-01-04 11:09:25 -08:00
Paul Gauthier
48b8f54c12 refactor: Move message and style initialization before try block in InputOutput 2025-01-04 11:04:32 -08:00
Paul Gauthier (aider)
cec9f90c1c style: Standardize string quotes in InputOutput class 2025-01-04 11:03:43 -08:00
Paul Gauthier (aider)
44d36f140a fix: handle UnicodeEncodeError in console output with ASCII fallback 2025-01-04 11:03:38 -08:00
paul-gauthier
f88adcfa85 Merge pull request #2764 from caseymcc/repo_index
Ignore directories in repo that have index errors
2025-01-04 13:59:32 -05:00
Paul Gauthier (aider)
c5919f0c15 refactor: improve cleanup error handling and verbose logging 2025-01-04 10:55:11 -08:00
Paul Gauthier
ac160cac12 chore: Ignore exceptions during Rust target directory cleanup 2025-01-04 10:55:09 -08:00
Paul Gauthier
867aaa5864 copy 2025-01-04 06:36:22 -08:00
Paul Gauthier
0b26505a20 Merge branch 'main' of github.com:Aider-AI/aider 2025-01-04 06:33:49 -08:00
paul-gauthier
98ad513621 Merge pull request #2753 from aweis89/fix-linting-cmd
fix: lint command with nested spaced strings
2025-01-04 09:33:38 -05:00
Paul Gauthier
591edbb003 improve prompts so that switching between ask/code works better with deepseek 2025-01-04 06:28:20 -08:00
Paul Gauthier
a17b1c2ab7 Merge branch 'main' of github.com:Aider-AI/aider 2025-01-04 06:27:42 -08:00
Paul Gauthier
648f14d95b copy 2025-01-04 06:25:19 -08:00
Paul Gauthier (aider)
2e4c2422b1 feat: Add voice format and input device initialization in Commands 2025-01-04 06:21:19 -08:00
Paul Gauthier
463fdb1ed9 refactor: Increase max chat history tokens limit from 4k to 8k 2025-01-04 06:19:38 -08:00
Paul Gauthier (aider)
d6b612a4a3 style: Break long comment line to comply with flake8 E501 2025-01-04 06:18:40 -08:00
Paul Gauthier (aider)
d24376608e refactor: generalize token calculation using division in Model class 2025-01-04 06:18:15 -08:00
Paul Gauthier
ff41f9bd9a refactor: adjust max_chat_history_tokens calculation based on max_input_tokens 2025-01-04 06:18:12 -08:00
paul-gauthier
6d3dd5c484 Merge pull request #2767 from apaz-cli/ap/suppress_streamlit
Disable streamlit email prompt
2025-01-03 16:02:02 -05:00
apaz-cli
f0bc8983b8 Disable streamlit email prompt 2025-01-03 14:43:18 -06:00
Paul Gauthier (aider)
729354b038 chore: Add cleanup for node_modules directories in benchmark tests 2025-01-03 14:19:06 -05:00
Paul Gauthier (aider)
c0be857f37 chore: Add Java build directory cleanup to test runner 2025-01-03 14:16:51 -05:00
Paul Gauthier
98b0e88ace refactor: simplify Rust target directory cleanup logic 2025-01-03 14:16:49 -05:00
Paul Gauthier (aider)
3d501df21f chore: Clean up Rust target/debug directory after all test attempts 2025-01-03 14:14:44 -05:00
Paul Gauthier
1b4abb747d style: Add blank line for readability in benchmark.py 2025-01-03 14:14:42 -05:00
Paul Gauthier
b1d418f7fb copy 2025-01-03 12:26:55 -04:00
Paul Gauthier
a702b4752b copy 2025-01-03 12:25:03 -04:00
Paul Gauthier
684ba7c0cb Merge branch 'main' of github.com:Aider-AI/aider 2025-01-03 12:16:43 -04:00
Krazer
1bcc27d2be little clean up 2025-01-03 09:07:27 -06:00
Krazer
50d3b305d4 make it a warning 2025-01-03 09:01:34 -06:00
Krazer
a341c98ec6 handle repo index errors 2025-01-03 08:58:42 -06:00
paul-gauthier
fa5c8a00e4 Merge pull request #2706 from Hambaobao/polyglot-qwen2.5-coder-32b-instruct-whole-results
Polyglot Qwen2.5-Coder-32B-Instruct Results [Whole]
2025-01-03 09:35:20 -04:00
paul-gauthier
42f6c20ada Merge branch 'main' into polyglot-qwen2.5-coder-32b-instruct-whole-results 2025-01-03 09:35:14 -04:00
paul-gauthier
787738094d Update README.md 2025-01-02 21:50:30 -04:00
Paul Gauthier
a44ebfe99f copy 2025-01-02 17:26:14 -04:00
Paul Gauthier
c5959664e4 Merge branch 'main' of github.com:Aider-AI/aider 2025-01-02 17:23:42 -04:00
Paul Gauthier
9b581268de copy 2025-01-02 17:23:10 -04:00
Aaron Weisberg
acf654c984 fix: lint command with nested spaced strings 2025-01-02 17:27:33 +01:00
paul-gauthier
94f83eb9e3 Merge pull request #2750 from bkowalik/patch-1
Document boto3 install process with aider installed by uv or one-liner
2025-01-02 09:44:22 -04:00
Bartek Kowalik
07c675ed06 Document boto3 install process with uv 2025-01-02 08:39:20 +01:00
Paul Gauthier
f292e01980 Merge branch 'main' of github.com:Aider-AI/aider 2024-12-30 14:37:27 -04:00
Paul Gauthier (aider)
61f9123147 style: Run linter 2024-12-30 14:21:39 -04:00
Paul Gauthier (aider)
60708a7fd7 fix: Remove unused imports in commands.py 2024-12-30 14:21:35 -04:00
Paul Gauthier
761fb93aba refactor: Move test_cmd_load_with_switch_coder to test file 2024-12-30 14:21:28 -04:00
Paul Gauthier (aider)
20bc718bdc style: Format voice init for readability 2024-12-30 14:19:21 -04:00
Paul Gauthier (aider)
07337d2f41 feat: Handle voice-format command line argument 2024-12-30 14:19:14 -04:00
Paul Gauthier (aider)
3d2de00f49 style: Apply linter fixes 2024-12-30 14:17:25 -04:00
Paul Gauthier (aider)
a7242ca846 refactor: Pass voice settings to Commands as params 2024-12-30 14:17:16 -04:00
paul-gauthier
d3298ac5f2 Merge pull request #2725 from joshvera/fix-benchmark-java-ca-pkg
Install ca-certificates before openjdk-21 to resolve cacerts error
2024-12-29 15:07:51 -04:00
Josh Vera
e486243c06 Install ca-certificates before openjdk-21 to resolve cacerts error 2024-12-29 10:55:09 -08:00
Paul Gauthier (aider)
8eaefb57d3 feat: Add RevCumulative column to problem stats 2024-12-28 11:45:41 -04:00
Paul Gauthier
c21f7afdcb Merge branch 'main' of github.com:Aider-AI/aider 2024-12-28 10:24:22 -04:00
Paul Gauthier
d734dee589 copy 2024-12-28 10:24:17 -04:00
Paul Gauthier (aider)
f035c4c01a fix: Remove max_apply_update_errors from threaded call 2024-12-27 16:36:58 -04:00
Paul Gauthier (aider)
8fcdcecf36 refactor: Remove deprecated max_apply_update_errors 2024-12-27 16:36:47 -04:00
Paul Gauthier
3f9ee1ac2e refactor: Remove deprecated max_apply_update_errors 2024-12-27 16:36:46 -04:00
Paul Gauthier
188e1f788d chore: Rename exercism dir to polyglot-benchmark 2024-12-27 16:33:04 -04:00
paul-gauthier
98a0f1cf5b Merge pull request #2698 from paulmaunders/fix-macos-go-tests
Fix Go installation and benchmark tests for Apple Silicon
2024-12-27 12:31:36 -05:00
Paul Gauthier
1467a673b9 style: Remove mobile height override for blame chart 2024-12-26 20:11:14 -04:00
Paul Gauthier
889eb86d89 fix: Correct chart legend position and reverse order 2024-12-26 20:09:09 -04:00
Paul Gauthier (aider)
125da0e2db feat: Move chart legend to top-left 2024-12-26 20:04:37 -04:00
Paul Gauthier
14b274c707 style: Reduce blame chart height on website 2024-12-26 20:04:37 -04:00
Paul Gauthier (aider)
dedbc20ac6 feat: Make charts responsive and taller on mobile 2024-12-26 20:02:11 -04:00
Paul Gauthier (aider)
36cf2348d0 style: Change human bar color to light grey 2024-12-26 19:57:59 -04:00
Paul Gauthier
a19f8996b8 fix: Improve blame chart labels and stacking 2024-12-26 19:57:57 -04:00
Paul Gauthier (aider)
7293263773 fix: Stack x-axis for full width bars 2024-12-26 19:55:33 -04:00
Paul Gauthier (aider)
ed5b07374d fix: Use minus filter for subtraction in liquid template 2024-12-26 19:54:09 -04:00
Paul Gauthier (aider)
07b96bef95 feat: Create stacked bar chart for lines of code by author 2024-12-26 19:50:21 -04:00
Paul Gauthier
5c3cca157d switch to deepseek-chat instead of deepseek-coder 2024-12-26 19:40:06 -04:00
Paul Gauthier
f1f66a9b9d copy 2024-12-26 19:28:14 -04:00
柏枫
7c86dc9ac6 add polyglot-qwen2.5-coder-32b-instruct-whole-results 2024-12-26 15:01:45 +08:00
Paul Maunders
b68f34eb9e feat: Fix Go installation for Apple Silicon and add tmp.benchmarks to gitignore 2024-12-24 17:30:41 +00:00
82 changed files with 3323 additions and 1466 deletions

View File

@@ -4,23 +4,25 @@ on:
push:
paths-ignore:
- 'aider/website/**'
- README.md
- HISTORY.md
- 'README.md'
- 'HISTORY.md'
- '.github/workflows/*'
- '!.github/workflows/docker-build-test.yml'
branches:
- main
pull_request:
paths-ignore:
- 'aider/website/**'
- README.md
- 'README.md'
- 'HISTORY.md'
- '.github/workflows/*'
- '!.github/workflows/docker-build-test.yml'
branches:
- main
# copy most of these steps from release.yml, but push: false and no tags:
jobs:
build:
docker_build_and_push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -29,11 +31,19 @@ jobs:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker standard image
- name: Login to DockerHub
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build Docker images (PR)
if: ${{ github.event_name == 'pull_request' }}
uses: docker/build-push-action@v5
with:
context: .
@@ -42,7 +52,19 @@ jobs:
push: false
target: aider
- name: Build Docker full image
- name: Build Docker images (Push)
if: ${{ github.event_name != 'pull_request' }}
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/aider:dev
target: aider
- name: Build Docker full image (PR)
if: ${{ github.event_name == 'pull_request' }}
uses: docker/build-push-action@v5
with:
context: .
@@ -50,3 +72,14 @@ jobs:
platforms: linux/amd64,linux/arm64
push: false
target: aider-full
- name: Build Docker full image (Push)
if: ${{ github.event_name != 'pull_request' }}
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/aider-full:dev
target: aider-full

View File

@@ -12,6 +12,7 @@ on:
- "main"
paths:
- "aider/website/**"
- ".github/workflows/pages.yml"
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
@@ -55,10 +56,9 @@ jobs:
env:
JEKYLL_ENV: production
- name: Upload artifact
# Automatically uploads an artifact from the './_site' directory by default
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v3
with:
path: "aider/website/_site/"
path: "aider/website/_site"
# Deployment job
deploy:
@@ -70,7 +70,7 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5

View File

@@ -4,14 +4,19 @@ on:
push:
paths-ignore:
- 'aider/website/**'
- README.md
- HISTORY.md
- 'README.md'
- 'HISTORY.md'
- '.github/workflows/*'
- '!.github/workflows/ubuntu-tests.yml'
branches:
- main
pull_request:
paths-ignore:
- 'aider/website/**'
- README.md
- 'README.md'
- 'HISTORY.md'
- '.github/workflows/*'
- '!.github/workflows/ubuntu-tests.yml'
branches:
- main

View File

@@ -4,14 +4,19 @@ on:
push:
paths-ignore:
- 'aider/website/**'
- README.md
- HISTORY.md
- 'README.md'
- 'HISTORY.md'
- '.github/workflows/*'
- '!.github/workflows/windows-tests.yml'
branches:
- main
pull_request:
paths-ignore:
- 'aider/website/**'
- README.md
- 'README.md'
- 'HISTORY.md'
- '.github/workflows/*'
- '!.github/workflows/windows-tests.yml'
branches:
- main

1
.gitignore vendored
View File

@@ -15,3 +15,4 @@ aider/_version.py
.venv/
.#*
.gitattributes
tmp.benchmarks/

View File

@@ -56,13 +56,6 @@ It is recommended to create a virtual environment outside of the repository to k
python -m venv /path/to/venv
```
#### Using `virtualenv` (for older Python versions)
```
pip install virtualenv
virtualenv /path/to/venv
```
### Activate the Virtual Environment
#### On Windows

View File

@@ -1,14 +1,67 @@
# Release history
### main branch
### Aider v0.72.3
- Enforce user/assistant turn order to avoid R1 errors, by miradnanali.
- Case-insensitive model name matching while preserving original case.
- Aider wrote 67% of the code in this release.
### Aider v0.72.2
- Harden against user/assistant turn order problems which cause R1 errors.
- Added environment variable AIDER_SANITY_CHECK_TURNS for turn order validation.
### Aider v0.72.1
- Fix model metadata for `openrouter/deepseek/deepseek-r1`
### Aider v0.72.0
- Support for DeepSeek R1.
- Use shortcut: `--model r1`
- Also via OpenRouter: `--model openrouter/deepseek/deepseek-r1`
- Added Kotlin syntax support to repo map, by Paul Walker.
- Added `--line-endings` for file writing, by Titusz Pan.
- Added examples_as_sys_msg=True for GPT-4o models, improves benchmark scores.
- Bumped all dependencies, to pick up litellm support for o1 system messages.
- Bugfix for turn taking when reflecting lint/test errors.
- Aider wrote 52% of the code in this release.
### Aider v0.71.1
- Fix permissions issue in Docker images.
- Added read-only file announcements.
- Bugfix: ASCII fallback for unicode errors.
- Bugfix: integer indices for list slicing in repomap calculations.
### Aider v0.71.0
- Prompts to help DeepSeek work better when alternating between `/ask` and `/code`.
- Streaming pretty LLM responses is smoother and faster for long replies.
- Streaming automatically turns of for model that don't support it
- Can now switch to/from `/model o1` and a streaming model
- Pretty output remains enabled even when editing files with triple-backtick fences
- Bare `/ask`, `/code` and `/architect` commands now switch the chat mode.
- Increased default size of the repomap.
- Increased max chat history tokens limit from 4k to 8k.
- Turn off fancy input and watch files if terminal is dumb.
- Added support for custom voice format and input device settings.
- Disabled Streamlit email prompt, by apaz-cli.
- Docker container runs as non-root user.
- Fixed lint command handling of nested spaced strings, by Aaron Weisberg.
- Added token count feedback when adding command output to chat.
- Improved error handling for large audio files with automatic format conversion.
- Improved handling of git repo index errors, by Krazer.
- Improved unicode handling in console output with ASCII fallback.
- Added AssertionError, AttributeError to git error handling.
- Aider wrote 60% of the code in this release.
### Aider v0.70.0
- Full support for o1 models.
- Watch files now honors `--subtree-only`, and only watches that sub tree.
- Watch files now honors `--subtree-only`, and only watches that subtree.
- Improved prompting for watch files, to work more reliably with more models.
- New install methods via uv, including one-liners.
- Support for openrouter/deepseek/deepseek-chat model.
- Better error handling when non-interactive commands are attempted via `/load` or `--load`.
- Display read-only files with abs path if it's shorter than rel path.
- Better error handling when interactive commands are attempted via `/load` or `--load`.
- Display read-only files with abs path if its shorter than rel path.
- Ask 10% of users to opt-in to analytics.
- Bugfix for auto-suggest.
- Gracefully handle unicode errors in git path names.

View File

@@ -5,9 +5,9 @@
Aider lets you pair program with LLMs,
to edit code in your local git repository.
Start a new project or work with an existing git repo.
Aider works best with GPT-4o & Claude 3.5 Sonnet and can
[connect to almost any LLM](https://aider.chat/docs/llms.html).
Start a new project or work with an existing code base.
Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
<!-- SCREENCAST START -->
<p align="center">
@@ -77,16 +77,17 @@ for more details.
- Update docs.
- Aider will edit your files to complete your request.
- Aider [automatically git commits](https://aider.chat/docs/git.html) changes with a sensible commit message.
- [Use aider inside your favorite editor or IDE](https://aider.chat/docs/usage/watch.html).
- Aider works with [most popular languages](https://aider.chat/docs/languages.html): python, javascript, typescript, php, html, css, and more...
- Aider works best with GPT-4o & Claude 3.5 Sonnet and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
- Aider can edit multiple files at once for complex requests.
- Aider uses a [map of your entire git repo](https://aider.chat/docs/repomap.html), which helps it work well in larger codebases.
- Edit files in your editor while chatting with aider,
- Edit files in your editor or IDE while chatting with aider,
and it will always use the latest version.
Pair program with AI.
- [Add images to the chat](https://aider.chat/docs/usage/images-urls.html) (GPT-4o, Claude 3.5 Sonnet, etc).
- [Add URLs to the chat](https://aider.chat/docs/usage/images-urls.html) and aider will read their content.
- [Code with your voice](https://aider.chat/docs/usage/voice.html).
- Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
## Top tier performance

View File

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

View File

@@ -106,7 +106,7 @@ def get_parser(default_config_files, git_root):
const=gpt_3_model_name,
help=f"Use {gpt_3_model_name} model for the main chat",
)
deepseek_model = "deepseek/deepseek-coder"
deepseek_model = "deepseek/deepseek-chat"
group.add_argument(
"--deepseek",
action="store_const",
@@ -287,7 +287,7 @@ def get_parser(default_config_files, git_root):
"--map-tokens",
type=int,
default=None,
help="Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)",
help="Suggested number of tokens to use for repo map, use 0 to disable",
)
group.add_argument(
"--map-refresh",
@@ -766,6 +766,12 @@ def get_parser(default_config_files, git_root):
default="utf-8",
help="Specify the encoding for input and output (default: utf-8)",
)
group.add_argument(
"--line-endings",
choices=["platform", "lf", "crlf"],
default="platform",
help="Line endings to use when writing files (default: platform)",
)
group.add_argument(
"-c",
"--config",

View File

@@ -7,6 +7,8 @@ class AskPrompts(CoderPrompts):
main_system = """Act as an expert code analyst.
Answer questions about the supplied code.
Always reply to the user in {language}.
Describe code changes however you like. Don't use SEARCH/REPLACE blocks!
"""
example_messages = []

View File

@@ -59,7 +59,8 @@ def wrap_fence(name):
all_fences = [
("``" + "`", "``" + "`"),
("`" * 3, "`" * 3),
("`" * 4, "`" * 4),
wrap_fence("source"),
wrap_fence("code"),
wrap_fence("pre"),
@@ -230,10 +231,10 @@ class Coder:
if map_tokens > 0:
refresh = self.repo_map.refresh
lines.append(f"Repo-map: using {map_tokens} tokens, {refresh} refresh")
max_map_tokens = 2048
max_map_tokens = self.main_model.get_repo_map_tokens() * 2
if map_tokens > max_map_tokens:
lines.append(
f"Warning: map-tokens > {max_map_tokens} is not recommended as too much"
f"Warning: map-tokens > {max_map_tokens} is not recommended. Too much"
" irrelevant code can confuse LLMs."
)
else:
@@ -245,6 +246,10 @@ class Coder:
for fname in self.get_inchat_relative_files():
lines.append(f"Added {fname} to the chat.")
for fname in self.abs_read_only_fnames:
rel_fname = self.get_rel_fname(fname)
lines.append(f"Added {rel_fname} to the chat (read-only).")
if self.done_messages:
lines.append("Restored previous conversation history.")
@@ -348,7 +353,6 @@ class Coder:
self.done_messages = []
self.io = io
self.stream = stream
self.shell_commands = []
@@ -363,6 +367,8 @@ class Coder:
self.main_model = main_model
self.stream = stream and main_model.streaming
if cache_prompts and self.main_model.cache_control:
self.add_cache_headers = True
@@ -453,6 +459,7 @@ class Coder:
self.summarizer_thread = None
self.summarized_done_messages = []
self.summarizing_messages = None
if not self.done_messages and restore_chat_history:
history_md = self.io.read_text(self.io.chat_history_file)
@@ -519,7 +526,7 @@ class Coder:
return False
# only show pretty output if fences are the normal triple-backtick
if self.fence != self.fences[0]:
if self.fence[0][0] != "`":
return False
return True
@@ -613,9 +620,19 @@ class Coder:
def get_ident_filename_matches(self, idents):
all_fnames = defaultdict(set)
for fname in self.get_all_relative_files():
base = Path(fname).with_suffix("").name.lower()
if len(base) >= 5:
all_fnames[base].add(fname)
# Skip empty paths or just '.'
if not fname or fname == ".":
continue
try:
# Handle dotfiles properly
path = Path(fname)
base = path.stem.lower() # Use stem instead of with_suffix("").name
if len(base) >= 5:
all_fnames[base].add(fname)
except ValueError:
# Skip paths that can't be processed
continue
matches = set()
for ident in idents:
@@ -926,8 +943,9 @@ class Coder:
self.summarizer_thread.start()
def summarize_worker(self):
self.summarizing_messages = list(self.done_messages)
try:
self.summarized_done_messages = self.summarizer.summarize(self.done_messages)
self.summarized_done_messages = self.summarizer.summarize(self.summarizing_messages)
except ValueError as err:
self.io.tool_warning(err.args[0])
@@ -941,7 +959,9 @@ class Coder:
self.summarizer_thread.join()
self.summarizer_thread = None
self.done_messages = self.summarized_done_messages
if self.summarizing_messages == self.done_messages:
self.done_messages = self.summarized_done_messages
self.summarizing_messages = None
self.summarized_done_messages = []
def move_back_cur_messages(self, message):
@@ -1306,7 +1326,17 @@ class Coder:
self.show_usage_report()
self.add_assistant_reply_to_cur_messages()
if exhausted:
if self.cur_messages and self.cur_messages[-1]["role"] == "user":
self.cur_messages += [
dict(
role="assistant",
content="FinishReasonLength exception: you sent too many tokens",
),
]
self.show_exhausted_error()
self.num_exhausted_context_windows += 1
return
@@ -1337,14 +1367,14 @@ class Coder:
interrupted = True
if interrupted:
content += "\n^C KeyboardInterrupt"
self.cur_messages += [dict(role="assistant", content=content)]
self.cur_messages += [
dict(role="user", content="^C KeyboardInterrupt"),
dict(role="assistant", content="I see that you interrupted my previous reply."),
]
return
edited = self.apply_updates()
self.update_cur_messages()
if edited:
self.aider_edited_files.update(edited)
saved_message = self.auto_commit(edited)
@@ -1365,7 +1395,6 @@ class Coder:
ok = self.io.confirm_ask("Attempt to fix lint errors?")
if ok:
self.reflected_message = lint_errors
self.update_cur_messages()
return
shared_output = self.run_shell_commands()
@@ -1382,7 +1411,6 @@ class Coder:
ok = self.io.confirm_ask("Attempt to fix test errors?")
if ok:
self.reflected_message = test_errors
self.update_cur_messages()
return
def reply_completed(self):
@@ -1458,7 +1486,7 @@ class Coder:
return res
def update_cur_messages(self):
def add_assistant_reply_to_cur_messages(self):
if self.partial_response_content:
self.cur_messages += [dict(role="assistant", content=self.partial_response_content)]
if self.partial_response_function_call:

View File

@@ -183,6 +183,9 @@ If you want to put code in a new file, use a *SEARCH/REPLACE block* with:
To rename files which have been added to the chat, use shell commands at the end of your response.
If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed.
The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks.
{lazy_prompt}
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_reminder}

View File

@@ -38,7 +38,7 @@ class SingleWholeFileFunctionCoder(Coder):
self.gpt_prompts = SingleWholeFileFunctionPrompts()
super().__init__(*args, **kwargs)
def update_cur_messages(self, edited):
def add_assistant_reply_to_cur_messages(self, edited):
if edited:
self.cur_messages += [
dict(role="assistant", content=self.gpt_prompts.redacted_edit_message)

View File

@@ -49,7 +49,7 @@ class WholeFileFunctionCoder(Coder):
self.gpt_prompts = WholeFileFunctionPrompts()
super().__init__(*args, **kwargs)
def update_cur_messages(self, edited):
def add_assistant_reply_to_cur_messages(self, edited):
if edited:
self.cur_messages += [
dict(role="assistant", content=self.gpt_prompts.redacted_edit_message)

View File

@@ -7,7 +7,6 @@ import tempfile
from collections import OrderedDict
from os.path import expanduser
from pathlib import Path
from unittest import mock
import pyperclip
from PIL import Image, ImageGrab
@@ -18,12 +17,11 @@ from aider import models, prompts, voice
from aider.editor import pipe_editor
from aider.format_settings import format_settings
from aider.help import Help, install_help_extra
from aider.io import InputOutput
from aider.llm import litellm
from aider.repo import ANY_GIT_ERROR
from aider.run_cmd import run_cmd
from aider.scrape import Scraper, install_playwright
from aider.utils import GitTemporaryDirectory, is_image_file
from aider.utils import is_image_file
from .dump import dump # noqa: F401
@@ -54,6 +52,8 @@ class Commands:
io,
coder,
voice_language=None,
voice_input_device=None,
voice_format=None,
verify_ssl=True,
args=None,
parser=None,
@@ -71,6 +71,8 @@ class Commands:
voice_language = None
self.voice_language = voice_language
self.voice_format = voice_format
self.voice_input_device = voice_input_device
self.help = None
self.editor = editor
@@ -916,10 +918,14 @@ class Commands:
if combined_output is None:
return
# Calculate token count of output
token_count = self.coder.main_model.token_count(combined_output)
k_tokens = token_count / 1000
if add_on_nonzero_exit:
add = exit_status != 0
else:
add = self.io.confirm_ask("Add command output to the chat?")
add = self.io.confirm_ask(f"Add {k_tokens:.1f}k tokens of command output to the chat?")
if add:
num_lines = len(combined_output.strip().splitlines())
@@ -937,7 +943,7 @@ class Commands:
]
if add and exit_status != 0:
self.io.placeholder = "Fix that"
self.io.placeholder = "What's wrong? Fix"
def cmd_exit(self, args):
"Exit the application"
@@ -1055,21 +1061,21 @@ class Commands:
)
def cmd_ask(self, args):
"Ask questions about the code base without editing any files"
"""Ask questions about the code base without editing any files. If no prompt provided, switches to ask mode.""" # noqa
return self._generic_chat_command(args, "ask")
def cmd_code(self, args):
"Ask for changes to your code"
"""Ask for changes to your code. If no prompt provided, switches to code mode.""" # noqa
return self._generic_chat_command(args, self.coder.main_model.edit_format)
def cmd_architect(self, args):
"Enter architect mode to discuss high-level design and architecture"
"""Enter architect/editor mode using 2 different models. If no prompt provided, switches to architect/editor mode.""" # noqa
return self._generic_chat_command(args, "architect")
def _generic_chat_command(self, args, edit_format):
if not args.strip():
self.io.tool_error(f"Please provide a question or topic for the {edit_format} chat.")
return
# Switch to the corresponding chat mode if no args provided
return self.cmd_chat_mode(edit_format)
from aider.coders.base_coder import Coder
@@ -1119,7 +1125,7 @@ class Commands:
return
try:
self.voice = voice.Voice(
audio_format=self.args.voice_format, device_name=self.args.voice_input_device
audio_format=self.voice_format or "wav", device_name=self.voice_input_device
)
except voice.SoundDeviceError:
self.io.tool_error(
@@ -1318,36 +1324,6 @@ class Commands:
f"Command '{cmd}' is only supported in interactive mode, skipping."
)
def test_cmd_load_with_switch_coder(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create a temporary file with commands
commands_file = Path(repo_dir) / "test_commands.txt"
commands_file.write_text("/ask Tell me about the code\n/model gpt-4\n")
# Mock run to raise SwitchCoder for /ask and /model
def mock_run(cmd):
if cmd.startswith(("/ask", "/model")):
raise SwitchCoder()
return None
with mock.patch.object(commands, "run", side_effect=mock_run):
# Capture tool_error output
with mock.patch.object(io, "tool_error") as mock_tool_error:
commands.cmd_load(str(commands_file))
# Check that appropriate error messages were shown
mock_tool_error.assert_any_call(
"Command '/ask Tell me about the code' is only supported in interactive"
" mode, skipping."
)
mock_tool_error.assert_any_call(
"Command '/model gpt-4' is only supported in interactive mode, skipping."
)
def completions_raw_save(self, document, complete_event):
return self.completions_raw_read_only(document, complete_event)

View File

@@ -26,6 +26,12 @@ class ChatSummary:
return sized
def summarize(self, messages, depth=0):
messages = self.summarize_real(messages)
if messages and messages[-1]["role"] != "assistant":
messages.append(dict(role="assistant", content="Ok."))
return messages
def summarize_real(self, messages, depth=0):
if not self.models:
raise ValueError("No models available for summarization")
@@ -88,7 +94,7 @@ class ChatSummary:
if summary_tokens + tail_tokens < self.max_tokens:
return result
return self.summarize(result, depth + 1)
return self.summarize_real(result, depth + 1)
def summarize_all(self, messages):
content = ""

View File

@@ -17,6 +17,7 @@ from prompt_toolkit.history import FileHistory
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.keys import Keys
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.output.vt100 import is_dumb_terminal
from prompt_toolkit.shortcuts import CompleteStyle, PromptSession
from prompt_toolkit.styles import Style
from pygments.lexers import MarkdownLexer, guess_lexer_for_filename
@@ -197,6 +198,7 @@ class InputOutput:
completion_menu_current_bg_color=None,
code_theme="default",
encoding="utf-8",
line_endings="platform",
dry_run=False,
llm_history_file=None,
editingmode=EditingMode.EMACS,
@@ -243,14 +245,29 @@ class InputOutput:
self.chat_history_file = None
self.encoding = encoding
valid_line_endings = {"platform", "lf", "crlf"}
if line_endings not in valid_line_endings:
raise ValueError(
f"Invalid line_endings value: {line_endings}. "
f"Must be one of: {', '.join(valid_line_endings)}"
)
self.newline = (
None if line_endings == "platform" else "\n" if line_endings == "lf" else "\r\n"
)
self.dry_run = dry_run
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.append_chat_history(f"\n# aider chat started at {current_time}\n\n")
self.prompt_session = None
self.is_dumb_terminal = is_dumb_terminal()
if self.is_dumb_terminal:
self.pretty = False
fancy_input = False
if fancy_input:
# Initialize PromptSession
# Initialize PromptSession only if we have a capable terminal
session_kwargs = {
"input": self.input,
"output": self.output,
@@ -269,6 +286,8 @@ class InputOutput:
self.tool_error(f"Can't initialize prompt toolkit: {err}") # non-pretty
else:
self.console = Console(force_terminal=False, no_color=True) # non-pretty
if self.is_dumb_terminal:
self.tool_output("Detected dumb terminal, disabling fancy input and pretty output.")
self.file_watcher = file_watcher
self.root = root
@@ -333,10 +352,6 @@ class InputOutput:
try:
with open(str(filename), "r", encoding=self.encoding) as f:
return f.read()
except OSError as err:
if not silent:
self.tool_error(f"{filename}: unable to read: {err}")
return
except FileNotFoundError:
if not silent:
self.tool_error(f"{filename}: file not found error")
@@ -345,6 +360,10 @@ class InputOutput:
if not silent:
self.tool_error(f"{filename}: is a directory")
return
except OSError as err:
if not silent:
self.tool_error(f"{filename}: unable to read: {err}")
return
except UnicodeError as e:
if not silent:
self.tool_error(f"{filename}: {e}")
@@ -366,7 +385,7 @@ class InputOutput:
delay = initial_delay
for attempt in range(max_retries):
try:
with open(str(filename), "w", encoding=self.encoding) as f:
with open(str(filename), "w", encoding=self.encoding, newline=self.newline) as f:
f.write(content)
return # Successfully wrote the file
except PermissionError as err:
@@ -804,9 +823,17 @@ class InputOutput:
hist = message.strip() if strip else message
self.append_chat_history(hist, linebreak=True, blockquote=True)
message = Text(message)
if not isinstance(message, Text):
message = Text(message)
style = dict(style=color) if self.pretty and color else dict()
self.console.print(message, **style)
try:
self.console.print(message, **style)
except UnicodeEncodeError:
# Fallback to ASCII-safe output
if isinstance(message, Text):
message = message.plain
message = str(message).encode("ascii", errors="replace").decode("ascii")
self.console.print(message, **style)
def tool_error(self, message="", strip=True):
self.num_error_outputs += 1

View File

@@ -11,6 +11,7 @@ from grep_ast import TreeContext, filename_to_lang
from tree_sitter_languages import get_parser # noqa: E402
from aider.dump import dump # noqa: F401
from aider.run_cmd import run_cmd_subprocess # noqa: F401
# tree_sitter is throwing a FutureWarning
warnings.simplefilter("ignore", category=FutureWarning)
@@ -44,26 +45,22 @@ class Linter:
def run_cmd(self, cmd, rel_fname, code):
cmd += " " + rel_fname
cmd = cmd.split()
returncode = 0
stdout = ""
try:
process = subprocess.Popen(
returncode, stdout = run_cmd_subprocess(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
encoding=self.encoding,
errors="replace",
cwd=self.root,
encoding=self.encoding,
)
except OSError as err:
print(f"Unable to execute lint command: {err}")
return
stdout, _ = process.communicate()
errors = stdout
if process.returncode == 0:
if returncode == 0:
return # zero exit status
cmd = " ".join(cmd)
res = f"## Running: {cmd}\n\n"
res += errors

View File

@@ -113,7 +113,9 @@ def setup_git(git_root, io):
except ANY_GIT_ERROR:
pass
elif cwd == Path.home():
io.tool_warning("You should probably run aider in your project's directory, not your home dir.")
io.tool_warning(
"You should probably run aider in your project's directory, not your home dir."
)
return
elif cwd and io.confirm_ask(
"No git repo found, create one to track aider's changes (recommended)?"
@@ -173,7 +175,7 @@ def check_gitignore(git_root, io, ask=True):
existing_lines = content.splitlines()
for pat in patterns:
if pat not in existing_lines:
if '*' in pat or (Path(git_root) / pat).exists():
if "*" in pat or (Path(git_root) / pat).exists():
patterns_to_add.append(pat)
except OSError as e:
io.tool_error(f"Error when trying to read {gitignore_file}: {e}")
@@ -213,6 +215,22 @@ def check_streamlit_install(io):
)
def write_streamlit_credentials():
from streamlit.file_util import get_streamlit_file_path
# See https://github.com/Aider-AI/aider/issues/772
credential_path = Path(get_streamlit_file_path()) / "credentials.toml"
if not os.path.exists(credential_path):
empty_creds = '[general]\nemail = ""\n'
os.makedirs(os.path.dirname(credential_path), exist_ok=True)
with open(credential_path, "w") as f:
f.write(empty_creds)
else:
print("Streamlit credentials already exist.")
def launch_gui(args):
from streamlit.web import cli
@@ -221,6 +239,9 @@ def launch_gui(args):
print()
print("CONTROL-C to exit...")
# Necessary so streamlit does not prompt the user for an email address.
write_streamlit_credentials()
target = gui.__file__
st_args = ["run", target]
@@ -358,18 +379,18 @@ def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"):
def register_litellm_models(git_root, model_metadata_fname, io, verbose=False):
model_metatdata_files = []
model_metadata_files = []
# Add the resource file path
resource_metadata = importlib_resources.files("aider.resources").joinpath("model-metadata.json")
model_metatdata_files.append(str(resource_metadata))
model_metadata_files.append(str(resource_metadata))
model_metatdata_files += generate_search_path_list(
model_metadata_files += generate_search_path_list(
".aider.model.metadata.json", git_root, model_metadata_fname
)
try:
model_metadata_files_loaded = models.register_litellm_models(model_metatdata_files)
model_metadata_files_loaded = models.register_litellm_models(model_metadata_files)
if len(model_metadata_files_loaded) > 0 and verbose:
io.tool_output("Loaded model metadata from:")
for model_metadata_file in model_metadata_files_loaded:
@@ -395,8 +416,8 @@ def sanity_check_repo(repo, io):
error_msg = str(repo.git_repo_error)
except UnicodeDecodeError as exc:
error_msg = (
f"Failed to read the Git repository. This issue is likely caused by a path encoded "
f"in a format different from the expected encoding \"{sys.getfilesystemencoding()}\".\n"
"Failed to read the Git repository. This issue is likely caused by a path encoded "
f'in a format different from the expected encoding "{sys.getfilesystemencoding()}".\n'
f"Internal error: {str(exc)}"
)
except ANY_GIT_ERROR as exc:
@@ -531,6 +552,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
code_theme=args.code_theme,
dry_run=args.dry_run,
encoding=args.encoding,
line_endings=args.line_endings,
llm_history_file=args.llm_history_file,
editingmode=editing_mode,
fancy_input=args.fancy_input,
@@ -802,6 +824,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
commands = Commands(
io,
None,
voice_language=args.voice_language,
voice_input_device=args.voice_input_device,
voice_format=args.voice_format,
verify_ssl=args.verify_ssl,
args=args,
parser=parser,
@@ -824,6 +849,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
)
args.stream = False
if args.map_tokens is None:
map_tokens = main_model.get_repo_map_tokens()
else:
map_tokens = args.map_tokens
try:
coder = Coder.create(
main_model=main_model,
@@ -836,7 +866,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
auto_commits=args.auto_commits,
dirty_commits=args.dirty_commits,
dry_run=args.dry_run,
map_tokens=args.map_tokens,
map_tokens=map_tokens,
verbose=args.verbose,
stream=args.stream,
use_git=args.git,

View File

@@ -10,10 +10,17 @@ from rich.text import Text
from aider.dump import dump # noqa: F401
_text = """
_text_prefix = """
# Header
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged. It was popularised in
the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,
and more recently with desktop publishing software like Aldus PageMaker
including versions of Lorem Ipsum.
@@ -27,10 +34,9 @@ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem
```python
import sys
"""
def greeting():
print("Hello world!")
_text_suffix = """
```
## Sub header too
@@ -41,81 +47,146 @@ The end.
class MarkdownStream:
live = None
when = 0
min_delay = 0.050
live_window = 6
"""Streaming markdown renderer that progressively displays content with a live updating window.
Uses rich.console and rich.live to render markdown content with smooth scrolling
and partial updates. Maintains a sliding window of visible content while streaming
in new markdown text.
"""
live = None # Rich Live display instance
when = 0 # Timestamp of last update
min_delay = 1.0 / 20 # Minimum time between updates (20fps)
live_window = 6 # Number of lines to keep visible at bottom during streaming
def __init__(self, mdargs=None):
self.printed = []
"""Initialize the markdown stream.
Args:
mdargs (dict, optional): Additional arguments to pass to rich Markdown renderer
"""
self.printed = [] # Stores lines that have already been printed
if mdargs:
self.mdargs = mdargs
else:
self.mdargs = dict()
# Initialize rich Live display with empty text
self.live = Live(Text(""), refresh_per_second=1.0 / self.min_delay)
self.live.start()
def _render_markdown_to_lines(self, text):
"""Render markdown text to a list of lines.
Args:
text (str): Markdown text to render
Returns:
list: List of rendered lines with line endings preserved
"""
# Render the markdown to a string buffer
string_io = io.StringIO()
console = Console(file=string_io, force_terminal=True)
markdown = Markdown(text, **self.mdargs)
console.print(markdown)
output = string_io.getvalue()
# Split rendered output into lines
return output.splitlines(keepends=True)
def __del__(self):
"""Destructor to ensure Live display is properly cleaned up."""
if self.live:
try:
self.live.stop()
except Exception:
pass
pass # Ignore any errors during cleanup
def update(self, text, final=False):
"""Update the displayed markdown content.
Args:
text (str): The markdown text received so far
final (bool): If True, this is the final update and we should clean up
Splits the output into "stable" older lines and the "last few" lines
which aren't considered stable. They may shift around as new chunks
are appended to the markdown text.
The stable lines emit to the console above the Live window.
The unstable lines emit into the Live window so they can be repainted.
Markdown going to the console works better in terminal scrollback buffers.
The live window doesn't play nice with terminal scrollback.
"""
now = time.time()
# Throttle updates to maintain smooth rendering
if not final and now - self.when < self.min_delay:
return
self.when = now
string_io = io.StringIO()
console = Console(file=string_io, force_terminal=True)
# Measure render time and adjust min_delay to maintain smooth rendering
start = time.time()
lines = self._render_markdown_to_lines(text)
render_time = time.time() - start
markdown = Markdown(text, **self.mdargs)
# Set min_delay to render time plus a small buffer
self.min_delay = min(max(render_time * 10, 1.0 / 20), 2)
console.print(markdown)
output = string_io.getvalue()
lines = output.splitlines(keepends=True)
num_lines = len(lines)
# How many lines have "left" the live window and are now considered stable?
# Or if final, consider all lines to be stable.
if not final:
num_lines -= self.live_window
# If we have stable content to display...
if final or num_lines > 0:
# How many stable lines do we need to newly show above the live window?
num_printed = len(self.printed)
show = num_lines - num_printed
# Skip if no new lines to show above live window
if show <= 0:
return
# Get the new lines and display them
show = lines[num_printed:num_lines]
show = "".join(show)
show = Text.from_ansi(show)
self.live.console.print(show)
self.live.console.print(show) # to the console above the live area
# Update our record of printed lines
self.printed = lines[:num_lines]
# Handle final update cleanup
if final:
self.live.update(Text(""))
self.live.stop()
self.live = None
else:
rest = lines[num_lines:]
rest = "".join(rest)
# rest = '...\n' + rest
rest = Text.from_ansi(rest)
self.live.update(rest)
return
# Update the live window with remaining lines
rest = lines[num_lines:]
rest = "".join(rest)
rest = Text.from_ansi(rest)
self.live.update(rest)
def find_minimal_suffix(self, text, match_lines=50):
"""
Splits text into chunks on blank lines "\n\n".
"""
if __name__ == "__main__":
_text = 5 * _text
with open("aider/io.py", "r") as f:
code = f.read()
_text = _text_prefix + code + _text_suffix
_text = _text * 10
pm = MarkdownStream()
for i in range(6, len(_text)):
for i in range(6, len(_text), 5):
pm.update(_text[:i])
time.sleep(0.01)

View File

@@ -75,7 +75,8 @@ MODEL_ALIASES = {
"35-turbo": "gpt-3.5-turbo",
"3": "gpt-3.5-turbo",
# Other models
"deepseek": "deepseek/deepseek-coder",
"deepseek": "deepseek/deepseek-chat",
"r1": "deepseek/deepseek-reasoner",
"flash": "gemini/gemini-2.0-flash-exp",
}
@@ -162,6 +163,7 @@ MODEL_SETTINGS = [
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
examples_as_sys_msg=True,
),
ModelSettings(
"openai/gpt-4o-2024-08-06",
@@ -170,6 +172,7 @@ MODEL_SETTINGS = [
use_repo_map=True,
lazy=True,
reminder="sys",
examples_as_sys_msg=True,
),
ModelSettings(
"gpt-4o-2024-08-06",
@@ -178,6 +181,7 @@ MODEL_SETTINGS = [
use_repo_map=True,
lazy=True,
reminder="sys",
examples_as_sys_msg=True,
),
ModelSettings(
"gpt-4o-2024-11-20",
@@ -186,6 +190,7 @@ MODEL_SETTINGS = [
use_repo_map=True,
lazy=True,
reminder="sys",
examples_as_sys_msg=True,
),
ModelSettings(
"openai/gpt-4o-2024-11-20",
@@ -194,6 +199,7 @@ MODEL_SETTINGS = [
use_repo_map=True,
lazy=True,
reminder="sys",
examples_as_sys_msg=True,
),
ModelSettings(
"gpt-4o",
@@ -203,6 +209,7 @@ MODEL_SETTINGS = [
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
examples_as_sys_msg=True,
),
ModelSettings(
"gpt-4o-mini",
@@ -616,12 +623,43 @@ MODEL_SETTINGS = [
use_repo_map=True,
send_undo_reply=False,
),
ModelSettings(
"openrouter/deepseek/deepseek-r1",
"diff",
weak_model_name="openrouter/deepseek/deepseek-chat",
editor_model_name="openrouter/deepseek/deepseek-chat",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
use_temperature=False,
reminder="user",
caches_by_default=True,
extra_params={
"max_tokens": 8192,
},
),
ModelSettings(
"deepseek/deepseek-reasoner",
"diff",
weak_model_name="deepseek/deepseek-chat",
editor_model_name="deepseek/deepseek-chat",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
use_temperature=False,
reminder="user",
caches_by_default=True,
extra_params={
"max_tokens": 8192,
},
),
ModelSettings(
"deepseek/deepseek-chat",
"diff",
use_repo_map=True,
examples_as_sys_msg=True,
reminder="sys",
caches_by_default=True,
extra_params={
"max_tokens": 8192,
},
@@ -680,6 +718,7 @@ MODEL_SETTINGS = [
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
examples_as_sys_msg=True,
),
ModelSettings(
"openai/o1-mini",
@@ -920,10 +959,9 @@ class Model(ModelSettings):
self.keys_in_environment = res.get("keys_in_environment")
max_input_tokens = self.info.get("max_input_tokens") or 0
if max_input_tokens < 32 * 1024:
self.max_chat_history_tokens = 1024
else:
self.max_chat_history_tokens = 2 * 1024
# Calculate max_chat_history_tokens as 1/16th of max_input_tokens,
# with minimum 1k and maximum 8k
self.max_chat_history_tokens = min(max(max_input_tokens / 16, 1024), 8192)
self.configure_model_settings(model)
if weak_model is False:
@@ -1178,6 +1216,15 @@ class Model(ModelSettings):
return res
def get_repo_map_tokens(self):
map_tokens = 1024
max_inp_tokens = self.info.get("max_input_tokens")
if max_inp_tokens:
map_tokens = max_inp_tokens / 8
map_tokens = min(map_tokens, 4096)
map_tokens = max(map_tokens, 1024)
return map_tokens
def register_models(model_settings_fnames):
files_loaded = []
@@ -1301,8 +1348,8 @@ def fuzzy_match_models(name):
name = name.lower()
chat_models = set()
for model, attrs in litellm.model_cost.items():
model = model.lower()
for orig_model, attrs in litellm.model_cost.items():
model = orig_model.lower()
if attrs.get("mode") != "chat":
continue
provider = attrs.get("litellm_provider", "").lower()
@@ -1311,12 +1358,12 @@ def fuzzy_match_models(name):
provider += "/"
if model.startswith(provider):
fq_model = model
fq_model = orig_model
else:
fq_model = provider + model
fq_model = provider + orig_model
chat_models.add(fq_model)
chat_models.add(model)
chat_models.add(orig_model)
chat_models = sorted(chat_models)
# exactly matching model

View File

@@ -0,0 +1,27 @@
; Definitions
(class_declaration
(type_identifier) @name.definition.class) @definition.class
(function_declaration
(simple_identifier) @name.definition.function) @definition.function
(object_declaration
(type_identifier) @name.definition.object) @definition.object
; References
(call_expression
[
(simple_identifier) @name.reference.call
(navigation_expression
(navigation_suffix
(simple_identifier) @name.reference.call))
]) @reference.call
(delegation_specifier
[
(user_type) @name.reference.type
(constructor_invocation
(user_type) @name.reference.type)
]) @reference.type

View File

@@ -8,6 +8,7 @@ try:
ANY_GIT_ERROR = [
git.exc.ODBError,
git.exc.GitError,
git.exc.InvalidGitRepositoryError,
]
except ImportError:
git = None
@@ -26,6 +27,8 @@ ANY_GIT_ERROR += [
BufferError,
TypeError,
ValueError,
AttributeError,
AssertionError,
]
ANY_GIT_ERROR = tuple(ANY_GIT_ERROR)
@@ -285,9 +288,17 @@ class GitRepo:
files = self.tree_files[commit]
else:
try:
for blob in commit.tree.traverse():
if blob.type == "blob": # blob is a file
files.add(blob.path)
iterator = commit.tree.traverse()
while True:
try:
blob = next(iterator)
if blob.type == "blob": # blob is a file
files.add(blob.path)
except IndexError:
self.io.tool_warning(f"GitRepo: read error skipping {blob.path}")
continue
except StopIteration:
break
except ANY_GIT_ERROR as err:
self.git_repo_error = err
self.io.tool_error(f"Unable to list files in git repo: {err}")
@@ -359,8 +370,8 @@ class GitRepo:
def ignored_file_raw(self, fname):
if self.subtree_only:
fname_path = Path(self.normalize_path(fname))
try:
fname_path = Path(self.normalize_path(fname))
cwd_path = Path.cwd().resolve().relative_to(Path(self.root).resolve())
except ValueError:
# Issue #1524

View File

@@ -605,7 +605,7 @@ class RepoMap:
self.tree_cache = dict()
middle = min(max_map_tokens // 25, num_tags)
middle = min(int(max_map_tokens // 25), num_tags)
while lower_bound <= upper_bound:
# dump(lower_bound, middle, upper_bound)
@@ -628,7 +628,7 @@ class RepoMap:
else:
upper_bound = middle - 1
middle = (lower_bound + upper_bound) // 2
middle = int((lower_bound + upper_bound) // 2)
spin.end()
return best_tree

View File

@@ -1,27 +1,34 @@
{
"openrouter/openai/o1": {
"max_tokens": 100000,
"max_input_tokens": 200000,
"max_output_tokens": 100000,
"input_cost_per_token": 0.000015,
"output_cost_per_token": 0.00006,
"cache_read_input_token_cost": 0.0000075,
"deepseek-reasoner": {
"max_tokens": 8192,
"max_input_tokens": 64000,
"max_output_tokens": 8192,
"input_cost_per_token": 0.00000055,
"input_cost_per_token_cache_hit": 0.00000014,
"cache_read_input_token_cost": 0.00000014,
"cache_creation_input_token_cost": 0.0,
"output_cost_per_token": 0.00000219,
"litellm_provider": "deepseek",
"mode": "chat",
//"supports_function_calling": true,
"supports_assistant_prefill": true,
//"supports_tool_choice": true,
"supports_prompt_caching": true
},
"openrouter/deepseek/deepseek-r1": {
"max_tokens": 8192,
"max_input_tokens": 64000,
"max_output_tokens": 8192,
"input_cost_per_token": 0.00000055,
"input_cost_per_token_cache_hit": 0.00000014,
"cache_read_input_token_cost": 0.00000014,
"cache_creation_input_token_cost": 0.0,
"output_cost_per_token": 0.00000219,
"litellm_provider": "openrouter",
"mode": "chat",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
"supports_vision": true,
"supports_prompt_caching": true,
"supports_system_messages": true,
"supports_response_schema": true
},
"openrouter/deepseek/deepseek-chat": {
"max_tokens": 8192,
"max_input_tokens": 66000,
"max_output_tokens": 4096,
"input_cost_per_token": 0.00000014,
"output_cost_per_token": 0.00000028,
"litellm_provider": "openrouter",
"mode": "chat"
//"supports_function_calling": true,
"supports_assistant_prefill": true,
//"supports_tool_choice": true,
"supports_prompt_caching": true
},
}

View File

@@ -39,7 +39,7 @@ def get_windows_parent_process_name():
return None
def run_cmd_subprocess(command, verbose=False, cwd=None):
def run_cmd_subprocess(command, verbose=False, cwd=None, encoding=sys.stdout.encoding):
if verbose:
print("Using run_cmd_subprocess:", command)
@@ -65,7 +65,7 @@ def run_cmd_subprocess(command, verbose=False, cwd=None):
stderr=subprocess.STDOUT,
text=True,
shell=True,
encoding=sys.stdout.encoding,
encoding=encoding,
errors="replace",
bufsize=0, # Set bufsize to 0 for unbuffered output
universal_newlines=True,

View File

@@ -1,10 +1,12 @@
import hashlib
import json
import os
import time
from aider.dump import dump # noqa: F401
from aider.exceptions import LiteLLMExceptions
from aider.llm import litellm
from aider.utils import format_messages
# from diskcache import Cache
@@ -16,6 +18,65 @@ CACHE = None
RETRY_TIMEOUT = 60
def sanity_check_messages(messages):
"""Check if messages alternate between user and assistant roles.
System messages can be interspersed anywhere.
Also verifies the last non-system message is from the user.
Returns True if valid, False otherwise."""
last_role = None
last_non_system_role = None
for msg in messages:
role = msg.get("role")
if role == "system":
continue
if last_role and role == last_role:
turns = format_messages(messages)
raise ValueError("Messages don't properly alternate user/assistant:\n\n" + turns)
last_role = role
last_non_system_role = role
# Ensure last non-system message is from user
return last_non_system_role == "user"
def ensure_alternating_roles(messages):
"""Ensure messages alternate between 'assistant' and 'user' roles.
Inserts empty messages of the opposite role when consecutive messages
of the same role are found.
Args:
messages: List of message dictionaries with 'role' and 'content' keys.
Returns:
List of messages with alternating roles.
"""
if not messages:
return messages
fixed_messages = []
prev_role = None
for msg in messages:
current_role = msg.get("role") # Get 'role', None if missing
# If current role same as previous, insert empty message
# of the opposite role
if current_role == prev_role:
if current_role == "user":
fixed_messages.append({"role": "assistant", "content": ""})
else:
fixed_messages.append({"role": "user", "content": ""})
fixed_messages.append(msg)
prev_role = current_role
return fixed_messages
def send_completion(
model_name,
messages,
@@ -24,6 +85,16 @@ def send_completion(
temperature=0,
extra_params=None,
):
#
#
if os.environ.get("AIDER_SANITY_CHECK_TURNS"):
sanity_check_messages(messages)
#
#
if "deepseek-reasoner" in model_name:
messages = ensure_alternating_roles(messages)
kwargs = dict(
model=model_name,
messages=messages,
@@ -59,6 +130,9 @@ def send_completion(
def simple_send_with_retries(model, messages):
litellm_ex = LiteLLMExceptions()
if "deepseek-reasoner" in model.name:
messages = ensure_alternating_roles(messages)
retry_delay = 0.125
while True:
try:

View File

@@ -112,7 +112,7 @@ def format_messages(messages, title=None):
output.append(f"{title.upper()} {'*' * 50}")
for msg in messages:
output.append("")
output.append("-------")
role = msg["role"].upper()
content = msg.get("content")
if isinstance(content, list): # Handle list content (e.g., image messages)
@@ -300,12 +300,15 @@ class Spinner:
def find_common_root(abs_fnames):
if len(abs_fnames) == 1:
return safe_abs_path(os.path.dirname(list(abs_fnames)[0]))
elif abs_fnames:
return safe_abs_path(os.path.commonpath(list(abs_fnames)))
else:
return safe_abs_path(os.getcwd())
try:
if len(abs_fnames) == 1:
return safe_abs_path(os.path.dirname(list(abs_fnames)[0]))
elif abs_fnames:
return safe_abs_path(os.path.commonpath(list(abs_fnames)))
except OSError:
pass
return safe_abs_path(os.getcwd())
def format_tokens(count):

View File

@@ -18,6 +18,7 @@ warnings.filterwarnings("ignore", category=SyntaxWarning)
from pydub import AudioSegment # noqa
from pydub.exceptions import CouldntDecodeError, CouldntEncodeError # noqa
try:
import soundfile as sf
@@ -140,13 +141,28 @@ class Voice:
while not self.q.empty():
file.write(self.q.get())
if self.audio_format != "wav":
filename = tempfile.mktemp(suffix=f".{self.audio_format}")
audio = AudioSegment.from_wav(temp_wav)
audio.export(filename, format=self.audio_format)
os.remove(temp_wav)
else:
filename = temp_wav
use_audio_format = self.audio_format
# Check file size and offer to convert to mp3 if too large
file_size = os.path.getsize(temp_wav)
if file_size > 24.9 * 1024 * 1024 and self.audio_format == "wav":
print("\nWarning: {temp_wav} is too large, switching to mp3 format.")
use_audio_format = "mp3"
filename = temp_wav
if use_audio_format != "wav":
try:
new_filename = tempfile.mktemp(suffix=f".{use_audio_format}")
audio = AudioSegment.from_wav(temp_wav)
audio.export(new_filename, format=use_audio_format)
os.remove(temp_wav)
filename = new_filename
except (CouldntDecodeError, CouldntEncodeError) as e:
print(f"Error converting audio: {e}")
except (OSError, FileNotFoundError) as e:
print(f"File system error during conversion: {e}")
except Exception as e:
print(f"Unexpected error during audio conversion: {e}")
with open(filename, "rb") as fh:
try:
@@ -157,7 +173,7 @@ class Voice:
print(f"Unable to transcribe {filename}: {err}")
return
if self.audio_format != "wav":
if filename != temp_wav:
os.remove(filename)
text = transcript.text

View File

@@ -23,15 +23,68 @@ cog.out(text)
]]]-->
### main branch
### Aider v0.72.3
- Enforce user/assistant turn order to avoid R1 errors, by miradnanali.
- Case-insensitive model name matching while preserving original case.
- Aider wrote 67% of the code in this release.
### Aider v0.72.2
- Harden against user/assistant turn order problems which cause R1 errors.
- Added environment variable AIDER_SANITY_CHECK_TURNS for turn order validation.
### Aider v0.72.1
- Fix model metadata for `openrouter/deepseek/deepseek-r1`
### Aider v0.72.0
- Support for DeepSeek R1.
- Use shortcut: `--model r1`
- Also via OpenRouter: `--model openrouter/deepseek/deepseek-r1`
- Added Kotlin syntax support to repo map, by Paul Walker.
- Added `--line-endings` for file writing, by Titusz Pan.
- Added examples_as_sys_msg=True for GPT-4o models, improves benchmark scores.
- Bumped all dependencies, to pick up litellm support for o1 system messages.
- Bugfix for turn taking when reflecting lint/test errors.
- Aider wrote 52% of the code in this release.
### Aider v0.71.1
- Fix permissions issue in Docker images.
- Added read-only file announcements.
- Bugfix: ASCII fallback for unicode errors.
- Bugfix: integer indices for list slicing in repomap calculations.
### Aider v0.71.0
- Prompts to help DeepSeek work better when alternating between `/ask` and `/code`.
- Streaming pretty LLM responses is smoother and faster for long replies.
- Streaming automatically turns of for model that don't support it
- Can now switch to/from `/model o1` and a streaming model
- Pretty output remains enabled even when editing files with triple-backtick fences
- Bare `/ask`, `/code` and `/architect` commands now switch the chat mode.
- Increased default size of the repomap.
- Increased max chat history tokens limit from 4k to 8k.
- Turn off fancy input and watch files if terminal is dumb.
- Added support for custom voice format and input device settings.
- Disabled Streamlit email prompt, by apaz-cli.
- Docker container runs as non-root user.
- Fixed lint command handling of nested spaced strings, by Aaron Weisberg.
- Added token count feedback when adding command output to chat.
- Improved error handling for large audio files with automatic format conversion.
- Improved handling of git repo index errors, by Krazer.
- Improved unicode handling in console output with ASCII fallback.
- Added AssertionError, AttributeError to git error handling.
- Aider wrote 60% of the code in this release.
### Aider v0.70.0
- Full support for o1 models.
- Watch files now honors `--subtree-only`, and only watches that sub tree.
- Watch files now honors `--subtree-only`, and only watches that subtree.
- Improved prompting for watch files, to work more reliably with more models.
- New install methods via uv, including one-liners.
- Support for openrouter/deepseek/deepseek-chat model.
- Better error handling when non-interactive commands are attempted via `/load` or `--load`.
- Display read-only files with abs path if it's shorter than rel path.
- Better error handling when interactive commands are attempted via `/load` or `--load`.
- Display read-only files with abs path if its shorter than rel path.
- Ask 10% of users to opt-in to analytics.
- Bugfix for auto-suggest.
- Gracefully handle unicode errors in git path names.

View File

@@ -3457,3 +3457,233 @@
Paul Gauthier (aider): 207
start_tag: v0.68.0
total_lines: 305
- aider_percentage: 74.22
aider_total: 875
end_date: '2024-12-26'
end_tag: v0.70.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/analytics.py:
Paul Gauthier: 6
Paul Gauthier (aider): 41
aider/args.py:
Evan Johnson: 2
aider/coders/search_replace.py:
Paul Gauthier: 5
aider/commands.py:
Paul Gauthier (aider): 41
aider/help_pats.py:
Paul Gauthier: 3
aider/io.py:
Paul Gauthier: 7
Paul Gauthier (aider): 9
aider/main.py:
Paul Gauthier: 15
Paul Gauthier (aider): 5
apaz-cli: 3
mdk: 6
aider/models.py:
Paul Gauthier: 29
aider/repo.py:
Paul Gauthier: 14
aider/utils.py:
Paul Gauthier: 2
aider/watch.py:
Paul Gauthier: 13
aider/website/_includes/head_custom.html:
Paul Gauthier (aider): 4
aider/website/_includes/leaderboard.js:
Paul Gauthier (aider): 14
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 28
Paul Gauthier (aider): 2
benchmark/Dockerfile:
Paul Gauthier: 8
Paul Gauthier (aider): 43
benchmark/benchmark.py:
Paul Gauthier: 69
Paul Gauthier (aider): 153
benchmark/clone-exercism.sh:
Paul Gauthier: 2
Paul Gauthier (aider): 18
benchmark/cpp-test.sh:
Paul Gauthier: 10
Paul Gauthier (aider): 1
benchmark/docker.sh:
Paul Gauthier (aider): 4
benchmark/install-docker-ubuntu.sh:
Paul Gauthier (aider): 63
benchmark/npm-test.sh:
Paul Gauthier: 10
Paul Gauthier (aider): 3
benchmark/problem_stats.py:
Paul Gauthier: 35
Paul Gauthier (aider): 318
benchmark/rsync.sh:
Paul Gauthier: 7
Paul Gauthier (aider): 26
scripts/blame.py:
Paul Gauthier (aider): 6
scripts/my_models.py:
Paul Gauthier (aider): 95
scripts/update-blame.sh:
Paul Gauthier (aider): 3
scripts/update-docs.sh:
Paul Gauthier: 1
tests/basic/test_analytics.py:
Paul Gauthier (aider): 19
tests/basic/test_main.py:
Paul Gauthier (aider): 7
tests/basic/test_sanity_check_repo.py:
mdk: 28
grand_total:
Evan Johnson: 2
Paul Gauthier: 265
Paul Gauthier (aider): 875
apaz-cli: 3
mdk: 34
start_tag: v0.69.0
total_lines: 1179
- aider_percentage: 60.36
aider_total: 236
end_date: '2025-01-10'
end_tag: v0.71.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/args.py:
Paul Gauthier: 2
aider/coders/base_coder.py:
Paul Gauthier: 7
Paul Gauthier (aider): 13
aider/commands.py:
Paul Gauthier: 1
Paul Gauthier (aider): 22
aider/io.py:
Paul Gauthier: 3
Paul Gauthier (aider): 16
aider/linter.py:
Aaron Weisberg: 5
aider/main.py:
Paul Gauthier: 7
Paul Gauthier (aider): 13
apaz-cli: 18
aider/mdstream.py:
Paul Gauthier: 38
Paul Gauthier (aider): 58
aider/models.py:
Paul Gauthier: 11
Paul Gauthier (aider): 2
aider/repo.py:
Krazer: 10
Paul Gauthier: 5
aider/run_cmd.py:
Aaron Weisberg: 2
aider/utils.py:
Paul Gauthier: 9
aider/voice.py:
Paul Gauthier: 11
Paul Gauthier (aider): 13
aider/watch.py:
Paul Gauthier: 1
benchmark/Dockerfile:
Josh Vera: 1
Paul Maunders: 12
benchmark/benchmark.py:
Nimesh Ghelani: 1
Paul Gauthier: 6
Paul Gauthier (aider): 30
benchmark/problem_stats.py:
Paul Gauthier (aider): 5
docker/Dockerfile:
Paul Gauthier (aider): 32
scripts/update-history.py:
Paul Gauthier (aider): 1
tests/basic/test_commands.py:
Paul Gauthier: 2
tests/basic/test_io.py:
Paul Gauthier (aider): 6
tests/basic/test_linter.py:
Aaron Weisberg: 2
tests/basic/test_models.py:
Paul Gauthier (aider): 25
grand_total:
Aaron Weisberg: 9
Josh Vera: 1
Krazer: 10
Nimesh Ghelani: 1
Paul Gauthier: 104
Paul Gauthier (aider): 236
Paul Maunders: 12
apaz-cli: 18
start_tag: v0.70.0
total_lines: 391
- aider_percentage: 51.69
aider_total: 138
end_date: '2025-01-20'
end_tag: v0.72.0
file_counts:
.github/workflows/docker-build-test.yml:
Paul Gauthier (aider): 38
.github/workflows/pages.yml:
Paul Gauthier: 3
Paul Gauthier (aider): 1
.github/workflows/ubuntu-tests.yml:
Paul Gauthier (aider): 8
.github/workflows/windows-tests.yml:
Paul Gauthier (aider): 8
aider/__init__.py:
Paul Gauthier: 1
aider/args.py:
Titusz Pan: 6
aider/coders/base_coder.py:
Paul Gauthier: 11
aider/coders/single_wholefile_func_coder.py:
Paul Gauthier: 1
aider/coders/wholefile_func_coder.py:
Paul Gauthier: 1
aider/commands.py:
Paul Gauthier: 3
aider/history.py:
Paul Gauthier: 7
aider/io.py:
Paul Gauthier (aider): 14
Titusz Pan: 2
aider/main.py:
Titusz Pan: 1
aider/models.py:
Paul Gauthier: 16
aider/queries/tree-sitter-kotlin-tags.scm:
Paul Walker: 27
aider/repomap.py:
Paul Gauthier (aider): 2
aider/sendchat.py:
Paul Gauthier: 9
Paul Gauthier (aider): 22
aider/utils.py:
Paul Gauthier: 1
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 2
benchmark/benchmark.py:
Paul Gauthier: 9
benchmark/rsync.sh:
Paul Gauthier: 21
docker/Dockerfile:
Paul Gauthier: 2
Paul Gauthier (aider): 6
scripts/my_models.py:
Paul Gauthier: 3
scripts/update-docs.sh:
Paul Gauthier: 2
tests/basic/test_io.py:
Paul Gauthier (aider): 39
tests/basic/test_repomap.py:
Paul Walker: 1
grand_total:
Paul Gauthier: 92
Paul Gauthier (aider): 138
Paul Walker: 28
Titusz Pan: 9
start_tag: v0.71.0
total_lines: 267

View File

@@ -24,58 +24,84 @@
seconds_per_case: 17.3
total_cost: 0.3236
- dirname: 2024-12-21-18-44-28--polyglot-sonnet
- dirname: 2025-01-17-19-44-33--sonnet-baseline-jan-17
test_cases: 225
model: claude-3-5-sonnet-20241022
edit_format: diff
commit_hash: a755079-dirty
pass_rate_1: 18.7
pass_rate_2: 45.3
pass_num_1: 42
pass_num_2: 102
percent_cases_well_formed: 100.0
error_outputs: 1
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 14
commit_hash: 6451d59
pass_rate_1: 22.2
pass_rate_2: 51.6
pass_num_1: 50
pass_num_2: 116
percent_cases_well_formed: 99.6
error_outputs: 2
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 11
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 12
test_timeouts: 8
total_tests: 225
command: aider --model claude-3-5-sonnet-20241022
date: 2024-12-21
versions: 0.69.2.dev
seconds_per_case: 30.8
total_cost: 13.4847
- dirname: 2024-12-21-18-52-34--polyglot-gpt-4o-diff
date: 2025-01-17
versions: 0.71.2.dev
seconds_per_case: 21.4
total_cost: 14.4063
- dirname: 2024-12-30-20-57-12--gpt-4o-2024-11-20-ex-as-sys
test_cases: 225
model: gpt-4o-2024-11-20
edit_format: diff
commit_hash: a755079-dirty
commit_hash: 09ee197-dirty
pass_rate_1: 4.9
pass_rate_2: 15.1
pass_rate_2: 18.2
pass_num_1: 11
pass_num_2: 34
percent_cases_well_formed: 96.0
pass_num_2: 41
percent_cases_well_formed: 95.1
error_outputs: 12
num_malformed_responses: 11
num_with_malformed_responses: 9
user_asks: 34
num_malformed_responses: 12
num_with_malformed_responses: 11
user_asks: 53
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 19
exhausted_context_windows: 0
test_timeouts: 12
total_tests: 225
command: aider --model gpt-4o-2024-11-20
date: 2024-12-21
versions: 0.69.2.dev
seconds_per_case: 22.2
total_cost: 7.1835
date: 2024-12-30
versions: 0.70.1.dev
seconds_per_case: 12.1
total_cost: 6.7351
- dirname: 2024-12-30-20-44-54--gpt4o-ex-as-sys-clean-prompt
test_cases: 225
model: gpt-4o-2024-08-06
edit_format: diff
commit_hash: 09ee197-dirty
pass_rate_1: 4.9
pass_rate_2: 23.1
pass_num_1: 11
pass_num_2: 52
percent_cases_well_formed: 94.2
error_outputs: 21
num_malformed_responses: 21
num_with_malformed_responses: 13
user_asks: 65
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
total_tests: 225
command: aider --model gpt-4o-2024-08-06
date: 2024-12-30
versions: 0.70.1.dev
seconds_per_case: 16.0
total_cost: 7.0286
- dirname: 2024-12-21-19-23-03--polyglot-o1-hard-diff
test_cases: 224
model: o1-2024-12-17 (high)
@@ -286,7 +312,7 @@
- dirname: 2024-12-25-13-31-51--deepseekv3preview-diff2
test_cases: 225
model: DeepSeek Chat V3 Preview
model: DeepSeek Chat V3
edit_format: diff
commit_hash: 0a23c4a-dirty
pass_rate_1: 22.7
@@ -310,3 +336,108 @@
seconds_per_case: 34.8
total_cost: 0.3369
- dirname: 2024-12-26-00-55-20--Qwen2.5-Coder-32B-Instruct
test_cases: 225
model: Qwen2.5-Coder-32B-Instruct
edit_format: whole
commit_hash: b51768b0
pass_rate_1: 4.9
pass_rate_2: 16.4
pass_num_1: 11
pass_num_2: 37
percent_cases_well_formed: 99.6
error_outputs: 1
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 33
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 6
total_tests: 225
command: aider --model openai/Qwen2.5-Coder-32B-Instruct
date: 2024-12-26
versions: 0.69.2.dev
seconds_per_case: 42.0
total_cost: 0.0000
- dirname: 2025-01-13-18-17-25--codestral-whole2
test_cases: 225
model: Codestral 25.01
edit_format: whole
commit_hash: 0cba898-dirty
pass_rate_1: 4.0
pass_rate_2: 11.1
pass_num_1: 9
pass_num_2: 25
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 47
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 4
total_tests: 225
command: aider --model mistral/codestral-latest
date: 2025-01-13
versions: 0.71.2.dev
seconds_per_case: 9.3
total_cost: 1.9834
- dirname: 2025-01-20-19-11-38--ds-turns-upd-cur-msgs-fix-with-summarizer
test_cases: 225
model: DeepSeek R1
edit_format: diff
commit_hash: 5650697-dirty
pass_rate_1: 26.7
pass_rate_2: 56.9
pass_num_1: 60
pass_num_2: 128
percent_cases_well_formed: 96.9
error_outputs: 8
num_malformed_responses: 7
num_with_malformed_responses: 7
user_asks: 15
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 5
total_tests: 225
command: aider --model deepseek/deepseek-reasoner
date: 2025-01-20
versions: 0.71.2.dev
seconds_per_case: 113.7
total_cost: 5.4193
- dirname: 2025-01-23-19-14-48--r1-architect-sonnet
test_cases: 225
model: DeepSeek R1 + claude-3-5-sonnet-20241022
edit_format: architect
commit_hash: 05a77c7
editor_model: claude-3-5-sonnet-20241022
editor_edit_format: editor-diff
pass_rate_1: 27.1
pass_rate_2: 64.0
pass_num_1: 61
pass_num_2: 144
percent_cases_well_formed: 100.0
error_outputs: 2
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 392
lazy_comments: 6
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 5
total_tests: 225
command: aider --architect --model r1 --editor-model sonnet
date: 2025-01-23
versions: 0.72.3.dev
seconds_per_case: 251.6
total_cost: 13.2933

View File

@@ -0,0 +1,138 @@
- dirname: 2025-01-23-19-14-48--r1-architect-sonnet
test_cases: 225
model: R1+Sonnet
edit_format: architect
commit_hash: 05a77c7
editor_model: claude-3-5-sonnet-20241022
editor_edit_format: editor-diff
pass_rate_1: 27.1
pass_rate_2: 64.0
pass_num_1: 61
pass_num_2: 144
percent_cases_well_formed: 100.0
error_outputs: 2
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 392
lazy_comments: 6
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 5
total_tests: 225
command: aider --architect --model r1 --editor-model sonnet
date: 2025-01-23
versions: 0.72.3.dev
seconds_per_case: 251.6
total_cost: 13.2933
- dirname: 2025-01-20-19-11-38--ds-turns-upd-cur-msgs-fix-with-summarizer
test_cases: 225
model: R1
edit_format: diff
commit_hash: 5650697-dirty
pass_rate_1: 26.7
pass_rate_2: 56.9
pass_num_1: 60
pass_num_2: 128
percent_cases_well_formed: 96.9
error_outputs: 8
num_malformed_responses: 7
num_with_malformed_responses: 7
user_asks: 15
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 5
total_tests: 225
command: aider --model r1
date: 2025-01-20
versions: 0.71.2.dev
seconds_per_case: 113.7
total_cost: 5.4193
- dirname: 2024-12-21-19-23-03--polyglot-o1-hard-diff
test_cases: 224
model: o1
edit_format: diff
commit_hash: a755079-dirty
pass_rate_1: 23.7
pass_rate_2: 61.7
pass_num_1: 53
pass_num_2: 139
percent_cases_well_formed: 91.5
error_outputs: 25
num_malformed_responses: 24
num_with_malformed_responses: 19
user_asks: 16
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
total_tests: 225
command: aider --model o1
date: 2024-12-21
versions: 0.69.2.dev
seconds_per_case: 133.2
total_cost: 186.4958
- dirname: 2024-12-25-13-31-51--deepseekv3preview-diff2
test_cases: 225
model: DeepSeek V3
edit_format: diff
commit_hash: 0a23c4a-dirty
pass_rate_1: 22.7
pass_rate_2: 48.4
pass_num_1: 51
pass_num_2: 109
percent_cases_well_formed: 98.7
error_outputs: 7
num_malformed_responses: 7
num_with_malformed_responses: 3
user_asks: 19
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 8
total_tests: 225
command: aider --model deepseek
date: 2024-12-25
versions: 0.69.2.dev
seconds_per_case: 34.8
total_cost: 0.3369
- dirname: 2025-01-17-19-44-33--sonnet-baseline-jan-17
test_cases: 225
model: Sonnet
edit_format: diff
commit_hash: 6451d59
pass_rate_1: 22.2
pass_rate_2: 51.6
pass_num_1: 50
pass_num_2: 116
percent_cases_well_formed: 99.6
error_outputs: 2
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 11
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 8
total_tests: 225
command: aider --model sonnet
date: 2025-01-17
versions: 0.71.2.dev
seconds_per_case: 21.4
total_cost: 14.4063

View File

@@ -1,5 +1,18 @@
<canvas id="blameChart" width="800" height="360" style="margin-top: 20px"></canvas>
<canvas id="linesChart" width="800" height="360" style="margin-top: 20px"></canvas>
<div class="chart-container">
<canvas id="blameChart" style="margin-top: 20px"></canvas>
</div>
<div class="chart-container">
<canvas id="linesChart" style="margin-top: 20px"></canvas>
</div>
<style>
.chart-container {
position: relative;
width: 100%;
height: 300px;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>
@@ -24,10 +37,17 @@ document.addEventListener('DOMContentLoaded', function () {
var linesData = {
labels: labels,
datasets: [{
label: 'Aider\'s lines of new code',
label: 'Aider',
data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.aider_total }} },{% endfor %}],
backgroundColor: 'rgba(255, 99, 132, 0.8)',
borderColor: 'rgba(255, 99, 132, 1)',
backgroundColor: 'rgba(54, 162, 235, 0.8)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
},
{
label: 'Human',
data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.total_lines | minus: row.aider_total }} },{% endfor %}],
backgroundColor: 'rgba(200, 200, 200, 0.8)',
borderColor: 'rgba(200, 200, 200, 1)',
borderWidth: 1
}]
};
@@ -36,6 +56,7 @@ document.addEventListener('DOMContentLoaded', function () {
type: 'bar',
data: blameData,
options: {
maintainAspectRatio: false,
scales: {
x: {
type: 'category',
@@ -85,9 +106,11 @@ document.addEventListener('DOMContentLoaded', function () {
type: 'bar',
data: linesData,
options: {
maintainAspectRatio: false,
scales: {
x: {
type: 'category',
stacked: true,
title: {
display: true,
text: 'Version'
@@ -98,6 +121,7 @@ document.addEventListener('DOMContentLoaded', function () {
}
},
y: {
stacked: true,
title: {
display: true,
text: 'Lines of new code'
@@ -107,12 +131,14 @@ document.addEventListener('DOMContentLoaded', function () {
},
plugins: {
legend: {
display: false
display: true,
position: 'chartArea',
reverse: true
},
tooltip: {
callbacks: {
label: function(context) {
var label = 'New lines of code by aider';
var label = context.dataset.label;
var value = context.parsed.y || 0;
return `${label}: ${value}`;
}
@@ -120,7 +146,7 @@ document.addEventListener('DOMContentLoaded', function () {
},
title: {
display: true,
text: 'Lines of new code written by aider, by release',
text: 'Lines of new code, by release',
font: {
size: 16
}

View File

@@ -96,7 +96,7 @@ document.addEventListener('DOMContentLoaded', function () {
options: {
plugins: {
legend: {
display: true,
display: {% if show_legend == false %}false{% else %}true{% endif %},
labels: {
generateLabels: function(chart) {
return [

View File

@@ -1,2 +1 @@
Aider works best with GPT-4o & Claude 3.5 Sonnet and can
[connect to almost any LLM](https://aider.chat/docs/llms.html).
Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).

View File

@@ -0,0 +1,102 @@
---
title: Using uv as an installer
excerpt: Reliably packaging & distributing python CLI tools is hard. Aider uses uv in novel ways to make it easy to install the aider CLI, its dependencies and python 3.12. All in an isolated env.
draft: false
nav_exclude: true
---
{% if page.date %}
<p class="post-date">{{ page.date | date: "%B %d, %Y" }}</p>
{% endif %}
# Using uv as an installer
{: .no_toc }
It's hard to reliably
package and distribute python command line tools
to end users.
Users frequently encounter challenges:
dependency version conflicts, virtual environment management,
needing to install python or a specific version of python, etc.
Aider employs [uv](https://github.com/astral-sh/uv)
in a couple of novel ways to streamline the installation process:
1. Install aider with
`curl https://aider.chat/install.sh | sh` even if python isn't already installed.
2. Users who have python 3.8+ installed can `pip install aider-install && aider-install`.
Both methods use uv to **globally** install the `aider` command line program,
with all of its dependencies in an **isolated environment**.
They ensure that aider will run with **python 3.12**, and install that version
if it is not already available.
These uv install methods are especially helpful for aider, because it
has a large set of very specific dependencies.
Since not all of aider's dependencies are available on all python versions,
it requires python 3.9-3.12.
Most users don't want to worry about these details --
they just want a quick way to install and run aider.
## One-liners
Users can install aider with a shell one-liner, without even having python previously installed:
```bash
curl -LsSf https://aider.chat/install.sh | sh
```
This installs uv, then uses it to install python 3.12,
install the `aider` command line tool
and update the user's shell path.
Under the hood, it is simply a copy of
uv's own install script `https://astral.sh/uv/install.sh`
with [one line added](https://github.com/Aider-AI/aider/blob/4251e976b3aa52c2a3af08da4b203d4d524c8e92/aider/website/install.sh#L1181), to install aider as a tool:
```
ensure "${_install_dir}/uv" tool install --force --python python3.12 aider-chat@latest
```
## aider-install
The aider-install python package allows quick global installation of aider
for users who already have python 3.8+ installed.
It simply provides the `aider-install` command line program,
which users just need to run once.
```bash
pip install aider-install
aider-install
```
The `pip install aider-install` installs only two packages:
aider-install and the [uv python package](https://pypi.org/project/uv/).
This ensures that uv is available
in the user's environment.
Everything else is installed in a stand-alone environment created by uv.
When the user runs `aider-install`, it runs uv
to install aider as a tool and update the user's shell path if needed:
```bash
uv tool install --force --python python3.12 aider-chat
uv tool update-shell
```
## Benefits
These uv install methods have been popular with users,
providing a hassle free way to install aider and quickly get started.
Installs are also extremely fast, much faster than pip or pipx installs
even when uv is also installing python 3.12!
There are also a number of benefits from the perspective of the tool developer/publisher.
Since providing these install methods, far fewer users report dependency problems and
version conflicts as compared to users who `pip install aider-chat`.
There is also less pressure to rapidly support the newest python versions,
since aider always installs with python 3.12.

View File

@@ -0,0 +1,117 @@
---
title: R1+Sonnet set SOTA on aider's polyglot benchmark
excerpt: R1+Sonnet has set a new SOTA on the aider polyglot benchmark. At 14X less cost compared to o1.
highlight_image: /assets/r1-sonnet-sota.jpg
draft: false
nav_exclude: true
---
{% if page.date %}
<p class="post-date">{{ page.date | date: "%B %d, %Y" }}</p>
{% endif %}
# R1+Sonnet set SOTA on aider's polyglot benchmark
{: .no_toc }
<canvas id="editChart" width="800" height="450" style="margin-top: 20px"></canvas>
Aider supports [using a pair of models for coding](https://aider.chat/2024/09/26/architect.html):
- An Architect model is asked to describe how to solve the coding problem. Thinking/reasoning models often work well in this role.
- An Editor model is given the Architect's solution and asked to produce specific code editing instructions to apply those changes to existing source files.
**R1 as architect with Sonnet as editor has set a new SOTA of 64.0%** on the
[aider polyglot benchmark](/2024/12/21/polyglot.html).
They achieve this at **14X less cost** compared to the previous o1 SOTA result.
o1 paired with Sonnet didn't produce better results than just using o1 alone.
Using various other models as editor didn't seem to improve o1 or R1 versus their solo scores.
This is in contrast to the first wave of thinking models like o1-preview and o1-mini,
which improved when paired with many different editor models.
## Try it
Once you [install aider](https://aider.chat/docs/install.html),
you can use aider, R1 and Sonnet like this:
```bash
export DEEPSEEK_API_KEY=<your-key>
export ANTHROPIC_API_KEY=<your-key>
aider --architect --model r1 --editor-model sonnet
```
Or if you have an [OpenRouter](https://openrouter.ai) account:
```bash
export OPENROUTER_API_KEY=<your-key>
aider --architect --model openrouter/deepseek/deepseek-r1 --editor-model openrouter/anthropic/claude-3.5-sonnet
```
## Thinking output
There has been
[some recent discussion](https://github.com/Aider-AI/aider/pull/2973)
about extracting the `<think>` tokens from R1's responses
and feeding them to Sonnet.
That was an interesting experiment, for sure.
To be clear, the results above are *not* using R1's thinking tokens, just the normal
final output.
R1 is configured in aider's standard architect role with Sonnet as editor.
The benchmark results that used the thinking tokens appear to be worse than
the architect/editor results shared here.
## Results
<table style="width: 100%; max-width: 800px; margin: auto; border-collapse: collapse; box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 14px;">
<thead style="background-color: #f2f2f2;">
<tr>
<th style="padding: 8px; text-align: left;">Model</th>
<th style="padding: 8px; text-align: center;">Percent completed correctly</th>
<th style="padding: 8px; text-align: center;">Percent using correct edit format</th>
<th style="padding: 8px; text-align: left;">Command</th>
<th style="padding: 8px; text-align: center;">Edit format</th>
<th style="padding: 8px; text-align: center;">Total Cost</th>
</tr>
</thead>
<tbody>
{% assign edit_sorted = site.data.r1_architect | sort: 'pass_rate_2' | reverse %}
{% for row in edit_sorted %}
<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 8px;">{{ row.model }}</td>
<td style="padding: 8px; text-align: center;">{{ row.pass_rate_2 }}%</td>
<td style="padding: 8px; text-align: center;">{{ row.percent_cases_well_formed }}%</td>
<td style="padding: 8px;"><code>{{ row.command }}</code></td>
<td style="padding: 8px; text-align: center;">{{ row.edit_format }}</td>
<td style="padding: 8px; text-align: center;">{% if row.total_cost == 0 %}?{% else %}${{ row.total_cost | times: 1.0 | round: 2 }}{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
<script src="https://unpkg.com/patternomaly/dist/patternomaly.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
{% assign data_source = edit_sorted %}
{% assign pass_rate_field = "pass_rate_2" %}
{% assign highlight_model = "+" %}
{% assign show_legend = false %}
{% include leaderboard.js %}
</script>
<style>
tr.selected {
color: #0056b3;
}
table {
table-layout: fixed;
}
td, th {
word-wrap: break-word;
overflow-wrap: break-word;
}
td:nth-child(3), td:nth-child(4) {
font-size: 12px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

File diff suppressed because one or more lines are too long

View File

@@ -44,7 +44,7 @@
## Use gpt-3.5-turbo model for the main chat
#35turbo: false
## Use deepseek/deepseek-coder model for the main chat
## Use deepseek/deepseek-chat model for the main chat
#deepseek: false
## Use o1-mini model for the main chat
@@ -152,7 +152,7 @@
###################
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
## Suggested number of tokens to use for repo map, use 0 to disable
#map-tokens: xxx
## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto)
@@ -410,6 +410,9 @@
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Line endings to use when writing files (default: platform)
#line-endings: platform
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx

View File

@@ -48,7 +48,7 @@
## Use gpt-3.5-turbo model for the main chat
#AIDER_35TURBO=
## Use deepseek/deepseek-coder model for the main chat
## Use deepseek/deepseek-chat model for the main chat
#AIDER_DEEPSEEK=
## Use o1-mini model for the main chat
@@ -141,7 +141,7 @@
###################
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
## Suggested number of tokens to use for repo map, use 0 to disable
#AIDER_MAP_TOKENS=
## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto)
@@ -381,6 +381,9 @@
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Line endings to use when writing files (default: platform)
#AIDER_LINE_ENDINGS=platform
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env

View File

@@ -235,7 +235,7 @@ cog.out("```\n")
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: null
examples_as_sys_msg: false
examples_as_sys_msg: true
extra_params: null
lazy: true
name: openai/gpt-4o
@@ -251,7 +251,7 @@ cog.out("```\n")
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
examples_as_sys_msg: true
extra_params: null
lazy: true
name: openai/gpt-4o-2024-08-06
@@ -267,7 +267,7 @@ cog.out("```\n")
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
examples_as_sys_msg: true
extra_params: null
lazy: true
name: gpt-4o-2024-08-06
@@ -283,7 +283,7 @@ cog.out("```\n")
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
examples_as_sys_msg: true
extra_params: null
lazy: true
name: gpt-4o-2024-11-20
@@ -299,7 +299,7 @@ cog.out("```\n")
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
examples_as_sys_msg: true
extra_params: null
lazy: true
name: openai/gpt-4o-2024-11-20
@@ -315,7 +315,7 @@ cog.out("```\n")
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: null
examples_as_sys_msg: false
examples_as_sys_msg: true
extra_params: null
lazy: true
name: gpt-4o
@@ -1080,7 +1080,41 @@ cog.out("```\n")
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
caches_by_default: true
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: openrouter/deepseek/deepseek-chat
examples_as_sys_msg: true
extra_params:
max_tokens: 8192
lazy: false
name: openrouter/deepseek/deepseek-r1
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: false
weak_model_name: openrouter/deepseek/deepseek-chat
- cache_control: false
caches_by_default: true
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: deepseek/deepseek-chat
examples_as_sys_msg: true
extra_params:
max_tokens: 8192
lazy: false
name: deepseek/deepseek-reasoner
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: false
weak_model_name: deepseek/deepseek-chat
- cache_control: false
caches_by_default: true
edit_format: diff
editor_edit_format: null
editor_model_name: null
@@ -1184,7 +1218,7 @@ cog.out("```\n")
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: null
examples_as_sys_msg: false
examples_as_sys_msg: true
extra_params: null
lazy: true
name: openrouter/openai/gpt-4o

View File

@@ -7,13 +7,15 @@ description: How to configure aider with a yaml config file.
# YAML config file
Most of aider's options can be set in an `.aider.conf.yml` file.
Aider will look for a this file in these locations and
load whichever is found first.
Aider will look for a this file in these locations:
- As specified with the `--config <filename>` parameter.
- The current directory.
- The root of your git repo.
- Your home directory.
- The root of your git repo.
- The current directory.
If the files above exist, they will be loaded in that order. Files loaded last will take priority.
You can also specify the `--config <filename>` parameter, which will only load the one config file.
{% include keys.md %}
@@ -96,7 +98,7 @@ cog.outl("```")
## Use gpt-3.5-turbo model for the main chat
#35turbo: false
## Use deepseek/deepseek-coder model for the main chat
## Use deepseek/deepseek-chat model for the main chat
#deepseek: false
## Use o1-mini model for the main chat
@@ -204,7 +206,7 @@ cog.outl("```")
###################
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
## Suggested number of tokens to use for repo map, use 0 to disable
#map-tokens: xxx
## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto)
@@ -462,6 +464,9 @@ cog.outl("```")
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Line endings to use when writing files (default: platform)
#line-endings: platform
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx

View File

@@ -88,7 +88,7 @@ cog.outl("```")
## Use gpt-3.5-turbo model for the main chat
#AIDER_35TURBO=
## Use deepseek/deepseek-coder model for the main chat
## Use deepseek/deepseek-chat model for the main chat
#AIDER_DEEPSEEK=
## Use o1-mini model for the main chat
@@ -181,7 +181,7 @@ cog.outl("```")
###################
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
## Suggested number of tokens to use for repo map, use 0 to disable
#AIDER_MAP_TOKENS=
## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto)
@@ -421,6 +421,9 @@ cog.outl("```")
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Line endings to use when writing files (default: platform)
#AIDER_LINE_ENDINGS=platform
## Specify the .env file to load (default: .env in git root)
#AIDER_ENV_FILE=.env

View File

@@ -55,10 +55,11 @@ for alias, model in sorted(MODEL_ALIASES.items()):
- `4`: gpt-4-0613
- `4-turbo`: gpt-4-1106-preview
- `4o`: gpt-4o
- `deepseek`: deepseek/deepseek-coder
- `deepseek`: deepseek/deepseek-chat
- `flash`: gemini/gemini-2.0-flash-exp
- `haiku`: claude-3-5-haiku-20241022
- `opus`: claude-3-opus-20240229
- `r1`: deepseek/deepseek-reasoner
- `sonnet`: claude-3-5-sonnet-20241022
<!--[[[end]]]-->

View File

@@ -73,7 +73,7 @@ usage: aider [-h] [--model] [--opus] [--sonnet] [--haiku] [--4]
[--show-prompts] [--voice-format] [--voice-language]
[--voice-input-device] [--file] [--read] [--vim]
[--chat-language] [--yes-always] [-v] [--load]
[--encoding] [-c] [--env-file]
[--encoding] [--line-endings] [-c] [--env-file]
[--suggest-shell-commands | --no-suggest-shell-commands]
[--fancy-input | --no-fancy-input]
[--multiline | --no-multiline]
@@ -136,7 +136,7 @@ Aliases:
- `-3`
### `--deepseek`
Use deepseek/deepseek-coder model for the main chat
Use deepseek/deepseek-chat model for the main chat
Environment variable: `AIDER_DEEPSEEK`
### `--o1-mini`
@@ -275,7 +275,7 @@ Environment variable: `AIDER_CACHE_KEEPALIVE_PINGS`
## Repomap settings:
### `--map-tokens VALUE`
Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
Suggested number of tokens to use for repo map, use 0 to disable
Environment variable: `AIDER_MAP_TOKENS`
### `--map-refresh VALUE`
@@ -705,6 +705,11 @@ Specify the encoding for input and output (default: utf-8)
Default: utf-8
Environment variable: `AIDER_ENCODING`
### `--line-endings VALUE`
Line endings to use when writing files (default: platform)
Default: platform
Environment variable: `AIDER_LINE_ENDINGS`
### `--config CONFIG_FILE`
Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
Aliases:

View File

@@ -141,6 +141,18 @@ When starting a fresh aider session, you can include recent git history in the c
Remember, the chat history already includes recent changes made during the current session, so this tip is most useful when starting a new aider session and you want to provide context about recent work.
You can also use aider to review PR branches:
```
/run git diff one-branch..another-branch
...
Add 6.9k tokens of command output to the chat? (Y)es/(N)o [Yes]: Yes
/ask Are there any problems with the way this change works with the FooBar class?
```
{: .tip }
The `/git` command will not work for this purpose, as its output is not included in the chat.
@@ -237,11 +249,16 @@ tr:hover { background-color: #f5f5f5; }
</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,951,105</td><td class='right'>99.0%</td></tr>
<tr><td>claude-3-5-haiku-20241022</td><td class='right'>14,008</td><td class='right'>0.7%</td></tr>
<tr><td>gpt-4o</td><td class='right'>4,273</td><td class='right'>0.2%</td></tr>
<tr><td>openrouter/REDACTED</td><td class='right'>1,234</td><td class='right'>0.1%</td></tr>
<tr><td>openai/gpt-4o-mini</td><td class='right'>141</td><td class='right'>0.0%</td></tr>
<tr><td>deepseek/deepseek-chat</td><td class='right'>1,373,934</td><td class='right'>57.3%</td></tr>
<tr><td>claude-3-5-sonnet-20241022</td><td class='right'>652,556</td><td class='right'>27.2%</td></tr>
<tr><td>deepseek/REDACTED</td><td class='right'>308,841</td><td class='right'>12.9%</td></tr>
<tr><td>o1</td><td class='right'>25,121</td><td class='right'>1.0%</td></tr>
<tr><td>claude-3-5-haiku-20241022</td><td class='right'>10,083</td><td class='right'>0.4%</td></tr>
<tr><td>gemini/gemini-exp-1206</td><td class='right'>10,068</td><td class='right'>0.4%</td></tr>
<tr><td>mistral/codestral-latest</td><td class='right'>8,137</td><td class='right'>0.3%</td></tr>
<tr><td>deepseek/deepseek-reasoner</td><td class='right'>5,517</td><td class='right'>0.2%</td></tr>
<tr><td>gpt-4o</td><td class='right'>1,775</td><td class='right'>0.1%</td></tr>
<tr><td>o1-preview</td><td class='right'>175</td><td class='right'>0.0%</td></tr>
</table>
{: .note :}

View File

@@ -81,7 +81,7 @@ cog.out(get_supported_languages_md())
| jsdoc | .jsdoc | | ✓ |
| json | .json | | ✓ |
| julia | .jl | | ✓ |
| kotlin | .kt | | ✓ |
| kotlin | .kt | | ✓ |
| lua | .lua | | ✓ |
| make | .mk | | ✓ |
| objc | .m | | ✓ |

View File

@@ -113,9 +113,8 @@ import subprocess
import datetime
files = [
'aider/website/docs/leaderboards/index.md',
'aider/website/docs/leaderboards/edit.md',
'aider/website/_data/edit_leaderboard.yml',
'aider/website/_data/refactor_leaderboard.yml'
]
def get_last_modified_date(file):
@@ -129,6 +128,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 16, 2024.
January 16, 2025.
<!--[[[end]]]-->
</p>

View File

@@ -107,8 +107,7 @@ import datetime
files = [
'aider/website/docs/leaderboards/index.md',
'aider/website/_data/edit_leaderboard.yml',
'aider/website/_data/refactor_leaderboard.yml'
'aider/website/_data/polyglot_leaderboard.yml',
]
def get_last_modified_date(file):
@@ -122,6 +121,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 26, 2024.
January 25, 2025.
<!--[[[end]]]-->
</p>

View File

@@ -50,3 +50,29 @@ Therefore, results are available for fewer models.
</script>
<p class="post-date">
By Paul Gauthier,
last updated
<!--[[[cog
import subprocess
import datetime
files = [
'aider/website/docs/leaderboards/refactor.md',
'aider/website/_data/refactor_leaderboard.yml',
]
def get_last_modified_date(file):
result = subprocess.run(['git', 'log', '-1', '--format=%ct', file], capture_output=True, text=True)
if result.returncode == 0:
timestamp = int(result.stdout.strip())
return datetime.datetime.fromtimestamp(timestamp)
return datetime.datetime.min
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.')}")
]]]-->
January 16, 2025.
<!--[[[end]]]-->
</p>

View File

@@ -53,6 +53,12 @@ To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dep
pipx inject aider-chat boto3
```
You must install `boto3` dependency to aider's virtual environment installed via one-liner or uv by running
```bash
uv tool run --from aider-chat pip install boto3
```
## Running Aider with Bedrock

View File

@@ -65,14 +65,17 @@ cog.out(model_list)
- claude-3-sonnet-20240229
- codestral/codestral-2405
- codestral/codestral-latest
- deepseek-chat
- deepseek-coder
- deepseek/deepseek-chat
- deepseek/deepseek-coder
- deepseek/deepseek-reasoner
- eu.anthropic.claude-3-5-haiku-20241022-v1:0
- eu.anthropic.claude-3-5-sonnet-20241022-v2:0
- mistral/codestral-2405
- mistral/codestral-latest
- mistral/codestral-mamba-latest
- mistral/mistral-large-2402
- mistral/mistral-large-2407
- mistral/mistral-large-2411
- mistral/mistral-large-latest
- mistral/mistral-medium
- mistral/mistral-medium-2312
@@ -87,6 +90,8 @@ cog.out(model_list)
- mistral/open-mixtral-8x22b
- mistral/open-mixtral-8x7b
- mistral/pixtral-12b-2409
- mistral/pixtral-large-2411
- mistral/pixtral-large-latest
- openrouter/anthropic/claude-3.5-sonnet
- us.anthropic.claude-3-5-haiku-20241022-v1:0
- us.anthropic.claude-3-5-sonnet-20241022-v2:0

View File

@@ -62,6 +62,12 @@ Aider v0.50.2-dev
Models: claude-3-5-sonnet-20240620 with ♾️ diff edit format
```
## Try architect mode
Run aider with `--architect` or `/chat-mode architect` to enable [architect mode](../usage/modes.md#architect-mode-and-the-editor-model).
This mode first proposes changes, then uses a separate model to handle the file edits.
This two-step process often produces more reliable edits, especially with models that have trouble
following edit format instructions.
## More help

View File

@@ -22,11 +22,11 @@ cog.out(get_help_md())
|Command|Description|
|:------|:----------|
| **/add** | Add files to the chat so aider can edit them or review them in detail |
| **/architect** | Enter architect mode to discuss high-level design and architecture |
| **/ask** | Ask questions about the code base without editing any files |
| **/architect** | Enter architect/editor mode using 2 different models. If no prompt provided, switches to architect/editor mode. |
| **/ask** | Ask questions about the code base without editing any files. If no prompt provided, switches to ask mode. |
| **/chat-mode** | Switch to a new chat mode |
| **/clear** | Clear the chat history |
| **/code** | Ask for changes to your code |
| **/code** | Ask for changes to your code. If no prompt provided, switches to code mode. |
| **/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 |

View File

@@ -29,6 +29,14 @@ with the `/chat-mode <mode>` command:
/chat-mode help
```
Or you can switch between coding modes using these commands without arguments:
```
/code
/architect
/ask
```
Or you can launch aider in one of the modes with the `--chat-mode <mode>` switch.
There is also a special shortcut `--architect` to launch in `--chat-mode architect`.

View File

@@ -0,0 +1,179 @@
---
parent: Usage
nav_order: 901
description: Use aider to edit configuration files, documentation, and other text-based formats.
---
# Editing config & text files
Aider isn't just for code, it can be very helpful when editing
almost any text file.
You can use aider to make changes to your shell & ssh settings,
Dockerfiles
or pretty much any configuration or documentation file.
Here are some practical examples of modifying common config/text files:
## Shell Configuration
<div class="chat-transcript" markdown="1">
$ aider .bashrc
Added .bashrc to the chat.
#### Add an alias 'll' that lists all files, with all details in human readable format. And update PATH to include uv installed tools.
```
+ alias ll='ls -alh'
+ export PATH="$PATH:$HOME/.local/bin:$PATH"
```
</div>
## SSH Configurations
<div class="chat-transcript" markdown="1">
$ aider ~/.ssh/config
Added config to the chat.
#### Create a Host entry 'my-server' using bastion.example.com as JumpHost
```
+ Host my-server
+ HostName 192.168.1.100
+ User deploy
+ Port 2222
+ IdentityFile ~/.ssh/deploy_key
+ ProxyJump bastion.example.com
```
</div>
## Docker Setup
<div class="chat-transcript" markdown="1">
$ aider Dockerfile docker-compose.yml
Added Dockerfile and docker-compose.yml to the chat.
#### Set non-root user and enable healthchecks
```
+ USER appuser
+ HEALTHCHECK --interval=30s --timeout=3s \
+ CMD curl -f http://localhost:8000/health || exit 1
```
#### Expose port 5432 and add volume for postgres data
```
services:
postgres:
image: postgres:15
+ ports:
+ - "5432:5432"
+ volumes:
+ - pgdata:/var/lib/postgresql/data
```
</div>
## Git Configuration
<div class="chat-transcript" markdown="1">
$ aider .gitconfig
Added .gitconfig to the chat.
#### Set default push behavior to current branch and enable color UI
```
+ [push]
+ default = current
+ [color]
+ ui = auto
```
</div>
## System Configuration
<div class="chat-transcript" markdown="1">
$ aider /etc/hosts # May need sudo
Added hosts to the chat.
#### Block tracking domains by pointing them to 127.0.0.1
```
+ 127.0.0.1 ads.example.com
+ 127.0.0.1 track.analytics.co
```
</div>
## Editor Configs
<div class="chat-transcript" markdown="1">
$ aider .vimrc
Added .vimrc to the chat.
#### Enable line numbers and set 4-space tabs for Python
```
+ set number
+ autocmd FileType python set tabstop=4 shiftwidth=4 expandtab
```
</div>
## VSCode Configuration
<div class="chat-transcript" markdown="1">
$ aider settings.json
Added settings.json to the chat.
#### Enable auto-format on save and set default formatter
```
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
```
</div>
## Markdown Documentation
<div class="chat-transcript" markdown="1">
$ aider README.md
Added README.md to the chat.
#### Add installation section with brew and pip options
```
+ ## Installation
+ ```
+ # Homebrew
+ brew install cool-app-10k
+
+ # PyPI
+ pipx install cool-app-10k
+ ```
```
</div>
## XML Configuration
<div class="chat-transcript" markdown="1">
$ aider pom.xml
Added pom.xml to the chat.
#### Add JUnit 5 dependency with test scope
```
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>5.9.2</version>
+ <scope>test</scope>
+ </dependency>
```
</div>

View File

@@ -3,7 +3,7 @@ title: Aider in your IDE
#highlight_image: /assets/browser.jpg
parent: Usage
nav_order: 750
description: Aider can run in your browser, not just on the command line.
description: Aider can watch your files and respond to AI comments you add in your favorite IDE or text editor.
---
# Aider in your IDE
@@ -34,7 +34,7 @@ description: Aider can run in your browser, not just on the command line.
## AI comments
If you run aider with `--watch-files`, it will watch all files in your repo
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`, `AI!` or `AI?` like these:
@@ -52,14 +52,14 @@ Or in `//` comment languages...
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
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.
See the demo video above that shows aider working with AI comments in VSCode.
## Example
@@ -88,8 +88,8 @@ Aider only watches for these types of **one-liner** comments:
```
# Python and bash style
// Javascript style
-- SQL style
// Javascript style
-- SQL style
```
Aider will look for those comment types in all files.
@@ -102,7 +102,7 @@ This capability is quite flexible and powerful, and can be used in many ways.
### In-context instructions
You can add an AI comment in the function you want changed,
You can add an AI comment in the function you want changed,
explaining the change request in-context right where you want the changes.
```javascript
@@ -129,15 +129,15 @@ Just use `AI!` last, to trigger aider.
def factorial(n):
if n < 0:
return jsonify(error="Factorial is not defined for negative numbers"), 400
# AI: Refactor this code...
result = 1
for i in range(1, n + 1):
result *= i
# ... into to a compute_factorial() function. AI!
return jsonify(result=result)
```
@@ -180,7 +180,7 @@ 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.
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.
@@ -194,14 +194,14 @@ comments with full sentences, proper capitalization, punctuation, etc.
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.
inferring implied intent.
This often allows you to be quite lazy with your AI comments.
In particular, you can start and end comments with lowercase `ai` and `ai!`,
but you can also be much more terse with the request itself.
Below are simpler versions of some of the examples given above.
When the context clearly implies the needed action, `ai!` might be all you
need. For example, to implement a factorial function
need. For example, to implement a factorial function
in a program full of other math functions either of these
approaches would probably work:
@@ -237,15 +237,15 @@ Similarly, this refactor probably could have been requested with fewer words, li
def factorial(n):
if n < 0:
return jsonify(error="Factorial is not defined for negative numbers"), 400
# ai refactor...
result = 1
for i in range(1, n + 1):
result *= i
# ... to compute_factorial() ai!
return jsonify(result=result)
```
@@ -289,7 +289,6 @@ todo_app.py:
#### Credits
*This feature was inspired by
*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

@@ -32,9 +32,9 @@ cog.out(text)
Aider lets you pair program with LLMs,
to edit code in your local git repository.
Start a new project or work with an existing git repo.
Aider works best with GPT-4o & Claude 3.5 Sonnet and can
[connect to almost any LLM](https://aider.chat/docs/llms.html).
Start a new project or work with an existing code base.
Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
<!--
<p align="center">
@@ -104,16 +104,17 @@ for more details.
- Update docs.
- Aider will edit your files to complete your request.
- Aider [automatically git commits](https://aider.chat/docs/git.html) changes with a sensible commit message.
- [Use aider inside your favorite editor or IDE](https://aider.chat/docs/usage/watch.html).
- Aider works with [most popular languages](https://aider.chat/docs/languages.html): python, javascript, typescript, php, html, css, and more...
- Aider works best with GPT-4o & Claude 3.5 Sonnet and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
- Aider can edit multiple files at once for complex requests.
- Aider uses a [map of your entire git repo](https://aider.chat/docs/repomap.html), which helps it work well in larger codebases.
- Edit files in your editor while chatting with aider,
- Edit files in your editor or IDE while chatting with aider,
and it will always use the latest version.
Pair program with AI.
- [Add images to the chat](https://aider.chat/docs/usage/images-urls.html) (GPT-4o, Claude 3.5 Sonnet, etc).
- [Add URLs to the chat](https://aider.chat/docs/usage/images-urls.html) and aider will read their content.
- [Code with your voice](https://aider.chat/docs/usage/voice.html).
- Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
## Top tier performance

View File

@@ -11,6 +11,7 @@ RUN apt-get update && apt-get install -y \
python3.11-venv \
python3.11-dev \
python3-pip \
ca-certificates-java \
openjdk-21-jdk \
libtbb-dev \
&& rm -rf /var/lib/apt/lists/*
@@ -18,10 +19,18 @@ RUN apt-get update && apt-get install -y \
# Make python3.11 the default python3
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1
# Install Go
RUN curl -OL https://golang.org/dl/go1.21.5.linux-amd64.tar.gz && \
tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz && \
rm go1.21.5.linux-amd64.tar.gz
# Install Go with architecture detection
RUN ARCH=$(uname -m) && \
if [ "$ARCH" = "x86_64" ]; then \
GOARCH="amd64"; \
elif [ "$ARCH" = "aarch64" ]; then \
GOARCH="arm64"; \
else \
false; \
fi && \
curl -L "https://golang.org/dl/go1.21.5.linux-$GOARCH.tar.gz" -o go.tar.gz && \
tar -C /usr/local -xzf go.tar.gz && \
rm go.tar.gz
ENV PATH="/usr/local/go/bin:${PATH}"
# Install Rust

View File

@@ -16,6 +16,7 @@ from types import SimpleNamespace
from typing import List, Optional
import git
import importlib_resources
import lox
import pandas as pd
import prompts
@@ -31,7 +32,7 @@ from aider.io import InputOutput
BENCHMARK_DNAME = Path(os.environ.get("AIDER_BENCHMARK_DIR", "tmp.benchmarks"))
EXERCISES_DIR_DEFAULT = "exercism-python"
EXERCISES_DIR_DEFAULT = "polyglot-benchmark"
app = typer.Typer(add_completion=False, pretty_exceptions_enable=False)
@@ -176,11 +177,6 @@ def main(
"--replay",
help="Replay previous .aider.chat.history.md responses from previous benchmark run",
),
max_apply_update_errors: int = typer.Option(
3,
"--max-apply-update-errors",
help="Maximum number of apply update errors before stopping the test",
),
keywords: str = typer.Option(
None, "--keywords", "-k", help="Only run tests that contain keywords (comma sep)"
),
@@ -342,7 +338,6 @@ def main(
verbose,
commit_hash,
replay,
max_apply_update_errors,
editor_model,
editor_edit_format,
num_ctx,
@@ -367,7 +362,6 @@ def main(
verbose,
commit_hash,
replay,
max_apply_update_errors,
editor_model,
editor_edit_format,
)
@@ -645,7 +639,6 @@ def run_test_real(
verbose,
commit_hash,
replay,
max_apply_update_errors,
editor_model,
editor_edit_format,
num_ctx=None,
@@ -701,7 +694,7 @@ def run_test_real(
ignore_files.update(example_files)
# Remove any ignore files from the solution set that LLM will edit
solution_files.discard(ignore_files)
solution_files.difference_update(ignore_files)
# Copy all solution files
for file_path in solution_files:
@@ -725,17 +718,6 @@ def run_test_real(
else:
print(f"Warning: Solution file not found: {src}")
# Copy all test files
for file_path in test_files:
src = testdir / Path(file_path)
if src.exists():
original_fname = original_dname / testdir.name / file_path
if original_fname.exists():
os.makedirs(src.parent, exist_ok=True)
shutil.copy(original_fname, src)
else:
print(f"Warning: Test file not found: {src}")
file_list = " ".join(fname.name for fname in fnames)
instructions = ""
@@ -756,6 +738,10 @@ def run_test_real(
chat_history_file=history_fname,
)
resource_metadata = importlib_resources.files("aider.resources").joinpath("model-metadata.json")
model_metadata_files_loaded = models.register_litellm_models([resource_metadata])
dump(model_metadata_files_loaded)
# weak_model_name = model_name
weak_model_name = None
@@ -766,6 +752,8 @@ def run_test_real(
editor_edit_format=editor_edit_format,
)
dump(main_model.max_chat_history_tokens)
if num_ctx:
if not main_model.extra_params:
main_model.extra_params = {}
@@ -792,8 +780,8 @@ def run_test_real(
)
dump(coder.ignore_mentions)
coder.max_apply_update_errors = max_apply_update_errors
coder.show_announcements()
coder.get_file_mentions = lambda x: set() # No loading of any other files
timeouts = 0
@@ -805,6 +793,7 @@ def run_test_real(
test_outcomes = []
for i in range(tries):
start = time.time()
if no_aider:
pass
elif replay:
@@ -818,6 +807,7 @@ def run_test_real(
coder.apply_updates()
else:
response = coder.run(with_message=instructions, preproc=False)
dur += time.time() - start
if not no_aider:
@@ -861,6 +851,40 @@ def run_test_real(
instructions = errors
instructions += prompts.test_failures.format(file_list=file_list)
# Clean up build directories after all attempts
# Rust target/debug
target_dir = testdir / "target" / "debug"
if target_dir.exists():
try:
shutil.rmtree(target_dir)
if verbose:
print(f"Cleaned up Rust target/debug directory: {target_dir}")
except (OSError, shutil.Error, PermissionError) as e:
if verbose:
print(f"Failed to clean up Rust target/debug directory: {e}")
# Java build directories
java_build_dir = testdir / "build"
if java_build_dir.exists():
try:
shutil.rmtree(java_build_dir)
if verbose:
print(f"Cleaned up Java build directory: {java_build_dir}")
except (OSError, shutil.Error, PermissionError) as e:
if verbose:
print(f"Failed to clean up Java build directory: {e}")
# Node.js node_modules directories
node_modules_dir = testdir / "node_modules"
if node_modules_dir.exists():
try:
shutil.rmtree(node_modules_dir)
if verbose:
print(f"Cleaned up Node.js node_modules directory: {node_modules_dir}")
except (OSError, shutil.Error, PermissionError) as e:
if verbose:
print(f"Failed to clean up Node.js node_modules directory: {e}")
results = dict(
testdir=str(testdir),
testcase=testdir.name,
@@ -899,15 +923,6 @@ def run_test_real(
def run_unit_tests(original_dname, testdir, history_fname, test_files):
timeout = 60 * 3
# Remove @Disabled annotations from Java test files
for file_path in test_files:
if file_path.endswith(".java"):
test_file = testdir / file_path
if test_file.exists():
content = test_file.read_text()
content = re.sub(r"@Disabled\([^)]*\)\s*\n", "", content)
test_file.write_text(content)
# Map of file extensions to test commands
TEST_COMMANDS = {
".py": ["pytest"],
@@ -939,6 +954,15 @@ def run_unit_tests(original_dname, testdir, history_fname, test_files):
os.makedirs(dst.parent, exist_ok=True)
shutil.copy(src, dst)
# Remove @Disabled annotations from Java test files
for file_path in test_files:
if file_path.endswith(".java"):
test_file = testdir / file_path
if test_file.exists():
content = test_file.read_text()
content = re.sub(r"@Disabled\([^)]*\)\s*\n", "", content)
test_file.write_text(content)
print(" ".join(command))
result = subprocess.run(

View File

@@ -205,16 +205,18 @@ def analyze_exercise_solutions(dirs=None, topn=None, copy_hard_set=False):
# Distribution table of how many models solved each exercise
print("\nDistribution of solutions:")
print("Models Exercises Cumulative")
print("-" * 35)
print("Models Exercises Cumulative RevCumulative")
print("-" * 50)
counts = [0] * (total_models + 1)
for ex, models in exercise_solutions.items():
counts[len(models)] += 1
cumsum = 0
revcumsum = sum(counts) # Start with total number of exercises
for i, count in enumerate(counts):
cumsum += count
print(f"{i:>6d} {count:>9d} {cumsum:>10d}")
print(f"{i:>6d} {count:>9d} {cumsum:>10d} {revcumsum:>12d}")
revcumsum -= count # Decrement the reverse cumulative sum
# Count parse errors per exercise
parse_error_counts = defaultdict(int)

View File

@@ -19,15 +19,27 @@ git -C "$REPO_ROOT" ls-files --exclude-standard --others --ignored --directory >
# Create remote directory if needed
ssh "$DEST" "mkdir -p ~/aider"
# Sync the repository
rsync -avz --delete \
--exclude-from="$EXCLUDE_FILE" \
"$REPO_ROOT/" \
"$DEST:~/aider/"
sync_repo() {
# Sync the repository
rsync -avz --delete \
--exclude-from="$EXCLUDE_FILE" \
"$REPO_ROOT/" \
"$DEST:~/aider/" || sleep 0.1
rsync -a .env .gitignore "$DEST:~/aider/." || sleep 0.1
rsync -a .env .gitignore "$DEST:~/aider/."
echo Done syncing, waiting.
}
sync_repo
rsync -a ~/dotfiles/screenrc "$DEST:.screenrc"
while true; do
fswatch -o $REPO_ROOT | while read ; do
sync_repo
done
done
# Clean up
rm "$EXCLUDE_FILE"

View File

@@ -1,23 +1,26 @@
FROM python:3.10-slim AS base
# Install system dependencies
RUN apt-get update && \
apt-get install --no-install-recommends -y build-essential git libportaudio2 pandoc && \
rm -rf /var/lib/apt/lists/*
# Create app user with UID 1000
RUN useradd -m -u 1000 -s /bin/bash appuser
WORKDIR /app
# Create virtual environment
RUN python -m venv /venv
ENV PATH="/venv/bin:$PATH"
# https://playwright.dev/python/docs/browsers
ENV PLAYWRIGHT_BROWSERS_PATH=/pw-browsers
# Playwright browser settings
ENV PLAYWRIGHT_BROWSERS_PATH=/home/appuser/pw-browsers
ENV PLAYWRIGHT_SKIP_BROWSER_GC=1
# Permission kludges to support `docker run --user xxx`
RUN chmod a+rwx /venv /venv/bin /venv/include /venv/lib /venv/lib/python3.10/site-packages
RUN mkdir /.aider /.cache /pw-browsers
RUN chmod a+rwx /.aider /.cache /pw-browsers
# Create directories with proper permissions
RUN mkdir -p /home/appuser/.aider /home/appuser/.cache /home/appuser/pw-browsers && \
chown -R appuser:appuser /home/appuser /app /venv
# So git doesn't complain about unusual permissions
RUN git config --system --add safe.directory /app
@@ -28,14 +31,22 @@ FROM base AS aider-full
ENV AIDER_DOCKER_IMAGE=paulgauthier/aider-full
COPY . /tmp/aider
RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip \
&& /venv/bin/python -m pip install --no-cache-dir /tmp/aider[help,browser,playwright] \
--extra-index-url https://download.pytorch.org/whl/cpu \
&& rm -rf /tmp/aider
# Install dependencies as root
RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip && \
/venv/bin/python -m pip install --no-cache-dir /tmp/aider[help,browser,playwright] \
--extra-index-url https://download.pytorch.org/whl/cpu && \
rm -rf /tmp/aider
# Install playwright browsers
RUN /venv/bin/python -m playwright install --with-deps chromium
# Fix site-packages permissions
RUN find /venv/lib/python3.10/site-packages \( -type d -exec chmod a+rwx {} + \) -o \( -type f -exec chmod a+rw {} + \)
# Switch to appuser
USER appuser
ENTRYPOINT ["/venv/bin/aider"]
#########################
@@ -44,12 +55,20 @@ FROM base AS aider
ENV AIDER_DOCKER_IMAGE=paulgauthier/aider
COPY . /tmp/aider
RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip \
&& /venv/bin/python -m pip install --no-cache-dir /tmp/aider[playwright] \
--extra-index-url https://download.pytorch.org/whl/cpu \
&& rm -rf /tmp/aider
# Install dependencies as root
RUN /venv/bin/python -m pip install --upgrade --no-cache-dir pip && \
/venv/bin/python -m pip install --no-cache-dir /tmp/aider[playwright] \
--extra-index-url https://download.pytorch.org/whl/cpu && \
rm -rf /tmp/aider
# Install playwright browsers
RUN /venv/bin/python -m playwright install --with-deps chromium
# Fix site-packages permissions
RUN find /venv/lib/python3.10/site-packages \( -type d -exec chmod a+rwx {} + \) -o \( -type f -exec chmod a+rw {} + \)
# Switch to appuser
USER appuser
ENTRYPOINT ["/venv/bin/aider"]

View File

@@ -6,18 +6,18 @@
#
aiohappyeyeballs==2.4.4
# via aiohttp
aiohttp==3.11.10
aiohttp==3.11.11
# via litellm
aiosignal==1.3.1
aiosignal==1.3.2
# via aiohttp
annotated-types==0.7.0
# via pydantic
anyio==4.7.0
anyio==4.8.0
# via
# httpx
# openai
# watchfiles
attrs==24.2.0
attrs==24.3.0
# via
# aiohttp
# jsonschema
@@ -28,7 +28,7 @@ backoff==2.2.1
# posthog
beautifulsoup4==4.12.3
# via -r requirements/requirements.in
certifi==2024.8.30
certifi==2024.12.14
# via
# httpcore
# httpx
@@ -37,9 +37,9 @@ cffi==1.17.1
# via
# sounddevice
# soundfile
charset-normalizer==3.4.0
charset-normalizer==3.4.1
# via requests
click==8.1.7
click==8.1.8
# via litellm
configargparse==1.7
# via -r requirements/requirements.in
@@ -57,11 +57,11 @@ frozenlist==1.5.0
# via
# aiohttp
# aiosignal
fsspec==2024.10.0
fsspec==2024.12.0
# via huggingface-hub
gitdb==4.0.11
gitdb==4.0.12
# via gitpython
gitpython==3.1.43
gitpython==3.1.44
# via -r requirements/requirements.in
grep-ast==0.4.1
# via -r requirements/requirements.in
@@ -73,7 +73,7 @@ httpx==0.27.2
# via
# litellm
# openai
huggingface-hub==0.26.5
huggingface-hub==0.27.1
# via tokenizers
idna==3.10
# via
@@ -85,11 +85,11 @@ importlib-metadata==7.2.1
# via
# -r requirements/requirements.in
# litellm
importlib-resources==6.4.5
importlib-resources==6.5.2
# via -r requirements/requirements.in
jinja2==3.1.4
jinja2==3.1.5
# via litellm
jiter==0.8.0
jiter==0.8.2
# via openai
json5==0.10.0
# via -r requirements/requirements.in
@@ -99,7 +99,7 @@ jsonschema==4.23.0
# litellm
jsonschema-specifications==2024.10.1
# via jsonschema
litellm==1.53.9
litellm==1.58.2
# via -r requirements/requirements.in
markdown-it-py==3.0.0
# via rich
@@ -123,7 +123,8 @@ numpy==1.26.4
# via
# -r requirements/requirements.in
# scipy
openai==1.57.0
# soundfile
openai==1.59.7
# via litellm
packaging==24.2
# via
@@ -137,7 +138,7 @@ pexpect==4.9.0
# via -r requirements/requirements.in
pillow==10.4.0
# via -r requirements/requirements.in
posthog==3.7.4
posthog==3.8.3
# via -r requirements/requirements.in
prompt-toolkit==3.0.48
# via -r requirements/requirements.in
@@ -145,7 +146,7 @@ propcache==0.2.1
# via
# aiohttp
# yarl
psutil==6.1.0
psutil==6.1.1
# via -r requirements/requirements.in
ptyprocess==0.7.0
# via pexpect
@@ -153,19 +154,19 @@ pycodestyle==2.12.1
# via flake8
pycparser==2.22
# via cffi
pydantic==2.10.3
pydantic==2.10.5
# via
# litellm
# openai
pydantic-core==2.27.1
pydantic-core==2.27.2
# via pydantic
pydub==0.25.1
# via -r requirements/requirements.in
pyflakes==3.2.0
# via flake8
pygments==2.18.0
pygments==2.19.1
# via rich
pypandoc==1.14
pypandoc==1.15
# via -r requirements/requirements.in
pyperclip==1.9.0
# via -r requirements/requirements.in
@@ -177,7 +178,7 @@ pyyaml==6.0.2
# via
# -r requirements/requirements.in
# huggingface-hub
referencing==0.35.1
referencing==0.36.0
# via
# jsonschema
# jsonschema-specifications
@@ -186,7 +187,6 @@ regex==2024.11.6
requests==2.32.3
# via
# huggingface-hub
# litellm
# mixpanel
# posthog
# tiktoken
@@ -203,7 +203,7 @@ six==1.17.0
# mixpanel
# posthog
# python-dateutil
smmap==5.0.1
smmap==5.0.2
# via gitdb
sniffio==1.3.1
# via
@@ -212,7 +212,7 @@ sniffio==1.3.1
# openai
sounddevice==0.5.1
# via -r requirements/requirements.in
soundfile==0.12.1
soundfile==0.13.0
# via -r requirements/requirements.in
soupsieve==2.6
# via beautifulsoup4
@@ -239,11 +239,12 @@ typing-extensions==4.12.2
# openai
# pydantic
# pydantic-core
urllib3==2.2.3
# referencing
urllib3==2.3.0
# via
# mixpanel
# requests
watchfiles==1.0.0
watchfiles==1.0.4
# via -r requirements/requirements.in
wcwidth==0.2.13
# via prompt-toolkit

View File

@@ -6,7 +6,7 @@
#
altair==5.5.0
# via streamlit
attrs==24.2.0
attrs==24.3.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -17,33 +17,33 @@ blinker==1.9.0
# via streamlit
cachetools==5.5.0
# via streamlit
certifi==2024.8.30
certifi==2024.12.14
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
charset-normalizer==3.4.0
charset-normalizer==3.4.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
click==8.1.7
click==8.1.8
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
gitdb==4.0.11
gitdb==4.0.12
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# gitpython
gitpython==3.1.43
gitpython==3.1.44
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -55,7 +55,7 @@ idna==3.10
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
jinja2==3.1.4
jinja2==3.1.5
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -92,7 +92,7 @@ mdurl==0.1.2
# -c requirements.txt
# -c requirements/requirements-dev.txt
# markdown-it-py
narwhals==1.16.0
narwhals==1.22.0
# via altair
numpy==1.26.4
# via
@@ -122,13 +122,13 @@ pillow==10.4.0
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
protobuf==5.29.1
protobuf==5.29.3
# via streamlit
pyarrow==18.1.0
pyarrow==19.0.0
# via streamlit
pydeck==0.9.1
# via streamlit
pygments==2.18.0
pygments==2.19.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -144,7 +144,7 @@ pytz==2024.2
# via
# -c requirements/requirements-dev.txt
# pandas
referencing==0.35.1
referencing==0.36.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -175,14 +175,14 @@ six==1.17.0
# -c requirements.txt
# -c requirements/requirements-dev.txt
# python-dateutil
smmap==5.0.1
smmap==5.0.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# gitdb
streamlit==1.40.2
streamlit==1.41.1
# via -r requirements/requirements-browser.in
tenacity==8.5.0
tenacity==9.0.0
# via
# -c requirements/requirements-help.txt
# streamlit
@@ -197,12 +197,13 @@ typing-extensions==4.12.2
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# altair
# referencing
# streamlit
tzdata==2024.2
# via
# -c requirements/requirements-dev.txt
# pandas
urllib3==2.2.3
urllib3==2.3.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt

View File

@@ -10,19 +10,19 @@ babel==2.16.0
# via sphinx
build==1.2.2.post1
# via pip-tools
certifi==2024.8.30
certifi==2024.12.14
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# requests
cfgv==3.4.0
# via pre-commit
charset-normalizer==3.4.0
charset-normalizer==3.4.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# requests
click==8.1.7
click==8.1.8
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -51,9 +51,9 @@ filelock==3.16.1
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# virtualenv
fonttools==4.55.2
fonttools==4.55.3
# via matplotlib
identify==2.6.3
identify==2.6.5
# via pre-commit
idna==3.10
# via
@@ -66,12 +66,12 @@ imgcat==0.6.0
# via -r requirements/requirements-dev.in
iniconfig==2.0.0
# via pytest
jinja2==3.1.4
jinja2==3.1.5
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# sphinx
kiwisolver==1.4.7
kiwisolver==1.4.8
# via matplotlib
lox==0.12.0
# via -r requirements/requirements-dev.in
@@ -85,7 +85,7 @@ markupsafe==3.0.2
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# jinja2
matplotlib==3.9.3
matplotlib==3.10.0
# via -r requirements/requirements-dev.in
mdurl==0.1.2
# via
@@ -132,13 +132,13 @@ ppft==1.7.6.9
# via pathos
pre-commit==4.0.1
# via -r requirements/requirements-dev.in
pygments==2.18.0
pygments==2.19.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# rich
# sphinx
pyparsing==3.2.0
pyparsing==3.2.1
# via matplotlib
pyproject-hooks==1.2.0
# via
@@ -213,12 +213,12 @@ typing-extensions==4.12.2
# typer
tzdata==2024.2
# via pandas
urllib3==2.2.3
urllib3==2.3.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# requests
virtualenv==20.28.0
virtualenv==20.29.0
# via pre-commit
wheel==0.45.1
# via pip-tools
@@ -229,5 +229,5 @@ pip==24.3.1
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# pip-tools
setuptools==75.6.0
setuptools==75.8.0
# via pip-tools

View File

@@ -9,13 +9,13 @@ aiohappyeyeballs==2.4.4
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# aiohttp
aiohttp==3.11.10
aiohttp==3.11.11
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# huggingface-hub
# llama-index-core
aiosignal==1.3.1
aiosignal==1.3.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -25,17 +25,17 @@ annotated-types==0.7.0
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# pydantic
anyio==4.7.0
anyio==4.8.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# httpx
attrs==24.2.0
attrs==24.3.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# aiohttp
certifi==2024.8.30
certifi==2024.12.14
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -43,13 +43,13 @@ certifi==2024.8.30
# httpcore
# httpx
# requests
charset-normalizer==3.4.0
charset-normalizer==3.4.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/requirements-dev.txt
# requests
click==8.1.7
click==8.1.8
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -77,7 +77,7 @@ frozenlist==1.5.0
# -c requirements.txt
# aiohttp
# aiosignal
fsspec==2024.10.0
fsspec==2024.12.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.5
huggingface-hub[inference]==0.27.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -120,7 +120,7 @@ idna==3.10
# httpx
# requests
# yarl
jinja2==3.1.4
jinja2==3.1.5
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -130,11 +130,11 @@ joblib==1.4.2
# via
# nltk
# scikit-learn
llama-index-core==0.12.0
llama-index-core==0.12.11
# via
# -r requirements/requirements-help.in
# llama-index-embeddings-huggingface
llama-index-embeddings-huggingface==0.4.0
llama-index-embeddings-huggingface==0.5.0
# via -r requirements/requirements-help.in
markupsafe==3.0.2
# via
@@ -142,7 +142,7 @@ markupsafe==3.0.2
# -c requirements.txt
# -c requirements/requirements-dev.txt
# jinja2
marshmallow==3.23.1
marshmallow==3.25.1
# via dataclasses-json
mpmath==1.3.0
# via sympy
@@ -194,12 +194,12 @@ propcache==0.2.1
# -c requirements.txt
# aiohttp
# yarl
pydantic==2.10.3
pydantic==2.10.5
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# llama-index-core
pydantic-core==2.27.1
pydantic-core==2.27.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
@@ -228,9 +228,9 @@ requests==2.32.3
# llama-index-core
# tiktoken
# transformers
safetensors==0.4.5
safetensors==0.5.2
# via transformers
scikit-learn==1.5.2
scikit-learn==1.6.1
# via sentence-transformers
scipy==1.13.1
# via
@@ -246,13 +246,13 @@ sniffio==1.3.1
# -c requirements.txt
# anyio
# httpx
sqlalchemy[asyncio]==2.0.36
sqlalchemy[asyncio]==2.0.37
# via
# llama-index-core
# sqlalchemy
sympy==1.13.3
# via torch
tenacity==8.5.0
tenacity==9.0.0
# via llama-index-core
threadpoolctl==3.5.0
# via scikit-learn
@@ -296,13 +296,13 @@ typing-inspect==0.9.0
# via
# dataclasses-json
# llama-index-core
urllib3==2.2.3
urllib3==2.3.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/requirements-dev.txt
# requests
wrapt==1.17.0
wrapt==1.17.2
# via
# deprecated
# llama-index-core

View File

@@ -8,9 +8,13 @@ Do NOT add duplicate entries for changes that have existing history entries.
End each bullet with a period.
If the change was made by someone other than Paul Gauthier note it at the end of the bullet point as ", by XXX."
Be sure to attribute changes to the proper .x version.
Changes in the .x-dev version should be listed under a "### main branch" heading
Start a new "### main branch" section at the top of the file if needed.
Also, add this as the last bullet under the "### main branch" section:
{aider_line}
""" # noqa

View File

@@ -18,7 +18,10 @@ def collect_model_stats(n_lines=1000):
if event["event"] == "message_send":
properties = event["properties"]
main_model = properties.get("main_model")
total_tokens = properties.get("total_tokens", 0)
if main_model == "deepseek/deepseek-coder":
main_model = "deepseek/deepseek-chat"
if main_model:
model_stats[main_model] += total_tokens
except json.JSONDecodeError:

View File

@@ -27,6 +27,8 @@ cog $ARG \
aider/website/docs/config/adv-model-settings.md \
aider/website/docs/config/model-aliases.md \
aider/website/docs/leaderboards/index.md \
aider/website/docs/leaderboards/edit.md \
aider/website/docs/leaderboards/refactor.md \
aider/website/docs/llms/other.md \
aider/website/docs/more/infinite-output.md \
aider/website/docs/legal/privacy.md

View File

@@ -24,6 +24,7 @@ def run_git_log():
"git",
"log",
"-p",
"--pretty=full",
f"v{base_ver}..HEAD",
"--",
"aider/",

View File

@@ -7,11 +7,12 @@ from unittest.mock import MagicMock, patch
import git
from aider.coders import Coder
from aider.coders.base_coder import UnknownEditFormat
from aider.coders.base_coder import FinishReasonLength, UnknownEditFormat
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
from aider.models import Model
from aider.repo import GitRepo
from aider.sendchat import sanity_check_messages
from aider.utils import GitTemporaryDirectory
@@ -974,6 +975,71 @@ This command will print 'Hello, World!' to the console."""
self.assertIn("Output tokens:", error_message)
self.assertIn("Total tokens:", error_message)
def test_keyboard_interrupt_handling(self):
with GitTemporaryDirectory():
io = InputOutput(yes=True)
coder = Coder.create(self.GPT35, "diff", io=io)
# Simulate keyboard interrupt during message processing
def mock_send(*args, **kwargs):
coder.partial_response_content = "Partial response"
coder.partial_response_function_call = dict()
raise KeyboardInterrupt()
coder.send = mock_send
# Initial valid state
sanity_check_messages(coder.cur_messages)
# Process message that will trigger interrupt
list(coder.send_message("Test message"))
# Verify messages are still in valid state
sanity_check_messages(coder.cur_messages)
self.assertEqual(coder.cur_messages[-1]["role"], "assistant")
def test_token_limit_error_handling(self):
with GitTemporaryDirectory():
io = InputOutput(yes=True)
coder = Coder.create(self.GPT35, "diff", io=io)
# Simulate token limit error
def mock_send(*args, **kwargs):
coder.partial_response_content = "Partial response"
coder.partial_response_function_call = dict()
raise FinishReasonLength()
coder.send = mock_send
# Initial valid state
sanity_check_messages(coder.cur_messages)
# Process message that hits token limit
list(coder.send_message("Long message"))
# Verify messages are still in valid state
sanity_check_messages(coder.cur_messages)
self.assertEqual(coder.cur_messages[-1]["role"], "assistant")
def test_message_sanity_after_partial_response(self):
with GitTemporaryDirectory():
io = InputOutput(yes=True)
coder = Coder.create(self.GPT35, "diff", io=io)
# Simulate partial response then interrupt
def mock_send(*args, **kwargs):
coder.partial_response_content = "Partial response"
coder.partial_response_function_call = dict()
raise KeyboardInterrupt()
coder.send = mock_send
list(coder.send_message("Test"))
# Verify message structure remains valid
sanity_check_messages(coder.cur_messages)
self.assertEqual(coder.cur_messages[-1]["role"], "assistant")
if __name__ == "__main__":
unittest.main()

View File

@@ -1721,3 +1721,33 @@ class TestCommands(TestCase):
del coder
del commands
def test_cmd_load_with_switch_coder(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create a temporary file with commands
commands_file = Path(repo_dir) / "test_commands.txt"
commands_file.write_text("/ask Tell me about the code\n/model gpt-4\n")
# Mock run to raise SwitchCoder for /ask and /model
def mock_run(cmd):
if cmd.startswith(("/ask", "/model")):
raise SwitchCoder()
return None
with mock.patch.object(commands, "run", side_effect=mock_run):
# Capture tool_error output
with mock.patch.object(io, "tool_error") as mock_tool_error:
commands.cmd_load(str(commands_file))
# Check that appropriate error messages were shown
mock_tool_error.assert_any_call(
"Command '/ask Tell me about the code' is only supported in interactive"
" mode, skipping."
)
mock_tool_error.assert_any_call(
"Command '/model gpt-4' is only supported in interactive mode, skipping."
)

View File

@@ -12,11 +12,35 @@ from aider.utils import ChdirTemporaryDirectory
class TestInputOutput(unittest.TestCase):
def test_line_endings_validation(self):
# Test valid line endings
for ending in ["platform", "lf", "crlf"]:
io = InputOutput(line_endings=ending)
self.assertEqual(
io.newline, None if ending == "platform" else "\n" if ending == "lf" else "\r\n"
)
# Test invalid line endings
with self.assertRaises(ValueError) as cm:
io = InputOutput(line_endings="invalid")
self.assertIn("Invalid line_endings value: invalid", str(cm.exception))
# Check each valid option is in the error message
self.assertIn("platform", str(cm.exception))
self.assertIn("crlf", str(cm.exception))
self.assertIn("lf", str(cm.exception))
def test_no_color_environment_variable(self):
with patch.dict(os.environ, {"NO_COLOR": "1"}):
io = InputOutput(fancy_input=False)
self.assertFalse(io.pretty)
def test_dumb_terminal(self):
with patch.dict(os.environ, {"TERM": "dumb"}):
io = InputOutput(fancy_input=True)
self.assertTrue(io.is_dumb_terminal)
self.assertFalse(io.pretty)
self.assertIsNone(io.prompt_session)
def test_autocompleter_get_command_completions(self):
# Step 3: Mock the commands object
commands = MagicMock()
@@ -278,6 +302,29 @@ class TestInputOutputMultilineMode(unittest.TestCase):
self.io.toggle_multiline_mode()
self.assertFalse(self.io.multiline_mode)
def test_tool_message_unicode_fallback(self):
"""Test that Unicode messages are properly converted to ASCII with replacement"""
io = InputOutput(pretty=False, fancy_input=False)
# Create a message with invalid Unicode that can't be encoded in UTF-8
# Using a surrogate pair that's invalid in UTF-8
invalid_unicode = "Hello \ud800World"
# Mock console.print to capture the output
with patch.object(io.console, "print") as mock_print:
# First call will raise UnicodeEncodeError
mock_print.side_effect = [UnicodeEncodeError("utf-8", "", 0, 1, "invalid"), None]
io._tool_message(invalid_unicode)
# Verify that the message was converted to ASCII with replacement
self.assertEqual(mock_print.call_count, 2)
args, kwargs = mock_print.call_args
converted_message = args[0]
# The invalid Unicode should be replaced with '?'
self.assertEqual(converted_message, "Hello ?World")
if __name__ == "__main__":
unittest.main()

View File

@@ -30,7 +30,7 @@ class TestLinter(unittest.TestCase):
def test_run_cmd(self, mock_popen):
mock_process = MagicMock()
mock_process.returncode = 0
mock_process.communicate.return_value = ("", None)
mock_process.stdout.read.side_effect = ("", None)
mock_popen.return_value = mock_process
result = self.linter.run_cmd("test_cmd", "test_file.py", "code")
@@ -40,7 +40,7 @@ class TestLinter(unittest.TestCase):
def test_run_cmd_with_errors(self, mock_popen):
mock_process = MagicMock()
mock_process.returncode = 1
mock_process.communicate.return_value = ("Error message", None)
mock_process.stdout.read.side_effect = ("Error message", None)
mock_popen.return_value = mock_process
result = self.linter.run_cmd("test_cmd", "test_file.py", "code")

View File

@@ -132,6 +132,31 @@ class TestModels(unittest.TestCase):
self.assertEqual(model.name, "github/o1-preview")
self.assertEqual(model.use_temperature, False)
def test_get_repo_map_tokens(self):
# Test default case (no max_input_tokens in info)
model = Model("gpt-4")
model.info = {}
self.assertEqual(model.get_repo_map_tokens(), 1024)
# Test minimum boundary (max_input_tokens < 8192)
model.info = {"max_input_tokens": 4096}
self.assertEqual(model.get_repo_map_tokens(), 1024)
# Test middle range (max_input_tokens = 16384)
model.info = {"max_input_tokens": 16384}
self.assertEqual(model.get_repo_map_tokens(), 2048)
# Test maximum boundary (max_input_tokens > 32768)
model.info = {"max_input_tokens": 65536}
self.assertEqual(model.get_repo_map_tokens(), 4096)
# Test exact boundary values
model.info = {"max_input_tokens": 8192}
self.assertEqual(model.get_repo_map_tokens(), 1024)
model.info = {"max_input_tokens": 32768}
self.assertEqual(model.get_repo_map_tokens(), 4096)
def test_aider_extra_model_settings(self):
import tempfile

View File

@@ -290,6 +290,7 @@ class TestRepoMapAllLanguages(unittest.TestCase):
"elixir": ("ex", "Greeter"),
"java": ("java", "Greeting"),
"javascript": ("js", "Person"),
"kotlin": ("kt", "Greeting"),
"ocaml": ("ml", "Greeter"),
"php": ("php", "greet"),
"python": ("py", "Person"),

View File

@@ -93,3 +93,80 @@ class TestSendChat(unittest.TestCase):
assert result is None
# Should only print the error message
assert mock_print.call_count == 1
def test_ensure_alternating_roles_empty(self):
from aider.sendchat import ensure_alternating_roles
messages = []
result = ensure_alternating_roles(messages)
assert result == []
def test_ensure_alternating_roles_single_message(self):
from aider.sendchat import ensure_alternating_roles
messages = [{"role": "user", "content": "Hello"}]
result = ensure_alternating_roles(messages)
assert result == messages
def test_ensure_alternating_roles_already_alternating(self):
from aider.sendchat import ensure_alternating_roles
messages = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi there"},
{"role": "user", "content": "How are you?"},
]
result = ensure_alternating_roles(messages)
assert result == messages
def test_ensure_alternating_roles_consecutive_user(self):
from aider.sendchat import ensure_alternating_roles
messages = [
{"role": "user", "content": "Hello"},
{"role": "user", "content": "Are you there?"},
]
expected = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": ""},
{"role": "user", "content": "Are you there?"},
]
result = ensure_alternating_roles(messages)
assert result == expected
def test_ensure_alternating_roles_consecutive_assistant(self):
from aider.sendchat import ensure_alternating_roles
messages = [
{"role": "assistant", "content": "Hi there"},
{"role": "assistant", "content": "How can I help?"},
]
expected = [
{"role": "assistant", "content": "Hi there"},
{"role": "user", "content": ""},
{"role": "assistant", "content": "How can I help?"},
]
result = ensure_alternating_roles(messages)
assert result == expected
def test_ensure_alternating_roles_mixed_sequence(self):
from aider.sendchat import ensure_alternating_roles
messages = [
{"role": "user", "content": "Hello"},
{"role": "user", "content": "Are you there?"},
{"role": "assistant", "content": "Yes"},
{"role": "assistant", "content": "How can I help?"},
{"role": "user", "content": "Write code"},
]
expected = [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": ""},
{"role": "user", "content": "Are you there?"},
{"role": "assistant", "content": "Yes"},
{"role": "user", "content": ""},
{"role": "assistant", "content": "How can I help?"},
{"role": "user", "content": "Write code"},
]
result = ensure_alternating_roles(messages)
assert result == expected

16
tests/fixtures/languages/kotlin/test.kt vendored Normal file
View File

@@ -0,0 +1,16 @@
interface Greeting {
fun greet(name: String): String
}
class Test : Greeting {
private val prefix = "Hello"
override fun greet(name: String): String {
return "$prefix, $name!"
}
}
fun main(args: Array<String>) {
val greeter = Test()
println(greeter.greet("World"))
}