Compare commits

...

598 Commits

Author SHA1 Message Date
Paul Gauthier
a73e77a819 set version to 0.65.1.dev 2024-11-26 08:57:36 -08:00
Paul Gauthier
b5f1659382 version bump to 0.65.0 2024-11-26 08:55:57 -08:00
Paul Gauthier
beb6722f57 copy 2024-11-26 08:04:17 -08:00
Paul Gauthier
a052b89152 copy 2024-11-26 07:42:16 -08:00
Paul Gauthier
95b391350f bumped deps 2024-11-26 07:41:31 -08:00
Paul Gauthier
5773eac03f copy 2024-11-26 07:37:56 -08:00
Paul Gauthier (aider)
da4ace2875 style: Fix string quote consistency in update-history.py 2024-11-26 07:31:36 -08:00
Paul Gauthier (aider)
e507c5b502 feat: add aider contribution percentage to history updates 2024-11-26 07:31:32 -08:00
Paul Gauthier (aider)
722c2c2668 style: fix linting errors in test_repomap.py 2024-11-26 07:28:02 -08:00
Paul Gauthier (aider)
8e7bfef9f1 test: add Dart language support to repo map tests 2024-11-26 07:27:57 -08:00
Paul Gauthier
1811f0d0d5 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-26 07:27:32 -08:00
paul-gauthier
6b9d534fe2 Merge pull request #2236 from malkoG/support-dart
Add dart support
2024-11-26 07:26:43 -08:00
Paul Gauthier (aider)
dc4562a845 feat: add docs update step after aider in update-history script 2024-11-26 07:10:32 -08:00
Paul Gauthier
c15af63bc9 copy 2024-11-26 07:10:03 -08:00
Paul Gauthier
5b68c2c7d9 fix test 2024-11-26 07:09:49 -08:00
Paul Gauthier (aider)
b70e0bd1f6 test: update invalid edit format test to check return code instead of SystemExit 2024-11-26 07:07:11 -08:00
Paul Gauthier (aider)
743f0f5540 test: add test for invalid edit format handling 2024-11-26 07:06:28 -08:00
Paul Gauthier (aider)
e647a5b733 feat: add tests for UnknownEditFormat exception handling 2024-11-26 07:04:43 -08:00
Paul Gauthier (aider)
df1d259e42 style: Fix linting issues in test_coder.py 2024-11-26 07:04:21 -08:00
Paul Gauthier (aider)
e3efab7fbf test: add UnknownEditFormat exception tests 2024-11-26 07:04:15 -08:00
Paul Gauthier (aider)
cd79f7f4b0 fix: import UnknownEditFormat exception from base_coder module 2024-11-26 07:03:26 -08:00
Paul Gauthier (aider)
5d175745bf fix: handle None values in valid_formats list generation 2024-11-26 07:02:34 -08:00
Paul Gauthier (aider)
e648bac74b fix: remove circular import of UnknownEditFormat in base_coder.py 2024-11-26 07:01:55 -08:00
Paul Gauthier (aider)
e5c0ebd0a0 style: fix import order in base_coder.py 2024-11-26 07:01:21 -08:00
Paul Gauthier (aider)
608a43402c refactor: move UnknownEditFormat exception to base_coder.py 2024-11-26 07:01:14 -08:00
Paul Gauthier (aider)
75bc2dd564 feat: add custom UnknownEditFormat exception with documentation link 2024-11-26 07:00:16 -08:00
Paul Gauthier
bbd81c3cf7 copy 2024-11-26 06:56:36 -08:00
Paul Gauthier
301eb7c74d copy 2024-11-26 06:50:18 -08:00
Paul Gauthier
a756039f27 copy 2024-11-26 06:49:28 -08:00
Paul Gauthier (aider)
b4d1b71ee7 test: add test for skipping duplicate basename file mentions 2024-11-26 06:46:53 -08:00
Paul Gauthier (aider)
8d85a4754d style: fix line wrapping in base_coder.py 2024-11-26 06:46:08 -08:00
Paul Gauthier (aider)
a1b48049a9 feat: skip files with duplicate basenames in file mentions 2024-11-26 06:46:01 -08:00
Paul Gauthier
6789844c1f copy 2024-11-26 06:42:42 -08:00
Paul Gauthier
c602a839ca better update history script 2024-11-26 06:42:36 -08:00
Paul Gauthier
01c7793e90 revert changes to get_ident_filename_matches() 2024-11-26 06:41:08 -08:00
Paul Gauthier (aider)
47b013b034 docs: update changelog with recent improvements and features 2024-11-26 06:38:59 -08:00
Paul Gauthier
dc2047804a docs: update changelog with URL detection and model alias features 2024-11-26 06:38:57 -08:00
Paul Gauthier (aider)
885e5cbd7c style: fix whitespace in base_coder.py 2024-11-26 06:33:37 -08:00
Paul Gauthier (aider)
635a5196e8 fix: exclude files with same name as existing chat or read-only files 2024-11-26 06:33:29 -08:00
Paul Gauthier
cbd339190b refactor: simplify file name matching logic in get_all_relative_files 2024-11-26 06:33:28 -08:00
Paul Gauthier (aider)
266093189d style: fix linting issues in get_ident_filename_matches 2024-11-26 06:26:26 -08:00
Paul Gauthier (aider)
62b02d4370 fix: remove incorrect file name filtering in get_ident_filename_matches 2024-11-26 06:25:15 -08:00
Paul Gauthier (aider)
8546a1dc86 docs: add main branch changes to release history 2024-11-26 06:25:00 -08:00
Paul Gauthier
ae98bf237f docs: remove unreleased changes from history file 2024-11-26 06:24:59 -08:00
Paul Gauthier (aider)
0398deb005 test: add tests for filename matching with existing and read-only files 2024-11-26 06:24:11 -08:00
Paul Gauthier (aider)
3a1492977b fix: skip suggesting files with same name as existing chat files 2024-11-26 06:22:57 -08:00
Paul Gauthier (aider)
ef40a456e8 docs: add main branch section with latest changes to history 2024-11-26 06:20:04 -08:00
Paul Gauthier
583b78c0c1 docs: update release history to remove unreleased changes 2024-11-26 06:20:03 -08:00
Paul Gauthier (aider)
c0988de581 docs: update release history with v0.64.1 and v0.64.2 changes 2024-11-26 06:17:06 -08:00
Paul Gauthier
34a190e29b docs: remove v0.64.2 release notes 2024-11-26 06:17:04 -08:00
Paul Gauthier (aider)
0940598708 docs: add v0.64.2 release notes to history 2024-11-26 06:12:13 -08:00
Paul Gauthier (aider)
7e6cbb3efa style: format update-history.py with black 2024-11-26 06:10:07 -08:00
Paul Gauthier (aider)
7dc4e00c75 feat: dynamically determine base version for history updates 2024-11-26 06:10:03 -08:00
Paul Gauthier (aider)
8a598eacaf style: format update-history.py with black 2024-11-26 06:09:44 -08:00
Paul Gauthier (aider)
8592fad9cd feat: add script to automate history updates from git diffs 2024-11-26 06:09:41 -08:00
Paul Gauthier
fa72a89d35 feat: add script to update history file 2024-11-26 06:09:38 -08:00
Paul Gauthier
5e99c51d93 copy 2024-11-26 06:01:46 -08:00
Paul Gauthier (aider)
905976e765 feat: add verbose and trace flags for Jekyll debugging 2024-11-26 05:59:52 -08:00
Paul Gauthier
3ebd47d3db copy 2024-11-25 21:12:01 -08:00
Paul Gauthier
bf4c7c475a copy 2024-11-25 21:08:27 -08:00
Paul Gauthier (aider)
bf38371971 test: add test cases for model name aliases 2024-11-25 21:06:29 -08:00
Paul Gauthier
18460f4f91 copy 2024-11-25 21:05:59 -08:00
Paul Gauthier (aider)
f94e3e6aba feat: add cog script to auto-generate model aliases docs 2024-11-25 21:03:35 -08:00
Paul Gauthier
1647da2942 docs: add frontmatter to model aliases documentation 2024-11-25 21:03:34 -08:00
Paul Gauthier (aider)
86e2cdb1fb docs: add documentation for model aliases configuration 2024-11-25 21:01:11 -08:00
Paul Gauthier
764702a377 docs: add model aliases configuration documentation 2024-11-25 21:01:10 -08:00
Paul Gauthier (aider)
837a97ffdf style: fix string quote consistency in alias split 2024-11-25 20:56:10 -08:00
Paul Gauthier (aider)
217e9b96d8 feat: add command-line model alias support via --alias flag 2024-11-25 20:56:04 -08:00
Paul Gauthier (aider)
524274fcf4 refactor: consolidate model aliases into central dictionary 2024-11-25 20:54:24 -08:00
Paul Gauthier
6d5f576b92 refactor: simplify model aliases to only include Claude-3 variants 2024-11-25 20:54:23 -08:00
Paul Gauthier (aider)
445f9fa7df feat: add model name aliases with canonical mapping 2024-11-25 20:51:37 -08:00
Paul Gauthier (aider)
2ff3a23606 fix: add num_ctx parameter to run_test_real function 2024-11-25 19:21:08 -08:00
Paul Gauthier (aider)
c5ce57ea7f style: fix linting issues in benchmark.py 2024-11-25 19:20:49 -08:00
Paul Gauthier (aider)
351b8e50f0 feat: add --num-ctx flag to override model context window size 2024-11-25 19:20:43 -08:00
Paul Gauthier
68be6c5742 copy 2024-11-25 19:11:18 -08:00
Paul Gauthier
7a34a2dfa9 ask 2.5% of users to opt-in to analytics 2024-11-25 19:09:59 -08:00
Paul Gauthier
49ce9e1209 copy 2024-11-25 18:42:28 -08:00
Paul Gauthier (aider)
c84e192324 style: remove extra blank line in test_coder.py 2024-11-25 18:42:09 -08:00
Paul Gauthier (aider)
d696673f07 test: remove shell command testing from URL detection test 2024-11-25 18:42:03 -08:00
Paul Gauthier (aider)
2957d463c9 test: add assertion for suggest_shell_commands flag 2024-11-25 18:41:21 -08:00
Paul Gauthier (aider)
af48e50898 test: add tests for URL detection functionality in Coder class 2024-11-25 18:39:49 -08:00
Paul Gauthier (aider)
f4b964a4b8 test: add tests for --[no-]detect-urls CLI option 2024-11-25 18:39:10 -08:00
Paul Gauthier
a79ce7a151 fix: remove duplicate detect_urls parameter and add to coder initialization 2024-11-25 18:38:34 -08:00
Paul Gauthier (aider)
21bb83c55a fix: remove duplicate detect_urls parameter in Coder class 2024-11-25 18:36:25 -08:00
Paul Gauthier (aider)
7122ceb16c feat: add --detect-urls flag to control URL detection behavior 2024-11-25 18:34:05 -08:00
Paul Gauthier
f9bcfe341c ignore .gitattributes 2024-11-25 15:09:46 -08:00
Paul Gauthier
13c5bfdd88 copy 2024-11-25 09:05:52 -08:00
Paul Gauthier
bf79c2cb99 copy 2024-11-25 08:28:42 -08:00
Paul Gauthier
325cdfcf57 refactor: Update Ollama model detection and context window documentation 2024-11-24 16:14:34 -08:00
Paul Gauthier
7d14d4ade9 copy 2024-11-24 15:23:47 -08:00
Paul Gauthier
1b7d12194e copy 2024-11-24 15:23:42 -08:00
Paul Gauthier (aider)
91f238aded style: Organize imports and remove unused import 2024-11-24 15:20:47 -08:00
Paul Gauthier (aider)
78ff489995 feat: Add ModelSettings import to main.py 2024-11-24 15:20:43 -08:00
Paul Gauthier (aider)
ff791439e2 fix: Import fields and ModelSettings to resolve flake8 errors 2024-11-24 15:20:35 -08:00
Paul Gauthier
3f8b2d6b99 refactor: Improve model info output with detailed settings display 2024-11-24 15:20:24 -08:00
Paul Gauthier
4dcbce58ed copy 2024-11-24 14:55:02 -08:00
Paul Gauthier
0427deb897 copy 2024-11-24 14:54:19 -08:00
Paul Gauthier
f3eb3409e3 copy 2024-11-24 14:54:12 -08:00
Paul Gauthier
86619052ca copy 2024-11-24 14:52:01 -08:00
Paul Gauthier
0c59d3234e copy 2024-11-24 12:03:21 -08:00
Paul Gauthier
939d7ea3fb copy 2024-11-24 12:02:48 -08:00
Paul Gauthier
dc8761763d copy 2024-11-24 07:56:12 -08:00
Paul Gauthier
4894914db1 copy 2024-11-24 07:50:19 -08:00
Paul Gauthier
aee94a0584 copy 2024-11-24 07:14:09 -08:00
Paul Gauthier (aider)
c550422168 feat: Add x-axis label "Provider: quantization" to chart 2024-11-24 07:13:14 -08:00
Paul Gauthier (aider)
cebd9cabb3 feat: Add real-time filtering to chart based on search input 2024-11-24 07:12:39 -08:00
Paul Gauthier (aider)
3f16652d56 feat: Escape colons in model names with quotes in YAML file 2024-11-24 07:06:41 -08:00
Paul Gauthier
2ebf48ca71 feat: Update quant.yml with refined model descriptions and new test results 2024-11-24 07:06:39 -08:00
Paul Gauthier
c2f184f5bb copy 2024-11-24 06:21:58 -08:00
Paul Gauthier
e56651e5c0 copy 2024-11-23 20:27:43 -08:00
Paul Gauthier
1d09e96127 copy 2024-11-23 20:19:11 -08:00
Paul Gauthier
73de0ea8be copy 2024-11-23 20:18:19 -08:00
Paul Gauthier
757eac0579 copy 2024-11-23 18:39:20 -08:00
Paul Gauthier
bb78e2f57f default Ollama num_ctx to 8k 2024-11-23 18:14:30 -08:00
Paul Gauthier
92579243c5 copy 2024-11-23 18:13:58 -08:00
Paul Gauthier (aider)
8d0ba40d67 feat: Sort chart data by pass rate in descending order 2024-11-23 17:48:34 -08:00
Paul Gauthier
ff8c1aace9 copy 2024-11-23 15:32:09 -08:00
Paul Gauthier
cf74dc9b48 copy 2024-11-23 15:30:28 -08:00
Paul Gauthier (aider)
e63df83091 refactor: Consolidate subprocess.call mock in test_pipe_editor 2024-11-23 14:23:26 -08:00
Paul Gauthier
14522dbbcd copy 2024-11-23 14:20:58 -08:00
Paul Gauthier
91daea9e01 simplify if 2024-11-23 14:15:36 -08:00
Paul Gauthier (aider)
12b789fc4e fix: Handle Mixpanel connection errors by disabling tracking 2024-11-23 14:14:11 -08:00
Paul Gauthier
baa13351a6 refactor: Improve model registration and settings handling 2024-11-23 12:57:24 -08:00
Paul Gauthier
8f83204f0f Merge branch 'main' of github.com:Aider-AI/aider 2024-11-23 12:37:26 -08:00
paul-gauthier
80f5b60e1d Merge pull request #2440 from ivanfioravanti/main
MLX 4bit and 8bit diff added
2024-11-23 12:36:18 -08:00
Paul Gauthier
54525f6696 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-23 12:35:36 -08:00
Ivan Fioravanti
3dc50216b5 Merge branch 'Aider-AI:main' into main 2024-11-23 19:52:23 +01:00
ivanfioravanti
324430a696 quant.yml mlx-community/Qwen2.5-Coder-32B-Instruct-8bit added 2024-11-23 19:51:48 +01:00
paul-gauthier
65d7957610 Update modes.md 2024-11-23 09:36:43 -08:00
paul-gauthier
6ac4993cf2 Update modes.md 2024-11-23 09:36:26 -08:00
ivanfioravanti
100744a952 Article updated to reflect change in mlx test 2024-11-23 17:34:01 +01:00
ivanfioravanti
3a331e55dc mlx 4bit diff 2024-11-23 17:32:08 +01:00
Paul Gauthier
a57f81ba5f copy 2024-11-23 07:02:58 -08:00
Paul Gauthier
ca0b55fbbf copy 2024-11-23 06:53:54 -08:00
Paul Gauthier
38a3cf98dd gemini 2024-11-22 19:45:52 -08:00
Paul Gauthier
1234ad92e5 gemini-exp-1114 2024-11-22 19:43:26 -08:00
Paul Gauthier
488edc24ce gemini-exp-1121 2024-11-22 19:42:11 -08:00
Paul Gauthier
307c23631a copy 2024-11-22 17:20:38 -08:00
Paul Gauthier
83d2241883 copy 2024-11-22 16:40:47 -08:00
Paul Gauthier
f9126416e8 copy 2024-11-22 16:38:02 -08:00
Paul Gauthier
4e9ae16cb3 copy 2024-11-22 15:42:10 -08:00
Paul Gauthier
ef8bfdffa7 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-22 15:41:27 -08:00
paul-gauthier
bfb090331f Merge pull request #2432 from ivanfioravanti/main 2024-11-22 15:40:42 -08:00
Paul Gauthier
5506d0f25b fixed xai docs 2024-11-22 14:21:00 -08:00
Ivan Fioravanti
6ebd2d0883 mlx Qwen2.5-Coder-32B-Instruct-4bit added to quant blog
mlx Qwen2.5-Coder-32B-Instruct-4bit added to quant blog
2024-11-22 22:24:13 +01:00
Paul Gauthier
a16dcaba4e copy 2024-11-22 11:38:14 -08:00
Paul Gauthier
f06452c6c5 copy 2024-11-22 10:56:33 -08:00
Paul Gauthier (aider)
6a0a97cb41 feat: Add host.docker.internal gateway to enable Ollama server access from container 2024-11-22 10:07:47 -08:00
Paul Gauthier
711102b438 copy 2024-11-22 09:39:23 -08:00
Paul Gauthier (aider)
6d53eb0aaa style: Increase canvas height for taller graph aspect ratio 2024-11-22 07:40:46 -08:00
Paul Gauthier
0ccf04a2c5 copy 2024-11-22 07:32:25 -08:00
Paul Gauthier
070ce35b44 copy 2024-11-22 07:32:00 -08:00
Paul Gauthier
a8296e5de5 copy 2024-11-22 07:29:50 -08:00
Paul Gauthier (aider)
d17f25e975 feat: Add interactive table with quantization model performance data 2024-11-22 07:17:23 -08:00
Paul Gauthier
23095ada85 docs: Update Qwen 2.5 Coder 32B Instruct model comparison with Hyperbolic labs API 2024-11-22 07:16:01 -08:00
Paul Gauthier
f9ef161991 copy 2024-11-22 07:07:41 -08:00
Paul Gauthier
28004bae2f copy 2024-11-22 07:06:43 -08:00
Paul Gauthier
17aef7be7d copy 2024-11-22 06:09:32 -08:00
Paul Gauthier
ebba8f5110 fix ollama models included in quant blog 2024-11-22 06:01:01 -08:00
Paul Gauthier
dbd7f51f5c fix ollama models included in quant blog 2024-11-22 05:56:03 -08:00
Paul Gauthier
fbadfcfa7c refactor: Remove unnecessary input logging and history tracking in pipe_editor command 2024-11-21 18:37:51 -08:00
Paul Gauthier
2c12234604 refactor: Update input handling to set and use placeholder text 2024-11-21 18:34:24 -08:00
Paul Gauthier (aider)
13cb6a315c style: Apply linter formatting to io.py 2024-11-21 18:32:03 -08:00
Paul Gauthier (aider)
48e7376002 feat: Add placeholder functionality to input prompts 2024-11-21 18:31:57 -08:00
Paul Gauthier
60d82eddee added Qwen2 72B Instruct to over time 2024-11-21 16:49:24 -08:00
Paul Gauthier (aider)
30ee89c7e9 style: Fix linting issues in over_time.py 2024-11-21 16:45:11 -08:00
Paul Gauthier (aider)
25bcea6aec feat: Add print of model release dates and names in sorted order 2024-11-21 16:45:07 -08:00
Paul Gauthier
488c88da91 update over time graphs 2024-11-21 14:19:31 -08:00
Paul Gauthier (aider)
8fdcd92260 feat: Update plot save paths to website assets directory 2024-11-21 14:19:05 -08:00
Paul Gauthier
781a40df52 fix: Update Gemini Pro legend label to Gemini 1.5 Pro 2024-11-21 14:19:03 -08:00
Paul Gauthier
2412c81d92 copy 2024-11-21 14:09:34 -08:00
Paul Gauthier (aider)
a7fc0f9d2e feat: Add color and legend support for Gemini Pro models 2024-11-21 14:02:27 -08:00
Paul Gauthier
9eab021a50 refactor: Modify offer_url method and release notes handling in main 2024-11-21 14:02:01 -08:00
Paul Gauthier (aider)
c189a52e5e style: Organize imports and apply linter formatting 2024-11-21 14:00:24 -08:00
Paul Gauthier (aider)
6d6d763dd3 refactor: Restructure benchmark plotting script for improved maintainability 2024-11-21 14:00:20 -08:00
Paul Gauthier
3cfbaa0ed6 copy 2024-11-21 13:07:18 -08:00
Paul Gauthier
e1b4571fdf set version to 0.64.2.dev 2024-11-21 12:58:23 -08:00
Paul Gauthier
08027ea9c4 version bump to 0.64.1 2024-11-21 12:56:49 -08:00
Paul Gauthier
d0528a00c1 copy 2024-11-21 12:55:10 -08:00
Paul Gauthier
7ae6a2ba9a disable o1 streaming on openrouter 2024-11-21 12:54:23 -08:00
Paul Gauthier
ad0e5c4770 copy 2024-11-21 12:53:21 -08:00
Paul Gauthier
51b181d5fb set version to 0.64.1.dev 2024-11-21 12:37:05 -08:00
Paul Gauthier
2785b0a857 version bump to 0.64.0 2024-11-21 12:35:35 -08:00
Paul Gauthier
45a113ff9e copy 2024-11-21 12:34:12 -08:00
Paul Gauthier
cee59c2ca3 chore: Ignore .DS_Store files in exclude patterns 2024-11-21 12:32:22 -08:00
Paul Gauthier
5cb9b242e2 debug 2024-11-21 12:25:17 -08:00
Paul Gauthier
1ed48de928 wip 2024-11-21 12:22:55 -08:00
Paul Gauthier
c4e4bc71ed debug 2024-11-21 12:12:18 -08:00
Paul Gauthier
ed0763706b debug 2024-11-21 12:11:28 -08:00
Paul Gauthier
1c79d517fc refactor: Update subprocess.run with text, shell, and encoding parameters 2024-11-21 12:09:28 -08:00
Paul Gauthier
1a7a2f3088 copy 2024-11-21 11:48:29 -08:00
Paul Gauthier
4199789786 copy 2024-11-21 11:47:47 -08:00
Paul Gauthier
c9b0941d1f copy 2024-11-21 11:41:12 -08:00
Paul Gauthier (aider)
3d544136d2 style: Increase font sizes for chart labels and title 2024-11-21 11:40:02 -08:00
Paul Gauthier
8448eff1eb copy 2024-11-21 11:38:41 -08:00
Paul Gauthier (aider)
a3dde4599a refactor: Improve chart label handling by splitting model names on newline 2024-11-21 11:14:01 -08:00
Paul Gauthier
3d7440c673 refactor: Modify chart labels to include additional text 2024-11-21 11:13:48 -08:00
Paul Gauthier
8f41006eba refactor: Simplify model label processing in quant-chart.js 2024-11-21 11:11:22 -08:00
Paul Gauthier (aider)
7d1379fe9f fix: Handle line breaks in x-axis labels for chart rendering 2024-11-21 11:08:23 -08:00
Paul Gauthier (aider)
ced4f9f0d9 feat: Add chart title, y-axis label, and remove legend 2024-11-21 11:06:52 -08:00
Paul Gauthier (aider)
7fba332f58 feat: Add quantization performance chart using Chart.js and quant.yml data 2024-11-21 10:57:03 -08:00
Paul Gauthier
8eda09533d init 2024-11-21 10:55:20 -08:00
Paul Gauthier
6c42ee4edf copy 2024-11-21 10:53:28 -08:00
Paul Gauthier
3053595bfe added qwen models 2024-11-21 10:52:10 -08:00
Paul Gauthier (aider)
6cf78d1a3f feat: Implement case-insensitive search in leaderboard filtering 2024-11-21 10:41:59 -08:00
Paul Gauthier (aider)
6c0ee9d917 feat: Enhance leaderboard search to support multi-word queries 2024-11-21 10:41:35 -08:00
Paul Gauthier
50051dbfd5 copy 2024-11-21 10:34:01 -08:00
Paul Gauthier (aider)
30a8c5e12e feat: Update leaderboard charts to filter bars based on search input 2024-11-21 10:32:32 -08:00
Paul Gauthier
4498549783 refactor: Add .js file extension to blame script file filter 2024-11-21 10:31:59 -08:00
Paul Gauthier (aider)
2ce3fedbfc fix: Correct table selector for refactoring leaderboard search 2024-11-21 10:31:43 -08:00
Paul Gauthier (aider)
8e10be665c fix: Remove raw tags from leaderboard script includes 2024-11-21 10:30:41 -08:00
Paul Gauthier (aider)
80636cb8aa feat: Add raw filter to JavaScript includes in leaderboard index.md 2024-11-21 10:29:18 -08:00
Paul Gauthier (aider)
1b893da07d refactor: Move JavaScript to separate files and use Jekyll includes 2024-11-21 10:28:09 -08:00
Paul Gauthier
2f8aa3471b feat: Add leaderboard JavaScript component 2024-11-21 10:24:56 -08:00
Paul Gauthier (aider)
92a6957f0b refactor: Move refactoring search box above its table 2024-11-21 10:22:57 -08:00
Paul Gauthier (aider)
d7248b11e5 feat: Add live search functionality to leaderboard tables 2024-11-21 10:21:39 -08:00
Paul Gauthier
6f4ed00105 copy 2024-11-21 10:15:28 -08:00
Paul Gauthier (aider)
347b299bbc refactor: Enforce strict parsing of multiline input start with { or {tag} 2024-11-21 10:10:45 -08:00
Paul Gauthier (aider)
614d297f22 fix: Use strip("\r\n") for precise line ending removal 2024-11-21 10:10:14 -08:00
Paul Gauthier (aider)
59d0fe00c3 refactor: Improve multi-line input handling with strict closing tag validation 2024-11-21 10:09:36 -08:00
Paul Gauthier
d6ebdff28f copy 2024-11-21 10:07:53 -08:00
Paul Gauthier
0ec16d0eab copy 2024-11-21 10:07:01 -08:00
Paul Gauthier
3906894fde Merge branch 'main' of github.com:Aider-AI/aider 2024-11-21 10:02:06 -08:00
Paul Gauthier
a43772b21d refactor: Remove unused file_editor function from editor module 2024-11-21 10:01:08 -08:00
Paul Gauthier (aider)
cd81c2619b refactor: Remove unused file_editor import and mock in test_editor.py 2024-11-21 09:58:53 -08:00
Paul Gauthier (aider)
5abadc31a3 style: Remove extra blank lines in test_editor.py 2024-11-21 09:58:39 -08:00
Paul Gauthier (aider)
87654b698b test: Update tests for editor functionality changes 2024-11-21 09:58:35 -08:00
Paul Gauthier (aider)
2a1d2ef294 refactor: Update editor discovery to support custom editor and remove AIDER_EDITOR 2024-11-21 09:55:15 -08:00
Paul Gauthier (aider)
2a387707ef feat: Add --editor switch to specify editor for /editor command 2024-11-21 09:52:14 -08:00
paul-gauthier
ce68062290 Merge pull request #2417 from caetanominuzzo/fix-typo-in-base_coder
fix: Correct typo in base_coder by removing duplicate 'in'
2024-11-21 09:36:34 -08:00
caetanominuzzo
1b9073b085 fix: Correct typo in base_coder by removing duplicate 'in'
This corrects a grammatical error in the system prompt within `base_coder.py`. The `language` variable was previously set as:

    language = "in the same language they are using"

Which resulted in the prompt:

    "Always reply to the user IN IN the same language they are using."
2024-11-21 14:19:39 -03:00
paul-gauthier
e94961a14f Merge pull request #2414 from thehunmonkgroup/editor-doc 2024-11-21 07:37:22 -08:00
Chad Phillips
d4e77b3be4 add documentation for /editor configuration 2024-11-21 09:46:25 -05:00
Paul Gauthier
b96b36d5ea refactor: Remove unnecessary assert_newlines check for updated lines 2024-11-21 06:42:04 -08:00
Paul Gauthier
72d559a92c fix: Remove duplicate assert_newlines call on original lines 2024-11-21 06:39:39 -08:00
Paul Gauthier (aider)
9a7bdcb6db style: Fix linter warnings in test_commands.py 2024-11-21 06:36:11 -08:00
Paul Gauthier (aider)
2e4cf48e7e test: Update cmd_run test to check cur_messages instead of return value 2024-11-21 06:36:05 -08:00
Paul Gauthier
b78f8abeb4 copy 2024-11-21 06:34:08 -08:00
Paul Gauthier (aider)
7aa4e44317 fix: Correct line/lines pluralization in command output messages 2024-11-21 06:30:52 -08:00
Paul Gauthier
2619b92131 fix: Add period to output message for consistency 2024-11-21 06:30:50 -08:00
Paul Gauthier (aider)
28be59582f refactor: Simplify cmd_run to use confirm_ask and add output to cur_messages 2024-11-21 06:28:41 -08:00
Paul Gauthier
f96cc03587 feat: Add opt-in analytics and improve output logging method 2024-11-21 06:25:10 -08:00
Paul Gauthier (aider)
cbd35b0e87 feat: Implement line count for command output in chat 2024-11-21 06:23:34 -08:00
Paul Gauthier
443acbe4b5 fix: Correct command output confirmation logic in base coder 2024-11-21 06:23:32 -08:00
Paul Gauthier
1f0d26e8c7 better over time plot 2024-11-20 20:19:44 -08:00
Paul Gauthier
8302e9d0dd improved over time plot 2024-11-20 20:16:35 -08:00
Paul Gauthier (aider)
c797af020a refactor: Update fontsize to use LABEL_FONT_SIZE constant in over_time.py 2024-11-20 20:13:46 -08:00
Paul Gauthier (aider)
1c85afa320 feat: Add LABEL_FONT_SIZE constant for dot label font size 2024-11-20 20:13:33 -08:00
Paul Gauthier
eb5317f8e5 fix: Adjust annotation vertical offset for brown color in over_time plot 2024-11-20 20:13:30 -08:00
Paul Gauthier (aider)
8b860615b8 style: Increase font size for scatter plot dot labels 2024-11-20 20:10:40 -08:00
Paul Gauthier (aider)
c15ac341e2 refactor: Remove Opus and Llama model variants from legend labels 2024-11-20 20:07:52 -08:00
Paul Gauthier (aider)
c2c7ee1047 feat: Change Opus label to "Opus" in legend 2024-11-20 20:06:48 -08:00
Paul Gauthier (aider)
72c46ccec6 feat: Add labels for Claude 3 Opus, Sonnet, and O1 Preview models 2024-11-20 20:06:04 -08:00
Paul Gauthier (aider)
dd3bfaee01 style: Format code with consistent indentation and line breaks 2024-11-20 20:05:24 -08:00
Paul Gauthier (aider)
03206ad90e feat: Add line labels directly on first points instead of using legend 2024-11-20 20:05:18 -08:00
Paul Gauthier (aider)
2e00307190 feat: Add color and legend label for o1-preview models 2024-11-20 20:03:49 -08:00
Paul Gauthier (aider)
b3e29ab20e style: Apply linter formatting to benchmark code 2024-11-20 20:02:52 -08:00
Paul Gauthier (aider)
5504ac535b feat: Add simplified model names for legend labels 2024-11-20 20:02:48 -08:00
Paul Gauthier (aider)
4b3dd7f4ea style: Apply linter formatting to over_time.py 2024-11-20 19:59:43 -08:00
Paul Gauthier (aider)
8edf9540d5 feat: Add legend to plot and remove point labels 2024-11-20 19:59:38 -08:00
Paul Gauthier
1c62ecd1b5 style: Adjust x-axis label rotation angle for better readability 2024-11-20 19:59:36 -08:00
Paul Gauthier
7cf3d9f3ce style: Increase annotation font size in benchmark plot 2024-11-20 19:45:42 -08:00
Paul Gauthier
9b5a703307 updated models-over-time 2024-11-20 19:40:59 -08:00
Paul Gauthier (aider)
370993cbed style: Rotate point labels by 45 degrees in benchmark plot 2024-11-20 18:47:30 -08:00
Paul Gauthier
ddc538cdfa refactor: Adjust plot figure size and y-axis limits for better visualization 2024-11-20 18:47:28 -08:00
Paul Gauthier (aider)
062dc43c87 style: Make graph aspect ratio square 2024-11-20 18:43:18 -08:00
Paul Gauthier (aider)
7d9b986c04 feat: Add cyan color and line for Mistral models in visualization 2024-11-20 18:38:06 -08:00
Paul Gauthier
bd2b9a12ed style: Change Qwen model color from purple to darkblue 2024-11-20 18:38:04 -08:00
Paul Gauthier (aider)
2b55707738 feat: Add purple color and line for Qwen models in visualization 2024-11-20 18:35:25 -08:00
Paul Gauthier (aider)
093540507e feat: Add pink color and line for Haiku models in benchmark visualization 2024-11-20 18:33:54 -08:00
Paul Gauthier (aider)
8f1dcfda07 feat: Add brown color for DeepSeek models in benchmark visualization 2024-11-20 18:31:46 -08:00
Paul Gauthier
16b319174b refactor: Simplify model color detection logic for Sonnet models 2024-11-20 18:31:44 -08:00
Paul Gauthier (aider)
35115f5707 feat: Add orange color for Claude 3 Sonnet models in benchmark visualization 2024-11-20 18:30:09 -08:00
Paul Gauthier
e9e51db9c7 improve precision, tests 2024-11-20 18:20:18 -08:00
Paul Gauthier (aider)
ec39f018e2 test: Update test_is_uuid_in_percentage with full-length UUIDs 2024-11-20 17:58:52 -08:00
Paul Gauthier
59f4a3bcc7 test: Update UUID percentage threshold test case 2024-11-20 17:58:50 -08:00
Paul Gauthier (aider)
1a8949eea3 fix: Correct UUID percentage calculation in analytics method 2024-11-20 17:58:18 -08:00
Paul Gauthier
fa85bdceed fix: Correct sampling logic by changing <= to < in UUID comparison 2024-11-20 17:58:16 -08:00
Paul Gauthier (aider)
6b703244ec fix: Correct percentage calculation in is_uuid_in_percentage method 2024-11-20 17:56:07 -08:00
Paul Gauthier (aider)
1a1cb0d3f1 fix: Correct percentage calculation in UUID sampling method 2024-11-20 17:55:40 -08:00
Paul Gauthier (aider)
95c9863d0a style: Fix linter formatting in analytics module 2024-11-20 17:54:22 -08:00
Paul Gauthier (aider)
82187f6a71 refactor: Extract UUID percentage testing logic into a separate method with tests 2024-11-20 17:54:16 -08:00
Paul Gauthier (aider)
75f52a1324 refactor: Improve user sampling logic with configurable percentage 2024-11-20 17:52:52 -08:00
Paul Gauthier
6e076a40a9 refactor: Modify analytics sampling logic to use 1% of users 2024-11-20 17:52:50 -08:00
Paul Gauthier
ded60036cb copy 2024-11-20 17:43:51 -08:00
Paul Gauthier
539a6cde63 feat: Enhance analytics opt-in logic with user sampling and explicit control 2024-11-20 16:22:01 -08:00
Paul Gauthier
3a28e74d89 copy 2024-11-20 16:03:51 -08:00
Paul Gauthier
c93f3faed9 cleanup openrouter/qwen/qwen-2.5-coder-32b-instruct in resources 2024-11-20 15:33:00 -08:00
Paul Gauthier
1aaa3d9279 gpt-4o-2024-11-20 2024-11-20 15:31:47 -08:00
Paul Gauthier
a06a9ed7d8 show the /editor message 2024-11-20 15:31:32 -08:00
Paul Gauthier
18a88596a6 Added gpt-4o-2024-11-20 2024-11-20 11:33:16 -08:00
Paul Gauthier (aider)
2ac077603b feat: Update add_to_input_history to immediately update prompt session history 2024-11-20 08:16:55 -08:00
Paul Gauthier (aider)
3bb8b163b8 feat: Update HISTORY.md with new release notes entries 2024-11-20 08:09:53 -08:00
Paul Gauthier (aider)
aac45097ca fix: Save empty dict to cache file on download failure 2024-11-20 07:57:56 -08:00
Paul Gauthier (aider)
788956e86d refactor: Update cache TTL in ModelInfoManager even on download failure 2024-11-20 07:56:28 -08:00
Paul Gauthier
e917424f5d copy 2024-11-20 07:13:15 -08:00
Paul Gauthier
1f6a5d04d9 chore: Update edit leaderboard with new Mistral model performance data 2024-11-20 07:09:38 -08:00
Paul Gauthier (aider)
dba844c7f9 style: Format code with linter 2024-11-19 17:45:44 -08:00
Paul Gauthier (aider)
09c11ef8ad test: Add --yes flag to prevent EOFError in test cases 2024-11-19 17:45:40 -08:00
Paul Gauthier
ff21669bb5 copy 2024-11-19 17:42:34 -08:00
Paul Gauthier
a059ca2537 refactor: Improve release notes display logic and user interaction flow 2024-11-19 17:41:57 -08:00
Paul Gauthier
f4531b9434 docs: Add release notes URL and section in HISTORY.md 2024-11-19 17:38:17 -08:00
Paul Gauthier (aider)
05b350ac4b style: Fix linter formatting in main.py 2024-11-19 17:37:19 -08:00
Paul Gauthier (aider)
cfba315a85 fix: Replace utils.open_url with webbrowser.open to resolve AttributeError 2024-11-19 17:37:14 -08:00
Paul Gauthier
12188b6684 refactor: Simplify release notes display logic in main function 2024-11-19 17:37:13 -08:00
Paul Gauthier (aider)
725b2fc16f style: Apply linter formatting to main.py 2024-11-19 17:33:22 -08:00
Paul Gauthier (aider)
90a28e31e8 feat: Add --show-release-notes option to control release notes display 2024-11-19 17:33:16 -08:00
Paul Gauthier
c057b00e08 refactor: Move release notes offer after announcements in main function 2024-11-19 17:33:13 -08:00
Paul Gauthier (aider)
b0c0104ba3 feat: Implement release notes URL offer on first run 2024-11-19 17:30:30 -08:00
Paul Gauthier
855b184e91 feat: Add TODO for displaying release notes on first run 2024-11-19 17:30:29 -08:00
Paul Gauthier (aider)
bc88242dc0 refactor: Move version check to main and pass to check_and_load_imports 2024-11-19 17:27:02 -08:00
Paul Gauthier (aider)
6357cd623f style: Apply linter formatting to main.py 2024-11-19 17:25:02 -08:00
Paul Gauthier (aider)
d3e7d20e30 refactor: Extract version checking logic into separate function 2024-11-19 17:24:57 -08:00
Paul Gauthier
7b568c2df3 copy 2024-11-19 17:22:08 -08:00
Paul Gauthier
2bff0522e8 refactor: Restructure file mention check and interrupt handling in base coder 2024-11-19 16:37:02 -08:00
Paul Gauthier (aider)
77e180171c style: Break long comment into two lines for flake8 compliance 2024-11-19 14:48:22 -08:00
Paul Gauthier (aider)
1e8fc97ba4 style: Apply linter formatting to test_models.py 2024-11-19 14:48:11 -08:00
Paul Gauthier (aider)
a799851832 fix: Resolve temporary file permission issues in test_models.py 2024-11-19 14:48:06 -08:00
Paul Gauthier
2c81105bfc copy 2024-11-19 14:33:21 -08:00
Paul Gauthier
bf99ac56a0 copy 2024-11-19 12:45:56 -08:00
Paul Gauthier
8bfb47948a copy 2024-11-19 12:45:00 -08:00
Paul Gauthier (aider)
b8c41198a3 docs: Add documentation links to v0.63.3 release notes 2024-11-19 12:43:17 -08:00
Paul Gauthier (aider)
fe138ac05b feat: Update HISTORY.md with v0.63.3 release details 2024-11-19 12:42:44 -08:00
Paul Gauthier
bed62fdcb5 chore: Update HISTORY.md for Aider v0.63.2 release 2024-11-19 12:42:41 -08:00
Paul Gauthier
f068df0297 copy 2024-11-19 12:40:09 -08:00
Paul Gauthier
6a05e34d20 copy 2024-11-19 12:37:16 -08:00
Paul Gauthier (aider)
8b69b9c6a4 docs: Add documentation for new multiline tag input method 2024-11-19 12:36:55 -08:00
Paul Gauthier (aider)
10192296fe style: Format code with linter 2024-11-19 12:34:47 -08:00
Paul Gauthier (aider)
7b98db2f7d fix: Escape f-string brace in multiline input tag handling 2024-11-19 12:34:43 -08:00
Paul Gauthier (aider)
81696c2e7a feat: Add support for optional multiline input tags with matching closing tag 2024-11-19 12:34:25 -08:00
Paul Gauthier
16a4f823bd refactor: Move pipe_editor import and return user input in cmd_editor method 2024-11-19 12:30:41 -08:00
Paul Gauthier
39bbfc56a4 copy 2024-11-19 12:30:30 -08:00
Paul Gauthier (aider)
308c49b2d8 fix: Modify discover_editor to dynamically check platform system 2024-11-19 12:26:37 -08:00
Paul Gauthier (aider)
53e46a9251 refactor: Remove unused platform import from test_editor.py 2024-11-19 12:26:06 -08:00
Paul Gauthier (aider)
6075b3dc33 style: Reorder imports and add whitespace in test_editor.py 2024-11-19 12:25:50 -08:00
Paul Gauthier (aider)
860a828973 test: Add comprehensive tests for editor module functionality 2024-11-19 12:25:46 -08:00
Paul Gauthier
033eaa36c6 test: Add test_editor.py for basic editor functionality 2024-11-19 12:25:44 -08:00
Paul Gauthier
b3566f5449 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-19 12:23:12 -08:00
paul-gauthier
f1306d3301 Merge pull request #2234 from thehunmonkgroup/main
add /editor command
2024-11-19 12:22:37 -08:00
Paul Gauthier
cc18441435 refactor: Update model settings name from "aider/extra" to "aider/extra_params" 2024-11-19 12:15:11 -08:00
Paul Gauthier (aider)
7e787d93e6 docs: Add documentation for aider/extra_params pseudo-model settings 2024-11-19 12:10:28 -08:00
Paul Gauthier
b08f444e74 docs: Remove default and override settings section from documentation 2024-11-19 12:10:26 -08:00
Paul Gauthier (aider)
09c1acdbe2 fix: Update model settings override name to match test configuration 2024-11-19 12:07:42 -08:00
Paul Gauthier (aider)
7a4a956eff fix: Remove unexpected skip_name argument in _copy_fields() method 2024-11-19 12:07:08 -08:00
Paul Gauthier (aider)
aabbf5a72f refactor: Remove unused import and add ANTHROPIC_BETA_HEADER import 2024-11-19 12:06:29 -08:00
Paul Gauthier (aider)
5ed44bb174 style: Format test_models.py with consistent whitespace and trailing commas 2024-11-19 12:06:19 -08:00
Paul Gauthier (aider)
92cf2cbd47 test: Implement TODOs in test_aider_extra_model_settings 2024-11-19 12:06:15 -08:00
Paul Gauthier
34aff6c786 test: Update model settings test to check extra parameters 2024-11-19 12:06:13 -08:00
Paul Gauthier (aider)
11f10e586a fix: Remove unused functools.wraps import 2024-11-19 12:03:14 -08:00
Paul Gauthier (aider)
a31feae2bd style: Apply linter formatting to models.py 2024-11-19 12:02:49 -08:00
Paul Gauthier (aider)
3517d58f01 feat: Implement deep merge for extra model settings with nested dict support 2024-11-19 12:02:44 -08:00
Paul Gauthier
9d13fadd41 refactor: Simplify model settings configuration and remove tracking decorator 2024-11-19 12:02:42 -08:00
Paul Gauthier (aider)
c1febce528 fix: Remove unused imports and add missing register_models import 2024-11-19 11:50:12 -08:00
Paul Gauthier (aider)
e0aadbd961 style: Format code with linter and improve readability 2024-11-19 11:50:01 -08:00
Paul Gauthier (aider)
7b9a76c5ea refactor: Use temporary YAML file for model settings in test_default_and_override_settings 2024-11-19 11:49:57 -08:00
Paul Gauthier
6133fa8384 test: Update test cases with new edit_format value 2024-11-19 11:49:55 -08:00
Paul Gauthier (aider)
67cc215ed3 style: Apply linter formatting to models.py 2024-11-19 11:45:37 -08:00
Paul Gauthier (aider)
ea4ad2ea4d feat: Add track_init_fields decorator to track explicitly set fields in ModelSettings 2024-11-19 11:45:32 -08:00
Paul Gauthier
847454a4f7 fix: Remove debug dump statement in ModelSettings initialization 2024-11-19 11:45:31 -08:00
Paul Gauthier (aider)
8cba1fdd71 feat: Track and copy only explicitly set fields in ModelSettings 2024-11-19 10:11:44 -08:00
Paul Gauthier
e56112739c refactor: Add debug dump calls for edit_format in Model initialization 2024-11-19 10:11:42 -08:00
Paul Gauthier (aider)
76988b746f refactor: Remove unused call import and rename loop variable 2024-11-19 10:05:01 -08:00
Paul Gauthier (aider)
32eb365a0b style: Reorder imports in test_models.py 2024-11-19 10:04:45 -08:00
Paul Gauthier (aider)
2c5feddad5 test: Add imports for ModelSettings and MODEL_SETTINGS 2024-11-19 10:04:41 -08:00
Paul Gauthier (aider)
210500ff3e style: Apply linter formatting to test_models.py 2024-11-19 10:04:23 -08:00
Paul Gauthier (aider)
7c8f10e832 test: Add tests for default and override model settings 2024-11-19 10:04:19 -08:00
Paul Gauthier (aider)
644da2f9e4 docs: Add documentation for aider/default and aider/override model settings 2024-11-19 10:03:26 -08:00
Paul Gauthier (aider)
2a80d9c555 feat: Apply generic model settings when no exact model match found 2024-11-19 10:02:25 -08:00
Paul Gauthier
76f8791f3c refactor: Restructure model settings application with early returns and simplified logic 2024-11-19 10:02:24 -08:00
Paul Gauthier (aider)
c51a013109 refactor: Extract field copying logic into reusable _copy_fields method 2024-11-19 10:00:23 -08:00
Paul Gauthier (aider)
88c2f95ea5 style: Format code with linter 2024-11-19 09:59:27 -08:00
Paul Gauthier (aider)
062fa7de78 refactor: Enhance model settings configuration with default and override handling 2024-11-19 09:59:22 -08:00
Paul Gauthier
d6c1a41e8d feat: Add Timeout exception to handle API provider timeouts 2024-11-19 09:27:16 -08:00
Paul Gauthier
20ab5f9326 copy 2024-11-19 06:52:15 -08:00
Paul Gauthier
ab5a8b24a5 updated blame 2024-11-18 13:56:46 -08:00
Paul Gauthier (aider)
21a28623ca feat: Explicitly include specific markdown files in blame script 2024-11-18 13:46:43 -08:00
Paul Gauthier (aider)
06a5fec612 feat: Include .md files from aider/website/share/ in blame statistics 2024-11-18 13:45:50 -08:00
Paul Gauthier (aider)
46ecb8a663 feat: Enhance share page security with markdown sanitization and error handling 2024-11-18 13:40:15 -08:00
Paul Gauthier (aider)
3c9c6eef6e feat: Add URL validation and Content Security Policy to share page 2024-11-18 13:37:02 -08:00
Paul Gauthier
72734de376 copy 2024-11-18 13:28:47 -08:00
Paul Gauthier
a20ea09a6e refactor: Remove redundant streaming=False from model settings 2024-11-18 13:28:14 -08:00
Paul Gauthier (aider)
4bd7bce232 docs: Add example of using .aiderignore to focus on specific directories in monorepo 2024-11-18 13:22:55 -08:00
Paul Gauthier
8adf42216d copy 2024-11-18 07:47:30 -08:00
Paul Gauthier (aider)
5f40aaabb5 style: Lint and clean up code formatting in issues.py script 2024-11-18 07:46:28 -08:00
Paul Gauthier (aider)
5295abbb83 style: Move #noqa comments to triple-quoted strings in issues.py 2024-11-18 07:46:23 -08:00
Paul Gauthier
201abe1524 refactor: Improve code formatting and add noqa comment in issues.py script 2024-11-18 07:46:00 -08:00
Paul Gauthier (aider)
6d26051d11 style: Reformat long string literals using parentheses 2024-11-18 07:44:54 -08:00
Paul Gauthier (aider)
4613bf78d5 feat: Add BOT_SUFFIX to issue comment templates 2024-11-18 07:44:50 -08:00
Paul Gauthier
1f8fdc6f5c refactor: Update issue script comments and add bot suffix 2024-11-18 07:44:48 -08:00
Paul Gauthier
abf804cf10 set version to 0.63.3.dev 2024-11-18 07:30:21 -08:00
Paul Gauthier
d7a195706f version bump to 0.63.2 2024-11-18 07:29:05 -08:00
Paul Gauthier
569370109a copy 2024-11-18 07:11:46 -08:00
Paul Gauthier
eae3f04c83 copy 2024-11-18 06:57:35 -08:00
Paul Gauthier (aider)
ee0987f331 feat: Update HISTORY.md with recent changes since v0.63.1 2024-11-18 06:57:04 -08:00
Paul Gauthier (aider)
bdafa842bd fix: Add missing time import for time.sleep() in write_text method 2024-11-15 16:23:37 -08:00
Paul Gauthier (aider)
76c7c2562c style: Format code with linter for improved readability 2024-11-15 16:23:26 -08:00
Paul Gauthier (aider)
f7de2234f2 fix: Handle different OSError types in write_text method 2024-11-15 16:23:21 -08:00
Paul Gauthier
c725c45726 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-15 16:22:23 -08:00
paul-gauthier
383bef456d Merge pull request #2381 from mark-asymbl/write_text_file_lock_fix
Added io.py write_text exponential backoff to gracefully handle transient file locks
2024-11-15 16:21:40 -08:00
mw
7f48f3d01d Added write_text exponential backoff to
Discord thread ID: 1306776889762906123

Resolve issue where Aider fails to write multiple, consecutive changes to a single file due to Visual Studio briefly locking a file for writing after it was edited. Presumably VS is doing some sort of processing, such as for IntelliSense, behind the scenes. This solution is applicable to other, similar editor/IDE behaviors.
2024-11-15 15:04:25 -08:00
Paul Gauthier
0bf17a48f7 copy 2024-11-15 07:42:17 -08:00
Paul Gauthier (aider)
c127f8f2f0 chore: Update HISTORY.md with v0.63.1 and v0.63.2 release notes 2024-11-15 07:37:14 -08:00
Paul Gauthier
d4d5d15e18 fix: Handle missing litellm_provider in fuzzy model matching 2024-11-15 06:14:15 -08:00
Paul Gauthier
b254afa498 refactor: Modify model metadata file loading to prioritize resource file 2024-11-15 05:33:59 -08:00
Paul Gauthier
0ce5a94c15 bumped deps 2024-11-15 05:29:29 -08:00
Paul Gauthier
38a5405c65 copy 2024-11-14 15:30:49 -08:00
Paul Gauthier
ecef784686 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-14 15:27:51 -08:00
Paul Gauthier
e82b2c12b4 cleanup 2024-11-14 15:27:40 -08:00
Paul Gauthier (aider)
3c26ced8db style: Apply linter formatting to main.py 2024-11-14 15:18:54 -08:00
Paul Gauthier (aider)
2681a41abb refactor: Expand read-only file paths to include all files in directories 2024-11-14 15:18:47 -08:00
Paul Gauthier
805deb1002 feat: Add comment to expand read-only directory files 2024-11-14 15:18:45 -08:00
Paul Gauthier
6b792de802 copy 2024-11-14 15:15:23 -08:00
paul-gauthier
26f8e34dcb Merge pull request #2369 from josx/fix_contrib_pytest_filename 2024-11-14 07:33:53 -08:00
José Luis Di Biase
e0c1b2458c fix: typo pytest filename 2024-11-14 12:27:12 -03:00
Paul Gauthier
66f94d2141 set version to 0.63.2.dev 2024-11-14 06:56:43 -08:00
Paul Gauthier
503a9a0038 version bump to 0.63.1 2024-11-14 06:55:05 -08:00
Paul Gauthier
d8a5bc3ae9 Revert "Merge branch 'issue2283'"
This reverts commit e1a1e43c3a, reversing
changes made to c538817b61.
2024-11-14 06:53:21 -08:00
Paul Gauthier (aider)
94c3957d92 fix: Add error handling for git.ignored() method 2024-11-14 06:48:35 -08:00
Paul Gauthier
266350b8ce fix: Handle potential git errors in git_ignored_file method 2024-11-14 06:48:33 -08:00
Paul Gauthier (aider)
721d852cc7 feat: Add vertical spacing div to improve FAQ anchor link behavior 2024-11-13 16:23:50 -08:00
Paul Gauthier
ffbf205aba docs: Add explanation for aider code stats computation 2024-11-13 16:20:07 -08:00
Paul Gauthier
e1a1e43c3a Merge branch 'issue2283' 2024-11-13 13:43:30 -08:00
Paul Gauthier
c538817b61 updated blame 2024-11-13 13:43:05 -08:00
Paul Gauthier
71d85d2771 fix: Update Qwen 2.5 Coder 32b model configuration condition 2024-11-13 13:40:35 -08:00
Paul Gauthier
69f4d5fca7 set version to 0.63.1.dev 2024-11-13 13:37:03 -08:00
Paul Gauthier
bb31fc5301 version bump to 0.63.0 2024-11-13 13:35:36 -08:00
Paul Gauthier
87ce51e314 copy 2024-11-13 13:32:20 -08:00
Paul Gauthier
33555ca2ea refactor: Simplify file display logic and label formatting 2024-11-13 13:31:38 -08:00
Paul Gauthier (aider)
6fc3776c0c style: Fix linter warnings in io.py 2024-11-13 13:27:11 -08:00
Paul Gauthier (aider)
8a05f05bd4 refactor: Improve file list display logic with line-based spacing 2024-11-13 13:27:06 -08:00
Paul Gauthier (aider)
0dff51920e feat: Conditionally print blank line between file sections based on file count 2024-11-13 13:26:09 -08:00
Paul Gauthier
262f217d04 style: Shorten file list labels for cleaner display 2024-11-13 13:26:08 -08:00
Paul Gauthier (aider)
8b9154bab0 feat: Add labels to read-only and editable files columns 2024-11-13 13:24:51 -08:00
Paul Gauthier (aider)
533613d92b fix: Remove unused repo variable in test_cmd_add_gitignored_file 2024-11-13 13:22:57 -08:00
Paul Gauthier
20d87e1136 refactor: Remove unnecessary .gitignore commit in test setup 2024-11-13 13:22:45 -08:00
Paul Gauthier (aider)
1450c4194e test: Add test to verify cmd_add respects .gitignore files 2024-11-13 13:20:52 -08:00
Paul Gauthier
bc82baa968 refactor: Reorder git ignored file check to handle non-git repos 2024-11-13 13:18:09 -08:00
Paul Gauthier
218623be28 feat: Add git_ignored_file method to check files against gitignore 2024-11-13 13:12:25 -08:00
Paul Gauthier
ea1a4ecdc6 fix: Handle empty content in reply_completed method 2024-11-13 12:57:45 -08:00
Paul Gauthier
6acbff3c11 fix: Handle empty content in ArchitectCoder reply_completed method 2024-11-13 12:57:38 -08:00
Paul Gauthier
153021efcf fix: Handle OSError in get_rel_repo_dir method for edge cases 2024-11-13 12:51:27 -08:00
Paul Gauthier
fef1b59b42 refactor: Restructure file mention check and interrupt handling in base coder 2024-11-13 12:50:17 -08:00
Paul Gauthier
733b11b7d4 copy 2024-11-13 12:40:43 -08:00
Paul Gauthier
400514ff10 fix: Remove hardcoded reminder and add Qwen 2.5 coder model configuration 2024-11-13 12:36:28 -08:00
Paul Gauthier
bbfac316fc feat: Add model metadata for Qwen 2.5 Coder 32B Instruct model 2024-11-13 12:24:32 -08:00
Paul Gauthier
7d0b67f70e copy 2024-11-12 19:12:19 -08:00
Paul Gauthier
d0f1b38848 feat: Add Qwen 2.5 Coder 32B model settings and improve model loading robustness 2024-11-12 19:10:48 -08:00
Paul Gauthier
4d4b5bc366 chore: Remove model-metadata.json file 2024-11-12 18:38:59 -08:00
Paul Gauthier
1f39c7ef0d refactor: Improve model info retrieval logic in ModelInfoManager 2024-11-12 18:37:33 -08:00
Paul Gauthier (aider)
2e97fcc47f fix: Remove double-counting of cached tokens in token calculation 2024-11-11 17:19:11 -08:00
Paul Gauthier
550c8322c4 copy 2024-11-11 15:54:38 -08:00
Paul Gauthier (aider)
2467e23033 feat: Add vertex_ai/gemini-pro-experimental model with diff-fenced edit mode 2024-11-11 15:53:53 -08:00
Paul Gauthier
0e53198c59 do not swallow litellm.get_model_info() exceptions #2318 2024-11-11 15:15:24 -08:00
Paul Gauthier
44063590e2 copy 2024-11-11 10:30:23 -08:00
Paul Gauthier
557f25bf80 copy 2024-11-11 10:30:00 -08:00
paul-gauthier
190531543f Merge pull request #2335 from Hambaobao/qwen2.5-coder-32b-diff-results
Add diff format evaluation results of Qwen2.5-Coder-32B-Instruct.
2024-11-11 10:29:16 -08:00
Paul Gauthier
acfb7c3a89 fix: Handle git repo initialization errors gracefully 2024-11-11 09:56:19 -08:00
Paul Gauthier
94a6d3bc7e fix: Handle case when current working directory is inaccessible in git setup 2024-11-11 09:55:23 -08:00
Paul Gauthier (aider)
5751bcd382 refactor: Move Path.cwd() call to top of setup_git and add OSError handling 2024-11-11 09:54:43 -08:00
Paul Gauthier
21b88c0e65 refactor: Update language reply prompts to use {language} placeholder 2024-11-11 09:38:30 -08:00
Paul Gauthier
f66b916d4b feat: Add language configuration for user communication in prompts 2024-11-11 09:36:23 -08:00
柏枫
bd9c43a48d Add evaluation results for Qwen2.5-Coder-32B-Instruct using the diff format. 2024-11-12 01:23:19 +08:00
Paul Gauthier
352b91f342 copy 2024-11-11 08:46:08 -08:00
Paul Gauthier
be6e3254ea copy 2024-11-11 08:45:42 -08:00
paul-gauthier
dd1ee209ab Merge pull request #2334 from Hambaobao/qwen2.5-coder-series-results
Add Evaluation Results of Qwen2.5-Coder Series.
2024-11-11 08:43:51 -08:00
柏枫
c0b1101a52 Add evaluation results of Qwen2.5-Coder series. 2024-11-11 20:18:30 +08:00
Paul Gauthier
52c49fc8fd feat: Add option to return web scrape content instead of printing 2024-11-08 14:27:59 -08:00
Paul Gauthier
77cb64958e refactor: Modify URL scraping and message handling in commands 2024-11-08 14:23:55 -08:00
Paul Gauthier (aider)
b3d13e44b2 refactor: Modify cmd_web to add scraped content to cur_messages as assistant reply 2024-11-08 14:21:59 -08:00
Paul Gauthier
9dd7b795ca fix: Handle NotFoundError in send chat test with single print call 2024-11-08 14:18:23 -08:00
Paul Gauthier (aider)
7a8399571a fix: Handle non-retryable errors by returning None in simple_send_with_retries 2024-11-08 10:03:49 -08:00
Paul Gauthier (aider)
d0e85d9c2c style: Apply linter formatting to sendchat.py and test_sendchat.py 2024-11-08 10:02:54 -08:00
Paul Gauthier (aider)
14d02bc843 fix: Handle None response and update InvalidRequestError test 2024-11-08 10:02:48 -08:00
Paul Gauthier (aider)
b79c09cf58 refactor: Remove unused CACHE import from test_sendchat.py 2024-11-08 10:01:45 -08:00
Paul Gauthier (aider)
c9dfe5daff style: Organize imports and format code in test_sendchat.py 2024-11-08 10:01:16 -08:00
Paul Gauthier (aider)
092e7f6b3c test: Add comprehensive tests for sendchat module functionality 2024-11-08 10:01:11 -08:00
Paul Gauthier (aider)
203634314c style: Format code with linter 2024-11-08 10:00:33 -08:00
Paul Gauthier (aider)
c472e6e160 fix: Update test_exceptions.py to provide required arguments for litellm exceptions 2024-11-08 10:00:30 -08:00
Paul Gauthier (aider)
86d9275375 refactor: Remove unused pytest import from test_exceptions.py 2024-11-08 09:59:44 -08:00
Paul Gauthier (aider)
9db6780af6 style: Sort imports and add whitespace in test_exceptions.py 2024-11-08 09:59:30 -08:00
Paul Gauthier (aider)
e10205ff69 test: Add comprehensive tests for LiteLLMExceptions module 2024-11-08 09:59:25 -08:00
Paul Gauthier
9f539436b8 test: Add test_exceptions.py to basic test suite 2024-11-08 09:59:23 -08:00
Paul Gauthier
acd75e1083 copy 2024-11-08 09:58:21 -08:00
Paul Gauthier
f30225db90 removing buggy close-stale.yml workflow 2024-11-08 09:58:06 -08:00
Paul Gauthier (aider)
007305962a style: Remove unnecessary line breaks in comment_url assignment 2024-11-08 09:56:20 -08:00
Paul Gauthier (aider)
8065e38797 style: Wrap long comment_url line to fix flake8 line length error 2024-11-08 09:56:15 -08:00
Paul Gauthier (aider)
34dc684867 style: Remove unnecessary line breaks in comment_url assignment 2024-11-08 09:56:06 -08:00
Paul Gauthier (aider)
7edc9603d0 fix: Break long line to resolve flake8 line length error 2024-11-08 09:55:59 -08:00
Paul Gauthier (aider)
479d476878 style: Format code with consistent indentation and line breaks 2024-11-08 09:55:42 -08:00
Paul Gauthier (aider)
92bbec1852 feat: Add function to process and close stale issues after 7 days of inactivity 2024-11-08 09:55:37 -08:00
Paul Gauthier
d406636878 refactor: Improve issue output formatting and message clarity 2024-11-08 09:55:35 -08:00
Paul Gauthier (aider)
6362199363 fix: Reorder stale label and comment operations in handle_stale_issues 2024-11-08 09:25:11 -08:00
Paul Gauthier
22dbcb7590 refactor: Update stale issue comment text for clarity and conciseness 2024-11-08 09:25:09 -08:00
Paul Gauthier (aider)
cefea38ee5 feat: Add issue URL to stale issue output for easier navigation 2024-11-08 09:17:55 -08:00
Paul Gauthier (aider)
d44cd01493 refactor: Add noqa comment to stale comment line to resolve flake8 warning 2024-11-08 09:11:41 -08:00
Paul Gauthier (aider)
e578655653 style: Format Python code with linter 2024-11-08 09:11:24 -08:00
Paul Gauthier (aider)
434dc27557 feat: Add stale issue detection for question-labeled issues with no activity 2024-11-08 09:11:19 -08:00
Paul Gauthier
79af39bd2c fix: Change tool_output to tool_warning for error message logging 2024-11-07 13:22:28 -08:00
Paul Gauthier (aider)
20d5a9fd4b style: Run linter to clean up whitespace in test_sendchat.py 2024-11-07 13:09:52 -08:00
Paul Gauthier (aider)
80e57ca074 fix: Remove unused import of httpx in test_sendchat.py 2024-11-07 13:09:50 -08:00
Paul Gauthier
8a3c95d8dd feat: Add LiteLLMExceptions loading in test for send chat functionality 2024-11-07 13:09:47 -08:00
Paul Gauthier
4941a360cb fix: Restore import of LiteLLMExceptions in base_coder.py 2024-11-07 13:02:17 -08:00
Paul Gauthier (aider)
9e7219c4d6 style: Run linter to clean up code formatting in sendchat.py 2024-11-07 13:02:10 -08:00
Paul Gauthier (aider)
4d96728709 fix: Remove unused import of 'backoff' in sendchat.py 2024-11-07 13:02:07 -08:00
Paul Gauthier
816fd5e65c refactor: Simplify error handling and remove unused retry exceptions code 2024-11-07 13:02:04 -08:00
Paul Gauthier (aider)
8d4175536f style: fix linting issues and whitespace in exceptions.py 2024-11-07 12:45:32 -08:00
Paul Gauthier (aider)
bba9ca3d5a feat: add get_ex_info method to lookup exception info 2024-11-07 12:45:29 -08:00
Paul Gauthier
8bc9ebf2aa feat: add LiteLLM exception handling with ExInfo dataclass 2024-11-07 12:45:27 -08:00
Paul Gauthier (aider)
dad335b8b6 refactor: remove unused comment from LiteLLMExceptions class 2024-11-07 12:19:45 -08:00
Paul Gauthier
62e93d4002 feat: add custom exceptions module 2024-11-07 12:19:41 -08:00
Paul Gauthier
728f4a0f81 copy 2024-11-07 11:54:53 -08:00
Paul Gauthier
0cafd6ee4b Merge branch 'main' of github.com:Aider-AI/aider 2024-11-07 11:50:28 -08:00
Paul Gauthier
2962e51dac test: Add webbrowser patching to TestCoder and fix argument order in test_sanity_check_repo 2024-11-07 11:48:17 -08:00
Paul Gauthier (aider)
cf5733b237 style: fix import order in test_sanity_check_repo.py 2024-11-07 11:47:39 -08:00
Paul Gauthier (aider)
c96e3326bc fix: update test to check for offer_url instead of confirm_ask 2024-11-07 11:47:35 -08:00
Paul Gauthier
1cd373c0a5 test: fix git index version test to use offer_url instead of confirm_ask 2024-11-07 11:47:33 -08:00
Paul Gauthier
ae970cf2da fix: Update webbrowser patch to use correct module path 2024-11-07 11:35:40 -08:00
Paul Gauthier
d43a01f182 cleanup 2024-11-07 11:29:47 -08:00
Paul Gauthier
42aac55b82 use offer_url 2024-11-07 11:29:05 -08:00
Paul Gauthier
a66f31dc87 bugfix 2024-11-07 11:28:52 -08:00
Paul Gauthier (aider)
64c48f2151 refactor: remove unused webbrowser import 2024-11-07 11:23:02 -08:00
Paul Gauthier (aider)
9eead8a904 style: Fix comment formatting and whitespace 2024-11-07 10:30:45 -08:00
Paul Gauthier (aider)
7761bccffe refactor: replace confirm_ask/webbrowser.open with io.offer_url 2024-11-07 10:30:41 -08:00
Paul Gauthier
a848933875 chore: add TODO comment for refactoring URL handling 2024-11-07 10:30:38 -08:00
Paul Gauthier (aider)
e475f3d752 refactor: move webbrowser import to io.py and remove from base_coder.py 2024-11-07 10:26:54 -08:00
Paul Gauthier (aider)
4d24dbc661 style: fix linting issues in io.py header comment 2024-11-07 10:26:41 -08:00
Paul Gauthier (aider)
0368c3fae9 refactor: extract URL opening functionality into dedicated io.offer_url method 2024-11-07 10:26:33 -08:00
Paul Gauthier
2cf93ccb54 refactor: simplify URL opening confirmation prompt 2024-11-07 10:26:31 -08:00
paul-gauthier
3d72cafea4 Merge pull request #2284 from Mushoz/main 2024-11-07 06:07:47 -08:00
Jaap Buurman
af0466ea83 Added Qwen2.5-7b-coder with the updated weights
The Qwen team still calls it Qwen2.5, but as can be seen from the
benchmarks the difference in performance compared to the old weights
is pretty substantial. The GGUF version of this model made by Bartowski
calls it 2.5.1 to differentiate it from the earlier version of the
same model.
2024-11-07 13:18:24 +01:00
Paul Gauthier
c84f2996ec copy 2024-11-06 20:13:38 -08:00
Paul Gauthier
add9b83d3b copy 2024-11-06 20:13:31 -08:00
Paul Gauthier
5411fb6fd4 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-06 20:13:02 -08:00
paul-gauthier
49fc1b40e5 Merge pull request #2277 from lattwood/lattwood/bedrock_claude_feature_parity
Add Sonnet & Haiku ModelSettings for Bedrock
2024-11-06 09:03:18 -08:00
Logan Attwood
daef2eecdd Add Sonnet & Haiku ModelSettings for Bedrock 2024-11-06 12:28:24 -04:00
Paul Gauthier
1520422cc3 copy 2024-11-05 15:39:17 -08:00
Paul Gauthier
c7530085a6 set version to 0.62.2.dev 2024-11-05 12:41:44 -08:00
Paul Gauthier
bf43c567d8 version bump to 0.62.1 2024-11-05 12:40:17 -08:00
Paul Gauthier
b81f3e4f8d style: reorder chart canvas elements in blame.md 2024-11-05 12:11:14 -08:00
Paul Gauthier
97051b9d40 refactor: Replace GitTemporaryDirectory with ChdirTemporaryDirectory 2024-11-05 11:54:27 -08:00
Paul Gauthier
90730845de style: fix indentation in test_editblock.py 2024-11-05 11:43:04 -08:00
Paul Gauthier (aider)
f7c0c433c3 refactor: add mock for sendchat.simple_send_with_retries in test 2024-11-05 11:42:31 -08:00
Paul Gauthier
538752d0cf test: add mock for sendchat.simple_send_with_retries in editblock test 2024-11-05 11:42:30 -08:00
Paul Gauthier
c71a92ac84 fix: handle empty original content when creating new files 2024-11-05 09:14:01 -08:00
Paul Gauthier
85f23b3408 copy 2024-11-05 09:06:56 -08:00
Paul Gauthier
44cab0a4d7 refactor: update Claude model references to use 3.5-haiku-20241022 2024-11-05 09:01:35 -08:00
Paul Gauthier (aider)
33db8ee0c3 feat: enable repo map for Claude 3.5 Haiku models 2024-11-05 08:49:56 -08:00
Paul Gauthier
da4b3770c0 refactor: set use_repo_map=True for Claude 3.5 Haiku models 2024-11-05 08:49:53 -08:00
Paul Gauthier
12698998b9 feat: add verbose output for file processing in RepoMap 2024-11-05 08:48:06 -08:00
Paul Gauthier
6177856baf refactor: simplify issues script by removing redundant flag 2024-11-05 08:45:48 -08:00
Paul Gauthier (aider)
54b9c46b96 style: Fix whitespace in issues.py script 2024-11-05 07:04:15 -08:00
Paul Gauthier (aider)
2dd83e7dbe feat: exclude pull requests from unlabeled issues search 2024-11-05 07:04:11 -08:00
Paul Gauthier (aider)
17351e8f91 refactor: extract issue handling into dedicated functions 2024-11-05 07:02:24 -08:00
Paul Gauthier
e8c153f72f docs: add refactoring comments for issue handling functions 2024-11-05 07:02:22 -08:00
Paul Gauthier (aider)
ddfd1276c5 style: Format issues.py with black linter 2024-11-05 06:58:44 -08:00
Paul Gauthier (aider)
46251c6a1c feat: add function to find unlabeled issues with paul-gauthier comments 2024-11-05 06:58:40 -08:00
Paul Gauthier
e699968be5 copy 2024-11-05 06:53:13 -08:00
Paul Gauthier
389b58b75b fix: remove premature return after disabling analytics 2024-11-05 06:52:50 -08:00
Paul Gauthier
a7cf34dea4 copy 2024-11-04 15:40:21 -08:00
Paul Gauthier
e601682706 updated blame 2024-11-04 13:00:42 -08:00
Paul Gauthier
55f16dc0b5 copy 2024-11-04 12:53:10 -08:00
Paul Gauthier
775011033f set version to 0.62.1.dev 2024-11-04 12:50:13 -08:00
Paul Gauthier
8ffe21a2dd version bump to 0.62.0 2024-11-04 12:48:44 -08:00
Paul Gauthier
73d63ef5ce copy 2024-11-04 12:37:21 -08:00
Paul Gauthier
e12b1a9184 copy 2024-11-04 12:36:46 -08:00
Paul Gauthier
d099a95b92 copy 2024-11-04 12:36:38 -08:00
Paul Gauthier
496ed90439 copy 2024-11-04 12:17:02 -08:00
Paul Gauthier (aider)
7883db1834 feat: add --haiku flag for claude-3-5-haiku model selection 2024-11-04 12:14:23 -08:00
Paul Gauthier
0cfc23b1a8 refactor: remove unused haiku formatting option 2024-11-04 12:14:22 -08:00
Paul Gauthier (aider)
d33104aec1 refactor: move haiku flag next to sonnet flag in args 2024-11-04 12:13:27 -08:00
Paul Gauthier
711b2a431c chore: add comment about sonnet flag placement 2024-11-04 12:13:25 -08:00
Paul Gauthier (aider)
09d21b5951 feat: add --haiku flag to format responses as haikus 2024-11-04 12:13:05 -08:00
Paul Gauthier
d9193387cc feat: add haiku command line argument placeholder 2024-11-04 12:13:04 -08:00
Paul Gauthier
d5330ae2f3 refactor: update highlight model constant in leaderboard chart 2024-11-04 12:12:32 -08:00
Paul Gauthier (aider)
571c1b47b5 refactor: extract Haiku model name to constant 2024-11-04 12:11:48 -08:00
Paul Gauthier (aider)
0c9d4dd123 fix: update Chart.js scales config and add null checks for labels 2024-11-04 12:09:47 -08:00
Paul Gauthier (aider)
7d79408683 feat: add distinct color for 3.5 Haiku models in leaderboard chart 2024-11-04 12:08:05 -08:00
Paul Gauthier
e6d4c3558b add 3.5 haiku to leaderboard 2024-11-04 11:40:37 -08:00
Paul Gauthier
3be2109964 fix: update Claude 3.5 Haiku models to use diff mode instead of whole 2024-11-04 11:33:40 -08:00
Paul Gauthier
ce37ff26b5 refactor: remove redundant examples_as_sys_msg flag from Claude 3.5 models 2024-11-04 11:32:41 -08:00
Paul Gauthier
03bbdb010f add haiku metadata 2024-11-04 11:18:55 -08:00
Paul Gauthier (aider)
0bde1da42c feat: add Claude 3.5 Haiku model and provider variants 2024-11-04 10:46:55 -08:00
Paul Gauthier
987cb3bca9 feat: add claude-3-haiku model configuration 2024-11-04 10:46:54 -08:00
Paul Gauthier
0b11024967 copy 2024-11-04 10:35:37 -08:00
Paul Gauthier (aider)
dfaaedb466 style: remove empty line at start of main.py 2024-11-04 10:34:27 -08:00
Paul Gauthier (aider)
8bc0d5544d feat: add --apply-clipboard-edits switch for direct clipboard editing 2024-11-04 10:34:21 -08:00
Paul Gauthier
c67e63bc09 feat: add clipboard edit mode via --apply-clipboard-edits flag 2024-11-04 10:34:19 -08:00
Paul Gauthier
129f5fae76 cleanup 2024-11-04 09:09:45 -08:00
Paul Gauthier
966a613ffe fix: handle non-existent files in EditBlockCoder #2233 2024-11-04 09:08:00 -08:00
Paul Gauthier (aider)
96ad107c19 style: add newline before error message in io.py 2024-11-04 09:05:28 -08:00
Paul Gauthier (aider)
ebdc126b00 feat: add traceback printing for file read errors 2024-11-04 09:05:24 -08:00
Paul Gauthier
5e1be966ed chore: add comment about printing traceback stack in error handling 2024-11-04 09:05:23 -08:00
Chad Phillips
8801fda972 formatting fixes 2024-11-04 10:10:37 -06:00
malkoG
a8a3e2401b Update languages.md for dart support 2024-11-04 13:22:22 +09:00
malkoG
a7f59a2e2b Add tags.scm for dart 2024-11-04 12:38:27 +09:00
Chad Phillips
d8e9da35d6 add /editor command
Opens an editor for constructing a user prompt, using the currently defined chat mode.

The editor is determined as follows:

Look for the following environment variables, in order:

1. AIDER_EDITOR
2. VISUAL
3. EDITOR

If none of these are defined, use the following defaults:

Windows: notepad
OS X: vim
*nix: vi

If an editor is not found, a RuntimeError is raised.

Any arguments passed after the /editor command are inserted as content.

The temporary file used for editing has an .md extension, which can be leveraged for syntax highlighting.

NOTE: The editor used MUST block the process until the editor is closed -- the default editors all do this.
2024-11-03 20:18:57 -05:00
Paul Gauthier
0022c1a67e copy 2024-11-01 11:26:39 -07:00
Paul Gauthier
6a0380b8c0 copy 2024-11-01 09:46:27 -07:00
96 changed files with 6309 additions and 2237 deletions

View File

@@ -1,24 +0,0 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '30 1 * * *'
workflow_dispatch:
permissions:
issues: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
stale-issue-message: 'This issue has been labelled stale because it has been open for 2 weeks with no activity. Remove stale label or add a comment to keep this issue open. Otherwise, it will be closed in 7 days.'
close-issue-message: 'This issue was closed because it has been stalled for 3 weeks with no activity. Feel free to add a comment here and we can re-open it. Or feel free to file a new issue any time.'
days-before-stale: 14
days-before-close: 7
stale-issue-label: 'stale'
stale-pr-label: 'stale'
only-labels: 'question'
days-before-pr-stale: -1
days-before-pr-close: -1

3
.gitignore vendored
View File

@@ -11,4 +11,5 @@ _site
.jekyll-cache/
.jekyll-metadata
aider/__version__.py
.venv/
.venv/
.gitattributes

View File

@@ -187,8 +187,8 @@ pytest
You can also run specific test files or test cases by providing the file path or test name:
```
pytest aider/tests/test_coder.py
pytest aider/tests/test_coder.py::TestCoder::test_specific_case
pytest tests/basic/test_coder.py
pytest tests/basic/test_coder.py::TestCoder::test_specific_case
```
#### Continuous Integration

View File

@@ -1,8 +1,82 @@
# Release history
### main branch
- Added `--alias` config to define [custom model aliases](https://aider.chat/docs/config/model-aliases.html).
- Added `--[no-]detect-urls` flag to disable detecting and offering to scrape URLs found in the chat.
- Ollama models now default to an 8k context window.
- Added [RepoMap support for Dart language](https://aider.chat/docs/languages.html) by @malkoG.
- Ask 2.5% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
- Skip suggesting files that share names with files already in chat.
- `/editor` returns and prefill the file content into the prompt, so you can use `/editor` to compose messages that start with `/commands`, etc.
- Enhanced error handling for analytics.
- Improved handling of UnknownEditFormat exceptions with helpful documentation links.
- Bumped dependencies to pick up grep-ast 0.4.0 for Dart language support.
- Aider wrote 81% of the code in this release.
### Aider v0.64.1
- Disable streaming for o1 on OpenRouter.
### Aider v0.64.0
- Added [`/editor` command](https://aider.chat/docs/usage/commands.html) to open system editor for writing prompts, by @thehunmonkgroup.
- Full support for `gpt-4o-2024-11-20`.
- Stream o1 models by default.
- `/run` and suggested shell commands are less mysterious and now confirm that they "Added XX lines of output to the chat."
- Ask 1% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
- Added support for [optional multiline input tags](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) with matching closing tags.
- Improved [model settings configuration](https://aider.chat/docs/config/adv-model-settings.html#global-extra-params) with support for global `extra_params` for `litellm.completion()`.
- Architect mode now asks to add files suggested by the LLM.
- Fixed bug in fuzzy model name matching.
- Added Timeout exception to handle API provider timeouts.
- Added `--show-release-notes` to control release notes display on first run of new version.
- Save empty dict to cache file on model metadata download failure, to delay retry.
- Improved error handling and code formatting.
- Aider wrote 74% of the code in this release.
### Aider v0.63.2
- Fixed bug in fuzzy model name matching when litellm provider info is missing.
- Modified model metadata file loading to allow override of resource file.
- Allow recursive loading of dirs using `--read`.
- Updated dependency versions to pick up litellm fix for ollama models.
- Added exponential backoff retry when writing files to handle editor file locks.
- Updated Qwen 2.5 Coder 32B model configuration.
### Aider v0.63.1
- Fixed bug in git ignored file handling.
- Improved error handling for git operations.
### Aider v0.63.0
- Support for Qwen 2.5 Coder 32B.
- `/web` command just adds the page to the chat, without triggering an LLM response.
- Improved prompting for the user's preferred chat language.
- Improved handling of LiteLLM exceptions.
- Bugfix for double-counting tokens when reporting cache stats.
- Bugfix for the LLM creating new files.
- Other small bug fixes.
- Aider wrote 55% of the code in this release.
### Aider v0.62.0
- Full support for Claude 3.5 Haiku
- Scored 75% on [aider's code editing leaderboard](https://aider.chat/docs/leaderboards/).
- Almost as good as Sonnet at much lower cost.
- Launch with `--haiku` to use it.
- Easily apply file edits from ChatGPT, Claude or other web apps
- Chat with ChatGPT or Claude via their web app.
- Give it your source files and ask for the changes you want.
- Use the web app's "copy response" button to copy the entire reply from the LLM.
- Run `aider --apply-clipboard-edits file-to-edit.js`.
- Aider will edit your file with the LLM's changes.
- Bugfix for creating new files.
- Aider wrote 84% of the code in this release.
### Aider v0.61.0
- Load and save aider slash-commands to files:
- `/save <fname>` command will make a file of `/add` and `/read-only` commands that recreate the current file context in the chat.
- `/load <fname>` will replay the commands in the file.

View File

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

View File

@@ -5,7 +5,7 @@ import time
import uuid
from pathlib import Path
from mixpanel import Mixpanel
from mixpanel import Mixpanel, MixpanelException
from posthog import Posthog
from aider import __version__
@@ -62,8 +62,47 @@ class Analytics:
self.permanently_disable = True
self.save_data()
def need_to_ask(self):
return not self.asked_opt_in and not self.permanently_disable
def need_to_ask(self, args_analytics):
if args_analytics is False:
return False
could_ask = not self.asked_opt_in and not self.permanently_disable
if not could_ask:
return False
if args_analytics is True:
return True
assert args_analytics is None, args_analytics
if not self.user_id:
return False
PERCENT = 2.5
return self.is_uuid_in_percentage(self.user_id, PERCENT)
def is_uuid_in_percentage(self, uuid_str, percent):
"""Check if a UUID string falls within the first X percent of the UUID space.
Args:
uuid_str: UUID string to test
percent: Percentage threshold (0-100)
Returns:
bool: True if UUID falls within the first X percent
"""
if not (0 <= percent <= 100):
raise ValueError("Percentage must be between 0 and 100")
if not uuid_str:
return False
# Convert percentage to hex threshold (1% = "04...", 10% = "1a...", etc)
# Using first 6 hex digits
if percent == 0:
return False
threshold = format(int(0xFFFFFF * percent / 100), "06x")
return uuid_str[:6] <= threshold
def get_data_file_path(self):
data_file = Path.home() / ".aider" / "analytics.json"
@@ -120,7 +159,7 @@ class Analytics:
return None
def event(self, event_name, main_model=None, **kwargs):
if not (self.mp or self.ph) and not self.logfile:
if not self.mp and not self.ph and not self.logfile:
return
properties = {}
@@ -143,7 +182,10 @@ class Analytics:
properties["aider_version"] = __version__
if self.mp:
self.mp.track(self.user_id, event_name, dict(properties))
try:
self.mp.track(self.user_id, event_name, dict(properties))
except MixpanelException:
self.mp = None # Disable mixpanel on connection errors
if self.ph:
self.ph.capture(self.user_id, event_name, dict(properties))

View File

@@ -66,6 +66,14 @@ def get_parser(default_config_files, git_root):
const=sonnet_model,
help=f"Use {sonnet_model} model for the main chat",
)
haiku_model = "claude-3-5-haiku-20241022"
group.add_argument(
"--haiku",
action="store_const",
dest="model",
const=haiku_model,
help=f"Use {haiku_model} model for the main chat",
)
gpt_4_model = "gpt-4-0613"
group.add_argument(
"--4",
@@ -185,6 +193,12 @@ def get_parser(default_config_files, git_root):
default=".aider.model.metadata.json",
help="Specify a file with context window and costs for unknown models",
)
group.add_argument(
"--alias",
action="append",
metavar="ALIAS:MODEL",
help="Add a model alias (can be used multiple times)",
)
group.add_argument(
"--verify-ssl",
action=argparse.BooleanOptionalAction,
@@ -554,8 +568,8 @@ def get_parser(default_config_files, git_root):
group.add_argument(
"--analytics",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable analytics for one session (default: False)",
default=None,
help="Enable/disable analytics for current session (default: random)",
)
group.add_argument(
"--analytics-log",
@@ -612,6 +626,12 @@ def get_parser(default_config_files, git_root):
help="Check for new aider versions on launch",
default=True,
)
group.add_argument(
"--show-release-notes",
action=argparse.BooleanOptionalAction,
help="Show release notes on first run of new version (default: None, ask user)",
default=None,
)
group.add_argument(
"--install-main-branch",
action="store_true",
@@ -630,6 +650,12 @@ def get_parser(default_config_files, git_root):
metavar="FILE",
help="Apply the changes from the given file instead of running the chat (debug)",
)
group.add_argument(
"--apply-clipboard-edits",
action="store_true",
help="Apply clipboard contents as edits using the main model's editor format",
default=False,
)
group.add_argument(
"--yes-always",
action="store_true",
@@ -718,6 +744,16 @@ def get_parser(default_config_files, git_root):
default=True,
help="Enable/disable fancy input with history and completion (default: True)",
)
group.add_argument(
"--detect-urls",
action=argparse.BooleanOptionalAction,
default=True,
help="Enable/disable detection and offering to add URLs to chat (default: True)",
)
group.add_argument(
"--editor",
help="Specify which editor to use for the /editor command",
)
##########
group = parser.add_argument_group("Voice Settings")

View File

@@ -10,6 +10,9 @@ class ArchitectCoder(AskCoder):
def reply_completed(self):
content = self.partial_response_content
if not content or not content.strip():
return
if not self.io.confirm_ask("Edit the files?"):
return

View File

@@ -13,7 +13,7 @@ Just show the changes needed.
DO NOT show the entire updated function/file/etc!
Always reply in the same language as the change request.
Always reply to the user in {language}.
"""
example_messages = []

View File

@@ -6,7 +6,7 @@ from .base_prompts import CoderPrompts
class AskPrompts(CoderPrompts):
main_system = """Act as an expert code analyst.
Answer questions about the supplied code.
Always reply to the user in the same language they are using.
Always reply to the user in {language}.
"""
example_messages = []

View File

@@ -13,7 +13,6 @@ import sys
import threading
import time
import traceback
import webbrowser
from collections import defaultdict
from datetime import datetime
from json.decoder import JSONDecodeError
@@ -23,6 +22,7 @@ from typing import List
from aider import __version__, models, prompts, urls, utils
from aider.analytics import Analytics
from aider.commands import Commands
from aider.exceptions import LiteLLMExceptions
from aider.history import ChatSummary
from aider.io import ConfirmGroup, InputOutput
from aider.linter import Linter
@@ -30,13 +30,22 @@ from aider.llm import litellm
from aider.repo import ANY_GIT_ERROR, GitRepo
from aider.repomap import RepoMap
from aider.run_cmd import run_cmd
from aider.sendchat import RETRY_TIMEOUT, retry_exceptions, send_completion
from aider.sendchat import RETRY_TIMEOUT, send_completion
from aider.utils import format_content, format_messages, format_tokens, is_image_file
from ..dump import dump # noqa: F401
from .chat_chunks import ChatChunks
class UnknownEditFormat(ValueError):
def __init__(self, edit_format, valid_formats):
self.edit_format = edit_format
self.valid_formats = valid_formats
super().__init__(
f"Unknown edit format {edit_format}. Valid formats are: {', '.join(valid_formats)}"
)
class MissingAPIKeyError(ValueError):
pass
@@ -91,6 +100,7 @@ class Coder:
cache_warming_thread = None
num_cache_warming_pings = 0
suggest_shell_commands = True
detect_urls = True
ignore_mentions = None
chat_language = None
@@ -156,7 +166,12 @@ class Coder:
res.original_kwargs = dict(kwargs)
return res
raise ValueError(f"Unknown edit format {edit_format}")
valid_formats = [
str(c.edit_format)
for c in coders.__all__
if hasattr(c, "edit_format") and c.edit_format is not None
]
raise UnknownEditFormat(edit_format, valid_formats)
def clone(self, **kwargs):
new_coder = Coder.create(from_coder=self, **kwargs)
@@ -267,6 +282,7 @@ class Coder:
num_cache_warming_pings=0,
suggest_shell_commands=True,
chat_language=None,
detect_urls=True,
):
# Fill in a dummy Analytics if needed, but it is never .enable()'d
self.analytics = analytics if analytics is not None else Analytics()
@@ -280,6 +296,7 @@ class Coder:
self.ignore_mentions = set()
self.suggest_shell_commands = suggest_shell_commands
self.detect_urls = detect_urls
self.num_cache_warming_pings = num_cache_warming_pings
@@ -355,6 +372,9 @@ class Coder:
for fname in fnames:
fname = Path(fname)
if self.repo and self.repo.git_ignored_file(fname):
self.io.tool_warning(f"Skipping {fname} that matches gitignore spec.")
if self.repo and self.repo.ignored_file(fname):
self.io.tool_warning(f"Skipping {fname} that matches aiderignore spec.")
continue
@@ -790,34 +810,9 @@ class Coder:
self.num_reflections += 1
message = self.reflected_message
def check_and_open_urls(self, exc: Exception) -> List[str]:
import openai
def check_and_open_urls(self, exc, friendly_msg=None):
"""Check exception for URLs, offer to open in a browser, with user-friendly error msgs."""
text = str(exc)
friendly_msg = None
if isinstance(exc, (openai.APITimeoutError, openai.APIConnectionError)):
friendly_msg = (
"There is a problem connecting to the API provider. Please try again later or check"
" your model settings."
)
elif isinstance(exc, openai.RateLimitError):
friendly_msg = (
"The API provider's rate limits have been exceeded. Check with your provider or"
" wait awhile and retry."
)
elif isinstance(exc, openai.InternalServerError):
friendly_msg = (
"The API provider seems to be down or overloaded. Please try again later."
)
elif isinstance(exc, openai.BadRequestError):
friendly_msg = "The API provider refused the request as invalid?"
elif isinstance(exc, openai.AuthenticationError):
friendly_msg = (
"The API provider refused your authentication. Please check that you are using a"
" valid API key."
)
if friendly_msg:
self.io.tool_warning(text)
@@ -829,12 +824,14 @@ class Coder:
urls = list(set(url_pattern.findall(text))) # Use set to remove duplicates
for url in urls:
url = url.rstrip(".',\"")
if self.io.confirm_ask("Open URL for more info about this error?", subject=url):
webbrowser.open(url)
self.io.offer_url(url)
return urls
def check_for_urls(self, inp: str) -> List[str]:
"""Check input for URLs and offer to add them to the chat."""
if not self.detect_urls:
return []
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*[^\s,.])")
urls = list(set(url_pattern.findall(inp))) # Use set to remove duplicates
added_urls = []
@@ -846,7 +843,7 @@ class Coder:
"Add URL to the chat?", subject=url, group=group, allow_never=True
):
inp += "\n\n"
inp += self.commands.cmd_web(url)
inp += self.commands.cmd_web(url, return_content=True)
added_urls.append(url)
else:
self.rejected_urls.add(url)
@@ -982,12 +979,18 @@ class Coder:
platform=platform_text
)
if self.chat_language:
language = self.chat_language
else:
language = "the same language they are using"
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,
language=language,
)
return prompt
@@ -1076,7 +1079,7 @@ class Coder:
max_input_tokens = self.main_model.info.get("max_input_tokens") or 0
# Add the reminder prompt if we still have room to include it.
if (
max_input_tokens is None
not max_input_tokens
or total_tokens < max_input_tokens
and self.gpt_prompts.system_reminder
):
@@ -1154,8 +1157,6 @@ class Coder:
return chunks
def send_message(self, inp):
import openai # for error codes below
self.cur_messages += [
dict(role="user", content=inp),
]
@@ -1175,6 +1176,8 @@ class Coder:
retry_delay = 0.125
litellm_ex = LiteLLMExceptions()
self.usage_report = None
exhausted = False
interrupted = False
@@ -1183,30 +1186,37 @@ class Coder:
try:
yield from self.send(messages, functions=self.functions)
break
except retry_exceptions() as err:
# Print the error and its base classes
# for cls in err.__class__.__mro__: dump(cls.__name__)
except litellm_ex.exceptions_tuple() as err:
ex_info = litellm_ex.get_ex_info(err)
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
self.mdstream = None
self.check_and_open_urls(err)
if ex_info.name == "ContextWindowExceededError":
exhausted = True
break
should_retry = ex_info.retry
if should_retry:
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
should_retry = False
if not should_retry:
self.mdstream = None
self.check_and_open_urls(err, ex_info.description)
break
err_msg = str(err)
self.io.tool_error(err_msg)
if ex_info.description:
self.io.tool_warning(err_msg)
self.io.tool_error(ex_info.description)
else:
self.io.tool_error(err_msg)
self.io.tool_output(f"Retrying in {retry_delay:.1f} seconds...")
time.sleep(retry_delay)
continue
except KeyboardInterrupt:
interrupted = True
break
except litellm.ContextWindowExceededError:
# The input is overflowing the context window!
exhausted = True
break
except litellm.exceptions.BadRequestError as br_err:
self.io.tool_error(f"BadRequestError: {br_err}")
return
except FinishReasonLength:
# We hit the output limit!
if not self.main_model.info.get("supports_assistant_prefill"):
@@ -1221,12 +1231,8 @@ class Coder:
messages.append(
dict(role="assistant", content=self.multi_response_content, prefix=True)
)
except (openai.APIError, openai.APIStatusError) as err:
# for cls in err.__class__.__mro__: dump(cls.__name__)
self.mdstream = None
self.check_and_open_urls(err)
break
except Exception as err:
self.mdstream = None
lines = traceback.format_exception(type(err), err, err.__traceback__)
self.io.tool_warning("".join(lines))
self.io.tool_error(str(err))
@@ -1259,10 +1265,19 @@ class Coder:
else:
content = ""
try:
self.reply_completed()
except KeyboardInterrupt:
interrupted = True
if not interrupted:
add_rel_files_message = self.check_for_file_mentions(content)
if add_rel_files_message:
if self.reflected_message:
self.reflected_message += "\n\n" + add_rel_files_message
else:
self.reflected_message = add_rel_files_message
return
try:
self.reply_completed()
except KeyboardInterrupt:
interrupted = True
if interrupted:
content += "\n^C KeyboardInterrupt"
@@ -1313,13 +1328,6 @@ class Coder:
self.update_cur_messages()
return
add_rel_files_message = self.check_for_file_mentions(content)
if add_rel_files_message:
if self.reflected_message:
self.reflected_message += "\n\n" + add_rel_files_message
else:
self.reflected_message = add_rel_files_message
def reply_completed(self):
pass
@@ -1374,11 +1382,9 @@ class Coder:
res.append("- Use /clear to clear the chat history.")
res.append("- Break your code into smaller source files.")
res.append("")
res.append(f"For more info: {urls.token_limits}")
res = "".join([line + "\n" for line in res])
self.io.tool_error(res)
self.io.offer_url(urls.token_limits)
def lint_edited(self, fnames):
res = ""
@@ -1419,9 +1425,18 @@ class Coder:
addable_rel_fnames = self.get_addable_relative_files()
# Get basenames of files already in chat or read-only
existing_basenames = {os.path.basename(f) for f in self.get_inchat_relative_files()} | {
os.path.basename(self.get_rel_fname(f)) for f in self.abs_read_only_fnames
}
mentioned_rel_fnames = set()
fname_to_rel_fnames = {}
for rel_fname in addable_rel_fnames:
# Skip files that share a basename with files already in chat
if os.path.basename(rel_fname) in existing_basenames:
continue
normalized_rel_fname = rel_fname.replace("\\", "/")
normalized_words = set(word.replace("\\", "/") for word in words)
if normalized_rel_fname in normalized_words:
@@ -1622,7 +1637,6 @@ class Coder:
completion.usage, "cache_creation_input_tokens"
):
self.message_tokens_sent += prompt_tokens
self.message_tokens_sent += cache_hit_tokens
self.message_tokens_sent += cache_write_tokens
else:
self.message_tokens_sent += prompt_tokens
@@ -1799,6 +1813,10 @@ class Coder:
self.check_for_dirty_commit(path)
return True
if self.repo and self.repo.git_ignored_file(path):
self.io.tool_warning(f"Skipping edits to {path} that matches gitignore spec.")
return
if not Path(full_path).exists():
if not self.io.confirm_ask("Create new file?", subject=path):
self.io.tool_output(f"Skipping edits to {path}")
@@ -2072,9 +2090,10 @@ class Coder:
if output:
accumulated_output += f"Output from {command}\n{output}\n"
if accumulated_output.strip() and not self.io.confirm_ask(
if accumulated_output.strip() and self.io.confirm_ask(
"Add command output to the chat?", allow_never=True
):
accumulated_output = ""
return accumulated_output
num_lines = len(accumulated_output.strip().splitlines())
line_plural = "line" if num_lines == 1 else "lines"
self.io.tool_output(f"Added {num_lines} {line_plural} of output to the chat.")
return accumulated_output

View File

@@ -46,9 +46,16 @@ class EditBlockCoder(Coder):
for edit in edits:
path, original, updated = edit
full_path = self.abs_root_path(path)
content = self.io.read_text(full_path)
new_content = do_replace(full_path, content, original, updated, self.fence)
if not new_content:
new_content = None
if Path(full_path).exists():
content = self.io.read_text(full_path)
new_content = do_replace(full_path, content, original, updated, self.fence)
# If the edit failed, and
# this is not a "create a new file" with an empty original...
# https://github.com/Aider-AI/aider/issues/2258
if not new_content and original.strip():
# try patching any of the other files in the chat
for full_path in self.abs_fnames:
content = self.io.read_text(full_path)

View File

@@ -11,7 +11,7 @@ Respect and use existing conventions, libraries, etc that are already present in
Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
Always reply to the user in the same language they are using.
Always reply to the user in {language}.
Once you understand the request you MUST:

View File

@@ -12,7 +12,7 @@ Respect and use existing conventions, libraries, etc that are already present in
Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
Always reply to the user in the same language they are using.
Always reply to the user in {language}.
For each file that needs to be changed, write out the changes similar to a unified diff like `diff -U0` would produce.
"""

View File

@@ -8,7 +8,7 @@ class WholeFilePrompts(CoderPrompts):
Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
Always reply to the user in the same language they are using.
Always reply to the user in {language}.
{lazy_prompt}
Once you understand the request you MUST:

View File

@@ -14,6 +14,7 @@ from prompt_toolkit.completion import Completion, PathCompleter
from prompt_toolkit.document import Document
from aider import models, prompts, voice
from aider.editor import pipe_editor
from aider.format_settings import format_settings
from aider.help import Help, install_help_extra
from aider.llm import litellm
@@ -45,7 +46,15 @@ class Commands:
)
def __init__(
self, io, coder, voice_language=None, verify_ssl=True, args=None, parser=None, verbose=False
self,
io,
coder,
voice_language=None,
verify_ssl=True,
args=None,
parser=None,
verbose=False,
editor=None,
):
self.io = io
self.coder = coder
@@ -60,6 +69,7 @@ class Commands:
self.voice_language = voice_language
self.help = None
self.editor = editor
def cmd_model(self, args):
"Switch to a new LLM"
@@ -139,7 +149,7 @@ class Commands:
else:
self.io.tool_output("Please provide a partial model name to search for.")
def cmd_web(self, args):
def cmd_web(self, args, return_content=False):
"Scrape a webpage, convert to markdown and send in a message"
url = args.strip()
@@ -158,11 +168,16 @@ class Commands:
)
content = self.scraper.scrape(url) or ""
content = f"{url}:\n\n" + content
content = f"Here is the content of {url}:\n\n" + content
if return_content:
return content
self.io.tool_output("... done.")
self.io.tool_output("... added to chat.")
return content
self.coder.cur_messages += [
dict(role="user", content=content),
dict(role="assistant", content="Ok."),
]
def is_command(self, inp):
return inp[0] in "/!"
@@ -738,6 +753,10 @@ class Commands:
)
continue
if self.coder.repo and self.coder.repo.git_ignored_file(matched_file):
self.io.tool_error(f"Can't add {matched_file} which is in gitignore")
continue
if abs_file_path in self.coder.abs_fnames:
self.io.tool_error(f"{matched_file} is already in the chat as an editable file")
continue
@@ -859,7 +878,6 @@ class Commands:
exit_status, combined_output = run_cmd(
args, verbose=self.verbose, error_print=self.io.tool_error
)
instructions = None
if combined_output is None:
return
@@ -867,36 +885,22 @@ class Commands:
if add_on_nonzero_exit:
add = exit_status != 0
else:
self.io.tool_output()
response = self.io.prompt_ask(
"Add the output to the chat?\n(Y)es/(n)o/message with instructions:",
).strip()
self.io.tool_output()
if response.lower() in ["yes", "y"]:
add = True
elif response.lower() in ["no", "n"]:
add = False
else:
add = True
instructions = response
if response.strip():
self.io.user_input(response, log_only=True)
self.io.add_to_input_history(response)
add = self.io.confirm_ask("Add command output to the chat?")
if add:
for line in combined_output.splitlines():
self.io.tool_output(line, log_only=True)
num_lines = len(combined_output.strip().splitlines())
line_plural = "line" if num_lines == 1 else "lines"
self.io.tool_output(f"Added {num_lines} {line_plural} of output to the chat.")
msg = prompts.run_output.format(
command=args,
output=combined_output,
)
if instructions:
msg = instructions + "\n\n" + msg
return msg
self.coder.cur_messages += [
dict(role="user", content=msg),
dict(role="assistant", content="Ok."),
]
def cmd_exit(self, args):
"Exit the application"
@@ -1357,6 +1361,13 @@ class Commands:
report_github_issue(issue_text, title=title, confirm=False)
def cmd_editor(self, initial_content=""):
"Open an editor to write a prompt"
user_input = pipe_editor(initial_content, suffix="md", editor=self.editor)
if user_input.strip():
self.io.set_placeholder(user_input.rstrip())
def expand_subdir(file_path):
if file_path.is_file():

View File

@@ -50,7 +50,6 @@ def diff_partial_update(lines_orig, lines_updated, final=False, fname=None):
# dump(lines_orig)
# dump(lines_updated)
assert_newlines(lines_orig)
assert_newlines(lines_orig)
num_orig_lines = len(lines_orig)

146
aider/editor.py Normal file
View File

@@ -0,0 +1,146 @@
"""
Editor module for handling system text editor interactions.
This module provides functionality to:
- Discover and launch the system's configured text editor
- Create and manage temporary files for editing
- Handle editor preferences from environment variables
- Support cross-platform editor operations
"""
import os
import platform
import shlex
import subprocess
import tempfile
from rich.console import Console
DEFAULT_EDITOR_NIX = "vi"
DEFAULT_EDITOR_OS_X = "vim"
DEFAULT_EDITOR_WINDOWS = "notepad"
console = Console()
def print_status_message(success, message, style=None):
"""
Print a status message with appropriate styling.
:param success: Whether the operation was successful
:param message: The message to display
:param style: Optional style override. If None, uses green for success and red for failure
"""
if style is None:
style = "bold green" if success else "bold red"
console.print(message, style=style)
print("")
def write_temp_file(
input_data="",
suffix=None,
prefix=None,
dir=None,
):
"""
Create a temporary file with the given input data.
:param input_data: Content to write to the temporary file
:param suffix: Optional file extension (without the dot)
:param prefix: Optional prefix for the temporary filename
:param dir: Optional directory to create the file in
:return: Path to the created temporary file
:raises: OSError if file creation or writing fails
"""
kwargs = {"prefix": prefix, "dir": dir}
if suffix:
kwargs["suffix"] = f".{suffix}"
fd, filepath = tempfile.mkstemp(**kwargs)
try:
with os.fdopen(fd, "w") as f:
f.write(input_data)
except Exception:
os.close(fd)
raise
return filepath
def get_environment_editor(default=None):
"""
Fetches the preferred editor from the environment variables.
This function checks the following environment variables in order to
determine the user's preferred editor:
- VISUAL
- EDITOR
:param default: The default editor to return if no environment variable is set.
:type default: str or None
:return: The preferred editor as specified by environment variables or the default value.
:rtype: str or None
"""
editor = os.environ.get("VISUAL", os.environ.get("EDITOR", default))
return editor
def discover_editor(editor_override=None):
"""
Discovers and returns the appropriate editor command as a list of arguments.
Handles cases where the editor command includes arguments, including quoted arguments
with spaces (e.g. 'vim -c "set noswapfile"').
:return: A list of command parts ready for subprocess execution
:rtype: list[str]
"""
system = platform.system()
if system == "Windows":
default_editor = DEFAULT_EDITOR_WINDOWS
elif system == "Darwin":
default_editor = DEFAULT_EDITOR_OS_X
else:
default_editor = DEFAULT_EDITOR_NIX
if editor_override:
editor = editor_override
else:
editor = get_environment_editor(default_editor)
try:
return shlex.split(editor)
except ValueError as e:
raise RuntimeError(f"Invalid editor command format '{editor}': {e}")
def pipe_editor(input_data="", suffix=None, editor=None):
"""
Opens the system editor with optional input data and returns the edited content.
This function creates a temporary file with the provided input data, opens it in
the system editor, waits for the user to make changes and close the editor, then
reads and returns the modified content. The temporary file is deleted afterwards.
:param input_data: Initial content to populate the editor with
:type input_data: str
:param suffix: Optional file extension for the temporary file (e.g. '.txt', '.md')
:type suffix: str or None
:return: The edited content after the editor is closed
:rtype: str
"""
filepath = write_temp_file(input_data, suffix)
command_parts = discover_editor(editor)
command_parts.append(filepath)
subprocess.call(command_parts)
with open(filepath, "r") as f:
output_data = f.read()
try:
os.remove(filepath)
except PermissionError:
print_status_message(
False,
(
f"WARNING: Unable to delete temporary file {filepath!r}. You may need to delete it"
" manually."
),
)
return output_data

81
aider/exceptions.py Normal file
View File

@@ -0,0 +1,81 @@
from dataclasses import dataclass
@dataclass
class ExInfo:
name: str
retry: bool
description: str
EXCEPTIONS = [
ExInfo("APIConnectionError", True, None),
ExInfo("APIError", True, None),
ExInfo("APIResponseValidationError", True, None),
ExInfo(
"AuthenticationError",
False,
"The API provider is not able to authenticate you. Check your API key.",
),
ExInfo("AzureOpenAIError", True, None),
ExInfo("BadRequestError", False, None),
ExInfo("BudgetExceededError", True, None),
ExInfo(
"ContentPolicyViolationError",
True,
"The API provider has refused the request due to a safety policy about the content.",
),
ExInfo("ContextWindowExceededError", False, None), # special case handled in base_coder
ExInfo("InternalServerError", True, "The API provider's servers are down or overloaded."),
ExInfo("InvalidRequestError", True, None),
ExInfo("JSONSchemaValidationError", True, None),
ExInfo("NotFoundError", False, None),
ExInfo("OpenAIError", True, None),
ExInfo(
"RateLimitError",
True,
"The API provider has rate limited you. Try again later or check your quotas.",
),
ExInfo("RouterRateLimitError", True, None),
ExInfo("ServiceUnavailableError", True, "The API provider's servers are down or overloaded."),
ExInfo("UnprocessableEntityError", True, None),
ExInfo("UnsupportedParamsError", True, None),
ExInfo(
"Timeout",
True,
"The API provider timed out without returning a response. They may be down or overloaded.",
),
]
class LiteLLMExceptions:
exceptions = dict()
def __init__(self):
self._load()
def _load(self, strict=False):
import litellm
for var in dir(litellm):
if not var.endswith("Error"):
continue
ex_info = None
for exi in EXCEPTIONS:
if var == exi.name:
ex_info = exi
break
if strict and not ex_info:
raise ValueError(f"{var} is in litellm but not in aider's exceptions list")
ex = getattr(litellm, var)
self.exceptions[ex] = ex_info
def exceptions_tuple(self):
return tuple(self.exceptions)
def get_ex_info(self, ex):
"""Return the ExInfo for a given exception instance"""
return self.exceptions.get(ex.__class__, ExInfo(None, None, None))

View File

@@ -7,4 +7,5 @@ exclude_website_pats = [
"docs/unified-diffs.md",
"docs/leaderboards/index.md",
"assets/**",
"**/.DS_Store",
]

View File

@@ -1,5 +1,7 @@
import base64
import os
import time
import webbrowser
from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime
@@ -196,6 +198,7 @@ class InputOutput:
editingmode=EditingMode.EMACS,
fancy_input=True,
):
self.placeholder = None
self.never_prompts = set()
self.editingmode = editingmode
no_color = os.environ.get("NO_COLOR")
@@ -332,14 +335,36 @@ class InputOutput:
self.tool_error("Use --encoding to set the unicode encoding.")
return
def write_text(self, filename, content):
def write_text(self, filename, content, max_retries=5, initial_delay=0.1):
"""
Writes content to a file, retrying with progressive backoff if the file is locked.
:param filename: Path to the file to write.
:param content: Content to write to the file.
:param max_retries: Maximum number of retries if a file lock is encountered.
:param initial_delay: Initial delay (in seconds) before the first retry.
"""
if self.dry_run:
return
try:
with open(str(filename), "w", encoding=self.encoding) as f:
f.write(content)
except OSError as err:
self.tool_error(f"Unable to write file {filename}: {err}")
delay = initial_delay
for attempt in range(max_retries):
try:
with open(str(filename), "w", encoding=self.encoding) as f:
f.write(content)
return # Successfully wrote the file
except PermissionError as err:
if attempt < max_retries - 1:
time.sleep(delay)
delay *= 2 # Exponential backoff
else:
self.tool_error(
f"Unable to write file {filename} after {max_retries} attempts: {err}"
)
raise
except OSError as err:
self.tool_error(f"Unable to write file {filename}: {err}")
raise
def rule(self):
if self.pretty:
@@ -403,8 +428,13 @@ class InputOutput:
try:
if self.prompt_session:
# Use placeholder if set, then clear it
default = self.placeholder or ""
self.placeholder = None
line = self.prompt_session.prompt(
show,
default=default,
completer=completer_instance,
reserve_space_for_menu=4,
complete_style=CompleteStyle.MULTI_COLUMN,
@@ -417,13 +447,38 @@ class InputOutput:
self.tool_error(str(err))
return ""
if line and line[0] == "{" and not multiline_input:
multiline_input = True
inp += line[1:] + "\n"
if line.strip("\r\n") and not multiline_input:
stripped = line.strip("\r\n")
if stripped == "{":
multiline_input = True
multiline_tag = None
inp += ""
elif stripped[0] == "{":
# Extract tag if it exists (only alphanumeric chars)
tag = "".join(c for c in stripped[1:] if c.isalnum())
if stripped == "{" + tag:
multiline_input = True
multiline_tag = tag
inp += ""
else:
inp = line
break
else:
inp = line
break
continue
elif line and line[-1] == "}" and multiline_input:
inp += line[:-1] + "\n"
break
elif multiline_input and line.strip():
if multiline_tag:
# Check if line is exactly "tag}"
if line.strip("\r\n") == f"{multiline_tag}}}":
break
else:
inp += line + "\n"
# Check if line is exactly "}"
elif line.strip("\r\n") == "}":
break
else:
inp += line + "\n"
elif multiline_input:
inp += line + "\n"
else:
@@ -439,8 +494,8 @@ class InputOutput:
return
FileHistory(self.input_history_file).append_string(inp)
# Also add to the in-memory history if it exists
if hasattr(self, "session") and hasattr(self.session, "history"):
self.session.history.append_string(inp)
if self.prompt_session and self.prompt_session.history:
self.prompt_session.history.append_string(inp)
def get_input_history(self):
if not self.input_history_file:
@@ -457,14 +512,17 @@ class InputOutput:
log_file.write(f"{role.upper()} {timestamp}\n")
log_file.write(content + "\n")
def display_user_input(self, inp):
if self.pretty and self.user_input_color:
style = dict(style=self.user_input_color)
else:
style = dict()
self.console.print(Text(inp), **style)
def user_input(self, inp, log_only=True):
if not log_only:
if self.pretty and self.user_input_color:
style = dict(style=self.user_input_color)
else:
style = dict()
self.console.print(Text(inp), **style)
self.display_user_input(inp)
prefix = "####"
if inp:
@@ -484,6 +542,15 @@ class InputOutput:
hist = "\n" + content.strip() + "\n\n"
self.append_chat_history(hist)
def offer_url(self, url, prompt="Open URL for more info?", allow_never=True):
"""Offer to open a URL in the browser, returns True if opened."""
if url in self.never_prompts:
return False
if self.confirm_ask(prompt, subject=url, allow_never=allow_never):
webbrowser.open(url)
return True
return False
def confirm_ask(
self,
question,
@@ -678,6 +745,10 @@ class InputOutput:
self.console.print(show_resp)
def set_placeholder(self, placeholder):
"""Set a one-time placeholder text for the next input prompt."""
self.placeholder = placeholder
def print(self, message=""):
print(message)
@@ -722,13 +793,23 @@ class InputOutput:
editable_files = [f for f in sorted(rel_fnames) if f not in rel_read_only_fnames]
if read_only_files:
console.print("Read only files:", style="bold")
console.print(Columns(read_only_files))
files_with_label = ["Readonly:"] + read_only_files
read_only_output = StringIO()
Console(file=read_only_output, force_terminal=False).print(Columns(files_with_label))
read_only_lines = read_only_output.getvalue().splitlines()
console.print(Columns(files_with_label))
if editable_files:
files_with_label = editable_files
if read_only_files:
console.print()
console.print("Editable files:", style="bold")
console.print(Columns(editable_files))
files_with_label = ["Editable:"] + editable_files
editable_output = StringIO()
Console(file=editable_output, force_terminal=False).print(Columns(files_with_label))
editable_lines = editable_output.getvalue().splitlines()
if len(read_only_lines) > 1 or len(editable_lines) > 1:
console.print()
console.print(Columns(files_with_label))
return output.getvalue()

View File

@@ -6,6 +6,7 @@ import sys
import threading
import traceback
import webbrowser
from dataclasses import fields
from pathlib import Path
import git
@@ -17,11 +18,13 @@ from aider import __version__, models, urls, utils
from aider.analytics import Analytics
from aider.args import get_parser
from aider.coders import Coder
from aider.coders.base_coder import UnknownEditFormat
from aider.commands import Commands, SwitchCoder
from aider.format_settings import format_settings, scrub_sensitive_info
from aider.history import ChatSummary
from aider.io import InputOutput
from aider.llm import litellm # noqa: F401; properly init litellm on launch
from aider.models import ModelSettings
from aider.repo import ANY_GIT_ERROR, GitRepo
from aider.report import report_uncaught_exceptions
from aider.versioncheck import check_version, install_from_main_branch, install_upgrade
@@ -88,15 +91,25 @@ def make_new_repo(git_root, io):
def setup_git(git_root, io):
try:
cwd = Path.cwd()
except OSError:
cwd = None
repo = None
if git_root:
repo = git.Repo(git_root)
elif Path.cwd() == Path.home():
try:
repo = git.Repo(git_root)
except ANY_GIT_ERROR:
pass
elif cwd == Path.home():
io.tool_warning("You should probably run aider in a directory, not your home dir.")
return
elif io.confirm_ask("No git repo found, create one to track aider's changes (recommended)?"):
git_root = str(Path.cwd().resolve())
elif cwd and io.confirm_ask(
"No git repo found, create one to track aider's changes (recommended)?"
):
git_root = str(cwd.resolve())
repo = make_new_repo(git_root, io)
if not repo:
@@ -323,14 +336,16 @@ def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"):
def register_litellm_models(git_root, model_metadata_fname, io, verbose=False):
model_metatdata_files = generate_search_path_list(
".aider.model.metadata.json", git_root, model_metadata_fname
)
model_metatdata_files = []
# Add the resource file path
resource_metadata = importlib_resources.files("aider.resources").joinpath("model-metadata.json")
model_metatdata_files.append(str(resource_metadata))
model_metatdata_files += generate_search_path_list(
".aider.model.metadata.json", git_root, model_metadata_fname
)
try:
model_metadata_files_loaded = models.register_litellm_models(model_metatdata_files)
if len(model_metadata_files_loaded) > 0 and verbose:
@@ -367,8 +382,7 @@ def sanity_check_repo(repo, io):
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.")
if io.confirm_ask("Open documentation url for more info?", subject=urls.git_index_version):
webbrowser.open(urls.git_index_version)
io.offer_url(urls.git_index_version, "Open documentation url for more info?")
return False
io.tool_error("Unable to read git repository, it may be corrupt?")
@@ -432,7 +446,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.analytics_disable:
analytics = Analytics(permanently_disable=True)
print("Analytics have been permanently disabled.")
return
if not args.verify_ssl:
import httpx
@@ -496,8 +509,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io.tool_warning("Terminal does not support pretty output (UnicodeDecodeError)")
analytics = Analytics(logfile=args.analytics_log, permanently_disable=args.analytics_disable)
if args.analytics:
if analytics.need_to_ask():
if args.analytics is not False:
if analytics.need_to_ask(args.analytics):
io.tool_output(
"Aider respects your privacy and never collects your code, chat messages, keys or"
" personal info."
@@ -533,7 +546,14 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
all_files = args.files + (args.file or [])
fnames = [str(Path(fn).resolve()) for fn in all_files]
read_only_fnames = [str(Path(fn).resolve()) for fn in (args.read or [])]
read_only_fnames = []
for fn in args.read or []:
path = Path(fn).resolve()
if path.is_dir():
read_only_fnames.extend(str(f) for f in path.rglob("*") if f.is_file())
else:
read_only_fnames.append(str(path))
if len(all_files) > 1:
good = True
for fname in all_files:
@@ -596,7 +616,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)
is_first_run = is_first_run_of_new_version(io, verbose=args.verbose)
check_and_load_imports(io, is_first_run, verbose=args.verbose)
if args.anthropic_api_key:
os.environ["ANTHROPIC_API_KEY"] = args.anthropic_api_key
@@ -615,6 +636,18 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
register_models(git_root, args.model_settings_file, io, verbose=args.verbose)
register_litellm_models(git_root, args.model_metadata_file, io, verbose=args.verbose)
# Process any command line aliases
if args.alias:
for alias_def in args.alias:
# Split on first colon only
parts = alias_def.split(":", 1)
if len(parts) != 2:
io.tool_error(f"Invalid alias format: {alias_def}")
io.tool_output("Format should be: alias:model-name")
return 1
alias, model = parts
models.MODEL_ALIASES[alias.strip()] = model.strip()
if not args.model:
args.model = "gpt-4o-2024-08-06"
if os.environ.get("ANTHROPIC_API_KEY"):
@@ -628,9 +661,15 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
)
if args.verbose:
io.tool_output("Model info:")
io.tool_output("Model metadata:")
io.tool_output(json.dumps(main_model.info, indent=4))
io.tool_output("Model settings:")
for attr in sorted(fields(ModelSettings), key=lambda x: x.name):
val = getattr(main_model, attr.name)
val = json.dumps(val, indent=4)
io.tool_output(f"{attr.name}: {val}")
lint_cmds = parse_lint_cmds(args.lint_cmd, io)
if lint_cmds is None:
return 1
@@ -642,10 +681,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io.tool_output("You can skip this check with --no-show-model-warnings")
try:
if io.confirm_ask(
"Open documentation url for more info?", subject=urls.model_warnings
):
webbrowser.open(urls.model_warnings)
io.offer_url(urls.model_warnings, "Open documentation url for more info?")
io.tool_output()
except KeyboardInterrupt:
return 1
@@ -674,7 +710,13 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
return 1
commands = Commands(
io, None, verify_ssl=args.verify_ssl, args=args, parser=parser, verbose=args.verbose
io,
None,
verify_ssl=args.verify_ssl,
args=args,
parser=parser,
verbose=args.verbose,
editor=args.editor,
)
summarizer = ChatSummary(
@@ -722,7 +764,12 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
num_cache_warming_pings=args.cache_keepalive_pings,
suggest_shell_commands=args.suggest_shell_commands,
chat_language=args.chat_language,
detect_urls=args.detect_urls,
)
except UnknownEditFormat as err:
io.tool_error(str(err))
io.offer_url(urls.edit_formats, "Open documentation about edit formats?")
return 1
except ValueError as err:
io.tool_error(str(err))
return 1
@@ -774,12 +821,28 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
coder.apply_updates()
return
if args.apply_clipboard_edits:
args.edit_format = main_model.editor_edit_format
args.message = "/paste"
if "VSCODE_GIT_IPC_HANDLE" in os.environ:
args.pretty = False
io.tool_output("VSCode terminal detected, pretty output has been disabled.")
io.tool_output('Use /help <question> for help, run "aider --help" to see cmd line args')
if args.show_release_notes is True:
io.tool_output(f"Opening release notes: {urls.release_notes}")
io.tool_output()
webbrowser.open(urls.release_notes)
elif args.show_release_notes is None and is_first_run:
io.tool_output()
io.offer_url(
urls.release_notes,
"Would you like to see what's new in this version?",
allow_never=False,
)
if git_root and Path.cwd().resolve() != Path(git_root).resolve():
io.tool_warning(
"Note: in-chat filenames are always relative to the git working dir, not the current"
@@ -835,7 +898,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
coder.show_announcements()
def check_and_load_imports(io, verbose=False):
def is_first_run_of_new_version(io, verbose=False):
"""Check if this is the first run of a new version/executable combination"""
installs_file = Path.home() / ".aider" / "installs.json"
key = (__version__, sys.executable)
@@ -856,7 +920,26 @@ def check_and_load_imports(io, verbose=False):
if verbose:
io.tool_output("Installs file does not exist, creating new dictionary")
if str(key) not in installs:
is_first_run = str(key) not in installs
if is_first_run:
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)
return is_first_run
except Exception as e:
io.tool_warning(f"Error checking version: {e}")
if verbose:
io.tool_output(f"Full exception details: {traceback.format_exc()}")
return True # Safer to assume it's a first run if we hit an error
def check_and_load_imports(io, is_first_run, verbose=False):
try:
if is_first_run:
if verbose:
io.tool_output(
"First run for this version and executable, loading imports synchronously"
@@ -866,17 +949,9 @@ def check_and_load_imports(io, verbose=False):
except Exception as err:
io.tool_error(str(err))
io.tool_output("Error loading required imports. Did you install aider properly?")
if io.confirm_ask(
"Open documentation url for more info?", subject=urls.install_properly
):
webbrowser.open(urls.install_properly)
io.offer_url(urls.install_properly, "Open documentation url for more info?")
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:
@@ -885,8 +960,9 @@ def check_and_load_imports(io, verbose=False):
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}")
io.tool_warning(f"Error in loading imports: {e}")
if verbose:
io.tool_output(f"Full exception details: {traceback.format_exc()}")

View File

@@ -52,6 +52,7 @@ ANTHROPIC_MODELS = """
claude-2
claude-2.1
claude-3-haiku-20240307
claude-3-5-haiku-20241022
claude-3-opus-20240229
claude-3-sonnet-20240229
claude-3-5-sonnet-20240620
@@ -60,6 +61,23 @@ claude-3-5-sonnet-20241022
ANTHROPIC_MODELS = [ln.strip() for ln in ANTHROPIC_MODELS.splitlines() if ln.strip()]
# Mapping of model aliases to their canonical names
MODEL_ALIASES = {
# Claude models
"sonnet": "claude-3-sonnet-20241022",
"haiku": "claude-3-haiku-20241022",
"opus": "claude-3-opus-20240229",
# GPT models
"4": "gpt-4-0613",
"4o": "gpt-4o-2024-08-06",
"4-turbo": "gpt-4-1106-preview",
"35turbo": "gpt-3.5-turbo",
"35-turbo": "gpt-3.5-turbo",
"3": "gpt-3.5-turbo",
# Other models
"deepseek": "deepseek/deepseek-coder",
}
@dataclass
class ModelSettings:
@@ -160,6 +178,22 @@ MODEL_SETTINGS = [
lazy=True,
reminder="sys",
),
ModelSettings(
"gpt-4o-2024-11-20",
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
lazy=True,
reminder="sys",
),
ModelSettings(
"openai/gpt-4o-2024-11-20",
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
lazy=True,
reminder="sys",
),
ModelSettings(
"gpt-4o",
"diff",
@@ -233,24 +267,24 @@ MODEL_SETTINGS = [
ModelSettings(
"claude-3-opus-20240229",
"diff",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="claude-3-5-haiku-20241022",
use_repo_map=True,
),
ModelSettings(
"openrouter/anthropic/claude-3-opus",
"diff",
weak_model_name="openrouter/anthropic/claude-3-haiku",
weak_model_name="openrouter/anthropic/claude-3-5-haiku",
use_repo_map=True,
),
ModelSettings(
"claude-3-sonnet-20240229",
"whole",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="claude-3-5-haiku-20241022",
),
ModelSettings(
"claude-3-5-sonnet-20240620",
"diff",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="claude-3-5-haiku-20241022",
editor_model_name="claude-3-5-sonnet-20240620",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -267,7 +301,7 @@ MODEL_SETTINGS = [
ModelSettings(
"anthropic/claude-3-5-sonnet-20240620",
"diff",
weak_model_name="anthropic/claude-3-haiku-20240307",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
editor_model_name="anthropic/claude-3-5-sonnet-20240620",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -284,7 +318,7 @@ MODEL_SETTINGS = [
ModelSettings(
"anthropic/claude-3-5-sonnet-20241022",
"diff",
weak_model_name="anthropic/claude-3-haiku-20240307",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
editor_model_name="anthropic/claude-3-5-sonnet-20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -298,10 +332,27 @@ MODEL_SETTINGS = [
cache_control=True,
reminder="user",
),
ModelSettings(
"bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
"diff",
weak_model_name="bedrock/anthropic.claude-3-5-haiku-20241022-v1:0",
editor_model_name="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
"max_tokens": 8192,
},
cache_control=True,
reminder="user",
),
ModelSettings(
"anthropic/claude-3-5-sonnet-latest",
"diff",
weak_model_name="anthropic/claude-3-haiku-20240307",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
editor_model_name="anthropic/claude-3-5-sonnet-20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -318,7 +369,7 @@ MODEL_SETTINGS = [
ModelSettings(
"claude-3-5-sonnet-20241022",
"diff",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="claude-3-5-haiku-20241022",
editor_model_name="claude-3-5-sonnet-20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -344,6 +395,52 @@ MODEL_SETTINGS = [
},
cache_control=True,
),
ModelSettings(
"anthropic/claude-3-5-haiku-20241022",
"diff",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
use_repo_map=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
},
cache_control=True,
),
ModelSettings(
"bedrock/anthropic.claude-3-5-haiku-20241022-v1:0",
"diff",
weak_model_name="bedrock/anthropic.claude-3-5-haiku-20241022-v1:0",
use_repo_map=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
},
cache_control=True,
),
ModelSettings(
"claude-3-5-haiku-20241022",
"diff",
weak_model_name="claude-3-5-haiku-20241022",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
},
cache_control=True,
),
ModelSettings(
"vertex_ai/claude-3-5-haiku@20241022",
"diff",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
use_repo_map=True,
extra_params={
"max_tokens": 4096,
},
),
ModelSettings(
"claude-3-haiku-20240307",
"whole",
@@ -359,7 +456,7 @@ MODEL_SETTINGS = [
ModelSettings(
"openrouter/anthropic/claude-3.5-sonnet",
"diff",
weak_model_name="openrouter/anthropic/claude-3-haiku",
weak_model_name="openrouter/anthropic/claude-3-5-haiku",
editor_model_name="openrouter/anthropic/claude-3.5-sonnet",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -373,7 +470,7 @@ MODEL_SETTINGS = [
ModelSettings(
"openrouter/anthropic/claude-3.5-sonnet:beta",
"diff",
weak_model_name="openrouter/anthropic/claude-3-haiku:beta",
weak_model_name="openrouter/anthropic/claude-3-5-haiku:beta",
editor_model_name="openrouter/anthropic/claude-3.5-sonnet:beta",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -389,7 +486,7 @@ MODEL_SETTINGS = [
ModelSettings(
"vertex_ai/claude-3-5-sonnet@20240620",
"diff",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
editor_model_name="vertex_ai/claude-3-5-sonnet@20240620",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -402,7 +499,7 @@ MODEL_SETTINGS = [
ModelSettings(
"vertex_ai/claude-3-5-sonnet-v2@20241022",
"diff",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
editor_model_name="vertex_ai/claude-3-5-sonnet-v2@20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -415,13 +512,13 @@ MODEL_SETTINGS = [
ModelSettings(
"vertex_ai/claude-3-opus@20240229",
"diff",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
use_repo_map=True,
),
ModelSettings(
"vertex_ai/claude-3-sonnet@20240229",
"whole",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
),
# Cohere
ModelSettings(
@@ -486,6 +583,11 @@ MODEL_SETTINGS = [
"diff-fenced",
use_repo_map=True,
),
ModelSettings(
"vertex_ai/gemini-pro-experimental",
"diff-fenced",
use_repo_map=True,
),
ModelSettings(
"gemini/gemini-1.5-flash-exp-0827",
"whole",
@@ -560,7 +662,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"azure/o1-mini",
@@ -572,7 +673,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"o1-mini",
@@ -584,7 +684,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openai/o1-preview",
@@ -596,7 +695,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"azure/o1-preview",
@@ -608,7 +706,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"o1-preview",
@@ -620,7 +717,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/openai/o1-mini",
@@ -646,6 +742,14 @@ MODEL_SETTINGS = [
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/qwen/qwen-2.5-coder-32b-instruct",
"diff",
weak_model_name="openrouter/qwen/qwen-2.5-coder-32b-instruct",
editor_model_name="openrouter/qwen/qwen-2.5-coder-32b-instruct",
editor_edit_format="editor-diff",
use_repo_map=True,
),
]
@@ -685,6 +789,11 @@ class ModelInfoManager:
pass
except Exception as ex:
print(str(ex))
try:
# Save empty dict to cache file on failure
self.cache_file.write_text("{}")
except OSError:
pass
def get_model_from_cached_json_db(self, model):
if not self.content:
@@ -706,16 +815,20 @@ class ModelInfoManager:
return dict()
def get_model_info(self, model):
if not litellm._lazy_module:
info = self.get_model_from_cached_json_db(model)
if info:
return info
cached_info = self.get_model_from_cached_json_db(model)
# If all else fails, do it the slow way...
try:
return litellm.get_model_info(model)
except Exception:
return dict()
litellm_info = None
if litellm._lazy_module or not cached_info:
try:
litellm_info = litellm.get_model_info(model)
except Exception as ex:
if "model_prices_and_context_window.json" not in str(ex):
print(str(ex))
if litellm_info:
return litellm_info
return cached_info
model_info_manager = ModelInfoManager()
@@ -723,11 +836,17 @@ model_info_manager = ModelInfoManager()
class Model(ModelSettings):
def __init__(self, model, weak_model=None, editor_model=None, editor_edit_format=None):
self.name = model
# Map any alias to its canonical name
self.name = MODEL_ALIASES.get(model, model)
self.max_chat_history_tokens = 1024
self.weak_model = None
self.editor_model = None
# Find the extra settings
self.extra_model_settings = next(
(ms for ms in MODEL_SETTINGS if ms.name == "aider/extra_params"), None
)
self.info = self.get_model_info(model)
# Are all needed keys/params available?
@@ -755,17 +874,44 @@ class Model(ModelSettings):
def get_model_info(self, model):
return model_info_manager.get_model_info(model)
def _copy_fields(self, source):
"""Helper to copy fields from a ModelSettings instance to self"""
for field in fields(ModelSettings):
val = getattr(source, field.name)
setattr(self, field.name, val)
def configure_model_settings(self, model):
# Look for exact model match
exact_match = False
for ms in MODEL_SETTINGS:
# direct match, or match "provider/<model>"
if model == ms.name:
for field in fields(ModelSettings):
val = getattr(ms, field.name)
setattr(self, field.name, val)
return # <--
self._copy_fields(ms)
exact_match = True
break # Continue to apply overrides
model = model.lower()
# If no exact match, try generic settings
if not exact_match:
self.apply_generic_model_settings(model)
# Apply override settings last if they exist
if self.extra_model_settings and self.extra_model_settings.extra_params:
# Initialize extra_params if it doesn't exist
if not self.extra_params:
self.extra_params = {}
# Deep merge the extra_params dicts
for key, value in self.extra_model_settings.extra_params.items():
if isinstance(value, dict) and isinstance(self.extra_params.get(key), dict):
# For nested dicts, merge recursively
self.extra_params[key] = {**self.extra_params[key], **value}
else:
# For non-dict values, simply update
self.extra_params[key] = value
def apply_generic_model_settings(self, model):
if ("llama3" in model or "llama-3" in model) and "70b" in model:
self.edit_format = "diff"
self.use_repo_map = True
@@ -787,21 +933,37 @@ class Model(ModelSettings):
if "gpt-3.5" in model or "gpt-4" in model:
self.reminder = "sys"
return # <--
if "3.5-sonnet" in model or "3-5-sonnet" in model:
self.edit_format = "diff"
self.use_repo_map = True
self.examples_as_sys_msg = True
self.reminder = "user"
return # <--
if model.startswith("o1-") or "/o1-" in model:
self.use_system_prompt = False
self.use_temperature = False
self.streaming = False
return # <--
if (
"qwen" in model
and "coder" in model
and ("2.5" in model or "2-5" in model)
and "32b" in model
):
self.edit_format = "diff"
self.editor_edit_format = "editor-diff"
self.use_repo_map = True
if model.startswith("ollama/") or model.startswith("ollama_chat/"):
self.extra_params = dict(num_ctx=8 * 1024)
return # <--
# use the defaults
if self.edit_format == "diff":
self.use_repo_map = True
return # <--
def __str__(self):
return self.name
@@ -958,6 +1120,9 @@ def register_models(model_settings_fnames):
if not os.path.exists(model_settings_fname):
continue
if not Path(model_settings_fname).read_text().strip():
continue
try:
with open(model_settings_fname, "r") as model_settings_file:
model_settings_list = yaml.safe_load(model_settings_file)
@@ -985,8 +1150,14 @@ def register_litellm_models(model_fnames):
continue
try:
with open(model_fname, "r") as model_def_file:
model_def = json5.load(model_def_file)
data = Path(model_fname).read_text()
if not data.strip():
continue
model_def = json5.loads(data)
if not model_def:
continue
# only load litellm if we have actual data
litellm._load_litellm()
litellm.register_model(model_def)
except Exception as e:
@@ -1069,7 +1240,10 @@ def fuzzy_match_models(name):
model = model.lower()
if attrs.get("mode") != "chat":
continue
provider = (attrs["litellm_provider"] + "/").lower()
provider = attrs.get("litellm_provider", "").lower()
if not provider:
continue
provider += "/"
if model.startswith(provider):
fq_model = model

View File

@@ -0,0 +1,91 @@
(class_definition
name: (identifier) @name.definition.class) @definition.class
(method_signature
(function_signature)) @definition.method
(type_alias
(type_identifier) @name.definition.type) @definition.type
(method_signature
(getter_signature
name: (identifier) @name.definition.method)) @definition.method
(method_signature
(setter_signature
name: (identifier) @name.definition.method)) @definition.method
(method_signature
(function_signature
name: (identifier) @name.definition.method)) @definition.method
(method_signature
(factory_constructor_signature
(identifier) @name.definition.method)) @definition.method
(method_signature
(constructor_signature
name: (identifier) @name.definition.method)) @definition.method
(method_signature
(operator_signature)) @definition.method
(method_signature) @definition.method
(mixin_declaration
(mixin)
(identifier) @name.definition.mixin) @definition.mixin
(extension_declaration
name: (identifier) @name.definition.extension) @definition.extension
(enum_declaration
name: (identifier) @name.definition.enum) @definition.enum
(function_signature
name: (identifier) @name.definition.function) @definition.function
(new_expression
(type_identifier) @name.reference.class) @reference.class
(initialized_variable_definition
name: (identifier)
value: (identifier) @name.reference.class
value: (selector
"!"?
(argument_part
(arguments
(argument)*))?)?) @reference.class
(assignment_expression
left: (assignable_expression
(identifier)
(unconditional_assignable_selector
"."
(identifier) @name.reference.call))) @reference.call
(assignment_expression
left: (assignable_expression
(identifier)
(conditional_assignable_selector
"?."
(identifier) @name.reference.call))) @reference.call
((identifier) @name
(selector
"!"?
(conditional_assignable_selector
"?." (identifier) @name.reference.call)?
(unconditional_assignable_selector
"."? (identifier) @name.reference.call)?
(argument_part
(arguments
(argument)*))?)*
(cascade_section
(cascade_selector
(identifier)) @name.reference.call
(argument_part
(arguments
(argument)*))?)?) @reference.call

View File

@@ -169,7 +169,7 @@ class GitRepo:
def get_rel_repo_dir(self):
try:
return os.path.relpath(self.repo.git_dir, os.getcwd())
except ValueError:
except (ValueError, OSError):
return self.repo.git_dir
def get_commit_message(self, diffs, context):
@@ -331,6 +331,15 @@ class GitRepo:
lines,
)
def git_ignored_file(self, path):
if not self.repo:
return
try:
if self.repo.ignored(path):
return True
except ANY_GIT_ERROR:
return False
def ignored_file(self, fname):
self.refresh_aider_ignore()

View File

@@ -28,7 +28,7 @@ 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)
SQLITE_ERRORS = (sqlite3.OperationalError, sqlite3.DatabaseError, OSError)
class RepoMap:
@@ -197,7 +197,7 @@ class RepoMap:
self.TAGS_CACHE = new_cache
return
except (SQLITE_ERRORS, OSError) as e:
except SQLITE_ERRORS as e:
# If anything goes wrong, warn and fall back to dict
self.io.tool_warning(
f"Unable to use tags cache at {path}, falling back to memory cache"
@@ -368,6 +368,8 @@ class RepoMap:
showing_bar = False
for fname in fnames:
if self.verbose:
self.io.tool_output(f"Processing {fname}")
if progress and not showing_bar:
progress()

View File

View File

@@ -2,9 +2,8 @@ import hashlib
import json
import time
import backoff
from aider.dump import dump # noqa: F401
from aider.exceptions import LiteLLMExceptions
from aider.llm import litellm
# from diskcache import Cache
@@ -17,52 +16,6 @@ CACHE = None
RETRY_TIMEOUT = 60
def retry_exceptions():
import httpx
import openai
return (
# httpx
httpx.ConnectError,
httpx.RemoteProtocolError,
httpx.ReadTimeout,
#
# litellm exceptions inherit from openai exceptions
# https://docs.litellm.ai/docs/exception_mapping
#
# openai.BadRequestError,
# litellm.ContextWindowExceededError,
# litellm.ContentPolicyViolationError,
#
# openai.AuthenticationError,
# openai.PermissionDeniedError,
# openai.NotFoundError,
#
openai.APITimeoutError,
openai.UnprocessableEntityError,
openai.RateLimitError,
openai.APIConnectionError,
# openai.APIError,
# openai.APIStatusError,
openai.InternalServerError,
)
def lazy_litellm_retry_decorator(func):
def wrapper(*args, **kwargs):
decorated_func = backoff.on_exception(
backoff.expo,
retry_exceptions(),
max_time=RETRY_TIMEOUT,
on_backoff=lambda details: print(
f"{details.get('exception', 'Exception')}\nRetry in {details['wait']:.1f} seconds."
),
)(func)
return decorated_func(*args, **kwargs)
return wrapper
def send_completion(
model_name,
messages,
@@ -104,6 +57,8 @@ def send_completion(
def simple_send_with_retries(model_name, messages, extra_params=None):
litellm_ex = LiteLLMExceptions()
retry_delay = 0.125
while True:
try:
@@ -116,14 +71,27 @@ def simple_send_with_retries(model_name, messages, extra_params=None):
}
_hash, response = send_completion(**kwargs)
if not response or not hasattr(response, "choices") or not response.choices:
return None
return response.choices[0].message.content
except retry_exceptions() as err:
except litellm_ex.exceptions_tuple() as err:
ex_info = litellm_ex.get_ex_info(err)
print(str(err))
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
break
if ex_info.description:
print(ex_info.description)
should_retry = ex_info.retry
if should_retry:
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
should_retry = False
if not should_retry:
return None
print(f"Retrying in {retry_delay:.1f} seconds...")
time.sleep(retry_delay)
continue
except AttributeError:
return
return None

View File

@@ -12,3 +12,5 @@ github_issues = "https://github.com/Aider-AI/aider/issues/new"
git_index_version = "https://github.com/Aider-AI/aider/issues/211"
install_properly = "https://aider.chat/docs/troubleshooting/imports.html"
analytics = "https://aider.chat/docs/more/analytics.html"
release_notes = "https://aider.chat/HISTORY.html#release-notes"
edit_formats = "https://aider.chat/docs/more/edit-formats.html"

View File

@@ -10,6 +10,12 @@ description: Release notes and stats on aider writing its own code.
{% include blame.md %}
The above
[stats are based on the git commit history](/docs/faq.html#how-are-the-aider-wrote-xx-of-code-stats-computed)
of the aider repo.
## Release notes
<!--[[[cog
# This page is a copy of HISTORY.md, adding the front matter above.
text = open("HISTORY.md").read()
@@ -18,9 +24,83 @@ cog.out(text)
]]]-->
### main branch
- Added `--alias` config to define [custom model aliases](https://aider.chat/docs/config/model-aliases.html).
- Added `--[no-]detect-urls` flag to disable detecting and offering to scrape URLs found in the chat.
- Ollama models now default to an 8k context window.
- Added [RepoMap support for Dart language](https://aider.chat/docs/languages.html) by @malkoG.
- Ask 2.5% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
- Skip suggesting files that share names with files already in chat.
- `/editor` returns and prefill the file content into the prompt, so you can use `/editor` to compose messages that start with `/commands`, etc.
- Enhanced error handling for analytics.
- Improved handling of UnknownEditFormat exceptions with helpful documentation links.
- Bumped dependencies to pick up grep-ast 0.4.0 for Dart language support.
- Aider wrote 81% of the code in this release.
### Aider v0.64.1
- Disable streaming for o1 on OpenRouter.
### Aider v0.64.0
- Added [`/editor` command](https://aider.chat/docs/usage/commands.html) to open system editor for writing prompts, by @thehunmonkgroup.
- Full support for `gpt-4o-2024-11-20`.
- Stream o1 models by default.
- `/run` and suggested shell commands are less mysterious and now confirm that they "Added XX lines of output to the chat."
- Ask 1% of users if they want to opt-in to [analytics](https://aider.chat/docs/more/analytics.html).
- Added support for [optional multiline input tags](https://aider.chat/docs/usage/commands.html#entering-multi-line-chat-messages) with matching closing tags.
- Improved [model settings configuration](https://aider.chat/docs/config/adv-model-settings.html#global-extra-params) with support for global `extra_params` for `litellm.completion()`.
- Architect mode now asks to add files suggested by the LLM.
- Fixed bug in fuzzy model name matching.
- Added Timeout exception to handle API provider timeouts.
- Added `--show-release-notes` to control release notes display on first run of new version.
- Save empty dict to cache file on model metadata download failure, to delay retry.
- Improved error handling and code formatting.
- Aider wrote 74% of the code in this release.
### Aider v0.63.2
- Fixed bug in fuzzy model name matching when litellm provider info is missing.
- Modified model metadata file loading to allow override of resource file.
- Allow recursive loading of dirs using `--read`.
- Updated dependency versions to pick up litellm fix for ollama models.
- Added exponential backoff retry when writing files to handle editor file locks.
- Updated Qwen 2.5 Coder 32B model configuration.
### Aider v0.63.1
- Fixed bug in git ignored file handling.
- Improved error handling for git operations.
### Aider v0.63.0
- Support for Qwen 2.5 Coder 32B.
- `/web` command just adds the page to the chat, without triggering an LLM response.
- Improved prompting for the user's preferred chat language.
- Improved handling of LiteLLM exceptions.
- Bugfix for double-counting tokens when reporting cache stats.
- Bugfix for the LLM creating new files.
- Other small bug fixes.
- Aider wrote 55% of the code in this release.
### Aider v0.62.0
- Full support for Claude 3.5 Haiku
- Scored 75% on [aider's code editing leaderboard](https://aider.chat/docs/leaderboards/).
- Almost as good as Sonnet at much lower cost.
- Launch with `--haiku` to use it.
- Easily apply file edits from ChatGPT, Claude or other web apps
- Chat with ChatGPT or Claude via their web app.
- Give it your source files and ask for the changes you want.
- Use the web app's "copy response" button to copy the entire reply from the LLM.
- Run `aider --apply-clipboard-edits file-to-edit.js`.
- Aider will edit your file with the LLM's changes.
- Bugfix for creating new files.
- Aider wrote 84% of the code in this release.
### Aider v0.61.0
- Load and save aider slash-commands to files:
- `/save <fname>` command will make a file of `/add` and `/read-only` commands that recreate the current file context in the chat.
- `/load <fname>` will replay the commands in the file.

View File

@@ -1801,8 +1801,8 @@
Paul Gauthier (aider): 113
start_tag: v0.44.0
total_lines: 266
- aider_percentage: 47.04
aider_total: 254
- aider_percentage: 53.3
aider_total: 339
end_date: '2024-07-29'
end_tag: v0.46.0
file_counts:
@@ -1853,6 +1853,9 @@
aider/scrape.py:
Paul Gauthier: 3
Paul Gauthier (aider): 32
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 11
Paul Gauthier (aider): 85
benchmark/Dockerfile:
Your Name: 1
tests/basic/test_coder.py:
@@ -1868,13 +1871,13 @@
Paul Gauthier (aider): 73
grand_total:
Charles Joachim: 4
Paul Gauthier: 209
Paul Gauthier (aider): 204
Paul Gauthier: 220
Paul Gauthier (aider): 289
Your Name: 73
Your Name (aider): 50
start_tag: v0.45.0
total_lines: 540
- aider_percentage: 59.12
total_lines: 636
- aider_percentage: 57.16
aider_total: 415
end_date: '2024-07-31'
end_tag: v0.47.0
@@ -1920,6 +1923,8 @@
Paul Gauthier (aider): 2
aider/utils.py:
Paul Gauthier: 7
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 24
docker/Dockerfile:
Paul Gauthier: 19
Paul Gauthier (aider): 21
@@ -1944,10 +1949,10 @@
tests/basic/test_repomap.py:
Paul Gauthier: 1
grand_total:
Paul Gauthier: 287
Paul Gauthier: 311
Paul Gauthier (aider): 415
start_tag: v0.46.0
total_lines: 702
total_lines: 726
- aider_percentage: 44.44
aider_total: 276
end_date: '2024-08-06'
@@ -2011,8 +2016,8 @@
paul-gauthier: 1
start_tag: v0.47.0
total_lines: 621
- aider_percentage: 61.52
aider_total: 478
- aider_percentage: 61.2
aider_total: 489
end_date: '2024-08-10'
end_tag: v0.49.0
file_counts:
@@ -2055,6 +2060,9 @@
aider/versioncheck.py:
Paul Gauthier: 3
Paul Gauthier (aider): 11
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 11
Paul Gauthier (aider): 11
docker/Dockerfile:
Paul Gauthier: 5
Paul Gauthier (aider): 2
@@ -2075,10 +2083,10 @@
Paul Gauthier: 1
Paul Gauthier (aider): 49
grand_total:
Paul Gauthier: 299
Paul Gauthier (aider): 478
Paul Gauthier: 310
Paul Gauthier (aider): 489
start_tag: v0.48.0
total_lines: 777
total_lines: 799
- aider_percentage: 66.05
aider_total: 214
end_date: '2024-08-13'
@@ -2135,8 +2143,8 @@
Paul Gauthier (aider): 201
start_tag: v0.49.0
total_lines: 324
- aider_percentage: 56.25
aider_total: 450
- aider_percentage: 52.49
aider_total: 580
end_date: '2024-08-20'
end_tag: v0.51.0
file_counts:
@@ -2170,6 +2178,14 @@
Paul Gauthier: 3
aider/utils.py:
Paul Gauthier (aider): 6
aider/website/_includes/code-in-json-benchmark.js:
Paul Gauthier: 101
Paul Gauthier (aider): 64
aider/website/_includes/code-in-json-syntax.js:
Paul Gauthier: 73
Paul Gauthier (aider): 66
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
benchmark/benchmark.py:
Paul Gauthier: 7
benchmark/over_time.py:
@@ -2188,11 +2204,11 @@
Paul Gauthier: 15
Paul Gauthier (aider): 104
grand_total:
Paul Gauthier: 350
Paul Gauthier (aider): 450
Paul Gauthier: 525
Paul Gauthier (aider): 580
start_tag: v0.50.0
total_lines: 800
- aider_percentage: 68.19
total_lines: 1105
- aider_percentage: 68.1
aider_total: 521
end_date: '2024-08-23'
end_tag: v0.52.0
@@ -2231,6 +2247,8 @@
Paul Gauthier (aider): 9
aider/versioncheck.py:
Paul Gauthier: 2
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
benchmark/benchmark.py:
Paul Gauthier: 1
scripts/blame.py:
@@ -2250,13 +2268,13 @@
tests/basic/test_wholefile.py:
Paul Gauthier: 8
grand_total:
Paul Gauthier: 242
Paul Gauthier: 243
Paul Gauthier (aider): 521
pcamp: 1
start_tag: v0.51.0
total_lines: 764
- aider_percentage: 58.61
aider_total: 405
total_lines: 765
- aider_percentage: 61.4
aider_total: 455
end_date: '2024-08-27'
end_tag: v0.53.0
file_counts:
@@ -2321,14 +2339,16 @@
tests/basic/test_repomap.py:
Paul Gauthier: 4
Paul Gauthier (aider): 63
tests/fixtures/sample-code-base/sample.js:
Paul Gauthier (aider): 50
tests/fixtures/sample-code-base/sample.py:
Paul Gauthier (aider): 68
grand_total:
Paul Gauthier: 286
Paul Gauthier (aider): 405
Paul Gauthier (aider): 455
start_tag: v0.52.0
total_lines: 691
- aider_percentage: 63.95
total_lines: 741
- aider_percentage: 63.75
aider_total: 204
end_date: '2024-08-28'
end_tag: v0.54.0
@@ -2364,6 +2384,8 @@
aider/versioncheck.py:
Paul Gauthier: 1
Paul Gauthier (aider): 13
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
tests/basic/test_coder.py:
Paul Gauthier: 36
Paul Gauthier (aider): 27
@@ -2376,11 +2398,11 @@
Paul Gauthier: 1
grand_total:
Antti Kaihola: 4
Paul Gauthier: 111
Paul Gauthier: 112
Paul Gauthier (aider): 204
start_tag: v0.53.0
total_lines: 319
- aider_percentage: 52.9
total_lines: 320
- aider_percentage: 52.87
aider_total: 811
end_date: '2024-09-04'
end_tag: v0.55.0
@@ -2450,6 +2472,8 @@
aider/voice.py:
Paul Gauthier: 7
Paul Gauthier (aider): 9
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
scripts/versionbump.py:
Paul Gauthier: 9
tests/basic/test_coder.py:
@@ -2478,11 +2502,11 @@
grand_total:
Antti Kaihola: 12
Nikolay Sedelnikov: 45
Paul Gauthier: 665
Paul Gauthier: 666
Paul Gauthier (aider): 811
start_tag: v0.54.0
total_lines: 1533
- aider_percentage: 55.6
total_lines: 1534
- aider_percentage: 55.4
aider_total: 154
end_date: '2024-09-09'
end_tag: v0.56.0
@@ -2517,6 +2541,8 @@
aider/report.py:
Paul Gauthier: 2
Paul Gauthier (aider): 20
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
benchmark/benchmark.py:
Paul Gauthier: 1
tests/basic/test_linter.py:
@@ -2526,13 +2552,13 @@
Paul Gauthier: 2
Paul Gauthier (aider): 9
grand_total:
Paul Gauthier: 108
Paul Gauthier: 109
Paul Gauthier (aider): 154
fry69: 15
start_tag: v0.55.0
total_lines: 277
- aider_percentage: 69.98
aider_total: 394
total_lines: 278
- aider_percentage: 70.36
aider_total: 406
end_date: '2024-09-21'
end_tag: v0.57.0
file_counts:
@@ -2575,6 +2601,10 @@
Paul Gauthier: 3
aider/utils.py:
Paul Gauthier: 2
aider/website/docs/leaderboards/index.md:
Anjor Kanekar: 1
Paul Gauthier: 1
Paul Gauthier (aider): 12
benchmark/benchmark.py:
Paul Gauthier: 4
scripts/issues.py:
@@ -2592,15 +2622,16 @@
Paul Gauthier: 18
Paul Gauthier (aider): 20
grand_total:
Anjor Kanekar: 1
Christian Clauss: 2
Jay Alammar: 1
Jay Alammar (aider): 13
Krazer: 33
Paul Gauthier: 133
Paul Gauthier (aider): 381
Paul Gauthier: 134
Paul Gauthier (aider): 393
start_tag: v0.56.0
total_lines: 563
- aider_percentage: 53.45
total_lines: 577
- aider_percentage: 47.95
aider_total: 712
end_date: '2024-09-29'
end_tag: v0.58.0
@@ -2677,6 +2708,8 @@
Mike Bailey: 17
Paul Gauthier: 2
Paul Gauthier (aider): 10
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 153
benchmark/benchmark.py:
Paul Gauthier: 25
Paul Gauthier (aider): 29
@@ -2705,14 +2738,14 @@
grand_total:
Jonathan Ellis: 2
Mike Bailey: 18
Paul Gauthier: 376
Paul Gauthier: 529
Paul Gauthier (aider): 712
Stein Martin Hustad: 26
fry69: 197
rti: 1
start_tag: v0.57.0
total_lines: 1332
- aider_percentage: 76.79
total_lines: 1485
- aider_percentage: 75.44
aider_total: 172
end_date: '2024-10-04'
end_tag: v0.59.0
@@ -2747,6 +2780,8 @@
Paul Gauthier: 2
aider/versioncheck.py:
Paul Gauthier: 1
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 4
scripts/issues.py:
Paul Gauthier: 1
scripts/update-docs.sh:
@@ -2762,11 +2797,11 @@
tests/help/test_help.py:
Paul Gauthier: 1
grand_total:
Paul Gauthier: 52
Paul Gauthier: 56
Paul Gauthier (aider): 172
start_tag: v0.58.0
total_lines: 224
- aider_percentage: 49.12
total_lines: 228
- aider_percentage: 48.95
aider_total: 140
end_date: '2024-10-22'
end_tag: v0.60.0
@@ -2804,6 +2839,8 @@
Paul Gauthier: 3
aider/sendchat.py:
Paul Gauthier: 3
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
tests/basic/test_editblock.py:
Paul Gauthier: 23
tests/basic/test_main.py:
@@ -2813,9 +2850,259 @@
Paul Gauthier (aider): 46
grand_total:
Jonathan Ellis: 10
Paul Gauthier: 93
Paul Gauthier: 94
Paul Gauthier (aider): 140
Sven Grunewaldt: 24
fry69: 18
start_tag: v0.59.0
total_lines: 285
total_lines: 286
- aider_percentage: 67.61
aider_total: 860
end_date: '2024-11-01'
end_tag: v0.61.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/analytics.py:
Paul Gauthier: 75
Paul Gauthier (aider): 89
aider/args.py:
Paul Gauthier: 5
Paul Gauthier (aider): 29
aider/coders/base_coder.py:
Paul Gauthier: 56
Paul Gauthier (aider): 43
aider/coders/editblock_coder.py:
Paul Gauthier: 14
aider/commands.py:
Paul Gauthier: 14
Paul Gauthier (aider): 86
aider/io.py:
Paul Gauthier: 12
Paul Gauthier (aider): 32
aider/linter.py:
Paul Gauthier: 6
aider/main.py:
Paul Gauthier: 48
Paul Gauthier (aider): 10
aider/models.py:
Paul Gauthier: 54
Paul Gauthier (aider): 63
kAIto47802: 4
aider/repomap.py:
Paul Gauthier: 12
Paul Gauthier (aider): 52
aider/sendchat.py:
Paul Gauthier: 23
Paul Gauthier (aider): 23
aider/urls.py:
Paul Gauthier: 2
aider/utils.py:
Paul Gauthier (aider): 6
scripts/issues.py:
Paul Gauthier (aider): 13
scripts/pip-compile.sh:
Paul Gauthier (aider): 13
scripts/update-docs.sh:
Paul Gauthier: 1
Paul Gauthier (aider): 5
tests/basic/test_analytics.py:
Paul Gauthier: 1
Paul Gauthier (aider): 99
tests/basic/test_commands.py:
Konstantin L: 34
Paul Gauthier: 45
Paul Gauthier (aider): 267
tests/basic/test_io.py:
Paul Gauthier: 2
Paul Gauthier (aider): 4
tests/basic/test_main.py:
Paul Gauthier (aider): 3
tests/basic/test_models.py:
Paul Gauthier: 3
Paul Gauthier (aider): 9
tests/basic/test_sanity_check_repo.py:
Paul Gauthier (aider): 6
tests/basic/test_sendchat.py:
Paul Gauthier (aider): 8
grand_total:
Konstantin L: 34
Paul Gauthier: 374
Paul Gauthier (aider): 860
kAIto47802: 4
start_tag: v0.60.0
total_lines: 1272
- aider_percentage: 82.42
aider_total: 75
end_date: '2024-11-04'
end_tag: v0.62.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/args.py:
Paul Gauthier (aider): 14
aider/coders/editblock_coder.py:
Paul Gauthier: 6
aider/main.py:
Paul Gauthier (aider): 4
aider/models.py:
Paul Gauthier: 5
Paul Gauthier (aider): 45
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 4
Paul Gauthier (aider): 12
grand_total:
Paul Gauthier: 16
Paul Gauthier (aider): 75
start_tag: v0.61.0
total_lines: 91
- aider_percentage: 55.08
aider_total: 385
end_date: '2024-11-13'
end_tag: v0.63.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/coders/architect_coder.py:
Paul Gauthier: 3
aider/coders/base_coder.py:
Paul Gauthier: 42
Paul Gauthier (aider): 1
aider/coders/editblock_coder.py:
Paul Gauthier: 4
aider/commands.py:
Paul Gauthier: 13
aider/exceptions.py:
Paul Gauthier: 72
Paul Gauthier (aider): 4
aider/io.py:
Paul Gauthier: 3
Paul Gauthier (aider): 23
aider/main.py:
Paul Gauthier: 9
Paul Gauthier (aider): 9
aider/models.py:
Logan Attwood: 29
Paul Gauthier: 50
Paul Gauthier (aider): 7
aider/repo.py:
Paul Gauthier: 7
aider/repomap.py:
Paul Gauthier: 4
aider/sendchat.py:
Paul Gauthier: 17
Paul Gauthier (aider): 4
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
scripts/issues.py:
Paul Gauthier: 4
Paul Gauthier (aider): 195
tests/basic/test_coder.py:
Paul Gauthier: 2
tests/basic/test_commands.py:
Paul Gauthier (aider): 20
tests/basic/test_editblock.py:
Paul Gauthier: 41
tests/basic/test_exceptions.py:
Paul Gauthier (aider): 65
tests/basic/test_main.py:
Paul Gauthier: 1
tests/basic/test_sanity_check_repo.py:
Paul Gauthier: 2
Paul Gauthier (aider): 2
tests/basic/test_sendchat.py:
Paul Gauthier: 8
Paul Gauthier (aider): 55
tests/scrape/test_scrape.py:
Paul Gauthier: 1
grand_total:
Logan Attwood: 29
Paul Gauthier: 285
Paul Gauthier (aider): 385
start_tag: v0.62.0
total_lines: 699
- aider_percentage: 73.15
aider_total: 880
end_date: '2024-11-21'
end_tag: v0.64.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/analytics.py:
Paul Gauthier: 20
Paul Gauthier (aider): 21
aider/args.py:
Paul Gauthier: 2
Paul Gauthier (aider): 10
aider/coders/base_coder.py:
Paul Gauthier: 15
Paul Gauthier (aider): 3
caetanominuzzo: 1
aider/commands.py:
Chad Phillips: 4
Paul Gauthier: 5
Paul Gauthier (aider): 19
aider/editor.py:
Chad Phillips: 133
Paul Gauthier (aider): 13
aider/exceptions.py:
Paul Gauthier: 5
aider/help_pats.py:
Paul Gauthier: 1
aider/io.py:
Chad Phillips: 9
Paul Gauthier (aider): 41
mw: 21
aider/main.py:
Paul Gauthier: 21
Paul Gauthier (aider): 41
aider/models.py:
Paul Gauthier: 41
Paul Gauthier (aider): 33
aider/repo.py:
Paul Gauthier (aider): 5
aider/urls.py:
Paul Gauthier: 1
aider/website/_includes/edit-leaderboard.js:
Paul Gauthier (aider): 97
aider/website/_includes/quant-chart.js:
Paul Gauthier: 3
Paul Gauthier (aider): 66
aider/website/_includes/refactor-leaderboard.js:
Paul Gauthier (aider): 90
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
Paul Gauthier (aider): 10
aider/website/share/index.md:
Paul Gauthier (aider): 29
benchmark/over_time.py:
Paul Gauthier: 11
Paul Gauthier (aider): 162
scripts/blame.py:
Paul Gauthier: 1
Paul Gauthier (aider): 2
scripts/issues.py:
Paul Gauthier: 5
Paul Gauthier (aider): 12
scripts/versionbump.py:
Paul Gauthier: 7
tests/basic/test_analytics.py:
Paul Gauthier: 12
Paul Gauthier (aider): 30
tests/basic/test_commands.py:
Paul Gauthier (aider): 4
tests/basic/test_editor.py:
Paul Gauthier (aider): 129
tests/basic/test_main.py:
Paul Gauthier (aider): 8
tests/basic/test_models.py:
Paul Gauthier: 3
Paul Gauthier (aider): 55
grand_total:
Chad Phillips: 146
Paul Gauthier: 155
Paul Gauthier (aider): 880
caetanominuzzo: 1
mw: 21
start_tag: v0.63.0
total_lines: 1203

View File

@@ -1,7 +1,7 @@
- dirname: 2024-05-01-20-05-59--direct-opus-filenames-outside-fence
test_cases: 133
model: claude-3-opus-20240229
released: 2024-02-29
_released: 2024-02-29
edit_format: diff
commit_hash: f4b1797-dirty, f4b1797
pass_rate_1: 53.4
@@ -20,7 +20,7 @@
versions: 0.30.2-dev
seconds_per_case: 32.4
total_cost: 13.8395
- dirname: 2024-03-06-16-42-00--claude3-sonnet-whole
test_cases: 133
model: claude-3-sonnet-20240229
@@ -43,10 +43,11 @@
versions: 0.25.1-dev
seconds_per_case: 23.1
total_cost: 0.0000
- dirname: 2024-05-03-20-47-24--gemini-1.5-pro-diff-fenced
test_cases: 133
model: gemini-1.5-pro-latest
released: 2024-05-03
model: gemini-1.5-pro-001
edit_format: diff-fenced
commit_hash: 3a48dfb, 5d32dd7
pass_rate_1: 45.9
@@ -88,7 +89,7 @@
versions: 0.33.1-dev
seconds_per_case: 6.5
total_cost: 0.5032
- dirname: 2023-11-06-21-23-59--gpt-3.5-turbo-0301
test_cases: 133
model: gpt-3.5-turbo-0301
@@ -111,7 +112,7 @@
versions: 0.16.4-dev
seconds_per_case: 6.5
total_cost: 0.4822
- dirname: 2023-11-07-02-41-07--gpt-3.5-turbo-0613
test_cases: 133
model: gpt-3.5-turbo-0613
@@ -155,7 +156,7 @@
versions: 0.30.2-dev
seconds_per_case: 5.3
total_cost: 0.3261
- dirname: 2024-01-25-23-37-15--jan-exercism-gpt-4-0125-preview-udiff
test_cases: 133
model: gpt-4-0125-preview
@@ -178,7 +179,7 @@
versions: 0.22.1-dev
seconds_per_case: 44.8
total_cost: 14.6428
- dirname: 2024-05-04-15-07-30--redo-gpt-4-0314-diff-reminder-rules
test_cases: 133
model: gpt-4-0314
@@ -201,7 +202,7 @@
versions: 0.31.2-dev
seconds_per_case: 19.8
total_cost: 16.2689
- dirname: 2023-12-16-21-24-28--editblock-gpt-4-0613-actual-main
test_cases: 133
model: gpt-4-0613
@@ -228,7 +229,7 @@
- dirname: 2024-05-08-21-16-03--may-gpt-4-1106-preview-udiff
test_cases: 133
model: gpt-4-1106-preview
released: 2023-11-06
released: 2023-11-06
edit_format: udiff
commit_hash: 87664dc
pass_rate_1: 51.9
@@ -247,7 +248,7 @@
versions: 0.33.1-dev
seconds_per_case: 20.4
total_cost: 6.6061
- dirname: 2024-05-01-02-09-20--gpt-4-turbo-examples
test_cases: 133
model: gpt-4-turbo-2024-04-09 (udiff)
@@ -270,11 +271,11 @@
versions: 0.30.2-dev
seconds_per_case: 22.8
total_cost: 6.3337
- dirname: 2024-05-03-22-24-48--openrouter--llama3-diff-examples-sys-msg
test_cases: 132
model: llama3-70b-8192
released: 2024-04-18
_released: 2024-04-18
edit_format: diff
commit_hash: b5bb453
pass_rate_1: 38.6
@@ -293,11 +294,11 @@
versions: 0.31.2-dev
seconds_per_case: 14.5
total_cost: 0.4311
- dirname: 2024-05-06-18-31-08--command-r-plus-whole-final
test_cases: 133
model: command-r-plus
released: 2024-04-04
_released: 2024-04-04
edit_format: whole
commit_hash: fc3a43e-dirty
pass_rate_1: 21.8
@@ -316,11 +317,11 @@
versions: 0.31.2-dev
seconds_per_case: 22.9
total_cost: 2.7494
- dirname: 2024-05-07-20-32-37--qwen1.5-110b-chat-whole
test_cases: 133
model: qwen1.5-110b-chat
released: 2024-02-04
released: 2024-02-04
edit_format: whole
commit_hash: 70b1c0c
pass_rate_1: 30.8
@@ -339,7 +340,7 @@
versions: 0.31.2-dev
seconds_per_case: 46.9
total_cost: 0.0000
- dirname: 2024-05-07-20-57-04--wizardlm-2-8x22b-whole
test_cases: 133
model: WizardLM-2 8x22B
@@ -384,7 +385,7 @@
versions: 0.34.1-dev
seconds_per_case: 6.0
total_cost: 0.0000
- dirname: 2024-04-12-22-18-20--gpt-4-turbo-2024-04-09-plain-diff
test_cases: 33
model: gpt-4-turbo-2024-04-09 (diff)
@@ -410,6 +411,7 @@
- dirname: 2024-06-08-22-37-55--qwen2-72b-instruct-whole
test_cases: 133
model: Qwen2 72B Instruct
released: 2024-06-08
edit_format: whole
commit_hash: 02c7335-dirty, 1a97498-dirty
pass_rate_1: 44.4
@@ -568,7 +570,7 @@
versions: 0.42.1-dev
seconds_per_case: 17.6
total_cost: 3.6346
- dirname: 2024-07-01-21-41-48--haiku-whole
test_cases: 133
model: claude-3-haiku-20240307
@@ -623,7 +625,7 @@
commit_hash: d31eef3-dirty
pass_rate_1: 40.6
pass_rate_2: 55.6
released: 2024-07-18
_released: 2024-07-18
percent_cases_well_formed: 100.0
error_outputs: 1
num_malformed_responses: 0
@@ -671,7 +673,7 @@
commit_hash: f7ce78b-dirty
pass_rate_1: 46.6
pass_rate_2: 63.9
released: 2024-07-23
_released: 2024-07-23
percent_cases_well_formed: 92.5
error_outputs: 84
num_malformed_responses: 19
@@ -691,6 +693,7 @@
- dirname: 2024-07-24-06-30-29--llama-405b-whole
test_cases: 133
model: llama-3.1-405b-instruct (whole)
_released: 2024-07-23
edit_format: whole
commit_hash: a362dea-dirty
pass_rate_1: 48.9
@@ -698,7 +701,6 @@
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
released: 2024-07-23
num_with_malformed_responses: 0
user_asks: 0
lazy_comments: 0
@@ -770,7 +772,7 @@
percent_cases_well_formed: 100.0
error_outputs: 27
num_malformed_responses: 0
released: 2024-07-23
_released: 2024-07-23
num_with_malformed_responses: 0
user_asks: 23
lazy_comments: 8
@@ -796,7 +798,7 @@
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 0
released: 2024-07-23
_released: 2024-07-23
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
@@ -835,6 +837,7 @@
- dirname: 2024-08-28-07-10-50--gemini-1.5-pro-exp-0827-diff-fenced
test_cases: 133
model: gemini-1.5-pro-exp-0827
released: 2024-08-27
edit_format: diff-fenced
commit_hash: d8adc75
pass_rate_1: 54.9
@@ -946,7 +949,7 @@
versions: 0.54.13.dev
seconds_per_case: 8.3
total_cost: 0.0000
released: 2024-09-04
_released: 2024-09-04
- dirname: 2024-09-04-16-17-33--yi-coder-9b-chat-q4_0-whole
test_cases: 133
@@ -973,6 +976,7 @@
- dirname: 2024-09-05-14-50-11--deepseek-sep5-no-shell
test_cases: 133
released: 2024-09-05
model: DeepSeek V2.5
edit_format: diff
commit_hash: 1279c86
@@ -1112,6 +1116,7 @@
- dirname: 2024-09-21-16-45-11--o1-preview-flex-sr-markers
test_cases: 133
model: o1-preview
_released: 2024-09-12
edit_format: diff
commit_hash: 5493654-dirty
pass_rate_1: 57.9
@@ -1131,7 +1136,7 @@
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
@@ -1154,7 +1159,7 @@
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)
@@ -1204,6 +1209,7 @@
- dirname: 2024-09-24-16-26-45--gemini-1.5-pro-002-diff-fenced
test_cases: 133
model: gemini-1.5-pro-002
released: 2024-09-24
edit_format: diff-fenced
commit_hash: 6b5fe9b, 3edcd71
pass_rate_1: 49.6
@@ -1458,7 +1464,7 @@
versions: 0.58.1.dev
seconds_per_case: 63.7
total_cost: 0.0000
- dirname: 2024-10-01-16-50-09--hermes3-whole-4
test_cases: 133
model: ollama/hermes3
@@ -1477,6 +1483,7 @@
- dirname: 2024-10-04-16-30-08--chatgpt-4o-latest-diff-oct4
test_cases: 133
model: openai/chatgpt-4o-latest
released: 2024-10-04
edit_format: diff
commit_hash: af10953
pass_rate_1: 56.4
@@ -1592,6 +1599,7 @@
- dirname: 2024-10-22-17-45-28--sonnet-1022-diff-fixed-model-settings
test_cases: 133
model: claude-3-5-sonnet-20241022
released: 2024-10-22
edit_format: diff
commit_hash: 3b14eb9
pass_rate_1: 69.2
@@ -1610,4 +1618,331 @@
date: 2024-10-22
versions: 0.59.2.dev
seconds_per_case: 18.6
total_cost: 0.0000
total_cost: 0.0000
- dirname: 2024-11-04-19-19-32--haiku35-diff-ex-as-sys-false
test_cases: 133
model: claude-3-5-haiku-20241022
released: 2024-10-22
edit_format: diff
commit_hash: 03bbdb0-dirty
pass_rate_1: 61.7
pass_rate_2: 75.2
percent_cases_well_formed: 95.5
error_outputs: 11
num_malformed_responses: 11
num_with_malformed_responses: 6
user_asks: 1
lazy_comments: 1
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model anthropic/claude-3-5-haiku-20241022
date: 2024-11-04
versions: 0.61.1.dev
seconds_per_case: 18.4
total_cost: 0.0000
- dirname: 2024-11-07-06-15-36--Qwen2.5.1-Coder-7B-Instruct-GGUF:Q8_0-32k-whole
test_cases: 133
model: ollama/Qwen2.5.1-Coder-7B-Instruct-GGUF:Q8_0-32k
edit_format: whole
commit_hash: e76704e
pass_rate_1: 52.6
pass_rate_2: 63.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: 1
command: aider --model ollama/Qwen2.5.1-Coder-7B-Instruct-GGUF:Q8_0-32k
date: 2024-11-07
versions: 0.59.2.dev
seconds_per_case: 18.2
total_cost: 0.0000
- dirname: 2024-10-29-00-29-09--Qwen2.5-Coder-0.5B-Instruct
test_cases: 133
model: Qwen2.5-Coder-0.5B-Instruct
edit_format: whole
commit_hash: 58bd375
pass_rate_1: 14.3
pass_rate_2: 14.3
percent_cases_well_formed: 100.0
error_outputs: 20
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 45
lazy_comments: 0
syntax_errors: 2
indentation_errors: 0
exhausted_context_windows: 20
test_timeouts: 2
command: aider --model openai/Qwen2.5-Coder-0.5B-Instruct
date: 2024-10-29
versions: 0.59.2.dev
seconds_per_case: 16.0
total_cost: 0.0000
- dirname: 2024-11-11-19-37-01--Qwen2.5-Coder-1.5B-Instruct
test_cases: 133
model: Qwen2.5-Coder-1.5B-Instruct
edit_format: whole
commit_hash: bb5681c
pass_rate_1: 28.6
pass_rate_2: 31.6
percent_cases_well_formed: 100.0
error_outputs: 5
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 13
lazy_comments: 2
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 5
test_timeouts: 2
command: aider --model openai/Qwen2.5-Coder-1.5B-Instruct
date: 2024-11-11
versions: 0.59.2.dev
seconds_per_case: 27.4
total_cost: 0.0000
- dirname: 2024-11-04-02-25-32--Qwen2.5-Coder-3B-Instruct
test_cases: 133
model: Qwen2.5-Coder-3B-Instruct
edit_format: whole
commit_hash: 0ba3647
pass_rate_1: 33.8
pass_rate_2: 39.1
percent_cases_well_formed: 100.0
error_outputs: 4
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 3
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 4
test_timeouts: 6
command: aider --model openai/Qwen2.5-Coder-3B-Instruct
date: 2024-11-04
versions: 0.59.2.dev
seconds_per_case: 18.7
total_cost: 0.0000
- dirname: 2024-10-16-16-20-59--Qwen2.5-Coder-7B-Instruct
test_cases: 133
model: Qwen2.5-Coder-7B-Instruct
edit_format: whole
commit_hash: 92fe979-dirty
pass_rate_1: 51.9
pass_rate_2: 57.9
percent_cases_well_formed: 100.0
error_outputs: 2
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 2
test_timeouts: 5
command: aider --model openai/Qwen2.5-Coder-7B-Instruct
date: 2024-10-16
versions: 0.59.2.dev
seconds_per_case: 10.5
total_cost: 0.0000
- dirname: 2024-10-29-11-53-39--Qwen2.5-Coder-14B-Instruct
test_cases: 133
model: Qwen2.5-Coder-14B-Instruct
edit_format: whole
commit_hash: 58bd375
pass_rate_1: 58.6
pass_rate_2: 69.2
percent_cases_well_formed: 100.0
error_outputs: 3
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 3
test_timeouts: 0
command: aider --model openai/Qwen2.5-Coder-14B-Instruct
date: 2024-10-29
versions: 0.59.2.dev
seconds_per_case: 18.3
total_cost: 0.0000
- dirname: 2024-11-09-11-09-15--Qwen2.5-Coder-32B-Instruct
test_cases: 133
model: Qwen2.5-Coder-32B-Instruct
released: 2024-11-12
edit_format: diff
commit_hash: ec9982a
pass_rate_1: 59.4
pass_rate_2: 71.4
percent_cases_well_formed: 94.7
error_outputs: 17
num_malformed_responses: 17
num_with_malformed_responses: 7
user_asks: 1
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model openai/hf:Qwen/Qwen2.5-Coder-32B-Instruct --openai-api-base https://glhf.chat/api/openai/v1
date: 2024-11-09
versions: 0.59.2.dev
seconds_per_case: 22.5
total_cost: 0.0000
- dirname: 2024-11-20-14-57-11--mistral-2411-direct-diff
test_cases: 133
model: Mistral Large (2411)
released: 2024-11-18
edit_format: diff
commit_hash: dba844c
pass_rate_1: 46.6
pass_rate_2: 65.4
percent_cases_well_formed: 96.2
error_outputs: 8
num_malformed_responses: 8
num_with_malformed_responses: 5
user_asks: 5
lazy_comments: 0
syntax_errors: 0
indentation_errors: 1
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model mistral/mistral-large-latest
date: 2024-11-20
versions: 0.63.3.dev
seconds_per_case: 24.9
total_cost: 3.2334
- dirname: 2024-11-20-19-28-30--gpt-4o-2024-11-20
test_cases: 133
model: gpt-4o-2024-11-20
released: 2024-11-20
edit_format: diff
commit_hash: 2ac0776-dirty
pass_rate_1: 58.6
pass_rate_2: 71.4
percent_cases_well_formed: 99.2
error_outputs: 1
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 4
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 5
command: aider --model openai/gpt-4o-2024-11-20
date: 2024-11-20
versions: 0.63.3.dev
seconds_per_case: 6.0
total_cost: 0.0000
- dirname: 2024-09-20-21-47-17--qwen2.5-32b-instruct-q8_0-whole
test_cases: 133
model: ollama/qwen2.5:32b-instruct-q8_0
edit_format: whole
commit_hash: 2753ac6
pass_rate_1: 46.6
pass_rate_2: 58.6
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 1
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model ollama/qwen2.5:32b-instruct-q8_0
date: 2024-09-20
versions: 0.56.1.dev
seconds_per_case: 1763.7
total_cost: 0.0000
- dirname: 2024-11-20-15-17-37--qwen25-32b-or-diff
test_cases: 133
model: openrouter/qwen/qwen-2.5-coder-32b-instruct
edit_format: diff
commit_hash: e917424
pass_rate_1: 49.6
pass_rate_2: 65.4
percent_cases_well_formed: 84.2
error_outputs: 43
num_malformed_responses: 31
num_with_malformed_responses: 21
user_asks: 43
lazy_comments: 0
syntax_errors: 2
indentation_errors: 2
exhausted_context_windows: 12
test_timeouts: 2
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
date: 2024-11-20
versions: 0.63.3.dev
seconds_per_case: 40.7
total_cost: 0.1497
- dirname: 2024-11-21-17-46-36--gemini-exp-1121-diff
test_cases: 133
model: gemini-exp-1121
released: 2024-11-21
edit_format: diff
commit_hash: e94961a
pass_rate_1: 46.6
pass_rate_2: 57.9
percent_cases_well_formed: 83.5
error_outputs: 101
num_malformed_responses: 101
num_with_malformed_responses: 22
user_asks: 5
lazy_comments: 0
syntax_errors: 0
indentation_errors: 2
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model gemini/gemini-exp-1121
date: 2024-11-21
versions: 0.63.3.dev
seconds_per_case: 60.3
total_cost: 0.0000
- dirname: 2024-11-15-20-33-31--gemini-exp-1114-diff
test_cases: 133
model: gemini-exp-1114
released: 2024-11-14
edit_format: diff
commit_hash: 0bf17a4
pass_rate_1: 50.4
pass_rate_2: 60.9
percent_cases_well_formed: 85.7
error_outputs: 70
num_malformed_responses: 70
num_with_malformed_responses: 19
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 4
command: aider --model gemini/gemini-exp-1114
date: 2024-11-15
versions: 0.63.2.dev
seconds_per_case: 38.6

View File

@@ -0,0 +1,299 @@
- dirname: 2024-11-09-11-09-15--Qwen2.5-Coder-32B-Instruct
test_cases: 133
model: "HuggingFace via GLHF: BF16"
released: 2024-11-12
edit_format: diff
commit_hash: ec9982a
pass_rate_1: 59.4
pass_rate_2: 71.4
percent_cases_well_formed: 94.7
error_outputs: 17
num_malformed_responses: 17
num_with_malformed_responses: 7
user_asks: 1
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model openai/hf:Qwen/Qwen2.5-Coder-32B-Instruct --openai-api-base https://glhf.chat/api/openai/v1
date: 2024-11-09
versions: 0.59.2.dev
seconds_per_case: 22.5
total_cost: 0.0000
- dirname: 2024-11-22-18-56-13--ollama-qwen2.5-coder:32b-instruct-fp16
test_cases: 132
model: "Ollama: fp16"
edit_format: diff
commit_hash: f06452c-dirty, 6a0a97c-dirty, 4e9ae16-dirty, 5506d0f-dirty
pass_rate_1: 58.3
pass_rate_2: 71.4
percent_cases_well_formed: 90.2
error_outputs: 27
num_malformed_responses: 26
num_with_malformed_responses: 13
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model ollama/qwen2.5-coder:32b-instruct-fp16
date: 2024-11-22
versions: 0.64.2.dev
seconds_per_case: 119.6
total_cost: 0.0000
- dirname: 2024-11-22-14-53-26--hyperbolic-qwen25coder32binstruct
test_cases: 133
model: "Hyperbolic: BF16"
edit_format: diff
commit_hash: f9ef161, 17aef7b-dirty
pass_rate_1: 57.9
pass_rate_2: 69.2
percent_cases_well_formed: 91.7
error_outputs: 30
num_malformed_responses: 29
num_with_malformed_responses: 11
user_asks: 9
lazy_comments: 0
syntax_errors: 4
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model openai/Qwen/Qwen2.5-Coder-32B-Instruct --openai-api-base https://api.hyperbolic.xyz/v1/
date: 2024-11-22
versions: 0.64.2.dev
seconds_per_case: 33.2
total_cost: 0.0000
- dirname: 2024-11-22-17-53-35--qwen25-coder-32b-Instruct-4bit
test_cases: 133
model: "mlx-community: 4bit"
edit_format: diff
commit_hash: a16dcab-dirty
pass_rate_1: 60.2
pass_rate_2: 72.2
percent_cases_well_formed: 88.7
error_outputs: 31
num_malformed_responses: 30
num_with_malformed_responses: 15
user_asks: 6
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 0
command: aider --model openai/mlx-community/Qwen2.5-Coder-32B-Instruct-4bit
date: 2024-11-23
versions: 0.64.2.dev
seconds_per_case: 53.4
total_cost: 0.0000
- dirname: 2024-11-23-15-07-20--qwen25-coder-32b-Instruct-8bit
test_cases: 133
model: "mlx-community: 8bit"
edit_format: diff
commit_hash: a16dcab-dirty
pass_rate_1: 59.4
pass_rate_2: 72.2
percent_cases_well_formed: 92.5
error_outputs: 20
num_malformed_responses: 15
num_with_malformed_responses: 10
user_asks: 7
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 5
test_timeouts: 2
command: aider --model openai/mlx-community/Qwen2.5-Coder-32B-Instruct-8bit
date: 2024-11-23
versions: 0.64.2.dev
seconds_per_case: 98.4
total_cost: 0.0000
- dirname: 2024-11-24-22-18-18--or-all-or-fixed-blank-messages2
test_cases: 133
model: "OpenRouter: multiple"
edit_format: diff
commit_hash: 0c59d32
pass_rate_1: 57.1
pass_rate_2: 67.7
percent_cases_well_formed: 95.5
error_outputs: 56
num_malformed_responses: 10
num_with_malformed_responses: 6
user_asks: 14
lazy_comments: 0
syntax_errors: 6
indentation_errors: 0
exhausted_context_windows: 3
test_timeouts: 1
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
date: 2024-11-24
versions: 0.64.2.dev
seconds_per_case: 21.2
total_cost: 0.1420
- dirname: 2024-11-23-21-08-53--ollama-qwen2.5-coder:32b-instruct-q4_K_M-8kctx
test_cases: 133
model: "Ollama: q4_K_M"
edit_format: diff
commit_hash: baa1335-dirty, e63df83-dirty, ff8c1aa-dirty
pass_rate_1: 54.9
pass_rate_2: 66.9
percent_cases_well_formed: 94.0
error_outputs: 21
num_malformed_responses: 21
num_with_malformed_responses: 8
user_asks: 5
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model ollama/qwen2.5-coder:32b-instruct-q4_K_M
date: 2024-11-23
versions: 0.64.2.dev
seconds_per_case: 35.7
total_cost: 0.0000
- dirname: 2024-11-24-02-23-32--deepinfra-qwen-diff
test_cases: 133
model: "Deepinfra: BF16"
edit_format: diff
commit_hash: bb78e2f
pass_rate_1: 58.6
pass_rate_2: 72.2
percent_cases_well_formed: 94.7
error_outputs: 15
num_malformed_responses: 13
num_with_malformed_responses: 7
user_asks: 3
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 2
test_timeouts: 3
command: aider --model deepinfra/Qwen/Qwen2.5-Coder-32B-Instruct
date: 2024-11-24
versions: 0.64.2.dev
seconds_per_case: 17.5
total_cost: 0.0000
- dirname: 2024-11-24-04-12-58--fireworks-qwen-diff
test_cases: 133
model: "Fireworks: unknown"
edit_format: diff
commit_hash: 757eac0
pass_rate_1: 57.9
pass_rate_2: 72.2
percent_cases_well_formed: 94.0
error_outputs: 23
num_malformed_responses: 19
num_with_malformed_responses: 8
user_asks: 8
lazy_comments: 0
syntax_errors: 6
indentation_errors: 0
exhausted_context_windows: 4
test_timeouts: 1
command: aider --model fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct
date: 2024-11-24
versions: 0.64.2.dev
seconds_per_case: 10.4
total_cost: 0.5759
- dirname: 2024-11-24-02-04-59--ollama-qwen2.5-coder:32b-instruct-q2_K-8kctx
test_cases: 133
model: "Ollama: q2_K"
edit_format: diff
commit_hash: 757eac0, bb78e2f, 8d0ba40-dirty, 1d09e96
pass_rate_1: 48.9
pass_rate_2: 61.7
percent_cases_well_formed: 91.7
error_outputs: 32
num_malformed_responses: 32
num_with_malformed_responses: 11
user_asks: 8
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model ollama/qwen2.5-coder:32b-instruct-q2_K
date: 2024-11-24
versions: 0.64.2.dev
seconds_per_case: 97.8
total_cost: 0.0000
- dirname: 2024-11-24-14-56-49--qwen25-32b-or-fireworks
test_cases: 133
model: "Fireworks via OpenRouter: unknown"
edit_format: diff
commit_hash: c2f184f
pass_rate_1: 55.6
pass_rate_2: 67.7
percent_cases_well_formed: 94.0
error_outputs: 39
num_malformed_responses: 24
num_with_malformed_responses: 8
user_asks: 13
lazy_comments: 0
syntax_errors: 1
indentation_errors: 1
exhausted_context_windows: 7
test_timeouts: 4
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
date: 2024-11-24
versions: 0.64.2.dev
seconds_per_case: 16.1
total_cost: 0.1391
- dirname: 2024-11-24-22-03-19--or-hyperbolic-or-fixed-blank-messages2
test_cases: 133
model: "Hyperbolic via OpenRouter: BF16"
edit_format: diff
commit_hash: 0c59d32
pass_rate_1: 55.6
pass_rate_2: 68.4
percent_cases_well_formed: 89.5
error_outputs: 28
num_malformed_responses: 24
num_with_malformed_responses: 14
user_asks: 29
lazy_comments: 0
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 4
test_timeouts: 1
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
date: 2024-11-24
versions: 0.64.2.dev
seconds_per_case: 41.5
total_cost: 0.1402
- dirname: 2024-11-24-15-00-50--qwen25-32b-or-deepinfra
test_cases: 133
model: "Deepinfra via OpenRouter: BF16"
edit_format: diff
commit_hash: c2f184f
pass_rate_1: 57.1
pass_rate_2: 69.9
percent_cases_well_formed: 89.5
error_outputs: 35
num_malformed_responses: 31
num_with_malformed_responses: 14
user_asks: 11
lazy_comments: 0
syntax_errors: 1
indentation_errors: 1
exhausted_context_windows: 4
test_timeouts: 1
command: aider --model openrouter/qwen/qwen-2.5-coder-32b-instruct
date: 2024-11-24
versions: 0.64.2.dev
seconds_per_case: 28.5
total_cost: 0.1390

View File

@@ -1,5 +1,5 @@
<canvas id="linesChart" width="800" height="360" style="margin-top: 20px"></canvas>
<canvas id="blameChart" width="800" height="360" style="margin-top: 20px"></canvas>
<canvas id="linesChart" width="800" height="360" style="margin-top: 20px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment"></script>

View File

@@ -0,0 +1,97 @@
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('editChart').getContext('2d');
const HIGHTLIGHT_MODEL = 'no no no no';
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: function(context) {
const label = context.chart.data.labels[context.dataIndex] || '';
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)';
},
borderColor: function(context) {
const label = context.chart.data.labels[context.dataIndex] || '';
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : '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: {
y: {
beginAtZero: true
}
}
}
});
updateChart();
// Add search functionality for edit table
document.getElementById('editSearchInput').addEventListener('keyup', function() {
var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0);
var tableBody = document.querySelector('table:first-of-type tbody');
var rows = tableBody.getElementsByTagName('tr');
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
for (var i = 0; i < rows.length; i++) {
var rowText = rows[i].textContent;
if (searchWords.every(word => rowText.toLowerCase().includes(word))) {
rows[i].style.display = '';
leaderboardData.labels.push(allData[i].model);
leaderboardData.datasets[0].data.push(allData[i].pass_rate_2);
} else {
rows[i].style.display = 'none';
}
}
leaderboardChart.update();
});
});

View File

View File

@@ -1,5 +1,15 @@
You can send long, multi-line messages in the chat in a few ways:
- Paste a multi-line message directly into the chat.
- Enter `{` alone on the first line to start a multiline message and `}` alone on the last line to end it.
- Or, start with `{tag` (where "tag" is any sequence of letters/numbers) and end with `tag}`. This is useful when you need to include closing braces `}` in your message.
- Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
- Use `/paste` to paste text from the clipboard into the chat.
- Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
Example with a tag:
```
{python
def hello():
print("Hello}") # Note: contains a brace
python}
```

View File

@@ -0,0 +1,95 @@
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('quantChart').getContext('2d');
var allData = [];
{% for row in site.data.quant %}
allData.push({
model: '{{ row.model }}',
pass_rate_2: {{ row.pass_rate_2 }}
});
{% endfor %}
// Sort data by pass_rate_2 in descending order
allData.sort((a, b) => b.pass_rate_2 - a.pass_rate_2);
var chart;
function updateChart(filterText) {
var filteredData = allData.filter(row =>
row.model.toLowerCase().includes(filterText.toLowerCase())
);
var chartData = {
labels: filteredData.map(row => row.model),
datasets: [{
label: 'Percent completed correctly',
data: filteredData.map(row => row.pass_rate_2),
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
};
if (chart) {
chart.data = chartData;
chart.update();
} else {
chart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'Aider code editing benchmark',
font: {
size: 16
}
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Percent completed correctly',
font: {
size: 14
}
},
ticks: {
font: {
size: 16
}
}
},
x: {
ticks: {
font: {
size: 16
}
},
title: {
display: true,
text: 'Provider: quantization',
font: {
size: 14
}
}
}
}
}
});
}
}
// Initial chart render
updateChart('');
// Connect search input to chart filtering
document.getElementById('quantSearchInput').addEventListener('keyup', function() {
updateChart(this.value);
});
});

View File

@@ -0,0 +1,90 @@
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: {
y: {
beginAtZero: true
}
}
}
});
updateChart();
// Add search functionality for refactoring table
document.getElementById('refacSearchInput').addEventListener('keyup', function() {
var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0);
var tableBody = document.querySelectorAll('table tbody')[1];
var rows = tableBody.getElementsByTagName('tr');
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
for (var i = 0; i < rows.length; i++) {
var rowText = rows[i].textContent;
if (searchWords.every(word => rowText.toLowerCase().includes(word))) {
rows[i].style.display = '';
leaderboardData.labels.push(allData[i].model);
leaderboardData.datasets[0].data.push(allData[i].pass_rate_1);
} else {
rows[i].style.display = 'none';
}
}
leaderboardChart.update();
});
});

View File

@@ -12,6 +12,10 @@ nav_exclude: true
[![self assembly](/assets/self-assembly.jpg)](https://aider.chat/assets/self-assembly.jpg)
{: .note }
This article is quite out dated. For current statistics, see
[aider's release history](/HISTORY.html).
The
[aider git repo](https://github.com/Aider-AI/aider)
currently contains about 4K commits and 14K lines of code.

View File

@@ -0,0 +1,169 @@
---
title: Details matter with open source models
excerpt: Open source LLMs are becoming very powerful, but pay attention to how you (or your provider) are serving the model. It can affect code editing skill.
highlight_image: /assets/quantization.jpg
draft: false
nav_exclude: true
---
{% if page.date %}
<p class="post-date">{{ page.date | date: "%B %d, %Y" }}</p>
{% endif %}
# Details matter with open source models
{: .no_toc }
Open source models like Qwen 2.5 32B Instruct are performing very well on
aider's code editing benchmark, rivaling closed source frontier models.
But pay attention to how your model is being served and quantized,
as it can impact code editing skill.
Open source models are often available at a variety of quantizations,
and can be served with different token limits.
These details matter when working with code.
The graph and table below compares different versions of the Qwen 2.5 Coder 32B Instruct model,
served both locally and from a variety of cloud providers.
- The [HuggingFace BF16 weights](https://huggingface.co/Qwen/Qwen2.5-Coder-32B-Instruct) served via [glhf.chat](https://glhf.chat).
- [4bit and 8bit quants for mlx](https://t.co/cwX3DYX35D).
- The results from [OpenRouter's mix of providers](https://openrouter.ai/qwen/qwen-2.5-coder-32b-instruct/providers) which serve the model with different levels of quantization.
- Results from individual providers served via OpenRouter and directly to their own APIs.
- Ollama locally serving different quantizations from the [Ollama model library](https://ollama.com/library/qwen2.5-coder:32b-instruct-q4_K_M).
The best versions of the model rival GPT-4o, while the worst performer
is more like the older GPT-4 Turbo.
Suboptimal choices in quantization and token limits can
easily produce far worse results.
This benchmarking effort highlighted a number of pitfalls and details which
can have a significant impact on the model's ability to correctly edit code:
- Quantization -- Open source models are often available at dozens of different quantizations.
- Context window -- Cloud providers can decide how large a context window to accept,
and they often choose differently. Ollama defaults to a tiny 2k context window,
and silently discards data that exceeds it.
- Output token limits -- Open source models are often served with wildly
differing output token limits. This has a direct impact on how much code the
model can write or edit in a response.
- Buggy cloud providers -- Between Qwen and DeepSeep, there were
multiple cloud providers with broken or buggy API endpoints that seemed
to be returning result different from expected based on the advertised
quantization and context sizes.
### Sections
{: .no_toc }
- TOC
{:toc}
## Benchmark results
<canvas id="quantChart" width="800" height="600" style="margin: 20px 0"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
{% include quant-chart.js %}
</script>
<input type="text" id="quantSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
<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>
{% assign quant_sorted = site.data.quant | sort: 'pass_rate_2' | reverse %}
{% for row in quant_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>
<script>
document.getElementById('quantSearchInput').addEventListener('keyup', function() {
var input = this.value.toLowerCase();
var rows = document.querySelectorAll('tbody tr');
rows.forEach(function(row) {
var text = row.textContent.toLowerCase();
if(text.includes(input)) {
row.style.display = '';
row.classList.add('selected');
} else {
row.style.display = 'none';
row.classList.remove('selected');
}
});
});
</script>
## Setting Ollama's context window size
[Ollama uses a 2k context window by default](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-specify-the-context-window-size),
which is very small for working with aider.
Unlike most other LLM servers, Ollama does not throw an error if you submit
a request that exceeds the context window.
Instead, it just silently truncates the request by discarding the "oldest" messages
in the chat to make it fit within the context window.
All of the Ollama results above were collected with at least an 8k context window, which
is large enough to attempt all the coding problems in the benchmark.
Aider sets Ollama's context window to 8k by default.
You can change the Ollama server's context window with a
[`.aider.model.settings.yml` file](https://aider.chat/docs/config/adv-model-settings.html#model-settings)
like this:
```
- name: ollama/qwen2.5-coder:32b-instruct-fp16
extra_params:
num_ctx: 8192
```
## Choosing providers with OpenRouter
OpenRouter allows you to ignore specific providers in your
[preferences](https://openrouter.ai/settings/preferences).
This can be used to limit your OpenRouter requests to be
served by only your preferred providers.
## Notes
This article went through many revisions as I received feedback from
numerous members of the community.
Here are some of the noteworthy learnings and changes:
- The first version of this article included incorrect Ollama models.
- Earlier Ollama results used the too small default 2k context window,
artificially harming the benchmark results.
- The benchmark results appear to have uncovered a problem in the way
OpenRouter was communicating with Hyperbolic.
They fixed the issue 11/24/24, shortly after it was pointed out.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 103 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,9 @@
## Use claude-3-5-sonnet-20241022 model for the main chat
#sonnet: false
## Use claude-3-5-haiku-20241022 model for the main chat
#haiku: false
## Use gpt-4-0613 model for the main chat
#4: false
@@ -83,6 +86,14 @@
## Specify a file with context window and costs for unknown models
#model-metadata-file: .aider.model.metadata.json
## Add a model alias (can be used multiple times)
#alias: xxx
## Specify multiple values like this:
#alias:
# - xxx
# - yyy
# - zzz
## Verify the SSL cert when connecting to models (default: True)
#verify-ssl: true
@@ -268,8 +279,8 @@
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#analytics: false
## Enable/disable analytics for current session (default: random)
#analytics: xxx
## Specify a file to log analytics events
#analytics-log: xxx
@@ -311,6 +322,9 @@
## Check for new aider versions on launch
#check-update: true
## Show release notes on first run of new version (default: None, ask user)
#show-release-notes: xxx
## Install the latest version from the main branch
#install-main-branch: false
@@ -320,6 +334,9 @@
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Always say yes to every confirmation
#yes-always: false
@@ -359,6 +376,12 @@
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
## Enable/disable detection and offering to add URLs to chat (default: True)
#detect-urls: true
## Specify which editor to use for the /editor command
#editor: xxx
#################
# Voice Settings:

View File

@@ -36,6 +36,9 @@
## Use claude-3-5-sonnet-20241022 model for the main chat
#AIDER_SONNET=
## Use claude-3-5-haiku-20241022 model for the main chat
#AIDER_HAIKU=
## Use gpt-4-0613 model for the main chat
#AIDER_4=
@@ -87,6 +90,9 @@
## Specify a file with context window and costs for unknown models
#AIDER_MODEL_METADATA_FILE=.aider.model.metadata.json
## Add a model alias (can be used multiple times)
#AIDER_ALIAS=
## Verify the SSL cert when connecting to models (default: True)
#AIDER_VERIFY_SSL=true
@@ -267,8 +273,8 @@
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#AIDER_ANALYTICS=false
## Enable/disable analytics for current session (default: random)
#AIDER_ANALYTICS=
## Specify a file to log analytics events
#AIDER_ANALYTICS_LOG=
@@ -297,6 +303,9 @@
## Check for new aider versions on launch
#AIDER_CHECK_UPDATE=true
## Show release notes on first run of new version (default: None, ask user)
#AIDER_SHOW_RELEASE_NOTES=
## Install the latest version from the main branch
#AIDER_INSTALL_MAIN_BRANCH=false
@@ -306,6 +315,9 @@
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
@@ -342,6 +354,12 @@
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## Enable/disable detection and offering to add URLs to chat (default: True)
#AIDER_DETECT_URLS=true
## Specify which editor to use for the /editor command
#AIDER_EDITOR=
#################
# Voice Settings:

View File

@@ -11,6 +11,13 @@ description: Configuring advanced settings for LLMs.
In most cases, you can safely ignore aider's warning about unknown context
window size and model costs.
{: .note }
Aider never *enforces* token limits, it only *reports* token limit errors
from the API provider.
You probably don't need to
configure aider with the proper token limits
for unusual models.
But, you can register context window limits and costs for models that aren't known
to aider. Create a `.aider.model.metadata.json` file in one of these locations:
@@ -55,8 +62,10 @@ These model settings are pre-configured for most popular models.
But it can sometimes be helpful to override them or add settings for
a model that aider doesn't know about.
To do that,
create a `.aider.model.settings.yml` file in one of these locations:
### Configuration file locations
You can override or add settings for any model by creating a `.aider.model.settings.yml` file in one of these locations:
- Your home directory.
- The root if your git repo.
@@ -66,9 +75,31 @@ create a `.aider.model.settings.yml` file in one of these locations:
If the files above exist, they will be loaded in that order.
Files loaded last will take priority.
The yaml file should be a a list of dictionary objects for each model.
For example, below are all the pre-configured model settings
to give a sense for the settings which are supported.
The yaml file should be a list of dictionary objects for each model.
### Global extra params
You can use the special model name `aider/extra_params` to define
`extra_params` that will be passed to `litellm.completion()` for all models.
Only the `extra_params` dict is used from this special model name.
For example:
```yaml
- name: aider/extra_params
extra_params:
extra_headers:
Custom-Header: value
max_tokens: 8192
```
These settings will be merged with any model-specific settings, with the
`aider/extra_params` settings taking precedence for any direct conflicts.
### Example model settings
Below are all the pre-configured model settings to give a sense for the settings which are supported.
You can also look at the `ModelSettings` class in
[models.py](https://github.com/Aider-AI/aider/blob/main/aider/models.py)
@@ -241,6 +272,38 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: true
name: gpt-4o-2024-11-20
reminder: sys
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: true
name: openai/gpt-4o-2024-11-20
reminder: sys
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- cache_control: false
caches_by_default: false
edit_format: diff
@@ -400,7 +463,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
weak_model_name: claude-3-5-haiku-20241022
- cache_control: false
caches_by_default: false
edit_format: diff
@@ -416,7 +479,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku
weak_model_name: openrouter/anthropic/claude-3-5-haiku
- cache_control: false
caches_by_default: false
edit_format: whole
@@ -432,7 +495,7 @@ cog.out("```\n")
use_repo_map: false
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
weak_model_name: claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
@@ -451,7 +514,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
weak_model_name: claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
@@ -470,7 +533,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
@@ -489,7 +552,26 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
max_tokens: 8192
lazy: false
name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
- cache_control: true
caches_by_default: false
edit_format: diff
@@ -508,7 +590,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
@@ -527,7 +609,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
weak_model_name: claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: whole
@@ -546,6 +628,77 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
lazy: false
name: anthropic/claude-3-5-haiku-20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
lazy: false
name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
lazy: false
name: claude-3-5-haiku-20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-5-haiku-20241022
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params:
max_tokens: 4096
lazy: false
name: vertex_ai/claude-3-5-haiku@20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: true
caches_by_default: false
edit_format: whole
@@ -580,7 +733,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku
weak_model_name: openrouter/anthropic/claude-3-5-haiku
- cache_control: true
caches_by_default: false
edit_format: diff
@@ -597,7 +750,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku:beta
weak_model_name: openrouter/anthropic/claude-3-5-haiku:beta
- cache_control: false
caches_by_default: false
edit_format: diff
@@ -614,7 +767,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: diff
@@ -631,7 +784,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: diff
@@ -647,7 +800,7 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: whole
@@ -663,7 +816,7 @@ cog.out("```\n")
use_repo_map: false
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: whole
@@ -824,6 +977,22 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: false
name: vertex_ai/gemini-pro-experimental
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: whole
@@ -951,7 +1120,7 @@ cog.out("```\n")
name: openai/o1-mini
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
@@ -967,7 +1136,7 @@ cog.out("```\n")
name: azure/o1-mini
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
@@ -983,7 +1152,7 @@ cog.out("```\n")
name: o1-mini
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
@@ -999,7 +1168,7 @@ cog.out("```\n")
name: openai/o1-preview
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
@@ -1015,7 +1184,7 @@ cog.out("```\n")
name: azure/o1-preview
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
@@ -1031,7 +1200,7 @@ cog.out("```\n")
name: o1-preview
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
@@ -1068,6 +1237,22 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: openrouter/openai/gpt-4o-mini
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct
examples_as_sys_msg: false
extra_params: null
lazy: false
name: openrouter/qwen/qwen-2.5-coder-32b-instruct
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct
```
<!--[[[end]]]-->

View File

@@ -88,6 +88,9 @@ cog.outl("```")
## Use claude-3-5-sonnet-20241022 model for the main chat
#sonnet: false
## Use claude-3-5-haiku-20241022 model for the main chat
#haiku: false
## Use gpt-4-0613 model for the main chat
#4: false
@@ -139,6 +142,14 @@ cog.outl("```")
## Specify a file with context window and costs for unknown models
#model-metadata-file: .aider.model.metadata.json
## Add a model alias (can be used multiple times)
#alias: xxx
## Specify multiple values like this:
#alias:
# - xxx
# - yyy
# - zzz
## Verify the SSL cert when connecting to models (default: True)
#verify-ssl: true
@@ -324,8 +335,8 @@ cog.outl("```")
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#analytics: false
## Enable/disable analytics for current session (default: random)
#analytics: xxx
## Specify a file to log analytics events
#analytics-log: xxx
@@ -367,6 +378,9 @@ cog.outl("```")
## Check for new aider versions on launch
#check-update: true
## Show release notes on first run of new version (default: None, ask user)
#show-release-notes: xxx
## Install the latest version from the main branch
#install-main-branch: false
@@ -376,6 +390,9 @@ cog.outl("```")
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Always say yes to every confirmation
#yes-always: false
@@ -415,6 +432,12 @@ cog.outl("```")
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
## Enable/disable detection and offering to add URLs to chat (default: True)
#detect-urls: true
## Specify which editor to use for the /editor command
#editor: xxx
#################
# Voice Settings:

View File

@@ -78,6 +78,9 @@ cog.outl("```")
## Use claude-3-5-sonnet-20241022 model for the main chat
#AIDER_SONNET=
## Use claude-3-5-haiku-20241022 model for the main chat
#AIDER_HAIKU=
## Use gpt-4-0613 model for the main chat
#AIDER_4=
@@ -129,6 +132,9 @@ cog.outl("```")
## Specify a file with context window and costs for unknown models
#AIDER_MODEL_METADATA_FILE=.aider.model.metadata.json
## Add a model alias (can be used multiple times)
#AIDER_ALIAS=
## Verify the SSL cert when connecting to models (default: True)
#AIDER_VERIFY_SSL=true
@@ -309,8 +315,8 @@ cog.outl("```")
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#AIDER_ANALYTICS=false
## Enable/disable analytics for current session (default: random)
#AIDER_ANALYTICS=
## Specify a file to log analytics events
#AIDER_ANALYTICS_LOG=
@@ -339,6 +345,9 @@ cog.outl("```")
## Check for new aider versions on launch
#AIDER_CHECK_UPDATE=true
## Show release notes on first run of new version (default: None, ask user)
#AIDER_SHOW_RELEASE_NOTES=
## Install the latest version from the main branch
#AIDER_INSTALL_MAIN_BRANCH=false
@@ -348,6 +357,9 @@ cog.outl("```")
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
@@ -384,6 +396,12 @@ cog.outl("```")
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## Enable/disable detection and offering to add URLs to chat (default: True)
#AIDER_DETECT_URLS=true
## Specify which editor to use for the /editor command
#AIDER_EDITOR=
#################
# Voice Settings:

View File

@@ -0,0 +1,127 @@
---
parent: Configuration
nav_order: 15
description: How to configure a custom editor for aider's /editor command
---
# Editor configuration
Aider allows you to configure your preferred text editor for use with the `/editor` command. The editor must be capable of running in "blocking mode", meaning the command line will wait until you close the editor before proceeding.
## Using `--editor`
You can specify the text editor with the `--editor` switch or using
`editor:` in aider's
[yaml config file](https://aider.chat/docs/config/aider_conf.html).
## Environment variables
Aider checks the following environment variables in order to determine which editor to use:
1. `AIDER_EDITOR`
2. `VISUAL`
3. `EDITOR`
## Default behavior
If no editor is configured, aider will use these platform-specific defaults:
- Windows: `notepad`
- macOS: `vim`
- Linux/Unix: `vi`
## Using a custom editor
You can set your preferred editor in your shell's configuration file (e.g., `.bashrc`, `.zshrc`):
```bash
export AIDER_EDITOR=vim
```
## Popular Editors by Platform
### macOS
1. **vim**
```bash
export AIDER_EDITOR=vim
```
2. **Emacs**
```bash
export AIDER_EDITOR=emacs
```
3. **VSCode**
```bash
export AIDER_EDITOR="code --wait"
```
4. **Sublime Text**
```bash
export AIDER_EDITOR="subl --wait"
```
5. **BBEdit**
```bash
export AIDER_EDITOR="bbedit --wait"
```
### Linux
1. **vim**
```bash
export AIDER_EDITOR=vim
```
2. **Emacs**
```bash
export AIDER_EDITOR=emacs
```
3. **nano**
```bash
export AIDER_EDITOR=nano
```
4. **VSCode**
```bash
export AIDER_EDITOR="code --wait"
```
5. **Sublime Text**
```bash
export AIDER_EDITOR="subl --wait"
```
### Windows
1. **Notepad**
```bat
set AIDER_EDITOR=notepad
```
2. **VSCode**
```bat
set AIDER_EDITOR="code --wait"
```
3. **Notepad++**
```bat
set AIDER_EDITOR="notepad++ -multiInst -notabbar -nosession -noPlugin -waitForClose"
```
## Editor command arguments
Some editors require specific command-line arguments to operate in blocking mode. The `--wait` flag (or equivalent) is commonly used to make the editor block until the file is closed.
## Troubleshooting
If you encounter issues with your editor not blocking (returning to the prompt immediately), verify that:
1. Your editor supports blocking mode
2. You've included the necessary command-line arguments for blocking mode
3. The editor command is properly quoted if it contains spaces or special characters, e.g.:
```bash
export AIDER_EDITOR="code --wait"
```

View File

@@ -0,0 +1,72 @@
---
parent: Configuration
nav_order: 1000
description: Assign convenient short names to models.
---
# Model Aliases
Model aliases allow you to create shorthand names for models you frequently use. This is particularly useful for models with long names or when you want to standardize model usage across your team.
## Command Line Usage
You can define aliases when launching aider using the `--alias` option:
```bash
aider --alias "fast:gpt-3.5-turbo" --alias "smart:gpt-4"
```
Multiple aliases can be defined by using the `--alias` option multiple times. Each alias definition should be in the format `alias:model-name`.
## Configuration File
You can also define aliases in your [`.aider.conf.yml` file](https://aider.chat/docs/config/aider_conf.html):
```yaml
alias:
- "fast:gpt-3.5-turbo"
- "smart:gpt-4"
- "hacker:claude-3-sonnet-20240229"
```
## Using Aliases
Once defined, you can use the alias instead of the full model name:
```bash
aider --model fast # Uses gpt-3.5-turbo
aider --model smart # Uses gpt-4
```
## Built-in Aliases
Aider includes some built-in aliases for convenience:
<!--[[[cog
import cog
from aider.models import MODEL_ALIASES
for alias, model in sorted(MODEL_ALIASES.items()):
cog.outl(f"- `{alias}`: {model}")
]]]-->
- `3`: gpt-3.5-turbo
- `35-turbo`: gpt-3.5-turbo
- `35turbo`: gpt-3.5-turbo
- `4`: gpt-4-0613
- `4-turbo`: gpt-4-1106-preview
- `4o`: gpt-4o-2024-08-06
- `deepseek`: deepseek/deepseek-coder
- `haiku`: claude-3-haiku-20241022
- `opus`: claude-3-opus-20240229
- `sonnet`: claude-3-sonnet-20241022
<!--[[[end]]]-->
## Priority
If the same alias is defined in multiple places, the priority is:
1. Command line aliases (highest priority)
2. Configuration file aliases
3. Built-in aliases (lowest priority)
This allows you to override built-in aliases with your own preferences.

View File

@@ -26,15 +26,15 @@ cog.out(get_md_help())
]]]-->
```
usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--opus] [--sonnet] [--4] [--4o] [--mini] [--4-turbo]
[--35turbo] [--deepseek] [--o1-mini] [--o1-preview]
[--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]
[--architect] [--weak-model] [--editor-model]
[--editor-edit-format]
[--opus] [--sonnet] [--haiku] [--4] [--4o] [--mini]
[--4-turbo] [--35turbo] [--deepseek] [--o1-mini]
[--o1-preview] [--list-models] [--openai-api-base]
[--openai-api-type] [--openai-api-version]
[--openai-api-deployment-id] [--openai-organization-id]
[--model-settings-file] [--model-metadata-file]
[--alias] [--verify-ssl | --no-verify-ssl]
[--edit-format] [--architect] [--weak-model]
[--editor-model] [--editor-edit-format]
[--show-model-warnings | --no-show-model-warnings]
[--max-chat-history-tokens] [--env-file]
[--cache-prompts | --no-cache-prompts]
@@ -66,14 +66,16 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--analytics-disable] [--file] [--read] [--vim]
[--chat-language] [--version] [--just-check-update]
[--check-update | --no-check-update]
[--show-release-notes | --no-show-release-notes]
[--install-main-branch] [--upgrade] [--apply]
[--yes-always] [-v] [--show-repo-map] [--show-prompts]
[--exit] [--message] [--message-file] [--load]
[--encoding] [-c]
[--apply-clipboard-edits] [--yes-always] [-v]
[--show-repo-map] [--show-prompts] [--exit] [--message]
[--message-file] [--load] [--encoding] [-c]
[--gui | --no-gui | --browser | --no-browser]
[--suggest-shell-commands | --no-suggest-shell-commands]
[--fancy-input | --no-fancy-input] [--voice-format]
[--voice-language]
[--fancy-input | --no-fancy-input]
[--detect-urls | --no-detect-urls] [--editor]
[--voice-format] [--voice-language]
```
@@ -107,6 +109,10 @@ Environment variable: `AIDER_OPUS`
Use claude-3-5-sonnet-20241022 model for the main chat
Environment variable: `AIDER_SONNET`
### `--haiku`
Use claude-3-5-haiku-20241022 model for the main chat
Environment variable: `AIDER_HAIKU`
### `--4`
Use gpt-4-0613 model for the main chat
Environment variable: `AIDER_4`
@@ -186,6 +192,10 @@ Specify a file with context window and costs for unknown models
Default: .aider.model.metadata.json
Environment variable: `AIDER_MODEL_METADATA_FILE`
### `--alias ALIAS:MODEL`
Add a model alias (can be used multiple times)
Environment variable: `AIDER_ALIAS`
### `--verify-ssl`
Verify the SSL cert when connecting to models (default: True)
Default: True
@@ -506,8 +516,7 @@ Environment variable: `AIDER_TEST`
## Analytics:
### `--analytics`
Enable/disable analytics for one session (default: False)
Default: False
Enable/disable analytics for current session (default: random)
Environment variable: `AIDER_ANALYTICS`
Aliases:
- `--analytics`
@@ -557,6 +566,13 @@ Aliases:
- `--check-update`
- `--no-check-update`
### `--show-release-notes`
Show release notes on first run of new version (default: None, ask user)
Environment variable: `AIDER_SHOW_RELEASE_NOTES`
Aliases:
- `--show-release-notes`
- `--no-show-release-notes`
### `--install-main-branch`
Install the latest version from the main branch
Default: False
@@ -574,6 +590,11 @@ Aliases:
Apply the changes from the given file instead of running the chat (debug)
Environment variable: `AIDER_APPLY`
### `--apply-clipboard-edits`
Apply clipboard contents as edits using the main model's editor format
Default: False
Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS`
### `--yes-always`
Always say yes to every confirmation
Environment variable: `AIDER_YES_ALWAYS`
@@ -657,6 +678,18 @@ Aliases:
- `--fancy-input`
- `--no-fancy-input`
### `--detect-urls`
Enable/disable detection and offering to add URLs to chat (default: True)
Default: True
Environment variable: `AIDER_DETECT_URLS`
Aliases:
- `--detect-urls`
- `--no-detect-urls`
### `--editor VALUE`
Specify which editor to use for the /editor command
Environment variable: `AIDER_EDITOR`
## Voice Settings:
### `--voice-format VOICE_FORMAT`

View File

@@ -30,7 +30,7 @@ current chat to build a compact
Adding a bunch of files that are mostly irrelevant to the
task at hand will often distract or confuse the LLM.
The LLM will give worse coding results, and sometimese even fail to correctly edit files.
Addings extra files will also increase the token costs on your OpenAI invoice.
Addings extra files will also increase your token costs.
Again, it's usually best to just add the files to the chat that will need to be modified.
If you still wish to add lots of files to the chat, you can:
@@ -60,6 +60,23 @@ directory you start in.
You can also create a `.aiderignore` file to tell aider
to ignore parts of the repo that aren't relevant to your task.
This file conforms to `.gitignore` syntax and conventions.
For example, to focus only on specific directories in a monorepo,
you could create a `.aiderignore` file with:
```
# Ignore everything
/*
# Allow specific directories and their contents
!foo/
!bar/
!baz/
# Allow nested files under these directories
!foo/**
!bar/**
!baz/**
```
You can use `--aiderignore <filename>` to name a specific file
to use for ignore patterns.
@@ -150,7 +167,6 @@ python -m aider
## Can I change the system prompts that aider uses?
Aider is set up to support different system prompts and edit formats
@@ -191,6 +207,16 @@ You can also refer to the
[instructions for installing a development version of aider](https://aider.chat/docs/install/optional.html#install-the-development-version-of-aider).
## How are the "aider wrote xx% of code" stats computed?
[Aider is tightly integrated with git](/docs/git.html) so all
of aider's code changes are committed to the repo with proper attribution.
The
[stats are computed](https://github.com/Aider-AI/aider/blob/main/scripts/blame.py)
by doing something like `git blame` on the repo,
and counting up who wrote all the new lines of code in each release.
Only lines in source code files are counted, not documentation or prompt files.
## Can I share my aider chat transcript?
Yes, you can now share aider chat logs in a pretty way.
@@ -213,6 +239,15 @@ This will give you a URL like this, which shows the chat history like you'd see
https://aider.chat/share/?mdurl=https://gist.github.com/Aider-AI/2087ab8b64034a078c0a209440ac8be0
```
## Can I edit files myself while aider is running?
Yes. Aider always reads the latest copy of files from the file
system when you send each message.
While you're waiting for aider's reply to complete, it's probably unwise to
edit files that you've added to the chat.
Your edits and aider's edits might conflict.
## What is Aider AI LLC?
Aider AI LLC is the company behind the aider AI coding tool.
@@ -222,11 +257,5 @@ under an
[Apache 2.0 license](https://github.com/Aider-AI/aider/blob/main/LICENSE.txt).
## Can I edit files myself while aider is running?
<div style="height:80vh"></div>
Yes. Aider always reads the latest copy of files from the file
system when you send each message.
While you're waiting for aider's reply to complete, it's probably unwise to
edit files that you've added to the chat.
Your edits and aider's edits might conflict.

View File

@@ -62,6 +62,7 @@ cog.out(get_supported_languages_md())
| cpp | .cc | ✓ | ✓ |
| cpp | .cpp | ✓ | ✓ |
| css | .css | | ✓ |
| dart | .dart | ✓ | ✓ |
| dockerfile | .dockerfile | | ✓ |
| dot | .dot | | ✓ |
| elisp | .el | ✓ | ✓ |

View File

@@ -31,6 +31,8 @@ This measures the LLM's coding ability, and whether it can
write new code that integrates into existing code.
The model also has to successfully apply all its changes to the source file without human intervention.
<input type="text" id="editSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
<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>
@@ -58,79 +60,7 @@ The model also has to successfully apply all its changes to the source file with
<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();
});
{% include edit-leaderboard.js %}
</script>
<style>
tr.selected {
@@ -156,6 +86,8 @@ The refactoring benchmark requires a large context window to
work with large source files.
Therefore, results are available for fewer models.
<input type="text" id="refacSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
<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>
@@ -183,79 +115,7 @@ Therefore, results are available for fewer models.
<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();
});
{% include refactor-leaderboard.js %}
</script>
@@ -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.')}")
]]]-->
October 22, 2024.
November 24, 2024.
<!--[[[end]]]-->
</p>

View File

@@ -1,22 +0,0 @@
---
parent: Connecting to LLMs
nav_order: 850
---
# Editing format
Aider uses different "edit formats" to collect code edits from different LLMs.
The "whole" format is the easiest for an LLM to use, but it uses a lot of tokens
and may limit how large a file can be edited.
Models which can use one of the diff formats are much more efficient,
using far fewer tokens.
Models that use a diff-like format are able to
edit larger files with less cost and without hitting token limits.
Aider is configured to use the best edit format for the popular OpenAI and Anthropic models
and the [other models recommended on the LLM page](https://aider.chat/docs/llms.html).
For lesser known models aider will default to using the "whole" editing format
since it is the easiest format for an LLM to use.
If you would like to experiment with the more advanced formats, you can
use these switches: `--edit-format diff` or `--edit-format udiff`.

View File

@@ -0,0 +1,26 @@
---
parent: Connecting to LLMs
nav_order: 400
---
# LM Studio
To use LM Studio:
```
python -m pip install -U aider-chat
export LM_STUDIO_API_KEY=<key> # Mac/Linux
setx LM_STUDIO_API_KEY <key> # Windows, restart shell after setx
export LM_STUDIO_API_BASE=<url> # Mac/Linux
setx LM_STUDIO_API_BASE <url> # Windows, restart shell after setx
aider --model lm_studio/<your-model-name>
```
See the [model warnings](warnings.html)
section for information on warnings which will occur
when working with models that aider is not familiar with.

View File

@@ -20,24 +20,49 @@ python -m pip install -U aider-chat
export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
aider --model ollama/<model>
aider --model ollama_chat/<model>
```
In particular, `llama3:70b` works well with aider:
{: .note }
Using `ollama_chat/` is recommended over `ollama/`.
```
ollama pull llama3:70b
ollama serve
# In another terminal window...
export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
aider --model ollama/llama3:70b
```
See the [model warnings](warnings.html)
section for information on warnings which will occur
when working with models that aider is not familiar with.
## API Key
If you are using an ollama that requires an API key you can set `OLLAMA_API_KEY`:
```
export OLLAMA_API_KEY=<api-key> # Mac/Linux
setx OLLAMA_API_KEY <api-key> # Windows, restart shell after setx
```
## Setting the context window size
[Ollama uses a 2k context window by default](https://github.com/ollama/ollama/blob/main/docs/faq.md#how-can-i-specify-the-context-window-size),
which is very small for working with aider.
Aider sets Ollama's context window to 8k by default.
If you would like
a larger context window
you can use a
[`.aider.model.settings.yml` file](https://aider.chat/docs/config/adv-model-settings.html#model-settings)
like this:
```
- name: ollama/qwen2.5-coder:32b-instruct-fp16
extra_params:
num_ctx: 8192
```
Unlike most other LLM servers, Ollama does not throw an error if you submit
a request that exceeds the context window.
Instead, it just silently truncates the request by discarding the "oldest" messages
in the chat to make it fit within the context window.
So if your context window is too small, you won't get an error.
Aider will probably just fail to work well and experience
a lot of
[file editing problems](https://aider.chat/docs/troubleshooting/edit-errors.html).

View File

@@ -95,5 +95,6 @@ cog.out(''.join(lines))
- TOGETHERAI_API_KEY
- VOLCENGINE_API_KEY
- VOYAGE_API_KEY
- XAI_API_KEY
- XINFERENCE_API_KEY
<!--[[[end]]]-->

View File

@@ -0,0 +1,24 @@
---
parent: Connecting to LLMs
nav_order: 400
---
# xAI
You'll need a [xAI API key](https://console.x.ai.).
To use xAI:
```
python -m pip install -U aider-chat
export XAI_API_KEY=<key> # Mac/Linux
setx XAI_API_KEY <key> # Windows, restart shell after setx
aider --model xai/grok-beta
# List models available from xAI
aider --list-models xai/
```

View File

@@ -31,7 +31,7 @@ features and commands are most used.
It also helps uncover bugs that users are experiencing, so that they can be fixed
in upcoming releases.
## Enabling & disabling analytics
## Disabling analytics
You can opt out of analytics forever by running this command one time:
@@ -39,10 +39,27 @@ You can opt out of analytics forever by running this command one time:
aider --analytics-disable
```
To enable analytics for a single session, you can run aider with `--analytics`.
This will *not* have any effect if you have permanently disabled analytics with the previous command.
## Enabling analytics
The first time, you will need to agree to opt-in.
The `--[no-]analytics` switch controls whether analytics are enabled for the
current session:
- `--analytics` will turn on analytics for the current session.
This will *not* have any effect if you have permanently disabled analytics
with `--analytics-disable`.
If this is the first time you have enabled analytics, aider
will confirm you wish to opt-in to analytics.
- `--no-analytics` will turn off analytics for the current session.
- By default, if you don't provide `--analytics` or `--no-analytics`,
aider will enable analytics for a random subset of users.
This will never happen if you have permanently disabled analytics
with `--analytics-disable`.
Randomly selected users will be asked if they wish to opt-in to analytics.
## Opting in
The first time analytics are enabled, you will need to agree to opt-in.
```
aider --analytics
@@ -53,13 +70,8 @@ For more info: https://aider.chat/docs/more/analytics.html
Allow collection of anonymous analytics to help improve aider? (Y)es/(N)o [Yes]:
```
If you've added `analytics: true` to your
[yaml config file](/docs/config/aider_conf.html),
you can disable analytics for a single session, you can run:
If you say "no", analytics will be permanently disabled.
```
aider --no-analytics
```
## Details about data being collected
@@ -100,7 +112,7 @@ aider --analytics-log filename.jsonl --no-analytics
If you have concerns about any of the analytics that aider is collecting
or our data practices
please contact us by opening a
[GitHub Issue](https://github.com/paul-gauthier/aider/issues).
[GitHub Issue](https://github.com/aider-ai/aider/issues).
## Privacy policy

View File

@@ -55,8 +55,9 @@ model_list = "\n".join(f"- {model}" for model in sorted(prefill_models))
cog.out(model_list)
]]]-->
- anthropic.claude-3-5-haiku-20241022-v1:0
- anthropic.claude-3-5-sonnet-20241022-v2:0
- anthropic/claude-3-5-sonnet-20241022
- claude-3-5-haiku-20241022
- claude-3-5-sonnet-20240620
- claude-3-5-sonnet-20241022
- claude-3-haiku-20240307
@@ -87,11 +88,19 @@ cog.out(model_list)
- mistral/open-mixtral-8x7b
- mistral/pixtral-12b-2409
- openrouter/anthropic/claude-3.5-sonnet
- us.anthropic.claude-3-5-haiku-20241022-v1:0
- us.anthropic.claude-3-5-sonnet-20241022-v2:0
- vertex_ai/claude-3-5-haiku
- vertex_ai/claude-3-5-haiku@20241022
- vertex_ai/claude-3-5-sonnet
- vertex_ai/claude-3-5-sonnet-v2
- vertex_ai/claude-3-5-sonnet-v2@20241022
- vertex_ai/claude-3-5-sonnet@20240620
- vertex_ai/claude-3-haiku
- vertex_ai/claude-3-haiku@20240307
- vertex_ai/claude-3-opus
- vertex_ai/claude-3-opus@20240229
- vertex_ai/claude-3-sonnet
- vertex_ai/claude-3-sonnet@20240229
<!--[[[end]]]-->

View File

@@ -95,3 +95,6 @@ io = InputOutput(yes=True)
coder = Coder.create(model=model, fnames=fnames, io=io)
```
{: .note }
The scripting API is not officially supported or documented and may
change without warning.

View File

@@ -19,31 +19,7 @@ LLM edits that are "almost" correctly formatted.
But sometimes the LLM just won't cooperate.
In these cases, here are some things you might try.
## Use a capable model
If possible try using GPT-4o, Claude 3.5 Sonnet or Claude 3 Opus,
as they are the strongest and most capable models.
Weaker models
are more prone to
disobeying the system prompt instructions.
Most local models are just barely capable of working with aider,
so editing errors are probably unavoidable.
Local models which have been quantized are even more likely to have problems
because they are not capable enough to follow aider's system prompts.
## Try the whole format
Run aider with `--edit-format whole` if the model is using a different edit format.
You can see which edit format it is using in the announce lines:
```
Aider v0.50.2-dev
Models: claude-3-5-sonnet-20240620 with ♾️ diff edit format
```
## Reduce distractions
## Don't add too many files
Many LLMs now have very large context windows,
but filling them with irrelevant code or conversation
@@ -55,6 +31,38 @@ Aider also sends the LLM a [map of your entire git repo](https://aider.chat/docs
- Use `/clear` to remove the conversation history, again to help the LLM focus.
- Use `/tokens` to see how many tokens you are using for each message.
## Use a more capable model
If possible try using GPT-4o, Claude 3.5 Sonnet or Claude 3 Opus,
as they are the strongest and most capable models.
Weaker models
are more prone to
disobeying the system prompt instructions.
Most local models are just barely capable of working with aider,
so editing errors are probably unavoidable.
## Local models: context window and quantization
Be especially careful about the
[Ollama context window](https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size)
when working with local models.
It defaults to be very small and silently discards data if you exceed it.
Local models which have been quantized are more likely to have editing problems
because they are not capable enough to follow aider's system prompts.
## Try the whole edit format
Run aider with `--edit-format whole` if were using a different edit format.
You can see which edit format it is using in the announce lines:
```
Aider v0.50.2-dev
Models: claude-3-5-sonnet-20240620 with ♾️ diff edit format
```
## More help
{% include help.md %}

View File

@@ -33,6 +33,13 @@ To reduce output tokens:
For more info: https://aider.chat/docs/token-limits.html
```
{: .note }
Aider never *enforces* token limits, it only *reports* token limit errors
from the API provider.
You probably don't need to
[configure aider with the proper token limits](http://0.0.0.0:4000/docs/config/adv-model-settings.html#context-window-size-and-token-costs)
for unusual models.
## Input tokens & context window size
The most common problem is trying to send too much data to a

View File

@@ -3,7 +3,14 @@ parent: Usage
nav_order: 50
description: Control aider with in-chat commands like /add, /model, etc.
---
# In-chat commands
{: .no_toc }
- TOC
{:toc}
## Slash commands
Aider supports commands from within the chat, which all start with `/`.
@@ -24,6 +31,7 @@ cog.out(get_help_md())
| **/copy** | Copy the last assistant message to the clipboard |
| **/diff** | Display the diff of changes since the last message |
| **/drop** | Remove files from the chat session to free up context space |
| **/editor** | Open an editor to write a prompt |
| **/exit** | Exit the application |
| **/git** | Run a git command (output excluded from chat) |
| **/help** | Ask questions about aider |

View File

@@ -1,7 +1,7 @@
---
parent: Usage
nav_order: 60
description: Using the chat, ask and help chat modes.
description: Using the code, architect, ask and help chat modes.
---
# Chat modes

View File

@@ -2,6 +2,12 @@
nav_exclude: true
---
<meta http-equiv="Content-Security-Policy"
content="default-src 'self';
script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com;
connect-src http: https:;
style-src 'self' 'unsafe-inline';">
# Shared aider chat transcript
A user has shared the following transcript of a pair programming chat session
@@ -37,11 +43,29 @@ print("goodbye")
</div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.6/purify.min.js"></script>
<script>
function isValidUrl(url) {
try {
const urlObj = new URL(url);
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
} catch {
return false;
}
}
// Configure marked with secure defaults
marked.setOptions({
headerIds: false,
mangle: false
});
window.onload = function() {
var urlParams = new URLSearchParams(window.location.search);
var conv = urlParams.get('mdurl');
if (!conv) {
if (!conv || !isValidUrl(conv)) {
document.querySelector('#shared-transcript').innerHTML =
'<div style="color: red; padding: 1em;">Error: Invalid or missing URL provided</div>';
return;
}
document.getElementById('mdurl').href = conv;
@@ -63,11 +87,14 @@ window.onload = function() {
return line;
}).join('\n');
var html = marked.parse(markdown);
var sanitizedHtml = DOMPurify.sanitize(html);
var divElement = document.querySelector('#shared-transcript');
divElement.innerHTML = html;
divElement.innerHTML = sanitizedHtml;
})
.catch(error => {
console.error('Error fetching markdown:', error);
document.querySelector('#shared-transcript').innerHTML =
'<div style="color: red; padding: 1em;">Error: Failed to load chat transcript</div>';
});
}
</script>

View File

@@ -155,6 +155,9 @@ def main(
tries: int = typer.Option(2, "--tries", "-r", help="Number of tries for running tests"),
threads: int = typer.Option(1, "--threads", "-t", help="Number of threads to run in parallel"),
num_tests: int = typer.Option(-1, "--num-tests", "-n", help="Number of tests to run"),
num_ctx: Optional[int] = typer.Option(
None, "--num-ctx", help="Override model context window size"
),
exercises_dir: str = typer.Option(
EXERCISES_DIR_DEFAULT, "--exercises-dir", help="Directory with exercise files"
),
@@ -247,6 +250,7 @@ def main(
max_apply_update_errors,
editor_model,
editor_edit_format,
num_ctx,
)
all_results.append(results)
@@ -526,6 +530,7 @@ def run_test_real(
max_apply_update_errors,
editor_model,
editor_edit_format,
num_ctx=None,
):
if not os.path.isdir(testdir):
print("Not a dir:", testdir)
@@ -588,6 +593,11 @@ def run_test_real(
editor_model=editor_model,
editor_edit_format=editor_edit_format,
)
if num_ctx:
if not main_model.extra_params:
main_model.extra_params = {}
main_model.extra_params["num_ctx"] = num_ctx
edit_format = edit_format or main_model.edit_format
dump(main_model)

View File

@@ -2,6 +2,7 @@
docker run \
-it --rm \
--add-host=host.docker.internal:host-gateway \
-v `pwd`:/aider \
-v `pwd`/tmp.benchmarks/.:/benchmarks \
-e OPENAI_API_KEY=$OPENAI_API_KEY \

View File

@@ -1,121 +1,168 @@
from dataclasses import dataclass
from datetime import date
from typing import Dict, List, Tuple
import matplotlib.pyplot as plt
import yaml
from imgcat import imgcat
from matplotlib import rc
from aider.dump import dump # noqa: 401
@dataclass
class ModelData:
name: str
release_date: date
pass_rate: float
@property
def color(self) -> str:
model = self.name.lower()
if "gemini" in model and "pro" in model:
return "magenta"
if "qwen" in model:
return "darkblue"
if "mistral" in model:
return "cyan"
if "haiku" in model:
return "pink"
if "deepseek" in model:
return "brown"
if "sonnet" in model:
return "orange"
if "-4o" in model:
return "purple"
if "gpt-4" in model:
return "red"
if "gpt-3.5" in model:
return "green"
return "lightblue"
@property
def legend_label(self) -> str:
model = self.name.lower()
if "gemini" in model and "pro" in model:
return "Gemini 1.5 Pro"
if "claude-3-sonnet" in model:
return "Sonnet"
if "o1-preview" in model:
return "O1 Preview"
if "gpt-3.5" in model:
return "GPT-3.5 Turbo"
if "gpt-4-" in model and "-4o" not in model:
return "GPT-4"
if "qwen" in model:
return "Qwen"
if "-4o" in model:
return "GPT-4o"
if "haiku" in model:
return "Haiku"
if "deepseek" in model:
return "DeepSeek"
if "mistral" in model:
return "Mistral"
return model
def get_model_color(model):
default = "lightblue"
class BenchmarkPlotter:
LABEL_FONT_SIZE = 16
if model == "gpt-4o-mini":
return default
def __init__(self):
self.setup_plot_style()
if "-4o" in model:
return "purple"
def setup_plot_style(self):
plt.rcParams["hatch.linewidth"] = 0.5
plt.rcParams["hatch.color"] = "#444444"
rc("font", **{"family": "sans-serif", "sans-serif": ["Helvetica"], "size": 10})
plt.rcParams["text.color"] = "#444444"
if "gpt-4" in model:
return "red"
def load_data(self, yaml_file: str) -> List[ModelData]:
with open(yaml_file, "r") as file:
data = yaml.safe_load(file)
if "gpt-3.5" in model:
return "green"
models = []
for entry in data:
if "released" in entry and "pass_rate_2" in entry:
model = ModelData(
name=entry["model"].split("(")[0].strip(),
release_date=entry["released"],
pass_rate=entry["pass_rate_2"],
)
models.append(model)
return models
return default
def create_figure(self) -> Tuple[plt.Figure, plt.Axes]:
fig, ax = plt.subplots(figsize=(12, 8))
ax.grid(axis="y", zorder=0, lw=0.2)
for spine in ax.spines.values():
spine.set_edgecolor("#DDDDDD")
spine.set_linewidth(0.5)
return fig, ax
def plot_model_series(self, ax: plt.Axes, models: List[ModelData]):
# Group models by color
color_groups: Dict[str, List[ModelData]] = {}
for model in models:
if model.color not in color_groups:
color_groups[model.color] = []
color_groups[model.color].append(model)
def plot_over_time(yaml_file):
with open(yaml_file, "r") as file:
data = yaml.safe_load(file)
# Plot each color group
for color, group in color_groups.items():
sorted_group = sorted(group, key=lambda x: x.release_date)
dates = [m.release_date for m in sorted_group]
rates = [m.pass_rate for m in sorted_group]
dates = []
pass_rates = []
models = []
# Plot line
ax.plot(dates, rates, c=color, alpha=0.5, linewidth=1)
print("Debug: Raw data from YAML file:")
print(data)
# Plot points
ax.scatter(dates, rates, c=color, alpha=0.5, s=120)
for entry in data:
if "released" in entry and "pass_rate_2" in entry:
dates.append(entry["released"])
pass_rates.append(entry["pass_rate_2"])
models.append(entry["model"].split("(")[0].strip())
# Add label for first point
first_model = sorted_group[0]
ax.annotate(
first_model.legend_label,
(first_model.release_date, first_model.pass_rate),
xytext=(10, 5),
textcoords="offset points",
color=color,
alpha=0.8,
fontsize=self.LABEL_FONT_SIZE,
)
print("Debug: Processed data:")
print("Dates:", dates)
print("Pass rates:", pass_rates)
print("Models:", models)
if not dates or not pass_rates:
print(
"Error: No data to plot. Check if the YAML file is empty or if the data is in the"
" expected format."
def set_labels_and_style(self, ax: plt.Axes):
ax.set_xlabel("Model release date", fontsize=18, color="#555")
ax.set_ylabel(
"Aider code editing benchmark,\npercent completed correctly", fontsize=18, color="#555"
)
return
ax.set_title("LLM code editing skill by model release date", fontsize=20)
ax.set_ylim(30, 90)
plt.xticks(fontsize=14, rotation=45, ha="right")
plt.tight_layout(pad=1.0)
plt.rcParams["hatch.linewidth"] = 0.5
plt.rcParams["hatch.color"] = "#444444"
def save_and_display(self, fig: plt.Figure):
plt.savefig("aider/website/assets/models-over-time.png")
plt.savefig("aider/website/assets/models-over-time.svg")
imgcat(fig)
rc("font", **{"family": "sans-serif", "sans-serif": ["Helvetica"], "size": 10})
plt.rcParams["text.color"] = "#444444"
fig, ax = plt.subplots(figsize=(12, 6)) # Increase figure size for better visibility
print("Debug: Figure created. Plotting data...")
ax.grid(axis="y", zorder=0, lw=0.2)
for spine in ax.spines.values():
spine.set_edgecolor("#DDDDDD")
spine.set_linewidth(0.5)
colors = [get_model_color(model) for model in models]
# Separate data points by color
purple_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "purple"]
red_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "red"]
green_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "green"]
# Plot lines for purple, red, and green points
if purple_points:
purple_dates, purple_rates = zip(*sorted(purple_points))
ax.plot(purple_dates, purple_rates, c="purple", alpha=0.5, linewidth=1)
if red_points:
red_dates, red_rates = zip(*sorted(red_points))
ax.plot(red_dates, red_rates, c="red", alpha=0.5, linewidth=1)
if green_points:
green_dates, green_rates = zip(*sorted(green_points))
ax.plot(green_dates, green_rates, c="green", alpha=0.5, linewidth=1)
# Plot all points
ax.scatter(dates, pass_rates, c=colors, alpha=0.5, s=120)
for i, model in enumerate(models):
ax.annotate(
model,
(dates[i], pass_rates[i]),
fontsize=8,
alpha=0.75,
xytext=(5, 5),
textcoords="offset points",
)
ax.set_xlabel("Model release date", fontsize=18, color="#555")
ax.set_ylabel(
"Aider code editing benchmark,\npercent completed correctly", fontsize=18, color="#555"
)
ax.set_title("LLM code editing skill by model release date", fontsize=20)
ax.set_ylim(0, 100) # Adjust y-axis limit to accommodate higher values
plt.xticks(fontsize=14, rotation=45, ha="right") # Rotate x-axis labels for better readability
plt.tight_layout(pad=3.0)
print("Debug: Saving figures...")
plt.savefig("tmp_over_time.png")
plt.savefig("tmp_over_time.svg")
print("Debug: Displaying figure with imgcat...")
imgcat(fig)
print("Debug: Figure generation complete.")
def plot(self, yaml_file: str):
models = self.load_data(yaml_file)
fig, ax = self.create_figure()
self.plot_model_series(ax, models)
self.set_labels_and_style(ax)
self.save_and_display(fig)
# Example usage
plot_over_time("aider/website/_data/edit_leaderboard.yml")
def main():
plotter = BenchmarkPlotter()
models = plotter.load_data("aider/website/_data/edit_leaderboard.yml")
# Print release dates and model names
for model in sorted(models, key=lambda x: x.release_date):
print(f"{model.release_date}: {model.name}")
plotter.plot("aider/website/_data/edit_leaderboard.yml")
if __name__ == "__main__":
main()

View File

@@ -58,6 +58,7 @@ include = ["aider*", "aider.website"]
"docs/unified-diffs.md",
"docs/leaderboards/index.md",
"assets/**",
"**/.DS_Store",
# [[[end]]]
]

View File

@@ -6,7 +6,7 @@
#
aiohappyeyeballs==2.4.3
# via aiohttp
aiohttp==3.10.10
aiohttp==3.11.7
# via litellm
aiosignal==1.3.1
# via aiohttp
@@ -62,11 +62,11 @@ gitdb==4.0.11
# via gitpython
gitpython==3.1.43
# via -r requirements/requirements.in
grep-ast==0.3.3
grep-ast==0.4.0
# via -r requirements/requirements.in
h11==0.14.0
# via httpcore
httpcore==1.0.6
httpcore==1.0.7
# via httpx
httpx==0.27.2
# via openai
@@ -86,9 +86,9 @@ importlib-resources==6.4.5
# via -r requirements/requirements.in
jinja2==3.1.4
# via litellm
jiter==0.7.0
jiter==0.7.1
# via openai
json5==0.9.25
json5==0.9.28
# via -r requirements/requirements.in
jsonschema==4.23.0
# via
@@ -96,7 +96,7 @@ jsonschema==4.23.0
# litellm
jsonschema-specifications==2024.10.1
# via jsonschema
litellm==1.51.2
litellm==1.52.16
# via -r requirements/requirements.in
markdown-it-py==3.0.0
# via rich
@@ -120,9 +120,9 @@ numpy==1.26.4
# via
# -r requirements/requirements.in
# scipy
openai==1.53.0
openai==1.55.1
# via litellm
packaging==24.1
packaging==24.2
# via
# -r requirements/requirements.in
# huggingface-hub
@@ -134,12 +134,14 @@ pexpect==4.9.0
# via -r requirements/requirements.in
pillow==10.4.0
# via -r requirements/requirements.in
posthog==3.7.0
posthog==3.7.3
# via -r requirements/requirements.in
prompt-toolkit==3.0.48
# via -r requirements/requirements.in
propcache==0.2.0
# via yarl
# via
# aiohttp
# yarl
psutil==6.1.0
# via -r requirements/requirements.in
ptyprocess==0.7.0
@@ -148,11 +150,11 @@ pycodestyle==2.12.1
# via flake8
pycparser==2.22
# via cffi
pydantic==2.9.2
pydantic==2.10.2
# via
# litellm
# openai
pydantic-core==2.23.4
pydantic-core==2.27.1
# via pydantic
pydub==0.25.1
# via -r requirements/requirements.in
@@ -176,7 +178,7 @@ referencing==0.35.1
# via
# jsonschema
# jsonschema-specifications
regex==2024.9.11
regex==2024.11.6
# via tiktoken
requests==2.32.3
# via
@@ -185,9 +187,9 @@ requests==2.32.3
# mixpanel
# posthog
# tiktoken
rich==13.9.3
rich==13.9.4
# via -r requirements/requirements.in
rpds-py==0.20.1
rpds-py==0.21.0
# via
# jsonschema
# referencing
@@ -217,7 +219,7 @@ tokenizers==0.19.1
# via
# -r requirements/requirements.in
# litellm
tqdm==4.66.6
tqdm==4.67.1
# via
# huggingface-hub
# openai
@@ -239,7 +241,7 @@ urllib3==2.2.3
# requests
wcwidth==0.2.13
# via prompt-toolkit
yarl==1.17.1
yarl==1.18.0
# via aiohttp
zipp==3.20.2
zipp==3.21.0
# via importlib-metadata

View File

@@ -4,109 +4,109 @@
#
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
#
altair==5.4.1
altair==5.5.0
# via streamlit
attrs==24.2.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-help.txt
# jsonschema
# referencing
blinker==1.8.2
blinker==1.9.0
# via streamlit
cachetools==5.5.0
# via streamlit
certifi==2024.8.30
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
charset-normalizer==3.4.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
click==8.1.7
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
gitdb==4.0.11
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# gitpython
gitpython==3.1.43
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# streamlit
idna==3.10
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
jinja2==3.1.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# altair
# pydeck
jsonschema==4.23.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# altair
jsonschema-specifications==2024.10.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# jsonschema
markdown-it-py==3.0.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# rich
markupsafe==3.0.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# jinja2
mdurl==0.1.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# markdown-it-py
narwhals==1.12.1
narwhals==1.14.2
# via altair
numpy==1.26.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# pandas
# pydeck
# streamlit
packaging==24.1
packaging==24.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# altair
@@ -117,27 +117,27 @@ pandas==2.2.3
# streamlit
pillow==10.4.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
protobuf==5.28.3
# via streamlit
pyarrow==18.0.0
pyarrow==18.1.0
# via streamlit
pydeck==0.9.1
# via streamlit
pygments==2.18.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# rich
python-dateutil==2.9.0.post0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# pandas
pytz==2024.2
@@ -146,41 +146,41 @@ pytz==2024.2
# pandas
referencing==0.35.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# jsonschema
# jsonschema-specifications
requests==2.32.3
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
rich==13.9.3
rich==13.9.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# streamlit
rpds-py==0.20.1
rpds-py==0.21.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# jsonschema
# referencing
six==1.16.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# python-dateutil
smmap==5.0.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# gitdb
streamlit==1.39.0
streamlit==1.40.2
# via -r requirements/requirements-browser.in
tenacity==8.5.0
# via
@@ -188,12 +188,12 @@ tenacity==8.5.0
# streamlit
toml==0.10.2
# via streamlit
tornado==6.4.1
tornado==6.4.2
# via streamlit
typing-extensions==4.12.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# altair
@@ -204,8 +204,8 @@ tzdata==2024.2
# pandas
urllib3==2.2.3
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests

View File

@@ -12,27 +12,27 @@ build==1.2.2.post1
# via pip-tools
certifi==2024.8.30
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
cfgv==3.4.0
# via pre-commit
charset-normalizer==3.4.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
click==8.1.7
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -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
contourpy==1.3.1
# via matplotlib
cycler==0.12.1
# via matplotlib
@@ -48,28 +48,28 @@ docutils==0.21.2
# sphinx-rtd-theme
filelock==3.16.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# virtualenv
fonttools==4.54.1
fonttools==4.55.0
# via matplotlib
identify==2.6.1
identify==2.6.3
# via pre-commit
idna==3.10
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
imagesize==1.4.1
# via sphinx
imgcat==0.5.0
imgcat==0.6.0
# via -r requirements/requirements-dev.in
iniconfig==2.0.0
# via pytest
jinja2==3.1.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# sphinx
kiwisolver==1.4.7
# via matplotlib
@@ -77,20 +77,20 @@ lox==0.12.0
# via -r requirements/requirements-dev.in
markdown-it-py==3.0.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# rich
markupsafe==3.0.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# jinja2
matplotlib==3.9.2
# via -r requirements/requirements-dev.in
mdurl==0.1.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# markdown-it-py
multiprocess==0.70.17
# via pathos
@@ -98,15 +98,15 @@ nodeenv==1.9.1
# via pre-commit
numpy==1.26.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# contourpy
# matplotlib
# pandas
packaging==24.1
packaging==24.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# build
# matplotlib
# pytest
@@ -117,8 +117,8 @@ pathos==0.3.3
# via lox
pillow==10.4.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# matplotlib
pip-tools==7.4.1
# via -r requirements/requirements-dev.in
@@ -134,8 +134,8 @@ pre-commit==4.0.1
# via -r requirements/requirements-dev.in
pygments==2.18.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# rich
# sphinx
pyparsing==3.2.0
@@ -148,26 +148,26 @@ pytest==8.3.3
# via -r requirements/requirements-dev.in
python-dateutil==2.9.0.post0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# matplotlib
# pandas
pytz==2024.2
# via pandas
pyyaml==6.0.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# pre-commit
requests==2.32.3
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# sphinx
rich==13.9.3
rich==13.9.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# typer
semver==3.0.2
# via -r requirements/requirements-dev.in
@@ -175,8 +175,8 @@ shellingham==1.5.4
# via typer
six==1.16.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# python-dateutil
snowballstemmer==2.2.0
# via sphinx
@@ -184,7 +184,7 @@ sphinx==8.1.3
# via
# sphinx-rtd-theme
# sphinxcontrib-jquery
sphinx-rtd-theme==3.0.1
sphinx-rtd-theme==3.0.2
# via lox
sphinxcontrib-applehelp==2.0.0
# via sphinx
@@ -200,23 +200,23 @@ sphinxcontrib-qthelp==2.0.0
# via sphinx
sphinxcontrib-serializinghtml==2.0.0
# via sphinx
typer==0.12.5
typer==0.13.1
# via -r requirements/requirements-dev.in
typing-extensions==4.12.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# typer
tzdata==2024.2
# via pandas
urllib3==2.2.3
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
virtualenv==20.27.1
virtualenv==20.28.0
# via pre-commit
wheel==0.44.0
wheel==0.45.1
# via pip-tools
# The following packages are considered to be unsafe in a requirements file:

View File

@@ -6,79 +6,81 @@
#
aiohappyeyeballs==2.4.3
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
aiohttp==3.10.10
aiohttp==3.11.7
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# huggingface-hub
# llama-index-core
aiosignal==1.3.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
annotated-types==0.7.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# pydantic
anyio==4.6.2.post1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# httpx
attrs==24.2.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
certifi==2024.8.30
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# httpcore
# httpx
# requests
charset-normalizer==3.4.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# requests
click==8.1.7
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# nltk
dataclasses-json==0.6.7
# via llama-index-core
deprecated==1.2.14
deprecated==1.2.15
# via llama-index-core
dirtyjson==1.0.8
# via llama-index-core
filelock==3.16.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# torch
# transformers
filetype==1.2.0
# via llama-index-core
frozenlist==1.5.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
# aiosignal
fsspec==2024.10.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# huggingface-hub
# llama-index-core
# torch
@@ -88,31 +90,31 @@ greenlet==3.0.3
# sqlalchemy
h11==0.14.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# httpcore
httpcore==1.0.6
httpcore==1.0.7
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# httpx
httpx==0.27.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
huggingface-hub[inference]==0.26.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-embeddings-huggingface
# sentence-transformers
# tokenizers
# transformers
idna==3.10
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# anyio
# httpx
@@ -120,34 +122,34 @@ idna==3.10
# yarl
jinja2==3.1.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# torch
joblib==1.4.2
# via
# nltk
# scikit-learn
llama-index-core==0.11.21
llama-index-core==0.12.0
# via
# -r requirements/requirements-help.in
# llama-index-embeddings-huggingface
llama-index-embeddings-huggingface==0.3.1
llama-index-embeddings-huggingface==0.4.0
# via -r requirements/requirements-help.in
markupsafe==3.0.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# jinja2
marshmallow==3.23.0
marshmallow==3.23.1
# via dataclasses-json
mpmath==1.3.0
# via sympy
multidict==6.1.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
# yarl
mypy-extensions==1.0.0
@@ -156,70 +158,71 @@ nest-asyncio==1.6.0
# via llama-index-core
networkx==3.2.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
# torch
nltk==3.9.1
# via llama-index-core
numpy==1.26.4
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# llama-index-core
# scikit-learn
# scipy
# transformers
packaging==24.1
packaging==24.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# marshmallow
# transformers
pillow==10.4.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# llama-index-core
# sentence-transformers
propcache==0.2.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
# yarl
pydantic==2.9.2
pydantic==2.10.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
pydantic-core==2.23.4
pydantic-core==2.27.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# pydantic
pyyaml==6.0.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# llama-index-core
# transformers
regex==2024.9.11
regex==2024.11.6
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# nltk
# tiktoken
# transformers
requests==2.32.3
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# llama-index-core
@@ -231,16 +234,16 @@ scikit-learn==1.5.2
# via sentence-transformers
scipy==1.13.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# scikit-learn
# sentence-transformers
sentence-transformers==3.2.1
sentence-transformers==3.3.1
# via llama-index-embeddings-huggingface
sniffio==1.3.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# anyio
# httpx
sqlalchemy[asyncio]==2.0.36
@@ -255,20 +258,20 @@ threadpoolctl==3.5.0
# via scikit-learn
tiktoken==0.8.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
tokenizers==0.19.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# transformers
torch==2.2.2
# via sentence-transformers
tqdm==4.66.6
tqdm==4.67.1
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# huggingface-hub
# llama-index-core
# nltk
@@ -278,8 +281,8 @@ transformers==4.44.2
# via sentence-transformers
typing-extensions==4.12.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# llama-index-core
@@ -294,16 +297,16 @@ typing-inspect==0.9.0
# llama-index-core
urllib3==2.2.3
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# requests
wrapt==1.16.0
wrapt==1.17.0
# via
# deprecated
# llama-index-core
yarl==1.17.1
yarl==1.18.0
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp

View File

@@ -15,8 +15,8 @@ pyee==12.0.0
# via playwright
typing-extensions==4.12.2
# via
# -c /Users/gauthier/Projects/aider/requirements.txt
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-browser.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt

View File

@@ -15,6 +15,6 @@ RUN bundle install --retry 5 --jobs 20
ENTRYPOINT [ "docker-entrypoint.sh" ]
# bundle exec jekyll serve --force_polling -H 0.0.0.0 -P 4000
CMD [ "bundle", "exec", "jekyll", "serve", "--force_polling", "-H", "0.0.0.0", "-P", "4000" ]
CMD [ "bundle", "exec", "jekyll", "serve", "--verbose", "--trace", "--force_polling", "-H", "0.0.0.0", "-P", "4000" ]

View File

@@ -23,8 +23,10 @@ def blame(start_tag, end_tag=None):
files = [
f
for f in files
if f.endswith((".py", ".scm", ".sh", "Dockerfile", "Gemfile"))
if f.endswith((".js", ".py", ".scm", ".sh", "Dockerfile", "Gemfile"))
or (f.startswith(".github/workflows/") and f.endswith(".yml"))
or f == "aider/website/share/index.md"
or f == "aider/website/docs/leaderboards/index.md"
]
files = [f for f in files if not f.endswith("prompts.py")]

View File

@@ -22,11 +22,27 @@ def has_been_reopened(issue_number):
# Load environment variables from .env file
load_dotenv()
DUPLICATE_COMMENT = """Thanks for trying aider and filing this issue.
BOT_SUFFIX = """Note: A [bot script](https://github.com/Aider-AI/aider/blob/main/scripts/issues.py) made these updates to the issue.
""" # noqa
DUPLICATE_COMMENT = (
"""Thanks for trying aider and filing this issue.
This looks like a duplicate of #{oldest_issue_number}. Please see the comments there for more information, and feel free to continue the discussion within that issue.
I'm going to close this issue for now. But please let me know if you think this is actually a distinct issue and I will reopen this issue.""" # noqa
+ BOT_SUFFIX
)
STALE_COMMENT = (
"""I'm labeling this issue as stale because it has been open for 2 weeks with no activity. If there are no additional comments, I will close it in 7 days.""" # noqa
+ BOT_SUFFIX
)
CLOSE_STALE_COMMENT = (
"""I'm closing this issue because it has been stalled for 3 weeks with no activity. Feel free to add a comment here and we can re-open it. Or feel free to file a new issue at any time.""" # noqa
+ BOT_SUFFIX
)
# GitHub API configuration
GITHUB_API_URL = "https://api.github.com"
@@ -112,22 +128,187 @@ def comment_and_close_duplicate(issue, oldest_issue):
print(f" - Commented and closed issue #{issue['number']}")
def main():
parser = argparse.ArgumentParser(description="Handle duplicate GitHub issues")
parser.add_argument(
"--yes", action="store_true", help="Automatically close duplicates without prompting"
)
args = parser.parse_args()
def find_unlabeled_with_paul_comments(issues):
unlabeled_issues = []
for issue in issues:
# Skip pull requests
if "pull_request" in issue:
continue
if not TOKEN:
print("Error: Missing GITHUB_TOKEN environment variable. Please check your .env file.")
if not issue["labels"] and issue["state"] == "open":
# Get comments for this issue
comments_url = (
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
)
response = requests.get(comments_url, headers=headers)
response.raise_for_status()
comments = response.json()
# Check if paul-gauthier has commented
if any(comment["user"]["login"] == "paul-gauthier" for comment in comments):
unlabeled_issues.append(issue)
return unlabeled_issues
def handle_unlabeled_issues(all_issues, auto_yes):
print("\nFinding unlabeled issues with paul-gauthier comments...")
unlabeled_issues = find_unlabeled_with_paul_comments(all_issues)
if not unlabeled_issues:
print("No unlabeled issues with paul-gauthier comments found.")
return
all_issues = get_issues("all")
print(f"\nFound {len(unlabeled_issues)} unlabeled issues with paul-gauthier comments:")
for issue in unlabeled_issues:
print(f" - #{issue['number']}: {issue['title']} {issue['html_url']}")
if not auto_yes:
confirm = input("\nDo you want to add the 'question' label to these issues? (y/n): ")
if confirm.lower() != "y":
print("Skipping labeling.")
return
print("\nAdding 'question' label to issues...")
for issue in unlabeled_issues:
url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}"
response = requests.patch(url, headers=headers, json={"labels": ["question"]})
response.raise_for_status()
print(f" - Added 'question' label to #{issue['number']}")
def handle_stale_issues(all_issues, auto_yes):
print("\nChecking for stale question issues...")
for issue in all_issues:
# Skip if not open, not a question, already stale, or has been reopened
if (
issue["state"] != "open"
or "question" not in [label["name"] for label in issue["labels"]]
or "stale" in [label["name"] for label in issue["labels"]]
or has_been_reopened(issue["number"])
):
continue
# Get latest activity timestamp from issue or its comments
latest_activity = datetime.strptime(issue["updated_at"], "%Y-%m-%dT%H:%M:%SZ")
# Check if issue is stale (no activity for 14 days)
days_inactive = (datetime.now() - latest_activity).days
if days_inactive >= 14:
print(f"\nStale issue found: #{issue['number']}: {issue['title']}\n{issue['html_url']}")
print(f" No activity for {days_inactive} days")
if not auto_yes:
confirm = input("Add stale label and comment? (y/n): ")
if confirm.lower() != "y":
print("Skipping this issue.")
continue
# Add comment
comment_url = (
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
)
response = requests.post(comment_url, headers=headers, json={"body": STALE_COMMENT})
response.raise_for_status()
# Add stale label
url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}"
response = requests.patch(url, headers=headers, json={"labels": ["question", "stale"]})
response.raise_for_status()
print(f" Added stale label and comment to #{issue['number']}")
def handle_stale_closing(all_issues, auto_yes):
print("\nChecking for issues to close or unstale...")
for issue in all_issues:
# Skip if not open or not stale
if issue["state"] != "open" or "stale" not in [label["name"] for label in issue["labels"]]:
continue
# Get the timeline to find when the stale label was last added
timeline_url = (
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/timeline"
)
response = requests.get(timeline_url, headers=headers)
response.raise_for_status()
events = response.json()
# Find the most recent stale label addition
stale_events = [
event
for event in events
if event.get("event") == "labeled" and event.get("label", {}).get("name") == "stale"
]
if not stale_events:
continue
latest_stale = datetime.strptime(stale_events[-1]["created_at"], "%Y-%m-%dT%H:%M:%SZ")
# Get comments since the stale label
comments_url = (
f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
)
response = requests.get(comments_url, headers=headers)
response.raise_for_status()
comments = response.json()
# Check for comments newer than the stale label
new_comments = [
comment
for comment in comments
if datetime.strptime(comment["created_at"], "%Y-%m-%dT%H:%M:%SZ") > latest_stale
]
if new_comments:
print(f"\nFound new activity on stale issue #{issue['number']}: {issue['title']}")
print(f" {len(new_comments)} new comments since stale label")
if not auto_yes:
confirm = input("Remove stale label? (y/n): ")
if confirm.lower() != "y":
print("Skipping this issue.")
continue
# Remove stale label but keep question label
url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}"
response = requests.patch(url, headers=headers, json={"labels": ["question"]})
response.raise_for_status()
print(f" Removed stale label from #{issue['number']}")
else:
# Check if it's been 7 days since stale label
days_stale = (datetime.now() - latest_stale).days
if days_stale >= 7:
print(f"\nStale issue ready for closing #{issue['number']}: {issue['title']}")
print(f" No activity for {days_stale} days since stale label")
if not auto_yes:
confirm = input("Close this issue? (y/n): ")
if confirm.lower() != "y":
print("Skipping this issue.")
continue
# Add closing comment
comment_url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments" # noqa
response = requests.post(
comment_url, headers=headers, json={"body": CLOSE_STALE_COMMENT}
)
response.raise_for_status()
# Close the issue
url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}"
response = requests.patch(url, headers=headers, json={"state": "closed"})
response.raise_for_status()
print(f" Closed issue #{issue['number']}")
def handle_duplicate_issues(all_issues, auto_yes):
open_issues = [issue for issue in all_issues if issue["state"] == "open"]
grouped_open_issues = group_issues_by_subject(open_issues)
print("Analyzing issues (skipping reopened issues)...")
print("Looking for duplicate issues (skipping reopened issues)...")
for subject, issues in grouped_open_issues.items():
oldest_issue = find_oldest_issue(subject, all_issues)
if not oldest_issue:
@@ -149,14 +330,12 @@ def main():
f" {oldest_issue['html_url']} ({oldest_issue['state']})"
)
if not args.yes:
# Confirmation prompt
if not auto_yes:
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)
@@ -165,5 +344,24 @@ def main():
print(f"Oldest issue #{oldest_issue['number']} left open")
def main():
parser = argparse.ArgumentParser(description="Handle duplicate GitHub issues")
parser.add_argument(
"--yes", action="store_true", help="Automatically close duplicates without prompting"
)
args = parser.parse_args()
if not TOKEN:
print("Error: Missing GITHUB_TOKEN environment variable. Please check your .env file.")
return
all_issues = get_issues("all")
handle_unlabeled_issues(all_issues, args.yes)
handle_stale_issues(all_issues, args.yes)
handle_stale_closing(all_issues, args.yes)
handle_duplicate_issues(all_issues, args.yes)
if __name__ == "__main__":
main()

View File

@@ -24,6 +24,7 @@ cog $ARG \
aider/website/docs/config/options.md \
aider/website/docs/config/aider_conf.md \
aider/website/docs/config/adv-model-settings.md \
aider/website/docs/config/model-aliases.md \
aider/website/docs/leaderboards/index.md \
aider/website/docs/llms/other.md \
aider/website/docs/more/infinite-output.md \

72
scripts/update-history.py Executable file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
import os
import re
import subprocess
import tempfile
from aider import __version__
def get_base_version():
# Parse current version like "0.64.2.dev" to get major.minor
match = re.match(r"(\d+\.\d+)", __version__)
if not match:
raise ValueError(f"Could not parse version: {__version__}")
return match.group(1) + ".0"
def run_git_log():
base_ver = get_base_version()
cmd = [
"git",
"log",
"-p",
f"v{base_ver}..HEAD",
"--",
"aider/",
":!aider/website/",
":!scripts/",
":!HISTORY.md",
]
result = subprocess.run(cmd, capture_output=True, text=True)
return result.stdout
def main():
# Get the git log output
diff_content = run_git_log()
# Save to temporary file
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".diff") as tmp:
tmp.write(diff_content)
tmp_path = tmp.name
# Run blame to get aider percentage
blame_result = subprocess.run(["python3", "scripts/blame.py"], capture_output=True, text=True)
aider_line = blame_result.stdout.strip().split("\n")[-1] # Get last line with percentage
# Construct and run the aider command
message = f"""
Update the history with changes shown in the diffs.
Describe actual user-facing changes, not every single commit that was made implementing them.
Don't edit or duplicate changes that have existing history entries, just add any new items not already listed.
Be sure to attribute changes to the proper .x version.
Changes in the .x-dev version should be listed under a "### main branch" heading
Also, add this as the last bullet under the "### main branch" section:
{aider_line}
""" # noqa
cmd = ["aider", "HISTORY.md", "--read", tmp_path, "--msg", message, "--no-auto-commit"]
subprocess.run(cmd)
# Run update-docs.sh after aider
subprocess.run(["scripts/update-docs.sh"])
# Cleanup
os.unlink(tmp_path)
if __name__ == "__main__":
main()

View File

@@ -124,7 +124,10 @@ def main():
for cmd in git_commands:
print(f"Running: {' '.join(cmd)}")
if not dry_run:
subprocess.run(cmd, check=True)
subprocess.run(
cmd,
check=True,
)
new_dev_version = f"{incremented_version}.dev"
updated_dev_content = re.sub(

View File

@@ -91,10 +91,49 @@ def test_system_info(temp_data_dir):
def test_need_to_ask(temp_data_dir):
analytics = Analytics()
assert analytics.need_to_ask() is True
assert analytics.need_to_ask(True) is True
assert analytics.need_to_ask(False) is False
analytics.user_id = "111"
assert analytics.need_to_ask(None) is False
analytics.user_id = "000"
assert analytics.need_to_ask(None) is True
analytics.asked_opt_in = True
assert analytics.need_to_ask() is False
assert analytics.need_to_ask(True) is False
analytics.permanently_disable = True
assert analytics.need_to_ask() is False
assert analytics.need_to_ask(True) is False
def test_is_uuid_in_percentage():
analytics = Analytics()
# Test basic percentage thresholds
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 1) is True
assert analytics.is_uuid_in_percentage("01999000000000000000000000000000", 1) is True
assert analytics.is_uuid_in_percentage("02000000000000000000000000000000", 1) is True
assert analytics.is_uuid_in_percentage("02910000000000000000000000000001", 1) is False
assert analytics.is_uuid_in_percentage("03000000000000000000000000000000", 1) is False
assert analytics.is_uuid_in_percentage("ff000000000000000000000000000000", 1) is False
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 10) is True
assert analytics.is_uuid_in_percentage("19000000000000000000000000000000", 10) is True
assert analytics.is_uuid_in_percentage("1a000000000000000000000000000000", 10) is False
assert analytics.is_uuid_in_percentage("ff000000000000000000000000000000", 10) is False
# Test edge cases
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 0) is False
assert analytics.is_uuid_in_percentage("00000000000000000000000000000000", 100) is True
assert analytics.is_uuid_in_percentage("ffffffffffffffffffffffffffffffff", 100) is True
# Test invalid inputs
with pytest.raises(ValueError):
analytics.is_uuid_in_percentage("00000000000000000000000000000000", -1)
with pytest.raises(ValueError):
analytics.is_uuid_in_percentage("00000000000000000000000000000000", 101)
# Test empty/None UUID
assert analytics.is_uuid_in_percentage("", 50) is False
assert analytics.is_uuid_in_percentage(None, 50) is False

View File

@@ -7,6 +7,7 @@ from unittest.mock import MagicMock, patch
import git
from aider.coders import Coder
from aider.coders.base_coder import UnknownEditFormat
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
from aider.models import Model
@@ -17,6 +18,8 @@ from aider.utils import GitTemporaryDirectory
class TestCoder(unittest.TestCase):
def setUp(self):
self.GPT35 = Model("gpt-3.5-turbo")
self.webbrowser_patcher = patch("aider.io.webbrowser.open")
self.mock_webbrowser = self.webbrowser_patcher.start()
def test_allowed_to_edit(self):
with GitTemporaryDirectory():
@@ -166,6 +169,37 @@ class TestCoder(unittest.TestCase):
self.assertEqual(coder.abs_fnames, set([str(fname.resolve())]))
def test_skip_duplicate_basename_mentions(self):
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
# Create files with same basename in different directories
fname1 = Path("dir1") / "file.txt"
fname2 = Path("dir2") / "file.txt"
fname3 = Path("dir3") / "unique.txt"
for fname in [fname1, fname2, fname3]:
fname.parent.mkdir(parents=True, exist_ok=True)
fname.touch()
# Add one file to chat
coder.add_rel_fname(str(fname1))
# Mock get_tracked_files to return all files
mock = MagicMock()
mock.return_value = set([str(fname1), str(fname2), str(fname3)])
coder.repo.get_tracked_files = mock
# Check that file mentions skip files with duplicate basenames
mentioned = coder.get_file_mentions(f"Check {fname2} and {fname3}")
self.assertEqual(mentioned, {str(fname3)})
# Add a read-only file with same basename
coder.abs_read_only_fnames.add(str(fname2.resolve()))
mentioned = coder.get_file_mentions(f"Check {fname1} and {fname3}")
self.assertEqual(mentioned, {str(fname3)})
def test_check_for_file_mentions_read_only(self):
with GitTemporaryDirectory():
io = InputOutput(
@@ -819,32 +853,55 @@ This command will print 'Hello, World!' to the console."""
with GitTemporaryDirectory():
io = InputOutput(yes=True)
coder = Coder.create(self.GPT35, "diff", io=io, suggest_shell_commands=False)
self.assertFalse(coder.suggest_shell_commands)
def mock_send(*args, **kwargs):
coder.partial_response_content = """Here's a shell command to run:
def test_detect_urls_enabled(self):
with GitTemporaryDirectory():
io = InputOutput(yes=True)
coder = Coder.create(self.GPT35, "diff", io=io, detect_urls=True)
coder.commands.scraper = MagicMock()
coder.commands.scraper.scrape = MagicMock(return_value="some content")
```bash
echo "Hello, World!"
```
# Test with a message containing a URL
message = "Check out https://example.com"
coder.check_for_urls(message)
coder.commands.scraper.scrape.assert_called_once_with("https://example.com")
This command will print 'Hello, World!' to the console."""
coder.partial_response_function_call = dict()
return []
def test_detect_urls_disabled(self):
with GitTemporaryDirectory():
io = InputOutput(yes=True)
coder = Coder.create(self.GPT35, "diff", io=io, detect_urls=False)
coder.commands.scraper = MagicMock()
coder.commands.scraper.scrape = MagicMock(return_value="some content")
coder.send = mock_send
# Test with a message containing a URL
message = "Check out https://example.com"
result = coder.check_for_urls(message)
self.assertEqual(result, [])
coder.commands.scraper.scrape.assert_not_called()
# Mock the handle_shell_commands method to check if it's called
coder.handle_shell_commands = MagicMock()
def test_unknown_edit_format_exception(self):
# Test the exception message format
invalid_format = "invalid_format"
valid_formats = ["diff", "whole", "map"]
exc = UnknownEditFormat(invalid_format, valid_formats)
expected_msg = (
f"Unknown edit format {invalid_format}. Valid formats are: {', '.join(valid_formats)}"
)
self.assertEqual(str(exc), expected_msg)
# Run the coder with a message
coder.run(with_message="Suggest a shell command")
def test_unknown_edit_format_creation(self):
# Test that creating a Coder with invalid edit format raises the exception
io = InputOutput(yes=True)
invalid_format = "invalid_format"
# Check if the shell command was added to the list
self.assertEqual(len(coder.shell_commands), 1)
self.assertEqual(coder.shell_commands[0].strip(), 'echo "Hello, World!"')
with self.assertRaises(UnknownEditFormat) as cm:
Coder.create(self.GPT35, invalid_format, io=io)
# Check if handle_shell_commands was called with the correct argument
coder.handle_shell_commands.assert_not_called()
exc = cm.exception
self.assertEqual(exc.edit_format, invalid_format)
self.assertIsInstance(exc.valid_formats, list)
self.assertTrue(len(exc.valid_formats) > 0)
def test_coder_create_with_new_file_oserror(self):
with GitTemporaryDirectory():

View File

@@ -1068,8 +1068,10 @@ class TestCommands(TestCase):
io.prompt_ask = lambda *args, **kwargs: "y"
# Test the cmd_run method with a command that should not raise an error
result = commands.cmd_run("exit 1", add_on_nonzero_exit=True)
self.assertIn("I ran this command", result)
commands.cmd_run("exit 1", add_on_nonzero_exit=True)
# Check that the output was added to cur_messages
self.assertTrue(any("exit 1" in msg["content"] for msg in coder.cur_messages))
def test_cmd_add_drop_untracked_files(self):
with GitTemporaryDirectory():
@@ -1210,6 +1212,26 @@ class TestCommands(TestCase):
del commands
del repo
def test_cmd_add_gitignored_file(self):
with GitTemporaryDirectory():
# Create a .gitignore file
gitignore = Path(".gitignore")
gitignore.write_text("*.ignored\n")
# Create a file that matches the gitignore pattern
ignored_file = Path("test.ignored")
ignored_file.write_text("This should be ignored")
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Try to add the ignored file
commands.cmd_add(str(ignored_file))
# Verify the file was not added
self.assertEqual(len(coder.abs_fnames), 0)
def test_cmd_add_aiderignored_file(self):
with GitTemporaryDirectory():
repo = git.Repo()

View File

@@ -10,6 +10,7 @@ from aider.coders import editblock_coder as eb
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
from aider.models import Model
from aider.utils import ChdirTemporaryDirectory
class TestUtils(unittest.TestCase):
@@ -341,6 +342,46 @@ These changes replace the `subprocess.run` patches with `subprocess.check_output
result = eb.replace_most_similar_chunk(whole, part, replace)
self.assertEqual(result, expected_output)
def test_create_new_file_with_other_file_in_chat(self):
# https://github.com/Aider-AI/aider/issues/2258
with ChdirTemporaryDirectory():
# Create a few temporary files
file1 = "file.txt"
with open(file1, "w", encoding="utf-8") as f:
f.write("one\ntwo\nthree\n")
files = [file1]
# Initialize the Coder object with the mocked IO and mocked repo
coder = Coder.create(
self.GPT35, "diff", use_git=False, io=InputOutput(yes=True), fnames=files
)
def mock_send(*args, **kwargs):
coder.partial_response_content = f"""
Do this:
newfile.txt
<<<<<<< SEARCH
=======
creating a new file
>>>>>>> REPLACE
"""
coder.partial_response_function_call = dict()
return []
coder.send = mock_send
coder.run(with_message="hi")
content = Path(file1).read_text(encoding="utf-8")
self.assertEqual(content, "one\ntwo\nthree\n")
content = Path("newfile.txt").read_text(encoding="utf-8")
self.assertEqual(content, "creating a new file\n")
def test_full_edit(self):
# Create a few temporary files
_, file1 = tempfile.mkstemp()

129
tests/basic/test_editor.py Normal file
View File

@@ -0,0 +1,129 @@
import os
from unittest.mock import MagicMock, patch
import pytest
from aider.editor import (
DEFAULT_EDITOR_NIX,
DEFAULT_EDITOR_OS_X,
DEFAULT_EDITOR_WINDOWS,
discover_editor,
get_environment_editor,
pipe_editor,
print_status_message,
write_temp_file,
)
def test_get_environment_editor():
# Test with no environment variables set
with patch.dict(os.environ, {}, clear=True):
assert get_environment_editor("default") == "default"
# Test EDITOR precedence
with patch.dict(os.environ, {"EDITOR": "vim"}):
assert get_environment_editor() == "vim"
# Test VISUAL overrides EDITOR
with patch.dict(os.environ, {"EDITOR": "vim", "VISUAL": "code"}):
assert get_environment_editor() == "code"
def test_discover_editor_defaults():
with patch("platform.system") as mock_system:
# Test Windows default
mock_system.return_value = "Windows"
with patch.dict(os.environ, {}, clear=True):
assert discover_editor() == [DEFAULT_EDITOR_WINDOWS]
# Test macOS default
mock_system.return_value = "Darwin"
with patch.dict(os.environ, {}, clear=True):
assert discover_editor() == [DEFAULT_EDITOR_OS_X]
# Test Linux default
mock_system.return_value = "Linux"
with patch.dict(os.environ, {}, clear=True):
assert discover_editor() == [DEFAULT_EDITOR_NIX]
def test_write_temp_file():
# Test basic file creation
content = "test content"
filepath = write_temp_file(content)
assert os.path.exists(filepath)
with open(filepath, "r") as f:
assert f.read() == content
os.remove(filepath)
# Test with suffix
filepath = write_temp_file("content", suffix="txt")
assert filepath.endswith(".txt")
os.remove(filepath)
# Test with prefix
filepath = write_temp_file("content", prefix="test_")
assert os.path.basename(filepath).startswith("test_")
os.remove(filepath)
def test_print_status_message(capsys):
# Test success message
print_status_message(True, "Success!")
captured = capsys.readouterr()
assert "Success!" in captured.out
# Test failure message
print_status_message(False, "Failed!")
captured = capsys.readouterr()
assert "Failed!" in captured.out
def test_discover_editor_override():
# Test editor override
assert discover_editor("code") == ["code"]
assert discover_editor('vim -c "set noswapfile"') == ["vim", "-c", "set noswapfile"]
# Test invalid editor command
with pytest.raises(RuntimeError):
discover_editor('vim "unclosed quote')
def test_pipe_editor():
# Test with default editor
test_content = "Initial content"
modified_content = "Modified content"
# Mock the file operations and editor call
with (
patch("aider.editor.write_temp_file") as mock_write,
patch("builtins.open") as mock_open,
patch("os.remove") as mock_remove,
patch("subprocess.call") as mock_subprocess,
):
# Setup mocks
mock_write.return_value = "temp.txt"
mock_file = MagicMock()
mock_file.__enter__.return_value.read.return_value = modified_content
mock_open.return_value = mock_file
# Test with default editor
result = pipe_editor(test_content)
assert result == modified_content
mock_write.assert_called_with(test_content, None)
mock_subprocess.assert_called()
# Test with custom editor
result = pipe_editor(test_content, editor="code")
assert result == modified_content
mock_subprocess.assert_called()
# Test with suffix
result = pipe_editor(test_content, suffix="md")
assert result == modified_content
mock_write.assert_called_with(test_content, "md")
# Test cleanup on permission error
mock_remove.side_effect = PermissionError
result = pipe_editor(test_content)
assert result == modified_content

View File

@@ -0,0 +1,65 @@
from aider.exceptions import ExInfo, LiteLLMExceptions
def test_litellm_exceptions_load():
"""Test that LiteLLMExceptions loads without errors"""
ex = LiteLLMExceptions()
assert len(ex.exceptions) > 0
def test_exceptions_tuple():
"""Test that exceptions_tuple returns a non-empty tuple"""
ex = LiteLLMExceptions()
assert isinstance(ex.exceptions_tuple(), tuple)
assert len(ex.exceptions_tuple()) > 0
def test_get_ex_info():
"""Test get_ex_info returns correct ExInfo"""
ex = LiteLLMExceptions()
# Test with a known exception type
from litellm import AuthenticationError
auth_error = AuthenticationError(
message="Invalid API key", llm_provider="openai", model="gpt-4"
)
ex_info = ex.get_ex_info(auth_error)
assert isinstance(ex_info, ExInfo)
assert ex_info.name == "AuthenticationError"
assert ex_info.retry is False
assert "API key" in ex_info.description
# Test with unknown exception type
class UnknownError(Exception):
pass
unknown = UnknownError()
ex_info = ex.get_ex_info(unknown)
assert isinstance(ex_info, ExInfo)
assert ex_info.name is None
assert ex_info.retry is None
assert ex_info.description is None
def test_rate_limit_error():
"""Test specific handling of RateLimitError"""
ex = LiteLLMExceptions()
from litellm import RateLimitError
rate_error = RateLimitError(message="Rate limit exceeded", llm_provider="openai", model="gpt-4")
ex_info = ex.get_ex_info(rate_error)
assert ex_info.retry is True
assert "rate limited" in ex_info.description.lower()
def test_context_window_error():
"""Test specific handling of ContextWindowExceededError"""
ex = LiteLLMExceptions()
from litellm import ContextWindowExceededError
ctx_error = ContextWindowExceededError(
message="Context length exceeded", model="gpt-4", llm_provider="openai"
)
ex_info = ex.get_ex_info(ctx_error)
assert ex_info.retry is False

View File

@@ -32,7 +32,7 @@ class TestMain(TestCase):
os.environ["HOME"] = self.homedir_obj.name
self.input_patcher = patch("builtins.input", return_value=None)
self.mock_input = self.input_patcher.start()
self.webbrowser_patcher = patch("webbrowser.open")
self.webbrowser_patcher = patch("aider.io.webbrowser.open")
self.mock_webbrowser = self.webbrowser_patcher.start()
def tearDown(self):
@@ -45,7 +45,7 @@ class TestMain(TestCase):
self.webbrowser_patcher.stop()
def test_main_with_empty_dir_no_files_on_command(self):
main(["--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
main(["--no-git", "--exit", "--yes"], input=DummyInput(), output=DummyOutput())
def test_main_with_emptqy_dir_new_file(self):
main(["foo.txt", "--yes", "--no-git", "--exit"], input=DummyInput(), output=DummyOutput())
@@ -332,7 +332,7 @@ class TestMain(TestCase):
def test_false_vals_in_env_file(self):
self.create_env_file(".env", "AIDER_SHOW_DIFFS=off")
with patch("aider.coders.Coder.create") as MockCoder:
main(["--no-git"], input=DummyInput(), output=DummyOutput())
main(["--no-git", "--yes"], input=DummyInput(), output=DummyOutput())
MockCoder.assert_called_once()
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["show_diffs"], False)
@@ -340,7 +340,7 @@ class TestMain(TestCase):
def test_true_vals_in_env_file(self):
self.create_env_file(".env", "AIDER_SHOW_DIFFS=on")
with patch("aider.coders.Coder.create") as MockCoder:
main(["--no-git"], input=DummyInput(), output=DummyOutput())
main(["--no-git", "--yes"], input=DummyInput(), output=DummyOutput())
MockCoder.assert_called_once()
_, kwargs = MockCoder.call_args
self.assertEqual(kwargs["show_diffs"], True)
@@ -381,7 +381,11 @@ 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", "--exit"], input=DummyInput(), output=DummyOutput())
main(
["--no-git", "--verbose", "--exit", "--yes"],
input=DummyInput(),
output=DummyOutput(),
)
output = mock_stdout.getvalue()
relevant_output = "\n".join(
line
@@ -633,6 +637,49 @@ class TestMain(TestCase):
)
self.assertTrue(coder.suggest_shell_commands)
def test_detect_urls_default(self):
with GitTemporaryDirectory():
coder = main(
["--exit", "--yes"],
input=DummyInput(),
output=DummyOutput(),
return_coder=True,
)
self.assertTrue(coder.detect_urls)
def test_detect_urls_disabled(self):
with GitTemporaryDirectory():
coder = main(
["--no-detect-urls", "--exit", "--yes"],
input=DummyInput(),
output=DummyOutput(),
return_coder=True,
)
self.assertFalse(coder.detect_urls)
def test_detect_urls_enabled(self):
with GitTemporaryDirectory():
coder = main(
["--detect-urls", "--exit", "--yes"],
input=DummyInput(),
output=DummyOutput(),
return_coder=True,
)
self.assertTrue(coder.detect_urls)
def test_invalid_edit_format(self):
with GitTemporaryDirectory():
with patch("aider.io.InputOutput.offer_url") as mock_offer_url:
result = main(
["--edit-format", "not-a-real-format", "--exit", "--yes"],
input=DummyInput(),
output=DummyOutput(),
)
self.assertEqual(result, 1) # main() should return 1 on error
mock_offer_url.assert_called_once()
args, _ = mock_offer_url.call_args
self.assertEqual(args[0], "https://aider.chat/docs/more/edit-formats.html")
def test_chat_language_spanish(self):
with GitTemporaryDirectory():
coder = main(

View File

@@ -2,8 +2,10 @@ import unittest
from unittest.mock import ANY, MagicMock, patch
from aider.models import (
ANTHROPIC_BETA_HEADER,
Model,
ModelInfoManager,
register_models,
sanity_check_model,
sanity_check_models,
)
@@ -80,7 +82,9 @@ class TestModels(unittest.TestCase):
) # Should return True because there's a problem with the editor model
mock_io.tool_warning.assert_called_with(ANY) # Ensure a warning was issued
warning_messages = [call.args[0] for call in mock_io.tool_warning.call_args_list]
warning_messages = [
warning_call.args[0] for warning_call in mock_io.tool_warning.call_args_list
]
print("Warning messages:", warning_messages) # Add this line
self.assertGreaterEqual(mock_io.tool_warning.call_count, 1) # Expect two warnings
@@ -88,6 +92,87 @@ class TestModels(unittest.TestCase):
any("bogus-model" in msg for msg in warning_messages)
) # Check that one of the warnings mentions the bogus model
def test_model_aliases(self):
# Test common aliases
model = Model("4")
self.assertEqual(model.name, "gpt-4-0613")
model = Model("4o")
self.assertEqual(model.name, "gpt-4o-2024-08-06")
model = Model("35turbo")
self.assertEqual(model.name, "gpt-3.5-turbo")
model = Model("35-turbo")
self.assertEqual(model.name, "gpt-3.5-turbo")
model = Model("3")
self.assertEqual(model.name, "gpt-3.5-turbo")
model = Model("sonnet")
self.assertEqual(model.name, "claude-3-sonnet-20241022")
model = Model("haiku")
self.assertEqual(model.name, "claude-3-haiku-20241022")
model = Model("opus")
self.assertEqual(model.name, "claude-3-opus-20240229")
# Test non-alias passes through unchanged
model = Model("gpt-4")
self.assertEqual(model.name, "gpt-4")
def test_aider_extra_model_settings(self):
import tempfile
import yaml
# Create temporary YAML file with test settings
test_settings = [
{
"name": "aider/extra_params",
"extra_params": {
"extra_headers": {"Foo": "bar"},
"some_param": "some value",
},
},
]
# Write to a regular file instead of NamedTemporaryFile
# for better cross-platform compatibility
tmp = tempfile.mktemp(suffix=".yml")
try:
with open(tmp, "w") as f:
yaml.dump(test_settings, f)
# Register the test settings
register_models([tmp])
# Test that defaults are applied when no exact match
model = Model("claude-3-5-sonnet-20240620")
# Test that both the override and existing headers are present
model = Model("claude-3-5-sonnet-20240620")
self.assertEqual(model.extra_params["extra_headers"]["Foo"], "bar")
self.assertEqual(
model.extra_params["extra_headers"]["anthropic-beta"],
ANTHROPIC_BETA_HEADER,
)
self.assertEqual(model.extra_params["some_param"], "some value")
self.assertEqual(model.extra_params["max_tokens"], 8192)
# Test that exact match overrides defaults but not overrides
model = Model("gpt-4")
self.assertEqual(model.extra_params["extra_headers"]["Foo"], "bar")
self.assertEqual(model.extra_params["some_param"], "some value")
finally:
# Clean up the temporary file
import os
try:
os.unlink(tmp)
except OSError:
pass
if __name__ == "__main__":
unittest.main()

View File

@@ -373,6 +373,19 @@ class TestRepoMapAllLanguages(unittest.TestCase):
def test_get_repo_map_all_languages(self):
language_files = {
"dart": (
"test.dart",
"""void main() {
print('Hello, World!');
}
class Greeter {
String sayHello(String name) {
return 'Hello, $name!';
}
}
""",
),
"c": (
"test.c",
(

View File

@@ -127,8 +127,9 @@ def test_git_index_version_greater_than_2(mock_browser, create_repo, mock_io):
"You may be able to convert your repo: git update-index --index-version=2"
)
mock_io.tool_output.assert_any_call("Or run aider --no-git to proceed without using git.")
mock_io.confirm_ask.assert_any_call(
"Open documentation url for more info?", subject=urls.git_index_version
mock_io.offer_url.assert_any_call(
urls.git_index_version,
"Open documentation url for more info?",
)

View File

@@ -1,10 +1,9 @@
import unittest
from unittest.mock import MagicMock, patch
import httpx
from aider.exceptions import LiteLLMExceptions
from aider.llm import litellm
from aider.sendchat import retry_exceptions, simple_send_with_retries
from aider.sendchat import send_completion, simple_send_with_retries
class PrintCalled(Exception):
@@ -12,9 +11,13 @@ class PrintCalled(Exception):
class TestSendChat(unittest.TestCase):
def test_retry_exceptions(self):
"""Test that retry_exceptions() can be called without raising errors"""
retry_exceptions() # Should not raise any exceptions
def setUp(self):
self.mock_messages = [{"role": "user", "content": "Hello"}]
self.mock_model = "gpt-4"
def test_litellm_exceptions(self):
litellm_ex = LiteLLMExceptions()
litellm_ex._load(strict=True)
@patch("litellm.completion")
@patch("builtins.print")
@@ -24,7 +27,7 @@ class TestSendChat(unittest.TestCase):
# Set up the mock to raise
mock_completion.side_effect = [
litellm.exceptions.RateLimitError(
litellm.RateLimitError(
"rate limit exceeded",
response=mock,
llm_provider="llm_provider",
@@ -35,17 +38,56 @@ class TestSendChat(unittest.TestCase):
# Call the simple_send_with_retries method
simple_send_with_retries("model", ["message"])
assert mock_print.call_count == 2
assert mock_print.call_count == 3
@patch("litellm.completion")
def test_send_completion_basic(self, mock_completion):
# Setup mock response
mock_response = MagicMock()
mock_completion.return_value = mock_response
# Test basic send_completion
hash_obj, response = send_completion(
self.mock_model, self.mock_messages, functions=None, stream=False
)
assert response == mock_response
mock_completion.assert_called_once()
@patch("litellm.completion")
def test_send_completion_with_functions(self, mock_completion):
mock_function = {"name": "test_function", "parameters": {"type": "object"}}
hash_obj, response = send_completion(
self.mock_model, self.mock_messages, functions=[mock_function], stream=False
)
# Verify function was properly included in tools
called_kwargs = mock_completion.call_args.kwargs
assert "tools" in called_kwargs
assert called_kwargs["tools"][0]["function"] == mock_function
@patch("litellm.completion")
def test_simple_send_attribute_error(self, mock_completion):
# Setup mock to raise AttributeError
mock_completion.return_value = MagicMock()
mock_completion.return_value.choices = None
# Should return None on AttributeError
result = simple_send_with_retries(self.mock_model, self.mock_messages)
assert result is None
@patch("litellm.completion")
@patch("builtins.print")
def test_simple_send_with_retries_connection_error(self, mock_print, mock_completion):
# Set up the mock to raise
mock_completion.side_effect = [
httpx.ConnectError("Connection error"),
None,
]
def test_simple_send_non_retryable_error(self, mock_print, mock_completion):
# Test with an error that shouldn't trigger retries
mock = MagicMock()
mock.status_code = 400
# Call the simple_send_with_retries method
simple_send_with_retries("model", ["message"])
assert mock_print.call_count == 2
mock_completion.side_effect = litellm.NotFoundError(
message="Invalid request", llm_provider="test_provider", model="test_model"
)
result = simple_send_with_retries(self.mock_model, self.mock_messages)
assert result is None
assert mock_print.call_count == 1

View File

@@ -44,7 +44,7 @@ class TestScrape(unittest.TestCase):
self.commands.io.tool_error = mock_print_error
# Run the cmd_web command
result = self.commands.cmd_web("https://example.com")
result = self.commands.cmd_web("https://example.com", return_content=True)
# Assert that the result contains some content
self.assertIsNotNone(result)