Compare commits

...

258 Commits

Author SHA1 Message Date
Paul Gauthier
6408a9fbf9 set version to 0.57.1.dev 2024-09-21 13:39:55 -07:00
Paul Gauthier
cf56369410 version bump to 0.57.0 2024-09-21 13:38:42 -07:00
Paul Gauthier
2ca093fb84 Bumping all dependencies 2024-09-21 11:04:57 -07:00
Paul Gauthier
237c4ab323 copy 2024-09-21 10:44:25 -07:00
Paul Gauthier
cfe1d540f1 update fence test to use backticks at start of line 2024-09-21 10:42:58 -07:00
Paul Gauthier
f29825ff22 copy 2024-09-21 10:41:43 -07:00
Paul Gauthier
565c305aa6 update o1-preview leaderboard to diff only 2024-09-21 10:27:50 -07:00
Paul Gauthier
b27738d39a copy 2024-09-21 10:16:51 -07:00
Paul Gauthier
412b8e7c3c copy 2024-09-21 10:09:26 -07:00
Paul Gauthier
5493654981 Merge remote-tracking branch 'refs/remotes/origin/main' 2024-09-21 09:32:51 -07:00
paul-gauthier
167b1ed491 Merge pull request #1586 from anjor/patch-1
Fix broken link
2024-09-21 09:32:27 -07:00
Paul Gauthier (aider)
454a2ebdcf style: format code using linter 2024-09-20 13:44:07 -07:00
Paul Gauthier (aider)
7fa1620f58 feat: Allow flexible matching of 5-9 characters in SEARCH/REPLACE block prefixes 2024-09-20 13:44:02 -07:00
Paul Gauthier (aider)
230ec50209 refactor: Improve choose_fence function to check for fence start in lines 2024-09-20 13:40:44 -07:00
Paul Gauthier
2753ac6b62 feat: Add new benchmark test case for qwen-2.5-72b-instruct-diff model 2024-09-20 13:27:58 -07:00
Paul Gauthier
5139594fa0 copy 2024-09-20 13:19:36 -07:00
Paul Gauthier
d26fca0bca feat: Add new leaderboard entry for qwen-2.5-72b-instruct model 2024-09-20 13:19:26 -07:00
paul-gauthier
d7051ce736 Merge pull request #1610 from youknow04/qwen2.5-7b-8q
Add Qwen2.5-coder:7b-instruct-q8_0 benchmark result to leaderboard
2024-09-20 12:57:25 -07:00
Paul Gauthier
b3e5caf330 fix: Add BufferError to ANY_GIT_ERROR tuple 2024-09-20 12:39:33 -07:00
Paul Gauthier
2a4527a5af fix: Ensure path_in_repo function handles empty path 2024-09-20 12:29:50 -07:00
Paul Gauthier (aider)
243be27eb8 style: Fix formatting in aider/models.py 2024-09-20 12:21:03 -07:00
Paul Gauthier (aider)
671c633d8f fix: handle errors when creating cache directory in get_model_info 2024-09-20 12:20:59 -07:00
Paul Gauthier
d94c1c0e1f fix: Remove redundant message when no changes were made 2024-09-20 12:14:52 -07:00
Paul Gauthier
88eaf8cf1d copy 2024-09-20 11:52:28 -07:00
Paul Gauthier
84ca8dd582 fix unicode errors in run_install 2024-09-20 11:52:24 -07:00
Paul Gauthier
8349cd5c15 fix: Handle FileNotFoundError in get_git_root function 2024-09-20 11:45:48 -07:00
Paul Gauthier (aider)
7d766d53ee style: format code for better readability 2024-09-20 11:40:28 -07:00
Paul Gauthier (aider)
2cabf9718c feat: Add comment count to issue output 2024-09-20 11:40:25 -07:00
Paul Gauthier (aider)
0030d11ac7 style: Improve formatting and readability of issues.py script 2024-09-20 11:38:57 -07:00
Paul Gauthier (aider)
31655889cf feat: List open issues in descending order by number 2024-09-20 11:38:54 -07:00
Paul Gauthier (aider)
851f0653d6 style: Run linter on Python script 2024-09-20 11:32:53 -07:00
Paul Gauthier (aider)
c111e7a30e feat: Add confirmation prompt and logic to comment and close duplicate issues 2024-09-20 11:32:49 -07:00
Paul Gauthier
7dd0a0f348 fix: Handle cases where there are no related issues for a subject 2024-09-20 11:32:30 -07:00
Paul Gauthier (aider)
3d70f88bcc style: Wrap long lines in f-strings 2024-09-20 11:23:53 -07:00
Paul Gauthier (aider)
215833d326 feat: Print issue URLs instead of issue numbers 2024-09-20 11:23:50 -07:00
Paul Gauthier (aider)
ba257d653c fix: Move import re statement to top of file 2024-09-20 11:21:34 -07:00
Paul Gauthier (aider)
99d196d06e style: format code 2024-09-20 11:20:42 -07:00
Paul Gauthier (aider)
619127925d feat: Add filter to only print issues matching "Uncaught xxx in xxx line ###" pattern 2024-09-20 11:20:39 -07:00
Paul Gauthier
86dc25d342 fix: Improve handling of issues with single subject 2024-09-20 11:20:38 -07:00
Paul Gauthier (aider)
dd1ae5bd3a style: Wrap long lines in f-strings 2024-09-20 11:18:13 -07:00
Paul Gauthier (aider)
40202a9cb8 chore: only print out issues with >1 in the group 2024-09-20 11:18:09 -07:00
Paul Gauthier (aider)
08d465c252 refactor: Improve efficiency by fetching all issues once and reusing the data 2024-09-20 11:16:53 -07:00
Paul Gauthier (aider)
81bad77fa9 refactor: Simplify script by hardcoding repository details 2024-09-20 11:12:02 -07:00
Paul Gauthier
ada7b3d7ab fix: make issues.py executable 2024-09-20 11:12:01 -07:00
Paul Gauthier (aider)
04aecbe9a9 chore: add shebang and chmod 2024-09-20 11:10:54 -07:00
Paul Gauthier (aider)
6b9fc86e99 style: Run linter on Python script 2024-09-20 11:09:48 -07:00
Paul Gauthier (aider)
1ede98bc07 feat: Implement GitHub issue analysis script 2024-09-20 11:09:44 -07:00
Paul Gauthier
eb078906b3 feat: Add issues.py script 2024-09-20 11:09:43 -07:00
Paul Gauthier
51017d7a5b copy 2024-09-20 11:05:33 -07:00
youknow
2463cbfd6c add Qwen2.5-7b-8q to leaderboard 2024-09-21 01:25:39 +09:00
Anjor Kanekar
c13aadaa0e Fix broken link 2024-09-18 14:54:04 +01:00
paul-gauthier
e6037140be Update 2024-09-12-o1.md 2024-09-12 21:09:15 -07:00
Paul Gauthier
eba845ea51 copy 2024-09-12 20:40:12 -07:00
Paul Gauthier (aider)
d747a3781d feat: add openrouter versions of o1-mini and o1-preview 2024-09-12 19:15:48 -07:00
Paul Gauthier
9768e84fcd feat: Change model settings from 'whole' to 'diff' 2024-09-12 19:15:47 -07:00
Paul Gauthier
72f52bdef0 copy 2024-09-12 15:41:02 -07:00
Paul Gauthier
c00ac80909 o1-mini diff results 2024-09-12 15:38:40 -07:00
Paul Gauthier
1fbb5079d5 unhack o1 mini 2024-09-12 15:38:28 -07:00
Paul Gauthier (aider)
752e823da8 feat: Dynamically generate legend labels based on unique edit formats 2024-09-12 15:23:33 -07:00
Paul Gauthier (aider)
45474a230e feat: Add distinct colors for edit formats in leaderboard chart 2024-09-12 15:22:28 -07:00
Paul Gauthier
af407c4c8f copy 2024-09-12 15:20:23 -07:00
Paul Gauthier (aider)
b4dad65e9f feat: Add configuration to display all x-axis labels 2024-09-12 15:18:57 -07:00
Paul Gauthier
291d3509eb copy 2024-09-12 15:17:32 -07:00
Paul Gauthier (aider)
84b1c1031a feat: add label to y-axis of leaderboard graph 2024-09-12 15:13:22 -07:00
Paul Gauthier (aider)
71c5fd1372 feat: Add legend to leaderboard chart 2024-09-12 15:12:10 -07:00
Paul Gauthier (aider)
2605d44db6 feat: Add different colors for 'whole' and 'diff' edit formats in leaderboard graph 2024-09-12 15:10:32 -07:00
Paul Gauthier
4598a376fd copy 2024-09-12 15:01:27 -07:00
Paul Gauthier
9f4d9d801e copy 2024-09-12 14:52:27 -07:00
Paul Gauthier (aider)
859fc1f184 fix: Adjust streaming settings before creating Coder object 2024-09-12 14:49:21 -07:00
Paul Gauthier
99a75ac213 feat: Add streaming option to ModelSettings 2024-09-12 14:47:18 -07:00
Paul Gauthier (aider)
94a2bc5ef5 style: Improve formatting of warning message 2024-09-12 14:46:36 -07:00
Paul Gauthier (aider)
efa0c0e292 fix: Disable streaming if main model does not support it 2024-09-12 14:46:32 -07:00
Paul Gauthier
fb420de09e feat: Add new model settings for openai/o1-preview and o1-preview 2024-09-12 14:42:52 -07:00
Paul Gauthier
09cb4c4b09 copy 2024-09-12 14:27:35 -07:00
Paul Gauthier
1755d2e0f4 fix: Use temperature setting from model configuration 2024-09-12 14:24:21 -07:00
Paul Gauthier
8aee4d25ed add ModelSettings.use_system_prompt 2024-09-12 14:19:53 -07:00
Paul Gauthier
71f3f3a22b copy 2024-09-12 14:12:48 -07:00
Paul Gauthier
297b51b997 pct 2024-09-12 14:11:26 -07:00
Paul Gauthier
6eb993999a copy 2024-09-12 14:07:41 -07:00
Paul Gauthier
96587f5f46 o1-mini blog article 2024-09-12 14:07:06 -07:00
Paul Gauthier
291b456a45 hack for o1-mini: no system prompt, no temperature 2024-09-12 13:05:25 -07:00
Paul Gauthier (aider)
d84a9d6df2 fix: update scale configuration in leaderboard_graph.html 2024-09-12 13:04:10 -07:00
Paul Gauthier (aider)
13d3b7c9b3 refactor: Refactor the edit leaderboard graph into a reusable component 2024-09-12 13:01:55 -07:00
Paul Gauthier
94af92c784 feat: Add leaderboard graph component 2024-09-12 13:01:54 -07:00
Paul Gauthier
36fa773376 fix: Simplify get_help_md function in commands.py 2024-09-11 14:38:23 -07:00
Paul Gauthier (aider)
05b3b3df88 fix: Remove f-string prefix from line without placeholders 2024-09-11 14:01:15 -07:00
Paul Gauthier
1603ffa6c2 fix: Update sample.aider.conf.yml and args_formatter.py 2024-09-11 14:01:10 -07:00
Paul Gauthier
615dc5fe4b copy 2024-09-11 13:18:07 -07:00
Paul Gauthier
385f2693c4 copy 2024-09-11 13:14:40 -07:00
Paul Gauthier
35588b6984 fix: Fix formatting of assistant_output assignment in base_coder.py 2024-09-11 09:54:47 -07:00
Paul Gauthier
ca43a37567 copy 2024-09-11 09:53:13 -07:00
Paul Gauthier
94a609d75e fix: Update model names in edit_leaderboard.yml 2024-09-11 08:56:46 -07:00
Paul Gauthier
13ac0f0968 fix: Update model names and commands in edit_leaderboard.yml 2024-09-11 08:55:25 -07:00
Paul Gauthier
408ecc1bd7 copy 2024-09-11 08:50:35 -07:00
Paul Gauthier
ba54e4a6e0 feat: Add new leaderboard entries for command-r-plus-08-2024 and command-r-08-2024 models 2024-09-11 08:50:28 -07:00
paul-gauthier
b43ed20085 Merge pull request #1492 from jalammar/cohere-model-refresh
Add New Cohere Models
2024-09-11 08:39:42 -07:00
Paul Gauthier
007f841328 copy 2024-09-11 08:18:07 -07:00
Jay Alammar
5cdcbb1a26 Add to docs 2024-09-11 11:04:38 -04:00
Jay Alammar
7315624b98 bugfix 2024-09-11 10:55:45 -04:00
Paul Gauthier
0a3b4147fa test: update main tests to handle None input and add --exit flag 2024-09-10 15:32:43 -07:00
Paul Gauthier (aider)
fa49ab09c4 test: update code_theme tests to check InputOutput initialization 2024-09-10 15:24:11 -07:00
paul-gauthier
d1384e9d5f Merge pull request #1402 from caseymcc/io_assistant_output
Modify output from Assistant and Commands to go through InputOutput
2024-09-10 15:08:10 -07:00
Paul Gauthier
33b11d0efb refactor: simplify console initialization and error handling 2024-09-10 14:48:54 -07:00
Paul Gauthier
fd18adb072 refactor: handle prompt toolkit initialization errors gracefully 2024-09-10 14:34:25 -07:00
Paul Gauthier
454c2f4d0e feat: add --exit flag to test cases for controlled termination 2024-09-10 14:30:04 -07:00
Paul Gauthier (aider)
59bdc45728 refactor: Remove unused mock_open import 2024-09-10 14:18:56 -07:00
Paul Gauthier (aider)
645252168c style: sort imports and fix quotation marks 2024-09-10 14:18:37 -07:00
Paul Gauthier (aider)
fb87dd883c test: patch input() to return empty string
This commit patches the `input()` builtin to return an empty string in the test setup, preventing tests from hanging while waiting for user input. It also adds cleanup for the patch in the teardown method.
2024-09-10 14:18:32 -07:00
Paul Gauthier (aider)
8da88eef64 fix: remove unused import of builtins module 2024-09-10 14:09:40 -07:00
Paul Gauthier (aider)
3685f307c7 style: reorder imports in test_io.py 2024-09-10 14:09:33 -07:00
Paul Gauthier (aider)
d5d087123a test: update input mocking in TestInputOutput 2024-09-10 14:09:29 -07:00
Paul Gauthier (aider)
1d312e372d refactor: Remove unused import of 'prompt' from prompt_toolkit 2024-09-10 14:07:32 -07:00
Paul Gauthier (aider)
13fe2036db style: remove trailing whitespace in io.py 2024-09-10 14:06:55 -07:00
Paul Gauthier (aider)
d4e47bc7e7 refactor: update confirm_ask to use prompt_session or input 2024-09-10 14:06:51 -07:00
Paul Gauthier (aider)
79a424bc10 refactor: conditionally initialize and use PromptSession based on pretty flag 2024-09-10 13:49:22 -07:00
Paul Gauthier
ed866d33e4 pip-compiled 2024-09-10 13:40:19 -07:00
Paul Gauthier
04556ef32d Merge remote-tracking branch 'refs/remotes/origin/main' 2024-09-10 13:39:06 -07:00
paul-gauthier
36553d797f Merge pull request #1003 from cclauss/patch-1
Fix typos discovered by codespell
2024-09-10 13:38:59 -07:00
Paul Gauthier
2c08cc47e6 copy 2024-09-10 13:38:25 -07:00
Paul Gauthier (aider)
971fe5017a feat: enable automatic writing of codespell changes in pyproject.toml 2024-09-10 13:38:14 -07:00
Paul Gauthier (aider)
e3e6437dca chore: configure codespell to use pyproject.toml and skip specific files 2024-09-10 13:37:18 -07:00
Paul Gauthier (aider)
c575bae710 feat: add codespell as pre-commit hook 2024-09-10 13:33:27 -07:00
Paul Gauthier (aider)
13f9685f13 style: Format code to comply with linter rules 2024-09-10 13:03:36 -07:00
Paul Gauthier (aider)
00f03d89b9 feat: expand read-only command to handle directories 2024-09-10 13:03:31 -07:00
Paul Gauthier
484fdd7aa3 fix: handle ValueError exception in run_cmd_pexpect function 2024-09-10 12:06:45 -07:00
Paul Gauthier
c152c96fcc copy 2024-09-10 10:05:01 -07:00
Paul Gauthier (aider)
89891efbb8 style: format prompt_session.prompt call to fit on one line 2024-09-10 10:00:05 -07:00
Paul Gauthier (aider)
43eaf91e8d refactor: use pre-initialized PromptSession in prompt_ask function 2024-09-10 10:00:00 -07:00
Paul Gauthier (aider)
bf3a165961 refactor: initialize and reuse PromptSession in InputOutput class 2024-09-10 09:57:09 -07:00
Paul Gauthier
33b69d2ee8 pip-compiled 2024-09-10 09:48:23 -07:00
Paul Gauthier (aider)
766569a278 refactor: Remove unused ctypes import 2024-09-10 09:45:05 -07:00
Paul Gauthier (aider)
cc94b51a0b style: use double quotes for string literals in run_cmd.py 2024-09-10 09:44:57 -07:00
Paul Gauthier (aider)
f1d1d1b37a feat: improve Windows parent process detection using psutil 2024-09-10 09:44:54 -07:00
Paul Gauthier
e84caa48a0 refactor: modify stdout reading chunk size in run_cmd_subprocess 2024-09-10 09:44:52 -07:00
Paul Gauthier (aider)
ab9d9c8429 refactor: improve subprocess output handling for real-time display 2024-09-10 09:34:58 -07:00
Paul Gauthier (aider)
625a49752b refactor: remove psutil dependency and check parent process only on Windows 2024-09-10 09:30:36 -07:00
Paul Gauthier
e5ff5eff75 refactor: rename and simplify parent process name retrieval function 2024-09-10 09:30:35 -07:00
Paul Gauthier (aider)
cb42464676 style: Reorder imports and format code 2024-09-10 09:28:42 -07:00
Paul Gauthier (aider)
5de0a0f7a9 feat: improve shell detection for Windows environments 2024-09-10 09:28:39 -07:00
Paul Gauthier
765ea801b1 refactor: simplify shell command execution logic 2024-09-10 09:25:50 -07:00
Paul Gauthier (aider)
1327c1e893 style: format command string for PowerShell execution 2024-09-10 06:51:43 -07:00
Paul Gauthier (aider)
4605969921 fix: improve PowerShell command execution and output capture on Windows 2024-09-10 06:51:38 -07:00
Paul Gauthier (aider)
e3b7b80280 feat: respect user's shell environment in subprocess execution 2024-09-10 06:40:07 -07:00
Paul Gauthier
b8ce472cb6 copy 2024-09-09 15:20:36 -07:00
Paul Gauthier
6a0ad9629b copy 2024-09-09 15:04:37 -07:00
Paul Gauthier
d99191e07b copy 2024-09-09 15:01:53 -07:00
Paul Gauthier
6cddc800f1 docs: update HISTORY.md and remove git operations from versionbump.py 2024-09-09 15:01:08 -07:00
Paul Gauthier (aider)
de84a08924 style: Apply linter suggestions to versionbump.py 2024-09-09 15:00:41 -07:00
Paul Gauthier (aider)
fb1a9254c7 feat: remove aider/__version__.py after version bump 2024-09-09 15:00:37 -07:00
Paul Gauthier
5420f67b2b copy 2024-09-09 14:56:44 -07:00
Paul Gauthier
fe2e36afda cache ro+repo or just ro if no repo 2024-09-09 14:51:33 -07:00
Paul Gauthier
b216d57107 copy 2024-09-09 14:47:56 -07:00
Paul Gauthier
509c880b68 set version to 0.56.1.dev 2024-09-09 14:46:20 -07:00
Paul Gauthier
6f2b064f53 version bump to 0.56.0 2024-09-09 14:45:11 -07:00
Paul Gauthier
26c2b2e3ed copy 2024-09-09 14:43:35 -07:00
Paul Gauthier
3976d4b8f1 copy 2024-09-09 14:37:18 -07:00
Paul Gauthier
964fe7e2dc fix: handle UnicodeEncodeError in prompt session 2024-09-09 13:56:27 -07:00
Paul Gauthier
eced076602 feat: add IndexError to ANY_GIT_ERROR tuple in repo.py 2024-09-09 13:46:03 -07:00
Paul Gauthier
bd21122e64 refactor: improve error handling for git version check 2024-09-09 13:44:02 -07:00
Paul Gauthier
00f42590c8 feat: add AssertionError to ANY_GIT_ERROR tuple 2024-09-09 13:41:28 -07:00
Paul Gauthier
4e63254704 refactor: Improve error handling in git repository checks 2024-09-09 13:40:56 -07:00
Paul Gauthier
3cd6790d9a fix: handle OSError in git repo operations 2024-09-09 13:37:24 -07:00
Paul Gauthier
d82d21b8c1 refactor: improve error handling for SQLite operations in RepoMap 2024-09-09 13:34:49 -07:00
Paul Gauthier
1a6284cb24 feat: add error handling for parser loading in basic_lint function 2024-09-09 13:28:04 -07:00
Paul Gauthier
abf6a9db2e fix: Handle additional Git-related errors in GitRepo.list_files 2024-09-09 13:26:07 -07:00
Paul Gauthier
73e7d7bd2a fix: handle git errors when listing files in the repository 2024-09-09 12:42:20 -07:00
Paul Gauthier
82f8aa5d6a copy 2024-09-09 10:26:32 -07:00
Paul Gauthier
cee348614e copy 2024-09-08 17:07:25 -07:00
Paul Gauthier
e40a07a8a1 refactor: move import check before API key setup 2024-09-08 09:26:39 -07:00
Paul Gauthier
99dc235a00 Merge remote-tracking branch 'refs/remotes/origin/main' 2024-09-08 09:20:20 -07:00
Paul Gauthier
9982f439e4 feat: improve error handling for import loading 2024-09-08 09:18:20 -07:00
Paul Gauthier (aider)
1e9ff842f3 style: format code with linter 2024-09-08 09:11:08 -07:00
Paul Gauthier (aider)
aeea629d17 feat: add verbose output to check_and_load_imports function 2024-09-08 09:11:03 -07:00
Paul Gauthier
b4389f98fb refactor: Synchronize slow imports and improve error handling 2024-09-08 09:11:00 -07:00
Paul Gauthier (aider)
f54b6860db feat: optimize slow imports loading based on version and executable 2024-09-08 09:07:19 -07:00
Paul Gauthier (aider)
ed7a9c6562 refactor: extract thread launch for load_slow_imports into function 2024-09-08 09:05:55 -07:00
paul-gauthier
ab35e473f3 Merge pull request #1423 from fry69/win-lint-fix
fix: handle OSError when executing lint command
2024-09-08 08:58:14 -07:00
fry69
e526d2890c fix: handle OSError when executing lint command 2024-09-08 13:15:31 +02:00
Paul Gauthier
2eae3738ff Merge remote-tracking branch 'refs/remotes/origin/main' 2024-09-07 07:27:21 -07:00
paul-gauthier
f98b64dd98 Merge pull request #1409 from fry69/fry69-contributing
Update CONTRIBUTING.md
2024-09-07 07:23:15 -07:00
Paul Gauthier
d2379a6d73 feat: add shell command suggestion toggle and related prompts 2024-09-07 07:21:41 -07:00
fry69
84758c6c8d Update CONTRIBUTING.md
fix link to benchmark data folder
2024-09-07 16:11:00 +02:00
Krazer
f4853d166f remove console 2024-09-06 18:08:51 -05:00
Krazer
69b9a4510d remove unused 2024-09-06 17:40:40 -05:00
Krazer
9d4316b1d5 add default empty message 2024-09-06 17:39:22 -05:00
Krazer
11020c8aee send output through InputOutput 2024-09-06 17:35:55 -05:00
Jay Alammar (aider)
df33498cad fix: correct syntax error by removing extra closing parenthesis in ModelSettings definition 2024-09-06 17:07:32 -04:00
Jay Alammar (aider)
d85979e1fb fix: correct syntax error by fixing misplaced parenthesis in ModelSettings entries 2024-09-06 17:07:23 -04:00
Jay Alammar (aider)
74f1ceff93 fix: resolve syntax error by removing extra closing parenthesis in model settings list 2024-09-06 17:07:16 -04:00
Jay Alammar (aider)
68bd2b75c6 refactor: group Cohere models together in the model settings list 2024-09-06 17:06:51 -04:00
Jay Alammar (aider)
5344052aeb feat: add support for new Cohere models command-r-08-2024 and command-r-plus-08-2024 2024-09-06 17:06:11 -04:00
Paul Gauthier
304566a914 added reflection 70b 2024-09-06 13:50:08 -07:00
Paul Gauthier
e9c0c82e03 added reflection 70b 2024-09-06 13:47:14 -07:00
Paul Gauthier
2aef59e624 update name to DeepSeek V2.5 2024-09-06 13:32:15 -07:00
Paul Gauthier
74631eec98 Merge remote-tracking branch 'refs/remotes/origin/main' 2024-09-06 12:02:20 -07:00
paul-gauthier
3a36edb8ec Merge pull request #1397 from fry69/prompt-cache
Enable prompt caching for OpenRouter
2024-09-06 06:04:32 -07:00
fry69
795810ffb8 fix: update model configurations 2024-09-06 13:44:42 +02:00
paul-gauthier
2663233b60 Merge pull request #1388 from cheahjs/docs/cleanup-yi-coder
docs: clean up yi-coder model names
2024-09-05 15:20:29 -07:00
Jun Siang Cheah
8d151a3573 docs: clean up yi-coder model names 2024-09-05 23:04:54 +01:00
Paul Gauthier
1c73e7d43a turn off suggest shell commands during benchmarks 2024-09-05 14:35:34 -07:00
Paul Gauthier
8cfdcbd976 refactor: remove redundant get_system_info method and update related test 2024-09-05 13:00:32 -07:00
Paul Gauthier (aider)
45855bd96c feat: add get_system_info method to Coder base class 2024-09-05 12:59:12 -07:00
Paul Gauthier (aider)
b57468a963 test: add test for Spanish chat language option 2024-09-05 12:58:18 -07:00
Paul Gauthier
34099408a5 copy 2024-09-05 12:55:09 -07:00
Paul Gauthier (aider)
781996fe84 feat: pass chat language to Coder.create 2024-09-05 12:52:26 -07:00
Paul Gauthier (aider)
3d73fac84c feat: add chat_language parameter to Coder class 2024-09-05 12:49:11 -07:00
Paul Gauthier (aider)
2bcc9a54a9 feat: add --chat-language argument for specifying chat language 2024-09-05 12:47:53 -07:00
Paul Gauthier
e4cbbb1fa8 remove eslint as default linter 2024-09-05 12:45:12 -07:00
Paul Gauthier
a35c532211 refactor: Move json import to top of file and remove unused import 2024-09-05 12:00:44 -07:00
Paul Gauthier (aider)
c2b8522e9a refactor: remove unused json import at top level 2024-09-05 12:00:28 -07:00
Paul Gauthier (aider)
5123d8c5de feat: add json import to main.py 2024-09-05 12:00:13 -07:00
Paul Gauthier (aider)
9b924237b7 style: add newline after json import in main.py 2024-09-05 11:59:56 -07:00
Paul Gauthier (aider)
c04453d282 feat: print model info as formatted JSON in verbose mode 2024-09-05 11:59:50 -07:00
Paul Gauthier
f02da16353 set max_tokens=8192 for deepseek models 2024-09-05 11:58:20 -07:00
Paul Gauthier
6c739d391b refactor: rename --models flag to --list-models 2024-09-05 11:40:31 -07:00
paul-gauthier
e3cd9a8f9a Merge pull request #1383 from fry69/list-models
Add --list-models alias for --models
2024-09-05 10:12:44 -07:00
Paul Gauthier
76bc0e11b8 add deepseek v2.5 to refac bench 2024-09-05 10:07:46 -07:00
fry69 (aider)
485d5487af feat: add --list-models alias for --models option 2024-09-05 18:27:05 +02:00
fry69
246ce318d2 fix: rename --models to --list-models in website docs 2024-09-05 18:23:55 +02:00
Paul Gauthier
6e3d8d90de Add deepseek v2.5 2024-09-05 07:59:32 -07:00
Paul Gauthier
2d866418da feat: add ignore_mentions attribute to cloned Coder instances 2024-09-04 14:40:21 -07:00
Paul Gauthier
ff15bcdb30 copy 2024-09-04 14:34:40 -07:00
Paul Gauthier
e799ada6f5 Merge remote-tracking branch 'refs/remotes/origin/main' 2024-09-04 14:33:59 -07:00
Paul Gauthier (aider)
7c5cad74ab style: Format code to comply with linter rules 2024-09-04 14:32:38 -07:00
Paul Gauthier (aider)
41e8f4401e fix: make test_get_rel_fname compatible with Windows 2024-09-04 14:32:35 -07:00
paul-gauthier
e271941aa2 Merge pull request #1349 from cheahjs/patch-1
docs: add benchmark results for yi-coder 9b
2024-09-04 14:14:36 -07:00
Paul Gauthier (aider)
6152a82513 fix: handle ValueError in os.path.relpath calls 2024-09-04 14:10:56 -07:00
Paul Gauthier
937a1cd847 fix: correct string handling in ESLint file path check 2024-09-04 14:06:30 -07:00
Paul Gauthier
867d19952c fix: handle spaces in ESLint file path for TypeScript linting 2024-09-04 14:05:44 -07:00
Paul Gauthier
7c5d999032 fix: correct eslint path in node_modules directory 2024-09-04 14:02:56 -07:00
Paul Gauthier
6d23b22e6f refactor: Remove redundant TypeScript linter fallback 2024-09-04 14:02:02 -07:00
Paul Gauthier
168598dad4 test: remove redundant Windows-specific ESLint test 2024-09-04 14:01:25 -07:00
Paul Gauthier (aider)
bd7ff9cca4 style: run linter and fix import order 2024-09-04 14:00:33 -07:00
Paul Gauthier (aider)
51f360ab9f fix: update ESLint command assertion in Windows test 2024-09-04 14:00:30 -07:00
Paul Gauthier
66ae9ae079 test: add debug output for linter languages in TestLinter 2024-09-04 14:00:28 -07:00
Paul Gauthier (aider)
65fd6b444c fix: simplify ESLint Windows test mock 2024-09-04 13:58:46 -07:00
Paul Gauthier (aider)
15abe6b921 style: Format long line in test_get_rel_fname method 2024-09-04 13:57:16 -07:00
Paul Gauthier (aider)
d8027030b0 fix: update ESLint check and test expectations 2024-09-04 13:57:09 -07:00
Paul Gauthier (aider)
edd9b44ad3 refactor: Remove unused import of Path from test_linter.py 2024-09-04 13:56:25 -07:00
Paul Gauthier (aider)
14fc3e3ad1 style: format code with black and isort 2024-09-04 13:55:53 -07:00
Paul Gauthier (aider)
cd551dbf63 test: add basic tests for Linter class 2024-09-04 13:55:49 -07:00
Paul Gauthier
ed349b65b5 test: add basic linter tests 2024-09-04 13:55:48 -07:00
Paul Gauthier (aider)
bb5bca5227 feat: support Windows ESLint executables in linter detection 2024-09-04 13:53:18 -07:00
Paul Gauthier (aider)
e98645698b refactor: make ESLint path detection cross-platform compatible 2024-09-04 13:52:41 -07:00
Paul Gauthier (aider)
376e8617f3 style: format eslint paths and remove trailing whitespace 2024-09-04 13:51:57 -07:00
Paul Gauthier (aider)
a3d585a4b4 feat: add ESLint detection for TypeScript linting 2024-09-04 13:51:53 -07:00
Jun Siang Cheah
5853c7fa92 docs: add benchmark results for yi-coder 9b 2024-09-04 18:34:52 +01:00
Paul Gauthier
18bf3a9f36 fixes #1348 2024-09-04 10:27:18 -07:00
Paul Gauthier
e7253d819e copy 2024-09-04 10:16:11 -07:00
Paul Gauthier
75c27a5dfb feat: enhance GitHub issue reporting functionality 2024-09-04 10:14:25 -07:00
Paul Gauthier (aider)
7598f883f5 style: format long line in report command for better readability 2024-09-04 10:09:13 -07:00
Paul Gauthier (aider)
1b5ef76c18 refactor: update cmd_report to use confirm=False and conditional user report prefix 2024-09-04 10:09:07 -07:00
Paul Gauthier (aider)
70994cfc5b feat: add confirm parameter to report_github_issue function 2024-09-04 10:08:16 -07:00
Paul Gauthier
c5ac621da1 docs: Update description of 'report' command 2024-09-04 10:08:08 -07:00
Paul Gauthier (aider)
5c6d4dbbf1 feat: add /report command to submit GitHub issues 2024-09-04 10:05:43 -07:00
Paul Gauthier
9434f99458 copy 2024-09-04 09:27:12 -07:00
Paul Gauthier
9988a3ff79 updated blame 2024-09-04 09:20:40 -07:00
Christian Clauss
9364ce1f15 Fix typos discovered by codespell 2024-08-05 13:37:28 +02:00
72 changed files with 2094 additions and 618 deletions

View File

@@ -14,3 +14,9 @@ repos:
hooks:
- id: flake8
args: ["--show-source"]
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
hooks:
- id: codespell
additional_dependencies:
- tomli

View File

@@ -20,7 +20,7 @@ See the
[benchmark README](https://github.com/paul-gauthier/aider/blob/main/benchmark/README.md)
for information on running aider's code editing benchmarks.
Submit results by opening a PR with edits to the
[benchmark results data files](https://github.com/paul-gauthier/aider/blob/main/_data/).
[benchmark results data files](https://github.com/paul-gauthier/aider/blob/main/aider/website/_data/).
## Pull Requests

View File

@@ -1,6 +1,36 @@
# Release history
### Aider v0.57.0
- Support for OpenAI o1 models:
- o1-preview now works well with diff edit format.
- o1-preview with diff now matches SOTA leaderboard result with whole edit format.
- `aider --model o1-mini`
- `aider --model o1-preview`
- On Windows, `/run` correctly uses PowerShell or cmd.exe.
- Support for new 08-2024 Cohere models, by @jalammar.
- Can now recursively add directories with `/read-only`.
- User input prompts now fall back to simple `input()` if `--no-pretty` or a Windows console is not available.
- Improved sanity check of git repo on startup.
- Improvements to prompt cache chunking strategy.
- Removed "No changes made to git tracked files".
- Numerous bug fixes for corner case crashes.
- Updated all dependency versions.
- Aider wrote 70% of the code in this release.
### Aider v0.56.0
- Enables prompt caching for Sonnet via OpenRouter by @fry69
- Enables 8k output tokens for Sonnet via VertexAI and DeepSeek V2.5.
- New `/report` command to open your browser with a pre-populated GitHub Issue.
- New `--chat-language` switch to set the spoken language.
- Now `--[no-]suggest-shell-commands` controls both prompting for and offering to execute shell commands.
- Check key imports on launch, provide helpful error message if dependencies aren't available.
- Renamed `--models` to `--list-models` by @fry69.
- Numerous bug fixes for corner case crashes.
- Aider wrote 56% of the code in this release.
### Aider v0.55.0
- Only print the pip command when self updating on Windows, without running it.
@@ -676,7 +706,7 @@
- Added `/git` command to run git from inside aider chats.
- Use Meta-ENTER (Esc+ENTER in some environments) to enter multiline chat messages.
- Create a `.gitignore` with `.aider*` to prevent users from accidentaly adding aider files to git.
- Create a `.gitignore` with `.aider*` to prevent users from accidentally adding aider files to git.
- Check pypi for newer versions and notify user.
- Updated keyboard interrupt logic so that 2 ^C in 2 seconds always forces aider to exit.
- Provide GPT with detailed error if it makes a bad edit block, ask for a retry.

View File

@@ -1,6 +1,6 @@
try:
from aider.__version__ import __version__
except Exception:
__version__ = "0.55.1.dev"
__version__ = "0.57.1.dev"
__all__ = [__version__]

View File

@@ -121,6 +121,7 @@ def get_parser(default_config_files, git_root):
##########
group = parser.add_argument_group("Model Settings")
group.add_argument(
"--list-models",
"--models",
metavar="MODEL",
help="List known models which match the (partial) MODEL name",
@@ -490,6 +491,12 @@ def get_parser(default_config_files, git_root):
default="en",
help="Specify the language for voice using ISO 639-1 code (default: auto)",
)
group.add_argument(
"--chat-language",
metavar="CHAT_LANGUAGE",
default=None,
help="Specify the language to use in the chat (default: None, uses system settings)",
)
group.add_argument(
"--version",
action="version",

View File

@@ -144,8 +144,12 @@ class YamlHelpFormatter(argparse.HelpFormatter):
if default:
parts.append(f"#{switch}: {default}\n")
elif action.nargs in ("*", "+") or isinstance(action, argparse._AppendAction):
parts.append(f"#{switch}: xxx")
parts.append("## Specify multiple values like this:")
parts.append(f"#{switch}: [xxx,yyyy,zzz]\n")
else:
parts.append(f"#{switch}:\n")
parts.append(f"#{switch}: xxx\n")
###
# parts.append(str(action))

View File

@@ -18,16 +18,12 @@ from datetime import datetime
from json.decoder import JSONDecodeError
from pathlib import Path
from rich.console import Console, Text
from rich.markdown import Markdown
from aider import __version__, models, prompts, urls, utils
from aider.commands import Commands
from aider.history import ChatSummary
from aider.io import ConfirmGroup, InputOutput
from aider.linter import Linter
from aider.llm import litellm
from aider.mdstream import MarkdownStream
from aider.repo import ANY_GIT_ERROR, GitRepo
from aider.repomap import RepoMap
from aider.run_cmd import run_cmd
@@ -93,6 +89,7 @@ class Coder:
num_cache_warming_pings = 0
suggest_shell_commands = True
ignore_mentions = None
chat_language = None
@classmethod
def create(
@@ -159,7 +156,9 @@ class Coder:
raise ValueError(f"Unknown edit format {edit_format}")
def clone(self, **kwargs):
return Coder.create(from_coder=self, **kwargs)
new_coder = Coder.create(from_coder=self, **kwargs)
new_coder.ignore_mentions = self.ignore_mentions
return new_coder
def get_announcements(self):
lines = []
@@ -238,8 +237,6 @@ class Coder:
dry_run=False,
map_tokens=1024,
verbose=False,
assistant_output_color="blue",
code_theme="default",
stream=True,
use_git=True,
cur_messages=None,
@@ -258,7 +255,9 @@ class Coder:
cache_prompts=False,
num_cache_warming_pings=0,
suggest_shell_commands=True,
chat_language=None,
):
self.chat_language = chat_language
self.commit_before_message = []
self.aider_commit_hashes = set()
self.rejected_urls = set()
@@ -310,17 +309,10 @@ class Coder:
self.auto_commits = auto_commits
self.dirty_commits = dirty_commits
self.assistant_output_color = assistant_output_color
self.code_theme = code_theme
self.dry_run = dry_run
self.pretty = self.io.pretty
if self.pretty:
self.console = Console()
else:
self.console = Console(force_terminal=False, no_color=True)
self.main_model = main_model
if cache_prompts and self.main_model.cache_control:
@@ -501,9 +493,10 @@ class Coder:
if content is not None:
all_content += content + "\n"
lines = all_content.splitlines()
good = False
for fence_open, fence_close in self.fences:
if fence_open in all_content or fence_close in all_content:
if any(line.startswith(fence_open) or line.startswith(fence_close) for line in lines):
continue
good = True
break
@@ -854,6 +847,9 @@ class Coder:
self.cur_messages = []
def get_user_language(self):
if self.chat_language:
return self.chat_language
try:
lang = locale.getlocale()[0]
if lang:
@@ -915,10 +911,21 @@ class Coder:
lazy_prompt = self.gpt_prompts.lazy_prompt if self.main_model.lazy else ""
platform_text = self.get_platform_info()
if self.suggest_shell_commands:
shell_cmd_prompt = self.gpt_prompts.shell_cmd_prompt.format(platform=platform_text)
shell_cmd_reminder = self.gpt_prompts.shell_cmd_reminder.format(platform=platform_text)
else:
shell_cmd_prompt = self.gpt_prompts.no_shell_cmd_prompt.format(platform=platform_text)
shell_cmd_reminder = self.gpt_prompts.no_shell_cmd_reminder.format(
platform=platform_text
)
prompt = prompt.format(
fence=self.fence,
lazy_prompt=lazy_prompt,
platform=platform_text,
shell_cmd_prompt=shell_cmd_prompt,
shell_cmd_reminder=shell_cmd_reminder,
)
return prompt
@@ -960,9 +967,16 @@ class Coder:
chunks = ChatChunks()
chunks.system = [
dict(role="system", content=main_sys),
]
if self.main_model.use_system_prompt:
chunks.system = [
dict(role="system", content=main_sys),
]
else:
chunks.system = [
dict(role="user", content=main_sys),
dict(role="assistant", content="Ok."),
]
chunks.examples = example_messages
self.summarize_end()
@@ -1088,11 +1102,7 @@ class Coder:
utils.show_messages(messages, functions=self.functions)
self.multi_response_content = ""
if self.show_pretty() and self.stream:
mdargs = dict(style=self.assistant_output_color, code_theme=self.code_theme)
self.mdstream = MarkdownStream(mdargs=mdargs)
else:
self.mdstream = None
self.mdstream = self.io.assistant_output("", self.stream)
retry_delay = 0.125
@@ -1372,6 +1382,11 @@ class Coder:
self.io.log_llm_history("TO LLM", format_messages(messages))
if self.main_model.use_temperature:
temp = self.temperature
else:
temp = None
completion = None
try:
hash_object, completion = send_completion(
@@ -1379,7 +1394,7 @@ class Coder:
messages,
functions,
self.stream,
self.temperature,
temp,
extra_headers=model.extra_headers,
max_tokens=model.max_tokens,
)
@@ -1444,14 +1459,7 @@ class Coder:
raise Exception("No data found in LLM response!")
show_resp = self.render_incremental_response(True)
if self.show_pretty():
show_resp = Markdown(
show_resp, style=self.assistant_output_color, code_theme=self.code_theme
)
else:
show_resp = Text(show_resp or "<no response>")
self.io.console.print(show_resp)
self.io.assistant_output(show_resp)
if (
hasattr(completion.choices[0], "finish_reason")
@@ -1624,7 +1632,10 @@ class Coder:
return cur + new
def get_rel_fname(self, fname):
return os.path.relpath(fname, self.root)
try:
return os.path.relpath(fname, self.root)
except ValueError:
return fname
def get_inchat_relative_files(self):
files = [self.get_rel_fname(fname) for fname in self.abs_fnames]
@@ -1869,7 +1880,6 @@ class Coder:
message=commit_message,
)
self.io.tool_output("No changes made to git tracked files.")
return self.gpt_prompts.files_content_gpt_no_edits
except ANY_GIT_ERROR as err:
self.io.tool_error(f"Unable to commit: {str(err)}")

View File

@@ -43,3 +43,8 @@ If you need to edit any of these files, ask me to *add them to the chat* first.
read_only_files_prefix = """Here are some READ ONLY files, provided for your reference.
Do not edit these files!
"""
shell_cmd_prompt = ""
shell_cmd_reminder = ""
no_shell_cmd_prompt = ""
no_shell_cmd_reminder = ""

View File

@@ -31,10 +31,12 @@ class ChatChunks:
else:
self.add_cache_control(self.system)
if self.readonly_files:
self.add_cache_control(self.readonly_files)
else:
if self.repo:
# this will mark both the readonly_files and repomap chunk as cacheable
self.add_cache_control(self.repo)
else:
# otherwise, just cache readonly_files if there are any
self.add_cache_control(self.readonly_files)
self.add_cache_control(self.chat_files)

View File

@@ -365,9 +365,13 @@ def do_replace(fname, content, before_text, after_text, fence=None):
return new_content
HEAD = "<<<<<<< SEARCH"
DIVIDER = "======="
UPDATED = ">>>>>>> REPLACE"
HEAD = r"<{5,9} SEARCH"
DIVIDER = r"={5,9}"
UPDATED = r">{5,9} REPLACE"
HEAD_ERR = "<<<<<<< SEARCH"
DIVIDER_ERR = "======="
UPDATED_ERR = ">>>>>>> REPLACE"
separators = "|".join([HEAD, DIVIDER, UPDATED])
@@ -407,6 +411,10 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE, valid_fnames=None)
i = 0
current_filename = None
head_pattern = re.compile(HEAD)
divider_pattern = re.compile(DIVIDER)
updated_pattern = re.compile(UPDATED)
while i < len(lines):
line = lines[i]
@@ -425,7 +433,7 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE, valid_fnames=None)
"```csh",
"```tcsh",
]
next_is_editblock = i + 1 < len(lines) and lines[i + 1].rstrip() == HEAD
next_is_editblock = i + 1 < len(lines) and head_pattern.match(lines[i + 1].strip())
if any(line.strip().startswith(start) for start in shell_starts) and not next_is_editblock:
shell_content = []
@@ -440,15 +448,13 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE, valid_fnames=None)
continue
# Check for SEARCH/REPLACE blocks
if line.strip() == HEAD:
if head_pattern.match(line.strip()):
try:
# if next line after HEAD exists and is DIVIDER, it's a new file
if i + 1 < len(lines) and lines[i + 1].strip() == DIVIDER:
if i + 1 < len(lines) and divider_pattern.match(lines[i + 1].strip()):
filename = find_filename(lines[max(0, i - 3) : i], fence, None)
else:
filename = find_filename(
lines[max(0, i - 3) : i], fence, valid_fnames
)
filename = find_filename(lines[max(0, i - 3) : i], fence, valid_fnames)
if not filename:
if current_filename:
@@ -460,21 +466,27 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE, valid_fnames=None)
original_text = []
i += 1
while i < len(lines) and not lines[i].strip() == DIVIDER:
while i < len(lines) and not divider_pattern.match(lines[i].strip()):
original_text.append(lines[i])
i += 1
if i >= len(lines) or lines[i].strip() != DIVIDER:
raise ValueError(f"Expected `{DIVIDER}`")
if i >= len(lines) or not divider_pattern.match(lines[i].strip()):
raise ValueError(f"Expected `{DIVIDER_ERR}`")
updated_text = []
i += 1
while i < len(lines) and not lines[i].strip() in (UPDATED, DIVIDER):
while i < len(lines) and not (
updated_pattern.match(lines[i].strip())
or divider_pattern.match(lines[i].strip())
):
updated_text.append(lines[i])
i += 1
if i >= len(lines) or lines[i].strip() not in (UPDATED, DIVIDER):
raise ValueError(f"Expected `{UPDATED}` or `{DIVIDER}`")
if i >= len(lines) or not (
updated_pattern.match(lines[i].strip())
or divider_pattern.match(lines[i].strip())
):
raise ValueError(f"Expected `{UPDATED_ERR}` or `{DIVIDER_ERR}`")
yield filename, "".join(original_text), "".join(updated_text)

View File

@@ -27,7 +27,10 @@ You can keep asking if you then decide you need to edit more files.
All changes to files must use this *SEARCH/REPLACE block* format.
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_prompt}
"""
shell_cmd_prompt = """
4. *Concisely* suggest any shell commands the user might want to run in ```bash blocks.
Just suggest shell commands this way, not example code.
@@ -36,7 +39,6 @@ Only suggest at most a few shell commands at a time, not more than 1-3.
Use the appropriate shell based on the user's system info:
{platform}
Examples of when to suggest shell commands:
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.
@@ -47,6 +49,10 @@ Examples of when to suggest shell commands:
- Etc.
"""
no_shell_cmd_prompt = """
Keep in mind these details about the user's platform and environment:
{platform}
"""
example_messages = [
dict(
role="user",
@@ -176,7 +182,10 @@ To rename files which have been added to the chat, use shell commands at the end
{lazy_prompt}
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_reminder}
"""
shell_cmd_reminder = """
Examples of when to suggest shell commands:
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.

View File

@@ -562,8 +562,7 @@ class Commands:
"HEAD",
)
# don't use io.tool_output() because we don't want to log or further colorize
print(diff)
self.io.print(diff)
def quote_fname(self, fname):
if " " in fname and '"' not in fname:
@@ -1030,9 +1029,9 @@ class Commands:
if text:
self.io.add_to_input_history(text)
print()
self.io.print()
self.io.user_input(text, log_only=False)
print()
self.io.print()
return text
@@ -1088,7 +1087,7 @@ class Commands:
def cmd_read_only(self, args):
"Add files to the chat that are for reference, not to be edited"
if not args.strip():
self.io.tool_error("Please provide filenames to read.")
self.io.tool_error("Please provide filenames or directories to read.")
return
filenames = parse_quoted_filenames(args)
@@ -1098,23 +1097,43 @@ class Commands:
abs_path = self.coder.abs_root_path(expanded_path)
if not os.path.exists(abs_path):
self.io.tool_error(f"File not found: {abs_path}")
self.io.tool_error(f"Path not found: {abs_path}")
continue
if not os.path.isfile(abs_path):
self.io.tool_error(f"Not a file: {abs_path}")
continue
if abs_path in self.coder.abs_fnames:
self.io.tool_error(f"{word} is already in the chat as an editable file")
continue
if abs_path in self.coder.abs_read_only_fnames:
self.io.tool_error(f"{word} is already in the chat as a read-only file")
continue
if os.path.isfile(abs_path):
self._add_read_only_file(abs_path, word)
elif os.path.isdir(abs_path):
self._add_read_only_directory(abs_path, word)
else:
self.io.tool_error(f"Not a file or directory: {abs_path}")
def _add_read_only_file(self, abs_path, original_name):
if abs_path in self.coder.abs_fnames:
self.io.tool_error(f"{original_name} is already in the chat as an editable file")
elif abs_path in self.coder.abs_read_only_fnames:
self.io.tool_error(f"{original_name} is already in the chat as a read-only file")
else:
self.coder.abs_read_only_fnames.add(abs_path)
self.io.tool_output(f"Added {word} to read-only files.")
self.io.tool_output(f"Added {original_name} to read-only files.")
def _add_read_only_directory(self, abs_path, original_name):
added_files = 0
for root, _, files in os.walk(abs_path):
for file in files:
file_path = os.path.join(root, file)
if (
file_path not in self.coder.abs_fnames
and file_path not in self.coder.abs_read_only_fnames
):
self.coder.abs_read_only_fnames.add(file_path)
added_files += 1
if added_files > 0:
self.io.tool_output(
f"Added {added_files} files from directory {original_name} to read-only files."
)
else:
self.io.tool_output(f"No new files added from directory {original_name}.")
def cmd_map(self, args):
"Print out the current repository map"
@@ -1135,6 +1154,20 @@ class Commands:
settings = format_settings(self.parser, self.args)
self.io.tool_output(settings)
def cmd_report(self, args):
"Report a problem by opening a GitHub Issue"
from aider.report import report_github_issue
announcements = "\n".join(self.coder.get_announcements())
issue_text = announcements
if args.strip():
title = args.strip()
else:
title = None
report_github_issue(issue_text, title=title, confirm=False)
def expand_subdir(file_path):
if file_path.is_file():
@@ -1154,11 +1187,7 @@ def parse_quoted_filenames(args):
def get_help_md():
from aider.coders import Coder
from aider.models import Model
coder = Coder(Model("gpt-3.5-turbo"), None)
md = coder.commands.get_help_md()
md = Commands(None, None).get_help_md()
return md

View File

@@ -5,7 +5,6 @@ from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from prompt_toolkit import prompt
from prompt_toolkit.completion import Completer, Completion, ThreadedCompleter
from prompt_toolkit.enums import EditingMode
from prompt_toolkit.history import FileHistory
@@ -18,6 +17,8 @@ from pygments.token import Token
from rich.console import Console
from rich.style import Style as RichStyle
from rich.text import Text
from rich.markdown import Markdown
from aider.mdstream import MarkdownStream
from .dump import dump # noqa: F401
from .utils import is_image_file
@@ -177,6 +178,8 @@ class InputOutput:
tool_output_color=None,
tool_error_color="red",
tool_warning_color="#FFA500",
assistant_output_color="blue",
code_theme="default",
encoding="utf-8",
dry_run=False,
llm_history_file=None,
@@ -191,6 +194,8 @@ class InputOutput:
self.tool_output_color = tool_output_color if pretty else None
self.tool_error_color = tool_error_color if pretty else None
self.tool_warning_color = tool_warning_color if pretty else None
self.assistant_output_color = assistant_output_color
self.code_theme = code_theme
self.input = input
self.output = output
@@ -211,14 +216,29 @@ class InputOutput:
self.encoding = encoding
self.dry_run = dry_run
if pretty:
self.console = Console()
else:
self.console = Console(force_terminal=False, no_color=True)
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
if self.pretty:
# Initialize PromptSession
session_kwargs = {
"input": self.input,
"output": self.output,
"lexer": PygmentsLexer(MarkdownLexer),
"editing_mode": self.editingmode,
}
if self.input_history_file is not None:
session_kwargs["history"] = FileHistory(self.input_history_file)
try:
self.prompt_session = PromptSession(**session_kwargs)
self.console = Console() # pretty console
except Exception as err:
self.console = Console(force_terminal=False, no_color=True)
self.tool_error(f"Can't initialize prompt toolkit: {err}") # non-pretty
else:
self.console = Console(force_terminal=False, no_color=True) # non-pretty
def read_image(self, filename):
try:
with open(str(filename), "rb") as image_file:
@@ -317,35 +337,31 @@ class InputOutput:
)
)
kb = KeyBindings()
@kb.add("escape", "c-m", eager=True)
def _(event):
event.current_buffer.insert_text("\n")
while True:
if multiline_input:
show = ". "
session_kwargs = {
"message": show,
"completer": completer_instance,
"reserve_space_for_menu": 4,
"complete_style": CompleteStyle.MULTI_COLUMN,
"input": self.input,
"output": self.output,
"lexer": PygmentsLexer(MarkdownLexer),
}
if style:
session_kwargs["style"] = style
if self.input_history_file is not None:
session_kwargs["history"] = FileHistory(self.input_history_file)
kb = KeyBindings()
@kb.add("escape", "c-m", eager=True)
def _(event):
event.current_buffer.insert_text("\n")
session = PromptSession(
key_bindings=kb, editing_mode=self.editingmode, **session_kwargs
)
line = session.prompt()
try:
if self.prompt_session:
line = self.prompt_session.prompt(
show,
completer=completer_instance,
reserve_space_for_menu=4,
complete_style=CompleteStyle.MULTI_COLUMN,
style=style,
key_bindings=kb,
)
else:
line = input(show)
except UnicodeEncodeError as err:
self.tool_error(str(err))
return ""
if line and line[0] == "{" and not multiline_input:
multiline_input = True
@@ -462,10 +478,14 @@ class InputOutput:
self.user_input(f"{question}{res}", log_only=False)
else:
while True:
res = prompt(
question,
style=Style.from_dict(style),
)
if self.prompt_session:
res = self.prompt_session.prompt(
question,
style=Style.from_dict(style),
)
else:
res = input(question)
if not res:
res = "y" # Default to Yes if no input
break
@@ -515,7 +535,10 @@ class InputOutput:
elif self.yes is False:
res = "no"
else:
res = prompt(question + " ", default=default, style=style)
if self.prompt_session:
res = self.prompt_session.prompt(question + " ", default=default, style=style)
else:
res = input(question + " ")
hist = f"{question.strip()} {res.strip()}"
self.append_chat_history(hist, linebreak=True, blockquote=True)
@@ -563,6 +586,27 @@ class InputOutput:
style = RichStyle(**style)
self.console.print(*messages, style=style)
def assistant_output(self, message, stream=False):
mdStream = None
show_resp = message
if self.pretty:
if stream:
mdargs = dict(style=self.assistant_output_color, code_theme=self.code_theme)
mdStream = MarkdownStream(mdargs=mdargs)
else:
show_resp = Markdown(
message, style=self.assistant_output_color, code_theme=self.code_theme
)
else:
show_resp = Text(message or "<no response>")
self.console.print(show_resp)
return mdStream
def print(self, message=""):
print(message)
def append_chat_history(self, text, linebreak=False, blockquote=False, strip=True):
if blockquote:
if strip:

View File

@@ -35,7 +35,10 @@ class Linter:
def get_rel_fname(self, fname):
if self.root:
return os.path.relpath(fname, self.root)
try:
return os.path.relpath(fname, self.root)
except ValueError:
return fname
else:
return fname
@@ -43,14 +46,18 @@ class Linter:
cmd += " " + rel_fname
cmd = cmd.split()
process = subprocess.Popen(
cmd,
cwd=self.root,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
encoding=self.encoding,
errors="replace",
)
try:
process = subprocess.Popen(
cmd,
cwd=self.root,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
encoding=self.encoding,
errors="replace",
)
except OSError as err:
print(f"Unable to execute lint command: {err}")
return
stdout, _ = process.communicate()
errors = stdout
if process.returncode == 0:
@@ -202,7 +209,12 @@ def basic_lint(fname, code):
if lang == "typescript":
return
parser = get_parser(lang)
try:
parser = get_parser(lang)
except OSError as err:
print(f"Unable to load parser: {err}")
return
tree = parser.parse(bytes(code, "utf-8"))
errors = traverse_tree(tree.root_node)

View File

@@ -1,8 +1,10 @@
import configparser
import json
import os
import re
import sys
import threading
import traceback
from pathlib import Path
import git
@@ -29,7 +31,7 @@ def get_git_root():
try:
repo = git.Repo(search_parent_directories=True)
return repo.working_tree_dir
except git.InvalidGitRepositoryError:
except (git.InvalidGitRepositoryError, FileNotFoundError):
return None
@@ -89,7 +91,7 @@ def setup_git(git_root, io):
pass
try:
user_email = config.get_value("user", "email", None)
except configparser.NoSectionError:
except (configparser.NoSectionError, configparser.NoOptionError):
pass
if user_name and user_email:
@@ -298,25 +300,33 @@ def sanity_check_repo(repo, io):
if not repo:
return True
if not repo.repo.working_tree_dir:
io.tool_error("The git repo does not seem to have a working tree?")
return False
try:
repo.get_tracked_files()
return True
if not repo.git_repo_error:
return True
error_msg = str(repo.git_repo_error)
except ANY_GIT_ERROR as exc:
error_msg = str(exc)
bad_ver = "version in (1, 2)" in error_msg
except AssertionError as exc:
error_msg = str(exc)
bad_ver = True
if "version in (1, 2)" in error_msg:
io.tool_error("Aider only works with git repos with version number 1 or 2.")
io.tool_output(
"You may be able to convert your repo: git update-index --index-version=2"
)
io.tool_output("Or run aider --no-git to proceed without using git.")
io.tool_output("https://github.com/paul-gauthier/aider/issues/211")
return False
io.tool_error("Unable to read git repository, it may be corrupt?")
io.tool_output(error_msg)
if bad_ver:
io.tool_error("Aider only works with git repos with version number 1 or 2.")
io.tool_output("You may be able to convert your repo: git update-index --index-version=2")
io.tool_output("Or run aider --no-git to proceed without using git.")
io.tool_output("https://github.com/paul-gauthier/aider/issues/211")
return False
io.tool_error("Unable to read git repository, it may be corrupt?")
io.tool_output(error_msg)
return False
def main(argv=None, input=None, output=None, force_git_root=None, return_coder=False):
report_uncaught_exceptions()
@@ -395,6 +405,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
user_input_color=args.user_input_color,
tool_output_color=args.tool_output_color,
tool_error_color=args.tool_error_color,
assistant_output_color=args.assistant_output_color,
code_theme=args.code_theme,
dry_run=args.dry_run,
encoding=args.encoding,
llm_history_file=args.llm_history_file,
@@ -468,8 +480,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.check_update:
check_version(io, verbose=args.verbose)
if args.models:
models.print_matching_models(io, args.models)
if args.list_models:
models.print_matching_models(io, args.list_models)
return 0
if args.git:
@@ -485,6 +497,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
cmd_line = scrub_sensitive_info(args, cmd_line)
io.tool_output(cmd_line, log_only=True)
check_and_load_imports(io, verbose=args.verbose)
if args.anthropic_api_key:
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
@@ -511,8 +525,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.verbose:
io.tool_output("Model info:")
for key, value in main_model.info.items():
io.tool_output(f" {key}: {value}")
io.tool_output(json.dumps(main_model.info, indent=4))
lint_cmds = parse_lint_cmds(args.lint_cmd, io)
if lint_cmds is None:
@@ -563,6 +576,13 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.cache_prompts and args.map_refresh == "auto":
args.map_refresh = "files"
if not main_model.streaming:
if args.stream:
io.tool_warning(
"Warning: Streaming is not supported by the selected model. Disabling streaming."
)
args.stream = False
try:
coder = Coder.create(
main_model=main_model,
@@ -577,8 +597,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
dry_run=args.dry_run,
map_tokens=args.map_tokens,
verbose=args.verbose,
assistant_output_color=args.assistant_output_color,
code_theme=args.code_theme,
stream=args.stream,
use_git=args.git,
restore_chat_history=args.restore_chat_history,
@@ -593,6 +611,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
map_mul_no_files=args.map_multiplier_no_files,
num_cache_warming_pings=args.cache_keepalive_pings,
suggest_shell_commands=args.suggest_shell_commands,
chat_language=args.chat_language,
)
except ValueError as err:
io.tool_error(str(err))
@@ -685,10 +704,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.exit:
return
thread = threading.Thread(target=load_slow_imports)
thread.daemon = True
thread.start()
while True:
try:
coder.run()
@@ -705,19 +720,72 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
coder.show_announcements()
def load_slow_imports():
def check_and_load_imports(io, verbose=False):
installs_file = Path.home() / ".aider" / "installs.json"
key = (__version__, sys.executable)
if verbose:
io.tool_output(
f"Checking imports for version {__version__} and executable {sys.executable}"
)
io.tool_output(f"Installs file: {installs_file}")
try:
if installs_file.exists():
with open(installs_file, "r") as f:
installs = json.load(f)
if verbose:
io.tool_output("Installs file exists and loaded")
else:
installs = {}
if verbose:
io.tool_output("Installs file does not exist, creating new dictionary")
if str(key) not in installs:
if verbose:
io.tool_output(
"First run for this version and executable, loading imports synchronously"
)
try:
load_slow_imports(swallow=False)
except Exception as err:
io.tool_error(str(err))
io.tool_output("Error loading required imports. Did you install aider properly?")
io.tool_output("https://aider.chat/docs/install/install.html")
sys.exit(1)
installs[str(key)] = True
installs_file.parent.mkdir(parents=True, exist_ok=True)
with open(installs_file, "w") as f:
json.dump(installs, f, indent=4)
if verbose:
io.tool_output("Imports loaded and installs file updated")
else:
if verbose:
io.tool_output("Not first run, loading imports in background thread")
thread = threading.Thread(target=load_slow_imports)
thread.daemon = True
thread.start()
except Exception as e:
io.tool_warning(f"Error in checking imports: {e}")
if verbose:
io.tool_output(f"Full exception details: {traceback.format_exc()}")
def load_slow_imports(swallow=True):
# These imports are deferred in various ways to
# improve startup time.
# This func is called in a thread to load them in the background
# while we wait for the user to type their first message.
# This func is called either synchronously or in a thread
# depending on whether it's been run before for this version and executable.
try:
import httpx # noqa: F401
import litellm # noqa: F401
import networkx # noqa: F401
import numpy # noqa: F401
except Exception:
pass
except Exception as e:
if not swallow:
raise e
if __name__ == "__main__":

View File

@@ -18,7 +18,7 @@ from aider.dump import dump # noqa: F401
from aider.llm import litellm
DEFAULT_MODEL_NAME = "gpt-4o"
ANTHROPIC_BETA_HEADER = "max-tokens-3-5-sonnet-2024-07-15,prompt-caching-2024-07-31"
ANTHROPIC_BETA_HEADER = "prompt-caching-2024-07-31"
OPENAI_MODELS = """
gpt-4
@@ -77,6 +77,9 @@ class ModelSettings:
max_tokens: Optional[int] = None
cache_control: bool = False
caches_by_default: bool = False
use_system_prompt: bool = True
use_temperature: bool = True
streaming: bool = True
# https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo
@@ -306,10 +309,8 @@ MODEL_SETTINGS = [
examples_as_sys_msg=True,
accepts_images=True,
max_tokens=8192,
extra_headers={
"anthropic-beta": "max-tokens-3-5-sonnet-2024-07-15",
},
reminder="user",
cache_control=True,
),
# Vertex AI Claude models
# Does not yet support 8k token
@@ -320,6 +321,7 @@ MODEL_SETTINGS = [
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
max_tokens=8192,
reminder="user",
),
ModelSettings(
@@ -340,6 +342,19 @@ MODEL_SETTINGS = [
weak_model_name="command-r-plus",
use_repo_map=True,
),
# New Cohere models
ModelSettings(
"command-r-08-2024",
"whole",
weak_model_name="command-r-08-2024",
use_repo_map=True,
),
ModelSettings(
"command-r-plus-08-2024",
"whole",
weak_model_name="command-r-plus-08-2024",
use_repo_map=True,
),
# Groq llama3
ModelSettings(
"groq/llama3-70b-8192",
@@ -386,6 +401,7 @@ MODEL_SETTINGS = [
use_repo_map=True,
examples_as_sys_msg=True,
reminder="sys",
max_tokens=8192,
),
ModelSettings(
"deepseek/deepseek-coder",
@@ -394,6 +410,7 @@ MODEL_SETTINGS = [
examples_as_sys_msg=True,
reminder="sys",
caches_by_default=True,
max_tokens=8192,
),
ModelSettings(
"openrouter/deepseek/deepseek-coder",
@@ -411,6 +428,66 @@ MODEL_SETTINGS = [
lazy=True,
reminder="sys",
),
ModelSettings(
"openai/o1-mini",
"whole",
weak_model_name="openai/gpt-4o-mini",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"o1-mini",
"whole",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openai/o1-preview",
"diff",
weak_model_name="openai/gpt-4o-mini",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"o1-preview",
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/openai/o1-mini",
"whole",
weak_model_name="openrouter/openai/gpt-4o-mini",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/openai/o1-preview",
"diff",
weak_model_name="openrouter/openai/gpt-4o-mini",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
]
@@ -437,21 +514,28 @@ def get_model_info(model):
if not litellm._lazy_module:
cache_dir = Path.home() / ".aider" / "caches"
cache_file = cache_dir / "model_prices_and_context_window.json"
cache_dir.mkdir(parents=True, exist_ok=True)
current_time = time.time()
cache_age = (
current_time - cache_file.stat().st_mtime if cache_file.exists() else float("inf")
)
try:
cache_dir.mkdir(parents=True, exist_ok=True)
use_cache = True
except OSError:
# If we can't create the cache directory, we'll skip using the cache
use_cache = False
if cache_age < 60 * 60 * 24:
try:
content = json.loads(cache_file.read_text())
res = get_model_flexible(model, content)
if res:
return res
except Exception as ex:
print(str(ex))
if use_cache:
current_time = time.time()
cache_age = (
current_time - cache_file.stat().st_mtime if cache_file.exists() else float("inf")
)
if cache_age < 60 * 60 * 24:
try:
content = json.loads(cache_file.read_text())
res = get_model_flexible(model, content)
if res:
return res
except Exception as ex:
print(str(ex))
import requests
@@ -459,7 +543,12 @@ def get_model_info(model):
response = requests.get(model_info_url, timeout=5)
if response.status_code == 200:
content = response.json()
cache_file.write_text(json.dumps(content, indent=4))
if use_cache:
try:
cache_file.write_text(json.dumps(content, indent=4))
except OSError:
# If we can't write to the cache file, we'll just skip caching
pass
res = get_model_flexible(model, content)
if res:
return res

View File

@@ -10,7 +10,7 @@ from aider.sendchat import simple_send_with_retries
from .dump import dump # noqa: F401
ANY_GIT_ERROR = (git.exc.ODBError, git.exc.GitError)
ANY_GIT_ERROR = (git.exc.ODBError, git.exc.GitError, OSError, IndexError, BufferError)
class GitRepo:
@@ -21,6 +21,7 @@ class GitRepo:
aider_ignore_last_check = 0
subtree_only = False
ignore_file_cache = {}
git_repo_error = None
def __init__(
self,
@@ -257,15 +258,26 @@ class GitRepo:
commit = self.repo.head.commit
except ValueError:
commit = None
except ANY_GIT_ERROR as err:
self.git_repo_error = err
self.io.tool_error(f"Unable to list files in git repo: {err}")
self.io.tool_output("Is your git repo corrupted?")
return []
files = set()
if commit:
if commit in self.tree_files:
files = self.tree_files[commit]
else:
for blob in commit.tree.traverse():
if blob.type == "blob": # blob is a file
files.add(blob.path)
try:
for blob in commit.tree.traverse():
if blob.type == "blob": # blob is a file
files.add(blob.path)
except ANY_GIT_ERROR as err:
self.git_repo_error = err
self.io.tool_error(f"Unable to list files in git repo: {err}")
self.io.tool_output("Is your git repo corrupted?")
return []
files = set(self.normalize_path(path) for path in files)
self.tree_files[commit] = set(files)
@@ -342,6 +354,8 @@ class GitRepo:
def path_in_repo(self, path):
if not self.repo:
return
if not path:
return
tracked_files = set(self.get_tracked_files())
return self.normalize_path(path) in tracked_files

View File

@@ -27,6 +27,9 @@ from tree_sitter_languages import get_language, get_parser # noqa: E402
Tag = namedtuple("Tag", "rel_fname fname line name kind".split())
SQLITE_ERRORS = (sqlite3.OperationalError, sqlite3.DatabaseError)
class RepoMap:
CACHE_VERSION = 3
TAGS_CACHE_DIR = f".aider.tags.cache.v{CACHE_VERSION}"
@@ -167,7 +170,7 @@ class RepoMap:
path = Path(self.root) / self.TAGS_CACHE_DIR
try:
self.TAGS_CACHE = Cache(path)
except sqlite3.OperationalError:
except SQLITE_ERRORS:
self.io.tool_warning(f"Unable to use tags cache, delete {path} to resolve.")
self.TAGS_CACHE = dict()
@@ -195,8 +198,12 @@ class RepoMap:
data = list(self.get_tags_raw(fname, rel_fname))
# Update the cache
self.TAGS_CACHE[cache_key] = {"mtime": file_mtime, "data": data}
self.save_tags_cache()
try:
self.TAGS_CACHE[cache_key] = {"mtime": file_mtime, "data": data}
self.save_tags_cache()
except SQLITE_ERRORS:
pass
return data
def get_tags_raw(self, fname, rel_fname):
@@ -316,6 +323,9 @@ class RepoMap:
if not file_ok:
if fname not in self.warned_files:
self.io.tool_warning(f"Repo-map can't include {fname}")
self.io.tool_output(
"Has it been deleted from the file system but not from git?"
)
self.warned_files.add(fname)
continue

View File

@@ -34,13 +34,14 @@ def get_git_info():
return "Git information unavailable"
def report_github_issue(issue_text, title=None):
def report_github_issue(issue_text, title=None, confirm=True):
"""
Compose a URL to open a new GitHub issue with the given text prefilled,
and attempt to launch it in the default web browser.
:param issue_text: The text of the issue to file
:param title: The title of the issue (optional)
:param confirm: Whether to ask for confirmation before opening the browser (default: True)
:return: None
"""
version_info = f"Aider version: {__version__}\n"
@@ -61,16 +62,17 @@ def report_github_issue(issue_text, title=None):
params["title"] = title
issue_url = f"{github_issues}?{urllib.parse.urlencode(params)}"
print(f"\n# {title}\n")
print(issue_text.strip())
print()
print("Please consider reporting this bug to help improve aider!")
prompt = "Open a GitHub Issue pre-filled with the above error in your browser? (Y/n) "
confirmation = input(prompt).strip().lower()
if confirm:
print(f"\n# {title}\n")
print(issue_text.strip())
print()
print("Please consider reporting this bug to help improve aider!")
prompt = "Open a GitHub Issue pre-filled with the above error in your browser? (Y/n) "
confirmation = input(prompt).strip().lower()
yes = not confirmation or confirmation.startswith("y")
if not yes:
return
yes = not confirmation or confirmation.startswith("y")
if not yes:
return
print("Attempting to open the issue URL in your default web browser...")
try:
@@ -79,13 +81,14 @@ def report_github_issue(issue_text, title=None):
except Exception:
pass
print()
print()
print("You can also use this URL to file the GitHub Issue:")
print()
print(issue_url)
print()
print()
if confirm:
print()
print()
print("You can also use this URL to file the GitHub Issue:")
print()
print(issue_url)
print()
print()
def exception_handler(exc_type, exc_value, exc_traceback):

View File

@@ -5,6 +5,7 @@ import sys
from io import BytesIO
import pexpect
import psutil
def run_cmd(command, verbose=False, error_print=None):
@@ -22,10 +23,42 @@ def run_cmd(command, verbose=False, error_print=None):
return 1, error_message
def get_windows_parent_process_name():
try:
current_process = psutil.Process()
while True:
parent = current_process.parent()
if parent is None:
break
parent_name = parent.name().lower()
if parent_name in ["powershell.exe", "cmd.exe"]:
return parent_name
current_process = parent
return None
except Exception:
return None
def run_cmd_subprocess(command, verbose=False):
if verbose:
print("Using run_cmd_subprocess:", command)
try:
shell = os.environ.get("SHELL", "/bin/sh")
parent_process = None
# Determine the appropriate shell
if platform.system() == "Windows":
parent_process = get_windows_parent_process_name()
if parent_process == "powershell.exe":
command = f"powershell -Command {command}"
if verbose:
print("Running command:", command)
print("SHELL:", shell)
if platform.system() == "Windows":
print("Parent process:", parent_process)
process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
@@ -34,14 +67,17 @@ def run_cmd_subprocess(command, verbose=False):
shell=True,
encoding=sys.stdout.encoding,
errors="replace",
bufsize=1,
bufsize=0, # Set bufsize to 0 for unbuffered output
universal_newlines=True,
)
output = []
for line in process.stdout:
print(line, end="") # Print the line in real-time
output.append(line) # Store the line for later use
while True:
chunk = process.stdout.read(1)
if not chunk:
break
print(chunk, end="", flush=True) # Print the chunk in real-time
output.append(chunk) # Store the chunk for later use
process.wait()
return process.returncode, "".join(output)
@@ -90,6 +126,6 @@ def run_cmd_pexpect(command, verbose=False):
child.close()
return child.exitstatus, output.getvalue().decode("utf-8", errors="replace")
except (pexpect.ExceptionPexpect, TypeError) as e:
except (pexpect.ExceptionPexpect, TypeError, ValueError) as e:
error_msg = f"Error running command {command}: {e}"
return 1, error_msg

View File

@@ -27,7 +27,7 @@ def retry_exceptions():
litellm.exceptions.ServiceUnavailableError,
litellm.exceptions.Timeout,
litellm.exceptions.InternalServerError,
litellm.llms.anthropic.AnthropicError,
litellm.llms.anthropic.chat.AnthropicError,
)
@@ -60,9 +60,10 @@ def send_completion(
kwargs = dict(
model=model_name,
messages=messages,
temperature=temperature,
stream=stream,
)
if temperature is not None:
kwargs["temperature"] = temperature
if functions is not None:
function = functions[0]

View File

@@ -234,6 +234,8 @@ def run_install(cmd):
text=True,
bufsize=1,
universal_newlines=True,
encoding=sys.stdout.encoding,
errors="replace",
)
spinner = Spinner("Installing...")

View File

@@ -16,6 +16,36 @@ cog.out(text)
# Release history
### Aider v0.57.0
- Support for OpenAI o1 models:
- o1-preview now works well with diff edit format.
- o1-preview with diff now matches SOTA leaderboard result with whole edit format.
- `aider --model o1-mini`
- `aider --model o1-preview`
- On Windows, `/run` correctly uses PowerShell or cmd.exe.
- Support for new 08-2024 Cohere models, by @jalammar.
- Can now recursively add directories with `/read-only`.
- User input prompts now fall back to simple `input()` if `--no-pretty` or a Windows console is not available.
- Improved sanity check of git repo on startup.
- Improvements to prompt cache chunking strategy.
- Removed "No changes made to git tracked files".
- Numerous bug fixes for corner case crashes.
- Updated all dependency versions.
- Aider wrote 70% of the code in this release.
### Aider v0.56.0
- Enables prompt caching for Sonnet via OpenRouter by @fry69
- Enables 8k output tokens for Sonnet via VertexAI and DeepSeek V2.5.
- New `/report` command to open your browser with a pre-populated GitHub Issue.
- New `--chat-language` switch to set the spoken language.
- Now `--[no-]suggest-shell-commands` controls both prompting for and offering to execute shell commands.
- Check key imports on launch, provide helpful error message if dependencies aren't available.
- Renamed `--models` to `--list-models` by @fry69.
- Numerous bug fixes for corner case crashes.
- Aider wrote 56% of the code in this release.
### Aider v0.55.0
- Only print the pip command when self updating on Windows, without running it.
@@ -691,7 +721,7 @@ cog.out(text)
- Added `/git` command to run git from inside aider chats.
- Use Meta-ENTER (Esc+ENTER in some environments) to enter multiline chat messages.
- Create a `.gitignore` with `.aider*` to prevent users from accidentaly adding aider files to git.
- Create a `.gitignore` with `.aider*` to prevent users from accidentally adding aider files to git.
- Check pypi for newer versions and notify user.
- Updated keyboard interrupt logic so that 2 ^C in 2 seconds always forces aider to exit.
- Provide GPT with detailed error if it makes a bad edit block, ask for a retry.

View File

@@ -41,4 +41,8 @@ repository: paul-gauthier/aider
callouts:
tip:
title: Tip
color: green
color: green
note:
title: Note
color: yellow

View File

@@ -2380,3 +2380,154 @@
Paul Gauthier (aider): 204
start_tag: v0.53.0
total_lines: 319
- aider_percentage: 52.9
aider_total: 811
end_date: '2024-09-04'
end_tag: v0.55.0
file_counts:
aider/__init__.py:
Paul Gauthier: 4
Paul Gauthier (aider): 2
aider/args.py:
Paul Gauthier (aider): 7
aider/coders/base_coder.py:
Paul Gauthier: 63
Paul Gauthier (aider): 42
aider/coders/editblock_coder.py:
Nikolay Sedelnikov: 8
aider/coders/editblock_func_coder.py:
Antti Kaihola: 2
aider/coders/search_replace.py:
Paul Gauthier: 2
aider/coders/wholefile_coder.py:
Paul Gauthier: 16
aider/commands.py:
Antti Kaihola: 7
Paul Gauthier: 85
Paul Gauthier (aider): 27
aider/format_settings.py:
Paul Gauthier (aider): 26
aider/gui.py:
Paul Gauthier: 4
aider/io.py:
Paul Gauthier: 63
Paul Gauthier (aider): 13
aider/linter.py:
Paul Gauthier: 5
aider/llm.py:
Paul Gauthier: 2
aider/main.py:
Paul Gauthier: 86
Paul Gauthier (aider): 22
aider/models.py:
Paul Gauthier: 24
Paul Gauthier (aider): 2
aider/repo.py:
Paul Gauthier: 85
aider/repomap.py:
Paul Gauthier: 32
Paul Gauthier (aider): 4
aider/report.py:
Paul Gauthier: 77
Paul Gauthier (aider): 120
aider/run_cmd.py:
Paul Gauthier: 17
Paul Gauthier (aider): 24
aider/scrape.py:
Paul Gauthier: 7
Paul Gauthier (aider): 8
aider/special.py:
Paul Gauthier: 5
Paul Gauthier (aider): 197
aider/urls.py:
Paul Gauthier (aider): 1
aider/utils.py:
Paul Gauthier: 31
Paul Gauthier (aider): 29
aider/versioncheck.py:
Paul Gauthier: 32
Paul Gauthier (aider): 6
aider/voice.py:
Paul Gauthier: 7
Paul Gauthier (aider): 9
scripts/versionbump.py:
Paul Gauthier: 9
tests/basic/test_coder.py:
Paul Gauthier: 3
Paul Gauthier (aider): 105
tests/basic/test_editblock.py:
Antti Kaihola: 3
Nikolay Sedelnikov: 37
tests/basic/test_io.py:
Paul Gauthier: 2
Paul Gauthier (aider): 15
tests/basic/test_main.py:
Paul Gauthier: 2
Paul Gauthier (aider): 10
tests/basic/test_models.py:
Paul Gauthier (aider): 4
tests/basic/test_repomap.py:
Paul Gauthier (aider): 42
tests/basic/test_run_cmd.py:
Paul Gauthier (aider): 11
tests/basic/test_special.py:
Paul Gauthier: 2
Paul Gauthier (aider): 74
tests/scrape/test_scrape.py:
Paul Gauthier (aider): 11
grand_total:
Antti Kaihola: 12
Nikolay Sedelnikov: 45
Paul Gauthier: 665
Paul Gauthier (aider): 811
start_tag: v0.54.0
total_lines: 1533
- aider_percentage: 55.6
aider_total: 154
end_date: '2024-09-09'
end_tag: v0.56.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/args.py:
Paul Gauthier: 2
Paul Gauthier (aider): 6
aider/coders/base_coder.py:
Paul Gauthier: 14
Paul Gauthier (aider): 10
aider/commands.py:
Paul Gauthier: 8
Paul Gauthier (aider): 6
aider/io.py:
Paul Gauthier: 5
aider/linter.py:
Paul Gauthier: 6
Paul Gauthier (aider): 4
fry69: 12
aider/main.py:
Paul Gauthier: 35
Paul Gauthier (aider): 48
aider/models.py:
Paul Gauthier: 2
fry69: 3
aider/repo.py:
Paul Gauthier: 16
aider/repomap.py:
Paul Gauthier: 13
aider/report.py:
Paul Gauthier: 2
Paul Gauthier (aider): 20
benchmark/benchmark.py:
Paul Gauthier: 1
tests/basic/test_linter.py:
Paul Gauthier: 1
Paul Gauthier (aider): 51
tests/basic/test_main.py:
Paul Gauthier: 2
Paul Gauthier (aider): 9
grand_total:
Paul Gauthier: 108
Paul Gauthier (aider): 154
fry69: 15
start_tag: v0.55.0
total_lines: 277

View File

@@ -317,29 +317,6 @@
seconds_per_case: 22.9
total_cost: 2.7494
- dirname: 2024-05-09-18-57-52--deepseek-chat-v2-diff-reverted-and-helpful-assistant2
test_cases: 133
model: DeepSeek Chat V2 (original)
released: 2024-05-06
edit_format: diff
commit_hash: 80a3f6d
pass_rate_1: 44.4
pass_rate_2: 60.9
percent_cases_well_formed: 97.0
error_outputs: 14
num_malformed_responses: 4
user_asks: 2
lazy_comments: 0
syntax_errors: 13
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model deepseek/deepseek-chat
date: 2024-05-09
versions: 0.33.1-dev
seconds_per_case: 86.8
total_cost: 0.0941
- dirname: 2024-05-07-20-32-37--qwen1.5-110b-chat-whole
test_cases: 133
model: qwen1.5-110b-chat
@@ -665,7 +642,7 @@
- dirname: 2024-07-19-08-57-13--openrouter-deepseek-chat-v2-0628
test_cases: 133
model: DeepSeek Chat V2 0628
model: DeepSeek Chat V2 0628 (deprecated)
edit_format: diff
commit_hash: 96ff06e-dirty
pass_rate_1: 60.9
@@ -737,7 +714,7 @@
- dirname: 2024-07-24-07-10-58--deepseek-coder2-0724-diff-direct
test_cases: 133
model: DeepSeek Coder V2 0724
model: DeepSeek Coder V2 0724 (deprecated)
edit_format: diff
commit_hash: 89965bf
pass_rate_1: 57.9
@@ -969,4 +946,258 @@
date: 2024-08-30
versions: 0.54.8-dev
seconds_per_case: 38.3
total_cost: 0.0000
- dirname: 2024-09-04-16-08-09--yi-coder-9b-whole
test_cases: 133
model: Yi Coder 9B Chat
edit_format: whole
commit_hash: c4e4967
pass_rate_1: 46.6
pass_rate_2: 54.1
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 9
lazy_comments: 0
syntax_errors: 14
indentation_errors: 2
exhausted_context_windows: 0
test_timeouts: 4
command: aider --model openai/hf:01-ai/Yi-Coder-9B-Chat --openai-api-base https://glhf.chat/api/openai/v1
date: 2024-09-04
versions: 0.54.13.dev
seconds_per_case: 8.3
total_cost: 0.0000
released: 2024-09-04
- dirname: 2024-09-04-16-17-33--yi-coder-9b-chat-q4_0-whole
test_cases: 133
model: yi-coder:9b-chat-q4_0
edit_format: whole
commit_hash: c4e4967
pass_rate_1: 41.4
pass_rate_2: 45.1
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 48
lazy_comments: 1
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model ollama/yi-coder:9b-chat-q4_0
date: 2024-09-04
versions: 0.54.13.dev
seconds_per_case: 125.3
total_cost: 0.0000
- dirname: 2024-09-05-14-50-11--deepseek-sep5-no-shell
test_cases: 133
model: DeepSeek V2.5
edit_format: diff
commit_hash: 1279c86
pass_rate_1: 54.9
pass_rate_2: 72.2
percent_cases_well_formed: 96.2
error_outputs: 5
num_malformed_responses: 5
num_with_malformed_responses: 5
user_asks: 4
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --deepseek
date: 2024-09-05
versions: 0.55.1.dev
seconds_per_case: 49.6
total_cost: 0.0998
- dirname: 2024-09-06-19-55-17--reflection-hyperbolic-whole-output2
test_cases: 133
model: Reflection-70B
edit_format: whole
commit_hash: 74631ee-dirty, 2aef59e-dirty
pass_rate_1: 33.1
pass_rate_2: 42.1
percent_cases_well_formed: 100.0
error_outputs: 2
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 10
lazy_comments: 26
syntax_errors: 1
indentation_errors: 3
exhausted_context_windows: 0
test_timeouts: 3
command: (not currently supported)
date: 2024-09-06
versions: 0.55.1.dev
seconds_per_case: 61.6
total_cost: 0.0000
- dirname: 2024-09-11-15-42-17--command-r-plus-08-2024-whole
test_cases: 133
model: Command R+ (08-24)
edit_format: whole
commit_hash: b43ed20
pass_rate_1: 27.1
pass_rate_2: 38.3
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 7
lazy_comments: 10
syntax_errors: 0
indentation_errors: 3
exhausted_context_windows: 0
test_timeouts: 4
command: aider --model command-r-plus-08-2024
date: 2024-09-11
versions: 0.56.1.dev
seconds_per_case: 20.3
total_cost: 0.0000
- dirname: 2024-09-11-15-47-02--command-r-08-2024-whole
test_cases: 133
model: Command R (08-24)
edit_format: whole
commit_hash: b43ed20-dirty
pass_rate_1: 30.1
pass_rate_2: 38.3
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 4
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model command-r-08-2024
date: 2024-09-11
versions: 0.56.1.dev
seconds_per_case: 7.6
total_cost: 0.0000
- dirname: 2024-09-12-19-57-35--o1-mini-whole
test_cases: 133
model: o1-mini (whole)
edit_format: whole
commit_hash: 36fa773-dirty, 291b456
pass_rate_1: 49.6
pass_rate_2: 70.7
percent_cases_well_formed: 90.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 17
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model o1-mini
date: 2024-09-12
versions: 0.56.1.dev
seconds_per_case: 103.0
total_cost: 5.3725
- dirname: 2024-09-12-20-56-22--o1-mini-diff
test_cases: 133
model: o1-mini (diff)
edit_format: diff
commit_hash: 4598a37-dirty, 291b456, 752e823-dirty
pass_rate_1: 45.1
pass_rate_2: 62.4
percent_cases_well_formed: 85.7
error_outputs: 26
num_malformed_responses: 26
num_with_malformed_responses: 19
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model o1-mini --edit-format diff
date: 2024-09-12
versions: 0.56.1.dev
seconds_per_case: 177.7
total_cost: 11.1071
- dirname: 2024-09-21-16-45-11--o1-preview-flex-sr-markers
test_cases: 133
model: o1-preview
edit_format: diff
commit_hash: 5493654-dirty
pass_rate_1: 57.9
pass_rate_2: 79.7
percent_cases_well_formed: 93.2
error_outputs: 11
num_malformed_responses: 11
num_with_malformed_responses: 9
user_asks: 3
lazy_comments: 0
syntax_errors: 10
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model o1-preview
date: 2024-09-21
versions: 0.56.1.dev
seconds_per_case: 80.9
total_cost: 63.9190
- dirname: 2024-09-19-16-58-29--qwen2.5-coder:7b-instruct-q8_0
test_cases: 133
model: qwen2.5-coder:7b-instruct-q8_0
edit_format: whole
commit_hash: 6f2b064-dirty
pass_rate_1: 45.1
pass_rate_2: 51.9
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 4
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model ollama/qwen2.5-coder:7b-instruct-q8_0
date: 2024-09-19
versions: 0.56.0
seconds_per_case: 9.3
total_cost: 0.0000
- dirname: 2024-09-20-20-20-19--qwen-2.5-72b-instruct-diff
test_cases: 133
model: qwen-2.5-72b-instruct (bf16)
edit_format: diff
commit_hash: 5139594
pass_rate_1: 53.4
pass_rate_2: 65.4
percent_cases_well_formed: 96.2
error_outputs: 9
num_malformed_responses: 9
num_with_malformed_responses: 5
user_asks: 3
lazy_comments: 0
syntax_errors: 2
indentation_errors: 1
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model openrouter/qwen/qwen-2.5-72b-instruct
date: 2024-09-20
versions: 0.56.1.dev
seconds_per_case: 39.8
total_cost: 0.0000

View File

@@ -0,0 +1,186 @@
- dirname: 2024-07-18-18-57-46--gpt-4o-mini-whole
test_cases: 133
model: gpt-4o-mini (whole)
edit_format: whole
commit_hash: d31eef3-dirty
pass_rate_1: 40.6
pass_rate_2: 55.6
released: 2024-07-18
percent_cases_well_formed: 100.0
error_outputs: 1
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 1
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model gpt-4o-mini
date: 2024-07-18
versions: 0.44.1-dev
seconds_per_case: 7.8
total_cost: 0.0916
- dirname: 2024-07-04-14-32-08--claude-3.5-sonnet-diff-continue
test_cases: 133
model: claude-3.5-sonnet (diff)
edit_format: diff
commit_hash: 35f21b5
pass_rate_1: 57.1
pass_rate_2: 77.4
percent_cases_well_formed: 99.2
error_outputs: 23
released: 2024-06-20
num_malformed_responses: 4
num_with_malformed_responses: 1
user_asks: 2
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --sonnet
date: 2024-07-04
versions: 0.42.1-dev
seconds_per_case: 17.6
total_cost: 3.6346
- dirname: 2024-08-06-18-28-39--gpt-4o-2024-08-06-diff-again
test_cases: 133
model: gpt-4o-2024-08-06 (diff)
edit_format: diff
commit_hash: ed9ed89
pass_rate_1: 57.1
pass_rate_2: 71.4
percent_cases_well_formed: 98.5
error_outputs: 18
num_malformed_responses: 2
num_with_malformed_responses: 2
user_asks: 10
lazy_comments: 0
syntax_errors: 6
indentation_errors: 2
exhausted_context_windows: 0
test_timeouts: 5
released: 2024-08-06
command: aider --model openai/gpt-4o-2024-08-06
date: 2024-08-06
versions: 0.48.1-dev
seconds_per_case: 6.5
total_cost: 0.0000
- dirname: 2024-09-12-19-57-35--o1-mini-whole
test_cases: 133
model: o1-mini (whole)
edit_format: whole
commit_hash: 36fa773-dirty, 291b456
pass_rate_1: 49.6
pass_rate_2: 70.7
percent_cases_well_formed: 90.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 17
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model o1-mini
date: 2024-09-12
versions: 0.56.1.dev
seconds_per_case: 103.0
total_cost: 5.3725
- dirname: 2024-09-12-20-56-22--o1-mini-diff
test_cases: 133
model: o1-mini (diff)
edit_format: diff
commit_hash: 4598a37-dirty, 291b456, 752e823-dirty
pass_rate_1: 45.1
pass_rate_2: 62.4
percent_cases_well_formed: 85.7
error_outputs: 26
num_malformed_responses: 26
num_with_malformed_responses: 19
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model o1-mini --edit-format diff
date: 2024-09-12
versions: 0.56.1.dev
seconds_per_case: 177.7
total_cost: 11.1071
- dirname: 2024-09-05-21-26-49--sonnet-whole-sep5
test_cases: 133
model: claude-3.5-sonnet (whole)
edit_format: whole
commit_hash: 8cfdcbd
pass_rate_1: 55.6
pass_rate_2: 75.2
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 0
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model openrouter/anthropic/claude-3.5-sonnet --edit-format whole
date: 2024-09-05
versions: 0.55.1.dev
seconds_per_case: 15.2
total_cost: 2.3502
- dirname: 2024-09-12-22-44-14--o1-preview-diff
test_cases: 133
model: o1-preview (diff)
edit_format: diff
commit_hash: 72f52bd
pass_rate_1: 56.4
pass_rate_2: 75.2
percent_cases_well_formed: 84.2
error_outputs: 27
num_malformed_responses: 27
num_with_malformed_responses: 21
user_asks: 8
lazy_comments: 0
syntax_errors: 7
indentation_errors: 3
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model o1-preview
date: 2024-09-12
versions: 0.56.1.dev
seconds_per_case: 95.8
total_cost: 71.7927
- dirname: 2024-09-13-02-13-59--o1-preview-whole
test_cases: 133
model: o1-preview (whole)
edit_format: whole
commit_hash: 72f52bd-dirty
pass_rate_1: 58.6
pass_rate_2: 79.7
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 2
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model o1-preview
date: 2024-09-13
versions: 0.56.1.dev
seconds_per_case: 47.4
total_cost: 38.0612

View File

@@ -167,7 +167,7 @@
- dirname: 2024-07-24-07-49-39--refac-deepseek-coder-v2-0724
test_cases: 89
model: DeepSeek Coder V2 0724
model: DeepSeek Coder V2 0724 (deprecated)
edit_format: diff
commit_hash: bb6e597
pass_rate_1: 32.6
@@ -208,4 +208,25 @@
versions: 0.48.1-dev
seconds_per_case: 16.9
total_cost: 4.0873
- dirname: 2024-09-05-15-19-05--refac-deepseek-v2.5-no-shell
test_cases: 89
model: DeepSeek Chat V2.5
edit_format: diff
commit_hash: 1279c86, 1279c86-dirty
pass_rate_1: 31.5
percent_cases_well_formed: 67.4
error_outputs: 90
num_malformed_responses: 88
num_with_malformed_responses: 29
user_asks: 8
lazy_comments: 7
syntax_errors: 0
indentation_errors: 6
exhausted_context_windows: 2
test_timeouts: 0
command: aider --deepseek
date: 2024-09-05
versions: 0.55.1.dev
seconds_per_case: 225.4
total_cost: 1.0338

View File

@@ -0,0 +1,170 @@
<canvas id="{{ include.chart_id }}" width="800" height="450" style="margin-top: 20px"></canvas>
<script>
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('{{ include.chart_id }}').getContext('2d');
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: [],
borderColor: [],
borderWidth: 1
}]
};
var allData = [];
{% for row in include.data %}
allData.push({
model: '{{ row.model }}',
pass_rate: {{ row[include.pass_rate_key] }},
percent_cases_well_formed: {{ row.percent_cases_well_formed }},
edit_format: '{{ row.edit_format }}'
});
{% endfor %}
function updateChart() {
var selectedRows = document.querySelectorAll('tr.selected');
var showAll = selectedRows.length === 0;
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
leaderboardData.datasets[0].backgroundColor = [];
leaderboardData.datasets[0].borderColor = [];
allData.forEach(function(row, index) {
var rowElement = document.getElementById('{{ include.row_prefix }}-' + index);
if (showAll) {
rowElement.classList.remove('selected');
}
if (showAll || rowElement.classList.contains('selected')) {
leaderboardData.labels.push(row.model);
leaderboardData.datasets[0].data.push(row.pass_rate);
switch (row.edit_format) {
case 'whole':
leaderboardData.datasets[0].backgroundColor.push('rgba(255, 99, 132, 0.2)');
leaderboardData.datasets[0].borderColor.push('rgba(255, 99, 132, 1)');
break;
case 'diff':
leaderboardData.datasets[0].backgroundColor.push('rgba(54, 162, 235, 0.2)');
leaderboardData.datasets[0].borderColor.push('rgba(54, 162, 235, 1)');
break;
case 'udiff':
leaderboardData.datasets[0].backgroundColor.push('rgba(75, 192, 192, 0.2)');
leaderboardData.datasets[0].borderColor.push('rgba(75, 192, 192, 1)');
break;
case 'diff-fenced':
leaderboardData.datasets[0].backgroundColor.push('rgba(153, 102, 255, 0.2)');
leaderboardData.datasets[0].borderColor.push('rgba(153, 102, 255, 1)');
break;
default:
leaderboardData.datasets[0].backgroundColor.push('rgba(201, 203, 207, 0.2)');
leaderboardData.datasets[0].borderColor.push('rgba(201, 203, 207, 1)');
}
}
});
// Apply legend filtering
var meta = leaderboardChart.getDatasetMeta(0);
meta.data.forEach(function(bar, index) {
if (leaderboardData.labels.includes(allData[index].model)) {
bar.hidden = (allData[index].edit_format === 'whole' && meta.data[0].hidden) ||
(allData[index].edit_format !== 'whole' && meta.data[1].hidden);
} else {
bar.hidden = true;
}
});
leaderboardChart.update();
}
var tableBody = document.querySelector('table tbody');
allData.forEach(function(row, index) {
var tr = tableBody.children[index];
tr.id = '{{ include.row_prefix }}-' + index;
tr.style.cursor = 'pointer';
tr.onclick = function() {
this.classList.toggle('selected');
updateChart();
};
});
var leaderboardChart = new Chart(ctx, {
type: 'bar',
data: leaderboardData,
options: {
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Correct Exercises (%)'
}
},
x: {
ticks: {
autoSkip: false,
maxRotation: 90,
minRotation: 0
}
}
},
plugins: {
legend: {
display: true,
position: 'top',
labels: {
generateLabels: function(chart) {
var uniqueFormats = [...new Set(allData.map(item => item.edit_format))];
return uniqueFormats.map(format => {
var color;
switch (format) {
case 'whole':
color = { fill: 'rgba(255, 99, 132, 0.2)', stroke: 'rgba(255, 99, 132, 1)' };
break;
case 'diff':
color = { fill: 'rgba(54, 162, 235, 0.2)', stroke: 'rgba(54, 162, 235, 1)' };
break;
case 'udiff':
color = { fill: 'rgba(75, 192, 192, 0.2)', stroke: 'rgba(75, 192, 192, 1)' };
break;
case 'diff-fenced':
color = { fill: 'rgba(153, 102, 255, 0.2)', stroke: 'rgba(153, 102, 255, 1)' };
break;
default:
color = { fill: 'rgba(201, 203, 207, 0.2)', stroke: 'rgba(201, 203, 207, 1)' };
}
return {
text: format,
fillStyle: color.fill,
strokeStyle: color.stroke,
lineWidth: 1,
hidden: false
};
});
}
},
onClick: function(e, legendItem, legend) {
var ci = legend.chart;
var clickedFormat = legendItem.text;
legendItem.hidden = !legendItem.hidden;
ci.data.datasets[0].data.forEach(function(dataPoint, i) {
var meta = ci.getDatasetMeta(0);
if (allData[i].edit_format === clickedFormat) {
meta.data[i].hidden = legendItem.hidden;
}
});
ci.update();
}
}
}
}
});
updateChart();
});
</script>

View File

@@ -0,0 +1,9 @@
To use aider with pipx on replit, you can run these commands in the replit shell:
```
pip install pipx
pipx run aider-chat ...normal aider args...
```
If you install aider with pipx on replit and try and run it as just `aider` it will crash with a missing `libstdc++.so.6` library.

View File

@@ -0,0 +1,116 @@
---
title: o1-preview is SOTA on the aider leaderboard
excerpt: Preliminary benchmark results for the new OpenAI o1 models.
nav_exclude: true
---
{% if page.date %}
<p class="post-date">{{ page.date | date: "%B %d, %Y" }}</p>
{% endif %}
# OpenAI o1-preview is SOTA on the aider leaderboard
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
{% assign edit_sorted = site.data.o1_results | sort: 'pass_rate_2' | reverse %}
{% include leaderboard_graph.html
chart_id="editChart"
data=edit_sorted
row_prefix="edit-row"
pass_rate_key="pass_rate_2"
%}
## o1-preview
OpenAI o1-preview scored 79.7% on aider's code editing benchmark,
a state of the art result.
It achieved this result with the
["whole" edit format](/docs/leaderboards/#notes-on-the-edit-format),
where the LLM returns a full copy of the source code file with changes.
It is much more practical to use aider's
["diff" edit format](/docs/leaderboards/#notes-on-the-edit-format),
which allows the LLM to return search/replace blocks to
efficiently edit the source code.
This saves significant time and token costs.
Using the diff edit format the o1-preview model had a strong
benchmark score of 75.2%.
This likely places o1-preview between Sonnet and GPT-4o for practical use,
but at significantly higher cost.
## o1-mini
OpenAI o1-mini is priced similarly to GPT-4o and Claude 3.5 Sonnet,
but scored below those models.
It also works best with the whole edit format.
## Future work
The o1-preview model had trouble conforming to aider's diff edit format.
The o1-mini model had trouble conforming to both the whole and diff edit formats.
Aider is extremely permissive and tries hard to accept anything close
to the correct formats.
It is surprising that such strong models had trouble with
the syntactic requirements of simple text output formats.
It seems likely that aider could optimize its prompts and edit formats to
better harness the o1 models.
## Using aider with o1
OpenAI's new o1 models are supported in v0.57.0 of aider:
```
aider --model o1-mini
aider --model o1-preview
```
{: .note }
> These are initial benchmark results for the o1 models,
> based on aider v0.56.1-dev.
> See the [aider leaderboards](/docs/leaderboards/) for up-to-date results
> based on the latest aider releases.
<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>
</tr>
</thead>
<tbody>
{% 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>
</tr>
{% endfor %}
</tbody>
</table>
<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>

View File

@@ -12,19 +12,19 @@
# options:
## show this help message and exit
#help:
#help: xxx
#######
# Main:
## Specify the OpenAI API key
#openai-api-key:
#openai-api-key: xxx
## Specify the Anthropic API key
#anthropic-api-key:
#anthropic-api-key: xxx
## Specify the model to use for the main chat
#model:
#model: xxx
## Use claude-3-opus-20240229 model for the main chat
#opus: false
@@ -54,22 +54,22 @@
# Model Settings:
## List known models which match the (partial) MODEL name
#models:
#list-models: xxx
## Specify the api base url
#openai-api-base:
#openai-api-base: xxx
## Specify the api_type
#openai-api-type:
#openai-api-type: xxx
## Specify the api_version
#openai-api-version:
#openai-api-version: xxx
## Specify the deployment_id
#openai-api-deployment-id:
#openai-api-deployment-id: xxx
## Specify the OpenAI organization ID
#openai-organization-id:
#openai-organization-id: xxx
## Specify a file with aider model settings for unknown models
#model-settings-file: .aider.model.settings.yml
@@ -81,16 +81,16 @@
#verify-ssl: true
## Specify what edit format the LLM should use (default depends on model)
#edit-format:
#edit-format: xxx
## Specify the model to use for commit messages and chat history summarization (default depends on --model)
#weak-model:
#weak-model: xxx
## Only work with models that have meta-data available (default: True)
#show-model-warnings: true
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
#map-tokens:
#map-tokens: xxx
## Control how often the repo map is refreshed (default: auto)
#map-refresh: auto
@@ -105,7 +105,7 @@
#map-multiplier-no-files: true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
#max-chat-history-tokens:
#max-chat-history-tokens: xxx
## Specify the .env file to load (default: .env in git root)
#env-file: .env
@@ -123,7 +123,7 @@
#restore-chat-history: false
## Log the conversation with the LLM to this file (for example, .aider.llm.history)
#llm-history-file:
#llm-history-file: xxx
##################
# Output Settings:
@@ -144,7 +144,7 @@
#user-input-color: #00cc00
## Set the color for tool output (default: None)
#tool-output-color:
#tool-output-color: xxx
## Set the color for tool error messages (default: #FF2222)
#tool-error-color: #FF2222
@@ -198,7 +198,7 @@
#commit: false
## Specify a custom prompt for generating commit messages
#commit-prompt:
#commit-prompt: xxx
## Perform a dry run without modifying files (default: False)
#dry-run: false
@@ -210,13 +210,15 @@
#lint: false
## Specify lint commands to run for different languages, eg: "python: flake8 --select=..." (can be used multiple times)
#lint-cmd:
#lint-cmd: xxx
## Specify multiple values like this:
#lint-cmd: [xxx,yyyy,zzz]
## Enable/disable automatic linting after changes (default: True)
#auto-lint: true
## Specify command to run tests
#test-cmd:
#test-cmd: xxx
## Enable/disable automatic testing after changes (default: False)
#auto-test: false
@@ -228,10 +230,14 @@
# Other Settings:
## specify a file to edit (can be used multiple times)
#file:
#file: xxx
## Specify multiple values like this:
#file: [xxx,yyyy,zzz]
## specify a read-only file (can be used multiple times)
#read:
#read: xxx
## Specify multiple values like this:
#read: [xxx,yyyy,zzz]
## Use VI editing mode in the terminal (default: False)
#vim: false
@@ -239,8 +245,11 @@
## Specify the language for voice using ISO 639-1 code (default: auto)
#voice-language: en
## Specify the language to use in the chat (default: None, uses system settings)
#chat-language: xxx
## Show the version number and exit
#version:
#version: xxx
## Check for updates and return status in the exit code
#just-check-update: false
@@ -255,7 +264,7 @@
#upgrade: false
## Apply the changes from the given file instead of running the chat (debug)
#apply:
#apply: xxx
## Always say yes to every confirmation
#yes: false
@@ -273,16 +282,16 @@
#exit: false
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#message:
#message: xxx
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file:
#message-file: xxx
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config:
#config: xxx
## Run aider in your browser
#gui: false

View File

@@ -58,7 +58,7 @@
# Model Settings:
## List known models which match the (partial) MODEL name
#AIDER_MODELS=
#AIDER_LIST_MODELS=
## Specify the api base url
#OPENAI_API_BASE=
@@ -243,6 +243,9 @@
## Specify the language for voice using ISO 639-1 code (default: auto)
#AIDER_VOICE_LANGUAGE=en
## Specify the language to use in the chat (default: None, uses system settings)
#AIDER_CHAT_LANGUAGE=
## Check for updates and return status in the exit code
#AIDER_JUST_CHECK_UPDATE=false

View File

@@ -89,3 +89,8 @@ The yaml file should be a a list of dictionary objects for each model, as follow
examples_as_sys_msg: false
```
You can look at the `ModelSettings` class in
[models.py](https://github.com/paul-gauthier/aider/blob/main/aider/models.py)
file for details about all of the model setting that aider supports.
That file also contains the settings for many popular models.

View File

@@ -60,19 +60,19 @@ cog.outl("```")
# options:
## show this help message and exit
#help:
#help: xxx
#######
# Main:
## Specify the OpenAI API key
#openai-api-key:
#openai-api-key: xxx
## Specify the Anthropic API key
#anthropic-api-key:
#anthropic-api-key: xxx
## Specify the model to use for the main chat
#model:
#model: xxx
## Use claude-3-opus-20240229 model for the main chat
#opus: false
@@ -102,22 +102,22 @@ cog.outl("```")
# Model Settings:
## List known models which match the (partial) MODEL name
#models:
#list-models: xxx
## Specify the api base url
#openai-api-base:
#openai-api-base: xxx
## Specify the api_type
#openai-api-type:
#openai-api-type: xxx
## Specify the api_version
#openai-api-version:
#openai-api-version: xxx
## Specify the deployment_id
#openai-api-deployment-id:
#openai-api-deployment-id: xxx
## Specify the OpenAI organization ID
#openai-organization-id:
#openai-organization-id: xxx
## Specify a file with aider model settings for unknown models
#model-settings-file: .aider.model.settings.yml
@@ -129,16 +129,16 @@ cog.outl("```")
#verify-ssl: true
## Specify what edit format the LLM should use (default depends on model)
#edit-format:
#edit-format: xxx
## Specify the model to use for commit messages and chat history summarization (default depends on --model)
#weak-model:
#weak-model: xxx
## Only work with models that have meta-data available (default: True)
#show-model-warnings: true
## Suggested number of tokens to use for repo map, use 0 to disable (default: 1024)
#map-tokens:
#map-tokens: xxx
## Control how often the repo map is refreshed (default: auto)
#map-refresh: auto
@@ -153,7 +153,7 @@ cog.outl("```")
#map-multiplier-no-files: true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
#max-chat-history-tokens:
#max-chat-history-tokens: xxx
## Specify the .env file to load (default: .env in git root)
#env-file: .env
@@ -171,7 +171,7 @@ cog.outl("```")
#restore-chat-history: false
## Log the conversation with the LLM to this file (for example, .aider.llm.history)
#llm-history-file:
#llm-history-file: xxx
##################
# Output Settings:
@@ -192,7 +192,7 @@ cog.outl("```")
#user-input-color: #00cc00
## Set the color for tool output (default: None)
#tool-output-color:
#tool-output-color: xxx
## Set the color for tool error messages (default: #FF2222)
#tool-error-color: #FF2222
@@ -246,7 +246,7 @@ cog.outl("```")
#commit: false
## Specify a custom prompt for generating commit messages
#commit-prompt:
#commit-prompt: xxx
## Perform a dry run without modifying files (default: False)
#dry-run: false
@@ -258,13 +258,15 @@ cog.outl("```")
#lint: false
## Specify lint commands to run for different languages, eg: "python: flake8 --select=..." (can be used multiple times)
#lint-cmd:
#lint-cmd: xxx
## Specify multiple values like this:
#lint-cmd: [xxx,yyyy,zzz]
## Enable/disable automatic linting after changes (default: True)
#auto-lint: true
## Specify command to run tests
#test-cmd:
#test-cmd: xxx
## Enable/disable automatic testing after changes (default: False)
#auto-test: false
@@ -276,10 +278,14 @@ cog.outl("```")
# Other Settings:
## specify a file to edit (can be used multiple times)
#file:
#file: xxx
## Specify multiple values like this:
#file: [xxx,yyyy,zzz]
## specify a read-only file (can be used multiple times)
#read:
#read: xxx
## Specify multiple values like this:
#read: [xxx,yyyy,zzz]
## Use VI editing mode in the terminal (default: False)
#vim: false
@@ -287,8 +293,11 @@ cog.outl("```")
## Specify the language for voice using ISO 639-1 code (default: auto)
#voice-language: en
## Specify the language to use in the chat (default: None, uses system settings)
#chat-language: xxx
## Show the version number and exit
#version:
#version: xxx
## Check for updates and return status in the exit code
#just-check-update: false
@@ -303,7 +312,7 @@ cog.outl("```")
#upgrade: false
## Apply the changes from the given file instead of running the chat (debug)
#apply:
#apply: xxx
## Always say yes to every confirmation
#yes: false
@@ -321,16 +330,16 @@ cog.outl("```")
#exit: false
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#message:
#message: xxx
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file:
#message-file: xxx
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config:
#config: xxx
## Run aider in your browser
#gui: false

View File

@@ -100,7 +100,7 @@ cog.outl("```")
# Model Settings:
## List known models which match the (partial) MODEL name
#AIDER_MODELS=
#AIDER_LIST_MODELS=
## Specify the api base url
#OPENAI_API_BASE=
@@ -285,6 +285,9 @@ cog.outl("```")
## Specify the language for voice using ISO 639-1 code (default: auto)
#AIDER_VOICE_LANGUAGE=en
## Specify the language to use in the chat (default: None, uses system settings)
#AIDER_CHAT_LANGUAGE=
## Check for updates and return status in the exit code
#AIDER_JUST_CHECK_UPDATE=false

View File

@@ -27,10 +27,11 @@ cog.out(get_md_help())
```
usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--opus] [--sonnet] [--4] [--4o] [--mini] [--4-turbo]
[--35turbo] [--deepseek] [--models] [--openai-api-base]
[--openai-api-type] [--openai-api-version]
[--openai-api-deployment-id] [--openai-organization-id]
[--model-settings-file] [--model-metadata-file]
[--35turbo] [--deepseek] [--list-models]
[--openai-api-base] [--openai-api-type]
[--openai-api-version] [--openai-api-deployment-id]
[--openai-organization-id] [--model-settings-file]
[--model-metadata-file]
[--verify-ssl | --no-verify-ssl] [--edit-format]
[--weak-model]
[--show-model-warnings | --no-show-model-warnings]
@@ -57,7 +58,7 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--lint] [--lint-cmd] [--auto-lint | --no-auto-lint]
[--test-cmd] [--auto-test | --no-auto-test] [--test]
[--file] [--read] [--vim] [--voice-language]
[--version] [--just-check-update]
[--chat-language] [--version] [--just-check-update]
[--check-update | --no-check-update]
[--install-main-branch] [--upgrade] [--apply] [--yes]
[-v] [--show-repo-map] [--show-prompts] [--exit]
@@ -130,9 +131,12 @@ Environment variable: `AIDER_DEEPSEEK`
## Model Settings:
### `--models MODEL`
### `--list-models MODEL`
List known models which match the (partial) MODEL name
Environment variable: `AIDER_MODELS`
Environment variable: `AIDER_LIST_MODELS`
Aliases:
- `--list-models MODEL`
- `--models MODEL`
### `--openai-api-base OPENAI_API_BASE`
Specify the api base url
@@ -464,6 +468,10 @@ Specify the language for voice using ISO 639-1 code (default: auto)
Default: en
Environment variable: `AIDER_VOICE_LANGUAGE`
### `--chat-language CHAT_LANGUAGE`
Specify the language to use in the chat (default: None, uses system settings)
Environment variable: `AIDER_CHAT_LANGUAGE`
### `--version`
Show the version number and exit

View File

@@ -12,6 +12,7 @@ nav_exclude: true
![robot flowchat](/assets/robot-flowchart.png)
## Updated
Aider no longer uses ctags to build a repo map.
@@ -228,7 +229,7 @@ Some possible approaches to reducing the amount of map data are:
- Distill the global map, to prioritize important symbols and discard "internal" or otherwise less globally relevant identifiers. Possibly enlist `gpt-3.5-turbo` to perform this distillation in a flexible and language agnostic way.
- Provide a mechanism for GPT to start with a distilled subset of the global map, and let it ask to see more detail about subtrees or keywords that it feels are relevant to the current coding task.
- Attempt to analyize the natural language coding task given by the user and predict which subset of the repo map is relevant. Possibly by analysis of prior coding chats within the specific repo. Work on certain files or types of features may require certain somewhat predictable context from elsewhere in the repo. Vector and keyword search against the chat history, repo map or codebase may help here.
- Attempt to analyze the natural language coding task given by the user and predict which subset of the repo map is relevant. Possibly by analysis of prior coding chats within the specific repo. Work on certain files or types of features may require certain somewhat predictable context from elsewhere in the repo. Vector and keyword search against the chat history, repo map or codebase may help here.
One key goal is to prefer solutions which are language agnostic or
which can be easily deployed against most popular code languages.

View File

@@ -37,7 +37,7 @@ If you still wish to add lots of files to the chat, you can:
- Use a wildcard when you launch aider: `aider src/*.py`
- Use a wildcard with the in-chat `/add` command: `/add src/*.py`
- Give the `/add` command a directory name and it will recurisvely add every file under that dir: `/add src`
- Give the `/add` command a directory name and it will recursively add every file under that dir: `/add src`
## Can I use aider in a large (mono) repo?

View File

@@ -29,12 +29,5 @@ pipx install aider-chat
## pipx on replit
To use aider with pipx on replit, you can run these commands in the replit shell:
```
pip install pipx
pipx run aider-chat ...normal aider args...
```
If you install aider with pipx on replit and try and run it as just `aider` it will crash with a missing `libstdc++.so.6` library.
{% include replit-pipx.md %}

View File

@@ -55,83 +55,14 @@ The model also has to successfully apply all its changes to the source file with
</tbody>
</table>
<canvas id="editChart" width="800" height="450" style="margin-top: 20px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('editChart').getContext('2d');
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
};
var allData = [];
{% for row in edit_sorted %}
allData.push({
model: '{{ row.model }}',
pass_rate_2: {{ row.pass_rate_2 }},
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
});
{% endfor %}
function updateChart() {
var selectedRows = document.querySelectorAll('tr.selected');
var showAll = selectedRows.length === 0;
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
allData.forEach(function(row, index) {
var rowElement = document.getElementById('edit-row-' + index);
if (showAll) {
rowElement.classList.remove('selected');
}
if (showAll || rowElement.classList.contains('selected')) {
leaderboardData.labels.push(row.model);
leaderboardData.datasets[0].data.push(row.pass_rate_2);
}
});
leaderboardChart.update();
}
var tableBody = document.querySelector('table tbody');
allData.forEach(function(row, index) {
var tr = tableBody.children[index];
tr.id = 'edit-row-' + index;
tr.style.cursor = 'pointer';
tr.onclick = function() {
this.classList.toggle('selected');
updateChart();
};
});
var leaderboardChart = new Chart(ctx, {
type: 'bar',
data: leaderboardData,
options: {
scales: {
yAxes: [{
scaleLabel: {
display: true,
},
ticks: {
beginAtZero: true
}
}]
}
}
});
updateChart();
});
</script>
{% include leaderboard_graph.html
chart_id="editChart"
data=edit_sorted
row_prefix="edit-row"
pass_rate_key="pass_rate_2"
%}
<style>
tr.selected {
color: #0056b3;
@@ -180,83 +111,12 @@ Therefore, results are available for fewer models.
</tbody>
</table>
<canvas id="refacChart" width="800" height="450" style="margin-top: 20px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('refacChart').getContext('2d');
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
};
var allData = [];
{% for row in refac_sorted %}
allData.push({
model: '{{ row.model }}',
pass_rate_1: {{ row.pass_rate_1 }},
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
});
{% endfor %}
function updateChart() {
var selectedRows = document.querySelectorAll('tr.selected');
var showAll = selectedRows.length === 0;
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
allData.forEach(function(row, index) {
var rowElement = document.getElementById('refac-row-' + index);
if (showAll) {
rowElement.classList.remove('selected');
}
if (showAll || rowElement.classList.contains('selected')) {
leaderboardData.labels.push(row.model);
leaderboardData.datasets[0].data.push(row.pass_rate_1);
}
});
leaderboardChart.update();
}
var tableBody = document.querySelectorAll('table tbody')[1];
allData.forEach(function(row, index) {
var tr = tableBody.children[index];
tr.id = 'refac-row-' + index;
tr.style.cursor = 'pointer';
tr.onclick = function() {
this.classList.toggle('selected');
updateChart();
};
});
var leaderboardChart = new Chart(ctx, {
type: 'bar',
data: leaderboardData,
options: {
scales: {
yAxes: [{
scaleLabel: {
display: true,
},
ticks: {
beginAtZero: true
}
}]
}
}
});
updateChart();
});
</script>
{% include leaderboard_graph.html
chart_id="refacChart"
data=refac_sorted
row_prefix="refac-row"
pass_rate_key="pass_rate_1"
%}
## LLM code editing skill by model release date
@@ -294,7 +154,7 @@ See the
[benchmark README](https://github.com/paul-gauthier/aider/blob/main/benchmark/README.md)
for information on running aider's code editing benchmarks.
Submit results by opening a PR with edits to the
[benchmark results data files](https://github.com/paul-gauthier/aider/blob/main/website/_data/).
[benchmark results data files](https://github.com/paul-gauthier/aider/blob/main/aider/website/_data/).
<p class="post-date">
@@ -321,6 +181,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.')}")
]]]-->
August 30, 2024.
September 21, 2024.
<!--[[[end]]]-->
</p>

View File

@@ -26,7 +26,7 @@ aider
aider --opus
# List models available from Anthropic
aider --models anthropic/
aider --list-models anthropic/
```
{: .tip }

View File

@@ -24,7 +24,7 @@ setx AZURE_API_BASE https://myendpt.openai.azure.com
aider --model azure/<your_deployment_name>
# List models available from Azure
aider --models azure/
aider --list-models azure/
```
Note that aider will also use environment variables

View File

@@ -54,7 +54,7 @@ aider --model bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0
To see some models available via Bedrock, run:
```
aider --models bedrock/
aider --list-models bedrock/
```
Make sure you have access to these models in your AWS account before attempting to use them with Aider.

View File

@@ -18,8 +18,8 @@ python -m pip install aider-chat
export COHERE_API_KEY=<key> # Mac/Linux
setx COHERE_API_KEY <key> # Windows, restart shell after setx
aider --model command-r-plus
aider --model command-r-plus-08-2024
# List models available from Cohere
aider --models cohere_chat/
aider --list-models cohere_chat/
```

View File

@@ -20,6 +20,6 @@ setx GEMINI_API_KEY <key> # Windows, restart shell after setx
aider --model gemini/gemini-1.5-pro-latest
# List models available from Gemini
aider --models gemini/
aider --list-models gemini/
```

View File

@@ -21,7 +21,7 @@ setx GROQ_API_KEY <key> # Windows, restart shell after setx
aider --model groq/llama3-70b-8192
# List models available from Groq
aider --models groq/
aider --list-models groq/
```

View File

@@ -29,7 +29,7 @@ aider --4-turbo
aider --35-turbo
# List models available from OpenAI
aider --models openai/
aider --list-models openai/
```
You can use `aider --model <model-name>` to use any other OpenAI model.

View File

@@ -18,7 +18,7 @@ setx OPENROUTER_API_KEY <key> # Windows, restart shell after setx
aider --model openrouter/<provider>/<model>
# List models available from OpenRouter
aider --models openrouter/
aider --list-models openrouter/
```
In particular, many aider users access Sonnet via OpenRouter:

View File

@@ -9,14 +9,14 @@ Aider uses the [litellm](https://docs.litellm.ai/docs/providers) package
to connect to hundreds of other models.
You can use `aider --model <model-name>` to use any supported model.
To explore the list of supported models you can run `aider --models <model-name>`
To explore the list of supported models you can run `aider --list-models <model-name>`
with a partial model name.
If the supplied name is not an exact match for a known model, aider will
return a list of possible matching models.
For example:
```
$ aider --models turbo
$ aider --list-models turbo
Aider v0.29.3-dev
Models which match "turbo":
@@ -63,6 +63,7 @@ cog.out(''.join(lines))
- AZURE_API_KEY
- AZURE_OPENAI_API_KEY
- BASETEN_API_KEY
- CEREBRAS_API_KEY
- CLARIFAI_API_KEY
- CLOUDFLARE_API_KEY
- CODESTRAL_API_KEY
@@ -71,18 +72,14 @@ cog.out(''.join(lines))
- DATABRICKS_API_KEY
- DEEPINFRA_API_KEY
- DEEPSEEK_API_KEY
- EMPOWER_API_KEY
- FIREWORKSAI_API_KEY
- FIREWORKS_AI_API_KEY
- FIREWORKS_API_KEY
- FRIENDLIAI_API_KEY
- GEMINI_API_KEY
- GITHUB_API_KEY
- GROQ_API_KEY
- HUGGINGFACE_API_KEY
- MARITALK_API_KEY
- MISTRAL_API_KEY
- MISTRAL_AZURE_API_KEY
- NLP_CLOUD_API_KEY
- NVIDIA_NIM_API_KEY
- OLLAMA_API_KEY
@@ -91,14 +88,11 @@ cog.out(''.join(lines))
- OR_API_KEY
- PALM_API_KEY
- PERPLEXITYAI_API_KEY
- PERPLEXITY_API_KEY
- PREDIBASE_API_KEY
- PROVIDER_API_KEY
- QDRANT_API_KEY
- REPLICATE_API_KEY
- TOGETHERAI_API_KEY
- TOGETHER_AI_API_KEY
- TOGETHER_API_KEY
- VOLCENGINE_API_KEY
- VOYAGE_API_KEY
- XINFERENCE_API_KEY

View File

@@ -26,7 +26,9 @@ for FILE in *.py ; do
done
```
User `aider --help` to see all the command line options, but these are useful for scripting:
Use `aider --help` to see all the
[command line options](/docs/config/options.html),
but these are useful for scripting:
```
--stream, --no-stream

View File

@@ -0,0 +1,51 @@
---
parent: Troubleshooting
nav_order: 28
---
# Import errors
Aider expects to be installed via `pip` or `pipx`, which will install
all of its required dependencies.
If aider reports `ImportErrors`, this probably means it has been installed
incorrectly.
## Install with pipx
If you are having problems with import errors you should consider
[installing aider using pipx](/docs/install/pipx.html).
This will ensure that aider is installed in its own python environment,
with the correct set of dependencies.
## Package managers like Homebrew, AUR, ports
Package managers often install aider with the wrong dependencies, leading
to import errors and other problems.
It is not recommended to install aider with these tools.
Instead, consider
[installing aider using pipx](/docs/install/pipx.html).
## Dependency versions matter
Aider pins its dependencies and is tested to work with those specific versions.
If you are installing aider with pip (rather than pipx),
you should be careful about upgrading or downgrading the python packages that
aider uses.
In particular, be careful with the packages with pinned versions
noted at the end of
[aider's requirements.in file](https://github.com/paul-gauthier/aider/blob/main/requirements/requirements.in).
These versions are pinned because aider is known not to work with the
latest versions of these libraries.
Also be wary of upgrading `litellm`, as it changes versions frequently
and sometimes introduces bugs or backwards incompatible changes.
## Replit
You can `pip install aider-chat` on replit.
Or you can install aider with
pipx as follows:
{% include replit-pipx.md %}

View File

@@ -13,6 +13,13 @@ Aider supports prompt caching for cost savings and faster coding.
Currently Anthropic provides caching for Sonnet and Haiku,
and DeepSeek provides caching for Coder.
Aider organizes the chat history to try and cache:
- The system prompt.
- Read only files added with `--read` or `/read-only`.
- The repository map.
- The editable files that have been added to the chat.
![Prompt caching](/assets/prompt-caching.jpg)

View File

@@ -34,6 +34,7 @@ cog.out(get_help_md())
| **/models** | Search the list of available models |
| **/quit** | Exit the application |
| **/read-only** | Add files to the chat that are for reference, not to be edited |
| **/report** | Report a problem by opening a GitHub Issue |
| **/reset** | Drop all files and clear the chat history |
| **/run** | Run a shell command and optionally add the output to the chat (alias: !) |
| **/settings** | Print out the current settings |

View File

@@ -8,6 +8,8 @@ description: Intro and tutorial videos made by aider users.
Here are some tutorial videos made by aider users:
- [Using aider to incrementally build a non-trivial app](https://youtu.be/QlUt06XLbJE) -- IndyDevDan
- [Aider and Replit on mobile with your voice](https://x.com/itsPaulAi/status/1830987090617831810) -- Paul Couvert
- [Aider is the OG AI Coding King (Mermaid Diagram AI Agent)](https://www.youtube.com/watch?v=ag-KxYS8Vuw) -- IndyDevDan
- [Installing aider in replit and making a Trello clone](https://x.com/itspaulai/status/1828834199597633724) -- Paul Couvert
- [Step-by-Step Development Environment Setup for AI-Assisted Coding](https://www.youtube.com/watch?v=DnBVgfe6ZQM) -- Coding the Future With AI

View File

@@ -8,7 +8,7 @@ has_toc: false
# Example chat transcripts
Below are some chat transcripts showing what it's like to code with aider.
In the chats, you'll see a varity of coding tasks like generating new code, editing existing code, debugging, exploring unfamiliar code, etc.
In the chats, you'll see a variety of coding tasks like generating new code, editing existing code, debugging, exploring unfamiliar code, etc.
* [**Hello World Flask App**](https://aider.chat/examples/hello-world-flask.html): Start from scratch and have aider create a simple Flask app with various endpoints, such as adding two numbers and calculating the Fibonacci sequence.

View File

@@ -549,7 +549,10 @@ def run_test_real(
chat_history_file=history_fname,
)
main_model = models.Model(model_name)
# weak_model_name = model_name
weak_model_name = None
main_model = models.Model(model_name, weak_model=weak_model_name)
edit_format = edit_format or main_model.edit_format
dump(main_model)
@@ -567,6 +570,7 @@ def run_test_real(
verbose=verbose,
# auto_lint=False, # disabled for code-in-json experiments
cache_prompts=True,
suggest_shell_commands=False,
)
coder.max_apply_update_errors = max_apply_update_errors

View File

@@ -67,3 +67,7 @@ build-backend = "setuptools.build_meta"
[tool.setuptools_scm]
write_to = "aider/__version__.py"
[tool.codespell]
skip = "*.svg,Gemfile.lock"
write-changes = true

View File

@@ -12,7 +12,7 @@ aiosignal==1.3.1
# via aiohttp
annotated-types==0.7.0
# via pydantic
anyio==4.4.0
anyio==4.6.0
# via
# httpx
# openai
@@ -25,12 +25,12 @@ backoff==2.2.1
# via -r requirements/requirements.in
beautifulsoup4==4.12.3
# via -r requirements/requirements.in
certifi==2024.7.4
certifi==2024.8.30
# via
# httpcore
# httpx
# requests
cffi==1.17.0
cffi==1.17.1
# via
# sounddevice
# soundfile
@@ -46,7 +46,7 @@ diskcache==5.6.3
# via -r requirements/requirements.in
distro==1.9.0
# via openai
filelock==3.15.4
filelock==3.16.1
# via huggingface-hub
flake8==7.1.1
# via -r requirements/requirements.in
@@ -54,7 +54,7 @@ frozenlist==1.4.1
# via
# aiohttp
# aiosignal
fsspec==2024.6.1
fsspec==2024.9.0
# via huggingface-hub
gitdb==4.0.11
# via gitpython
@@ -68,9 +68,9 @@ httpcore==1.0.5
# via httpx
httpx==0.27.2
# via openai
huggingface-hub==0.24.6
huggingface-hub==0.25.0
# via tokenizers
idna==3.8
idna==3.10
# via
# anyio
# httpx
@@ -80,7 +80,7 @@ importlib-metadata==7.2.1
# via
# -r requirements/requirements.in
# litellm
importlib-resources==6.4.4
importlib-resources==6.4.5
# via -r requirements/requirements.in
jinja2==3.1.4
# via litellm
@@ -94,7 +94,7 @@ jsonschema==4.23.0
# litellm
jsonschema-specifications==2023.12.1
# via jsonschema
litellm==1.44.7
litellm==1.47.0
# via -r requirements/requirements.in
markdown-it-py==3.0.0
# via rich
@@ -104,7 +104,7 @@ mccabe==0.7.0
# via flake8
mdurl==0.1.2
# via markdown-it-py
multidict==6.0.5
multidict==6.1.0
# via
# aiohttp
# yarl
@@ -114,13 +114,12 @@ numpy==1.26.4
# via
# -r requirements/requirements.in
# scipy
openai==1.42.0
openai==1.47.0
# via litellm
packaging==24.1
# via
# -r requirements/requirements.in
# huggingface-hub
# setuptools-scm
pathspec==0.12.1
# via
# -r requirements/requirements.in
@@ -131,17 +130,19 @@ pillow==10.4.0
# via -r requirements/requirements.in
prompt-toolkit==3.0.47
# via -r requirements/requirements.in
psutil==6.0.0
# via -r requirements/requirements.in
ptyprocess==0.7.0
# via pexpect
pycodestyle==2.12.1
# via flake8
pycparser==2.22
# via cffi
pydantic==2.8.2
pydantic==2.9.2
# via
# litellm
# openai
pydantic-core==2.20.1
pydantic-core==2.23.4
# via pydantic
pyflakes==3.2.0
# via flake8
@@ -161,14 +162,14 @@ referencing==0.35.1
# via
# jsonschema
# jsonschema-specifications
regex==2024.7.24
regex==2024.9.11
# via tiktoken
requests==2.32.3
# via
# huggingface-hub
# litellm
# tiktoken
rich==13.8.0
rich==13.8.1
# via -r requirements/requirements.in
rpds-py==0.20.0
# via
@@ -176,8 +177,6 @@ rpds-py==0.20.0
# referencing
scipy==1.13.1
# via -r requirements/requirements.in
setuptools-scm==8.1.0
# via -r requirements/requirements.in
smmap==5.0.1
# via gitdb
sniffio==1.3.1
@@ -213,14 +212,11 @@ typing-extensions==4.12.2
# openai
# pydantic
# pydantic-core
urllib3==2.2.2
urllib3==2.2.3
# via requests
wcwidth==0.2.13
# via prompt-toolkit
yarl==1.9.4
yarl==1.11.1
# via aiohttp
zipp==3.20.1
zipp==3.20.2
# via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
# setuptools

View File

@@ -15,7 +15,7 @@ blinker==1.8.2
# via streamlit
cachetools==5.5.0
# via streamlit
certifi==2024.7.4
certifi==2024.8.30
# via
# -c requirements/../requirements.txt
# requests
@@ -35,7 +35,7 @@ gitpython==3.1.43
# via
# -c requirements/../requirements.txt
# streamlit
idna==3.8
idna==3.10
# via
# -c requirements/../requirements.txt
# requests
@@ -64,7 +64,7 @@ mdurl==0.1.2
# via
# -c requirements/../requirements.txt
# markdown-it-py
narwhals==1.5.5
narwhals==1.8.2
# via altair
numpy==1.26.4
# via
@@ -78,13 +78,13 @@ packaging==24.1
# -c requirements/../requirements.txt
# altair
# streamlit
pandas==2.2.2
pandas==2.2.3
# via streamlit
pillow==10.4.0
# via
# -c requirements/../requirements.txt
# streamlit
protobuf==5.27.4
protobuf==5.28.2
# via streamlit
pyarrow==17.0.0
# via streamlit
@@ -96,7 +96,7 @@ pygments==2.18.0
# rich
python-dateutil==2.9.0.post0
# via pandas
pytz==2024.1
pytz==2024.2
# via pandas
referencing==0.35.1
# via
@@ -107,7 +107,7 @@ requests==2.32.3
# via
# -c requirements/../requirements.txt
# streamlit
rich==13.8.0
rich==13.8.1
# via
# -c requirements/../requirements.txt
# streamlit
@@ -137,7 +137,7 @@ typing-extensions==4.12.2
# streamlit
tzdata==2024.1
# via pandas
urllib3==2.2.2
urllib3==2.2.3
# via
# -c requirements/../requirements.txt
# requests

View File

@@ -12,3 +12,4 @@ imgcat
pre-commit
cogapp
semver
codespell

View File

@@ -8,9 +8,9 @@ alabaster==0.7.16
# via sphinx
babel==2.16.0
# via sphinx
build==1.2.1
build==1.2.2
# via pip-tools
certifi==2024.7.4
certifi==2024.8.30
# via
# -c requirements/../requirements.txt
# requests
@@ -25,6 +25,8 @@ click==8.1.7
# -c requirements/../requirements.txt
# pip-tools
# typer
codespell==2.3.0
# via -r requirements/requirements-dev.in
cogapp==3.4.1
# via -r requirements/requirements-dev.in
contourpy==1.3.0
@@ -41,15 +43,15 @@ docutils==0.20.1
# via
# sphinx
# sphinx-rtd-theme
filelock==3.15.4
filelock==3.16.1
# via
# -c requirements/../requirements.txt
# virtualenv
fonttools==4.53.1
# via matplotlib
identify==2.6.0
identify==2.6.1
# via pre-commit
idna==3.8
idna==3.10
# via
# -c requirements/../requirements.txt
# requests
@@ -63,7 +65,7 @@ jinja2==3.1.4
# via
# -c requirements/../requirements.txt
# sphinx
kiwisolver==1.4.5
kiwisolver==1.4.7
# via matplotlib
lox==0.12.0
# via -r requirements/requirements-dev.in
@@ -98,7 +100,7 @@ packaging==24.1
# matplotlib
# pytest
# sphinx
pandas==2.2.2
pandas==2.2.3
# via -r requirements/requirements-dev.in
pathos==0.3.2
# via lox
@@ -108,7 +110,7 @@ pillow==10.4.0
# matplotlib
pip-tools==7.4.1
# via -r requirements/requirements-dev.in
platformdirs==4.2.2
platformdirs==4.3.6
# via virtualenv
pluggy==1.5.0
# via pytest
@@ -129,13 +131,13 @@ pyproject-hooks==1.1.0
# via
# build
# pip-tools
pytest==8.3.2
pytest==8.3.3
# via -r requirements/requirements-dev.in
python-dateutil==2.9.0.post0
# via
# matplotlib
# pandas
pytz==2024.1
pytz==2024.2
# via pandas
pyyaml==6.0.2
# via
@@ -145,7 +147,7 @@ requests==2.32.3
# via
# -c requirements/../requirements.txt
# sphinx
rich==13.8.0
rich==13.8.1
# via
# -c requirements/../requirements.txt
# typer
@@ -185,11 +187,11 @@ typing-extensions==4.12.2
# typer
tzdata==2024.1
# via pandas
urllib3==2.2.2
urllib3==2.2.3
# via
# -c requirements/../requirements.txt
# requests
virtualenv==20.26.3
virtualenv==20.26.5
# via pre-commit
wheel==0.44.0
# via pip-tools

View File

@@ -21,7 +21,7 @@ annotated-types==0.7.0
# via
# -c requirements/../requirements.txt
# pydantic
anyio==4.4.0
anyio==4.6.0
# via
# -c requirements/../requirements.txt
# httpx
@@ -29,7 +29,7 @@ attrs==24.2.0
# via
# -c requirements/../requirements.txt
# aiohttp
certifi==2024.7.4
certifi==2024.8.30
# via
# -c requirements/../requirements.txt
# httpcore
@@ -49,7 +49,7 @@ deprecated==1.2.14
# via llama-index-core
dirtyjson==1.0.8
# via llama-index-core
filelock==3.15.4
filelock==3.16.1
# via
# -c requirements/../requirements.txt
# huggingface-hub
@@ -60,13 +60,13 @@ frozenlist==1.4.1
# -c requirements/../requirements.txt
# aiohttp
# aiosignal
fsspec==2024.6.1
fsspec==2024.9.0
# via
# -c requirements/../requirements.txt
# huggingface-hub
# llama-index-core
# torch
greenlet==3.0.3
greenlet==3.1.1
# via sqlalchemy
h11==0.14.0
# via
@@ -80,14 +80,14 @@ httpx==0.27.2
# via
# -c requirements/../requirements.txt
# llama-index-core
huggingface-hub[inference]==0.24.6
huggingface-hub[inference]==0.25.0
# via
# -c requirements/../requirements.txt
# llama-index-embeddings-huggingface
# sentence-transformers
# tokenizers
# transformers
idna==3.8
idna==3.10
# via
# -c requirements/../requirements.txt
# anyio
@@ -102,7 +102,7 @@ joblib==1.4.2
# via
# nltk
# scikit-learn
llama-index-core==0.11.2
llama-index-core==0.11.11
# via
# -r requirements/requirements-help.in
# llama-index-embeddings-huggingface
@@ -118,7 +118,7 @@ minijinja==2.2.0
# via huggingface-hub
mpmath==1.3.0
# via sympy
multidict==6.0.5
multidict==6.1.0
# via
# -c requirements/../requirements.txt
# aiohttp
@@ -140,7 +140,6 @@ numpy==1.26.4
# llama-index-core
# scikit-learn
# scipy
# sentence-transformers
# transformers
packaging==24.1
# via
@@ -153,11 +152,11 @@ pillow==10.4.0
# -c requirements/../requirements.txt
# llama-index-core
# sentence-transformers
pydantic==2.8.2
pydantic==2.9.2
# via
# -c requirements/../requirements.txt
# llama-index-core
pydantic-core==2.20.1
pydantic-core==2.23.4
# via
# -c requirements/../requirements.txt
# pydantic
@@ -167,7 +166,7 @@ pyyaml==6.0.2
# huggingface-hub
# llama-index-core
# transformers
regex==2024.7.24
regex==2024.9.11
# via
# -c requirements/../requirements.txt
# nltk
@@ -180,27 +179,27 @@ requests==2.32.3
# llama-index-core
# tiktoken
# transformers
safetensors==0.4.4
safetensors==0.4.5
# via transformers
scikit-learn==1.5.1
scikit-learn==1.5.2
# via sentence-transformers
scipy==1.13.1
# via
# -c requirements/../requirements.txt
# scikit-learn
# sentence-transformers
sentence-transformers==3.0.1
sentence-transformers==3.1.1
# via llama-index-embeddings-huggingface
sniffio==1.3.1
# via
# -c requirements/../requirements.txt
# anyio
# httpx
sqlalchemy[asyncio]==2.0.32
sqlalchemy[asyncio]==2.0.35
# via
# llama-index-core
# sqlalchemy
sympy==1.13.2
sympy==1.13.3
# via torch
tenacity==8.5.0
# via llama-index-core
@@ -240,7 +239,7 @@ typing-inspect==0.9.0
# via
# dataclasses-json
# llama-index-core
urllib3==2.2.2
urllib3==2.2.3
# via
# -c requirements/../requirements.txt
# requests
@@ -248,7 +247,7 @@ wrapt==1.16.0
# via
# deprecated
# llama-index-core
yarl==1.9.4
yarl==1.11.1
# via
# -c requirements/../requirements.txt
# aiohttp

View File

@@ -6,9 +6,9 @@
#
greenlet==3.0.3
# via playwright
playwright==1.46.0
playwright==1.47.0
# via -r requirements/requirements-playwright.in
pyee==11.1.0
pyee==12.0.0
# via playwright
typing-extensions==4.12.2
# via

View File

@@ -25,8 +25,9 @@ importlib_resources
pyperclip
pexpect
json5
psutil
# The proper depdendency is networkx[default], but this brings
# The proper dependency is networkx[default], but this brings
# in matplotlib and a bunch of other deps
# https://github.com/networkx/networkx/blob/d7132daa8588f653eacac7a5bae1ee85a183fa43/pyproject.toml#L57
# We really only need networkx itself and scipy for the repomap.

133
scripts/issues.py Executable file
View File

@@ -0,0 +1,133 @@
#!/usr/bin/env python3
import os
import re
from collections import defaultdict
from datetime import datetime
import requests
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# GitHub API configuration
GITHUB_API_URL = "https://api.github.com"
REPO_OWNER = "paul-gauthier"
REPO_NAME = "aider"
TOKEN = os.getenv("GITHUB_TOKEN")
headers = {"Authorization": f"token {TOKEN}", "Accept": "application/vnd.github.v3+json"}
def get_issues(state="open"):
issues = []
page = 1
while True:
response = requests.get(
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues",
headers=headers,
params={"state": state, "page": page, "per_page": 100},
)
response.raise_for_status()
page_issues = response.json()
if not page_issues:
break
issues.extend(page_issues)
page += 1
return issues
def group_issues_by_subject(issues):
grouped_issues = defaultdict(list)
pattern = r"Uncaught .+ in .+ line \d+"
for issue in issues:
if re.search(pattern, issue["title"]):
subject = issue["title"]
grouped_issues[subject].append(issue)
return grouped_issues
def find_oldest_issue(subject, all_issues):
oldest_issue = None
oldest_date = datetime.now()
for issue in all_issues:
if issue["title"] == subject:
created_at = datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ")
if created_at < oldest_date:
oldest_date = created_at
oldest_issue = issue
return oldest_issue
def comment_and_close_duplicate(issue, oldest_issue):
comment_url = (
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
)
close_url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}"
comment_body = (
f"This looks like a duplicate of #{oldest_issue['number']}, so I'm going to close it so"
" discussion can happen there. Please let me know if you think it's actually a distinct"
" issue."
)
# Post comment
response = requests.post(comment_url, headers=headers, json={"body": comment_body})
response.raise_for_status()
# Close issue
response = requests.patch(close_url, headers=headers, json={"state": "closed"})
response.raise_for_status()
print(f" - Commented and closed issue #{issue['number']}")
def main():
if not TOKEN:
print("Error: Missing GITHUB_TOKEN environment variable. Please check your .env file.")
return
all_issues = get_issues("all")
open_issues = [issue for issue in all_issues if issue["state"] == "open"]
grouped_open_issues = group_issues_by_subject(open_issues)
for subject, issues in grouped_open_issues.items():
oldest_issue = find_oldest_issue(subject, all_issues)
if not oldest_issue:
continue
related_issues = set(issue["number"] for issue in issues)
related_issues.add(oldest_issue["number"])
if len(related_issues) <= 1:
continue
print(f"\nIssue: {subject}")
print(f"Open issues: {len(issues)}")
sorted_issues = sorted(issues, key=lambda x: x["number"], reverse=True)
for issue in sorted_issues:
print(f" - #{issue['number']}: {issue['comments']} comments {issue['html_url']}")
print(
f"Oldest issue: #{oldest_issue['number']}: {oldest_issue['comments']} comments"
f" {oldest_issue['html_url']} ({oldest_issue['state']})"
)
# Confirmation prompt
confirm = input("Do you want to comment and close duplicate issues? (y/n): ")
if confirm.lower() != "y":
print("Skipping this group of issues.")
continue
# Comment and close duplicate issues
for issue in issues:
if issue["number"] != oldest_issue["number"]:
comment_and_close_duplicate(issue, oldest_issue)
print(f"Oldest issue #{oldest_issue['number']} left open")
if __name__ == "__main__":
main()

View File

@@ -2,6 +2,7 @@
import argparse
import datetime
import os
import re
import subprocess
import sys
@@ -150,6 +151,13 @@ def main():
if not dry_run:
subprocess.run(cmd, check=True)
# Remove aider/__version__.py if it exists
version_file = "aider/__version__.py"
if os.path.exists(version_file):
print(f"Removing {version_file}")
if not dry_run:
os.remove(version_file)
if __name__ == "__main__":
main()

View File

@@ -353,7 +353,7 @@ class TestCoder(unittest.TestCase):
_, file1 = tempfile.mkstemp()
with open(file1, "wb") as f:
f.write(b"this contains ``` backticks")
f.write(b"this contains\n```\nbackticks")
files = [file1]

View File

@@ -213,9 +213,9 @@ aider/coder.py
aider/coder.py
<<<<<<< SEARCH
self.console.print("[red]Skipped commmit.")
self.console.print("[red]Skipped commit.")
=======
self.io.tool_error("Skipped commmit.")
self.io.tool_error("Skipped commit.")
>>>>>>> REPLACE"""
# Should not raise a ValueError

View File

@@ -46,12 +46,8 @@ class TestInputOutput(unittest.TestCase):
autocompleter = AutoCompleter(root, rel_fnames, addable_rel_fnames, commands, "utf-8")
self.assertEqual(autocompleter.words, set(rel_fnames))
@patch("aider.io.PromptSession")
def test_get_input_is_a_directory_error(self, MockPromptSession):
# Mock the PromptSession to simulate user input
mock_session = MockPromptSession.return_value
mock_session.prompt.return_value = "test input"
@patch("builtins.input", return_value="test input")
def test_get_input_is_a_directory_error(self, mock_input):
io = InputOutput(pretty=False) # Windows tests throw UnicodeDecodeError
root = "/"
rel_fnames = ["existing_file.txt"]
@@ -62,105 +58,106 @@ class TestInputOutput(unittest.TestCase):
with patch("aider.io.open", side_effect=IsADirectoryError):
result = io.get_input(root, rel_fnames, addable_rel_fnames, commands)
self.assertEqual(result, "test input")
mock_input.assert_called_once()
@patch("aider.io.prompt")
def test_confirm_ask_explicit_yes_required(self, mock_prompt):
@patch("builtins.input")
def test_confirm_ask_explicit_yes_required(self, mock_input):
io = InputOutput(pretty=False)
# Test case 1: explicit_yes_required=True, self.yes=True
io.yes = True
result = io.confirm_ask("Are you sure?", explicit_yes_required=True)
self.assertFalse(result)
mock_prompt.assert_not_called()
mock_input.assert_not_called()
# Test case 2: explicit_yes_required=True, self.yes=False
io.yes = False
result = io.confirm_ask("Are you sure?", explicit_yes_required=True)
self.assertFalse(result)
mock_prompt.assert_not_called()
mock_input.assert_not_called()
# Test case 3: explicit_yes_required=True, user input required
io.yes = None
mock_prompt.return_value = "y"
mock_input.return_value = "y"
result = io.confirm_ask("Are you sure?", explicit_yes_required=True)
self.assertTrue(result)
mock_prompt.assert_called_once()
mock_input.assert_called_once()
# Reset mock_prompt
mock_prompt.reset_mock()
# Reset mock_input
mock_input.reset_mock()
# Test case 4: explicit_yes_required=False, self.yes=True
io.yes = True
result = io.confirm_ask("Are you sure?", explicit_yes_required=False)
self.assertTrue(result)
mock_prompt.assert_not_called()
mock_input.assert_not_called()
@patch("aider.io.prompt")
def test_confirm_ask_with_group(self, mock_prompt):
@patch("builtins.input")
def test_confirm_ask_with_group(self, mock_input):
io = InputOutput(pretty=False)
group = ConfirmGroup()
# Test case 1: No group preference, user selects 'All'
mock_prompt.return_value = "a"
mock_input.return_value = "a"
result = io.confirm_ask("Are you sure?", group=group)
self.assertTrue(result)
self.assertEqual(group.preference, "all")
mock_prompt.assert_called_once()
mock_prompt.reset_mock()
mock_input.assert_called_once()
mock_input.reset_mock()
# Test case 2: Group preference is 'All', should not prompt
result = io.confirm_ask("Are you sure?", group=group)
self.assertTrue(result)
mock_prompt.assert_not_called()
mock_input.assert_not_called()
# Test case 3: No group preference, user selects 'Skip all'
group.preference = None
mock_prompt.return_value = "s"
mock_input.return_value = "s"
result = io.confirm_ask("Are you sure?", group=group)
self.assertFalse(result)
self.assertEqual(group.preference, "skip")
mock_prompt.assert_called_once()
mock_prompt.reset_mock()
mock_input.assert_called_once()
mock_input.reset_mock()
# Test case 4: Group preference is 'Skip all', should not prompt
result = io.confirm_ask("Are you sure?", group=group)
self.assertFalse(result)
mock_prompt.assert_not_called()
mock_input.assert_not_called()
# Test case 5: explicit_yes_required=True, should not offer 'All' option
group.preference = None
mock_prompt.return_value = "y"
mock_input.return_value = "y"
result = io.confirm_ask("Are you sure?", group=group, explicit_yes_required=True)
self.assertTrue(result)
self.assertIsNone(group.preference)
mock_prompt.assert_called_once()
self.assertNotIn("(A)ll", mock_prompt.call_args[0][0])
mock_prompt.reset_mock()
mock_input.assert_called_once()
self.assertNotIn("(A)ll", mock_input.call_args[0][0])
mock_input.reset_mock()
@patch("aider.io.prompt")
def test_confirm_ask_yes_no(self, mock_prompt):
@patch("builtins.input")
def test_confirm_ask_yes_no(self, mock_input):
io = InputOutput(pretty=False)
# Test case 1: User selects 'Yes'
mock_prompt.return_value = "y"
mock_input.return_value = "y"
result = io.confirm_ask("Are you sure?")
self.assertTrue(result)
mock_prompt.assert_called_once()
mock_prompt.reset_mock()
mock_input.assert_called_once()
mock_input.reset_mock()
# Test case 2: User selects 'No'
mock_prompt.return_value = "n"
mock_input.return_value = "n"
result = io.confirm_ask("Are you sure?")
self.assertFalse(result)
mock_prompt.assert_called_once()
mock_prompt.reset_mock()
mock_input.assert_called_once()
mock_input.reset_mock()
# Test case 3: Empty input (default to Yes)
mock_prompt.return_value = ""
mock_input.return_value = ""
result = io.confirm_ask("Are you sure?")
self.assertTrue(result)
mock_prompt.assert_called_once()
mock_prompt.reset_mock()
mock_input.assert_called_once()
mock_input.reset_mock()
def test_get_command_completions(self):
root = ""

View File

@@ -0,0 +1,52 @@
import unittest
from unittest.mock import MagicMock, patch
from aider.dump import dump # noqa
from aider.linter import Linter
class TestLinter(unittest.TestCase):
def setUp(self):
self.linter = Linter(encoding="utf-8", root="/test/root")
def test_init(self):
self.assertEqual(self.linter.encoding, "utf-8")
self.assertEqual(self.linter.root, "/test/root")
self.assertIn("python", self.linter.languages)
def test_set_linter(self):
self.linter.set_linter("javascript", "eslint")
self.assertEqual(self.linter.languages["javascript"], "eslint")
def test_get_rel_fname(self):
import os
self.assertEqual(self.linter.get_rel_fname("/test/root/file.py"), "file.py")
expected_path = os.path.normpath("../../other/path/file.py")
actual_path = os.path.normpath(self.linter.get_rel_fname("/other/path/file.py"))
self.assertEqual(actual_path, expected_path)
@patch("subprocess.Popen")
def test_run_cmd(self, mock_popen):
mock_process = MagicMock()
mock_process.returncode = 0
mock_process.communicate.return_value = ("", None)
mock_popen.return_value = mock_process
result = self.linter.run_cmd("test_cmd", "test_file.py", "code")
self.assertIsNone(result)
@patch("subprocess.Popen")
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_popen.return_value = mock_process
result = self.linter.run_cmd("test_cmd", "test_file.py", "code")
self.assertIsNotNone(result)
self.assertIn("Error message", result.text)
if __name__ == "__main__":
unittest.main()

View File

@@ -29,6 +29,8 @@ class TestMain(TestCase):
# Fake home directory prevents tests from using the real ~/.aider.conf.yml file:
self.homedir_obj = IgnorantTemporaryDirectory()
os.environ["HOME"] = self.homedir_obj.name
self.input_patcher = patch("builtins.input", return_value=None)
self.mock_input = self.input_patcher.start()
def tearDown(self):
os.chdir(self.original_cwd)
@@ -36,24 +38,25 @@ class TestMain(TestCase):
self.homedir_obj.cleanup()
os.environ.clear()
os.environ.update(self.original_env)
self.input_patcher.stop()
def test_main_with_empty_dir_no_files_on_command(self):
main(["--no-git"], input=DummyInput(), output=DummyOutput())
main(["--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
def test_main_with_emptqy_dir_new_file(self):
main(["foo.txt", "--yes", "--no-git"], input=DummyInput(), output=DummyOutput())
main(["foo.txt", "--yes", "--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
self.assertTrue(os.path.exists("foo.txt"))
@patch("aider.repo.GitRepo.get_commit_message", return_value="mock commit message")
def test_main_with_empty_git_dir_new_file(self, _):
make_repo()
main(["--yes", "foo.txt"], input=DummyInput(), output=DummyOutput())
main(["--yes", "foo.txt", "--exit"], input=DummyInput(), output=DummyOutput())
self.assertTrue(os.path.exists("foo.txt"))
@patch("aider.repo.GitRepo.get_commit_message", return_value="mock commit message")
def test_main_with_empty_git_dir_new_files(self, _):
make_repo()
main(["--yes", "foo.txt", "bar.txt"], input=DummyInput(), output=DummyOutput())
main(["--yes", "foo.txt", "bar.txt", "--exit"], input=DummyInput(), output=DummyOutput())
self.assertTrue(os.path.exists("foo.txt"))
self.assertTrue(os.path.exists("bar.txt"))
@@ -70,7 +73,7 @@ class TestMain(TestCase):
subdir.mkdir()
make_repo(str(subdir))
main(
["--yes", str(subdir / "foo.txt"), str(subdir / "bar.txt")],
["--yes", str(subdir / "foo.txt"), str(subdir / "bar.txt"), "--exit"],
input=DummyInput(),
output=DummyOutput(),
)
@@ -104,7 +107,7 @@ class TestMain(TestCase):
# This will throw a git error on windows if get_tracked_files doesn't
# properly convert git/posix/paths to git\posix\paths.
# Because aider will try and `git add` a file that's already in the repo.
main(["--yes", str(fname)], input=DummyInput(), output=DummyOutput())
main(["--yes", str(fname), "--exit"], input=DummyInput(), output=DummyOutput())
def test_setup_git(self):
io = InputOutput(pretty=False, yes=True)
@@ -269,23 +272,25 @@ class TestMain(TestCase):
self.assertEqual(args[1], None)
def test_dark_mode_sets_code_theme(self):
# Mock Coder.create to capture the configuration
with patch("aider.coders.Coder.create") as MockCoder:
main(["--dark-mode", "--no-git"], input=DummyInput(), output=DummyOutput())
# Ensure Coder.create was called
MockCoder.assert_called_once()
# Mock InputOutput to capture the configuration
with patch("aider.main.InputOutput") as MockInputOutput:
MockInputOutput.return_value.get_input.return_value = None
main(["--dark-mode", "--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
# Ensure InputOutput was called
MockInputOutput.assert_called_once()
# Check if the code_theme setting is for dark mode
_, kwargs = MockCoder.call_args
_, kwargs = MockInputOutput.call_args
self.assertEqual(kwargs["code_theme"], "monokai")
def test_light_mode_sets_code_theme(self):
# Mock Coder.create to capture the configuration
with patch("aider.coders.Coder.create") as MockCoder:
main(["--light-mode", "--no-git"], input=DummyInput(), output=DummyOutput())
# Ensure Coder.create was called
MockCoder.assert_called_once()
# Mock InputOutput to capture the configuration
with patch("aider.main.InputOutput") as MockInputOutput:
MockInputOutput.return_value.get_input.return_value = None
main(["--light-mode", "--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
# Ensure InputOutput was called
MockInputOutput.assert_called_once()
# Check if the code_theme setting is for light mode
_, kwargs = MockCoder.call_args
_, kwargs = MockInputOutput.call_args
self.assertEqual(kwargs["code_theme"], "default")
def create_env_file(self, file_name, content):
@@ -295,25 +300,29 @@ class TestMain(TestCase):
def test_env_file_flag_sets_automatic_variable(self):
env_file_path = self.create_env_file(".env.test", "AIDER_DARK_MODE=True")
with patch("aider.coders.Coder.create") as MockCoder:
with patch("aider.main.InputOutput") as MockInputOutput:
MockInputOutput.return_value.get_input.return_value = None
MockInputOutput.return_value.get_input.confirm_ask = True
main(
["--env-file", str(env_file_path), "--no-git"],
["--env-file", str(env_file_path), "--no-git", "--exit"],
input=DummyInput(),
output=DummyOutput(),
)
MockCoder.assert_called_once()
MockInputOutput.assert_called_once()
# Check if the color settings are for dark mode
_, kwargs = MockCoder.call_args
_, kwargs = MockInputOutput.call_args
self.assertEqual(kwargs["code_theme"], "monokai")
def test_default_env_file_sets_automatic_variable(self):
self.create_env_file(".env", "AIDER_DARK_MODE=True")
with patch("aider.coders.Coder.create") as MockCoder:
main(["--no-git"], input=DummyInput(), output=DummyOutput())
# Ensure Coder.create was called
MockCoder.assert_called_once()
with patch("aider.main.InputOutput") as MockInputOutput:
MockInputOutput.return_value.get_input.return_value = None
MockInputOutput.return_value.get_input.confirm_ask = True
main(["--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
# Ensure InputOutput was called
MockInputOutput.assert_called_once()
# Check if the color settings are for dark mode
_, kwargs = MockCoder.call_args
_, kwargs = MockInputOutput.call_args
self.assertEqual(kwargs["code_theme"], "monokai")
def test_false_vals_in_env_file(self):
@@ -368,7 +377,7 @@ class TestMain(TestCase):
def test_verbose_mode_lists_env_vars(self):
self.create_env_file(".env", "AIDER_DARK_MODE=on")
with patch("sys.stdout", new_callable=StringIO) as mock_stdout:
main(["--no-git", "--verbose"], input=DummyInput(), output=DummyOutput())
main(["--no-git", "--verbose", "--exit"], input=DummyInput(), output=DummyOutput())
output = mock_stdout.getvalue()
relevant_output = "\n".join(
line
@@ -620,6 +629,17 @@ class TestMain(TestCase):
)
self.assertTrue(coder.suggest_shell_commands)
def test_chat_language_spanish(self):
with GitTemporaryDirectory():
coder = main(
["--chat-language", "Spanish", "--exit", "--yes"],
input=DummyInput(),
output=DummyOutput(),
return_coder=True,
)
system_info = coder.get_platform_info()
self.assertIn("Spanish", system_info)
@patch("git.Repo.init")
def test_main_exit_with_git_command_not_found(self, mock_git_init):
mock_git_init.side_effect = git.exc.GitCommandNotFound("git", "Command 'git' not found")