Compare commits

...

210 Commits

Author SHA1 Message Date
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
Chad Phillips
8801fda972 formatting fixes 2024-11-04 10:10:37 -06: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
53 changed files with 2954 additions and 1804 deletions

View File

@@ -3,6 +3,23 @@
### main branch
- 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`.

View File

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

View File

@@ -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 = 1
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"

View File

@@ -562,8 +562,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",
@@ -620,6 +620,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",
@@ -732,6 +738,10 @@ def get_parser(default_config_files, git_root):
default=True,
help="Enable/disable fancy input with history and completion (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

@@ -962,7 +962,7 @@ class Coder:
if self.chat_language:
language = self.chat_language
else:
language = "in the same language they are using"
language = "the same language they are using"
prompt = prompt.format(
fence=self.fence,
@@ -1245,10 +1245,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"
@@ -1299,13 +1308,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
@@ -2059,9 +2061,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

@@ -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"
@@ -868,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
@@ -876,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"
@@ -1366,6 +1361,14 @@ 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)
self.io.user_input(user_input, log_only=False)
self.io.add_to_input_history(user_input)
return user_input
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

View File

@@ -40,6 +40,11 @@ EXCEPTIONS = [
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.",
),
]

View File

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

View File

@@ -441,13 +441,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:
@@ -463,8 +488,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:
@@ -481,14 +506,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:

View File

@@ -5,6 +5,7 @@ import re
import sys
import threading
import traceback
import webbrowser
from pathlib import Path
import git
@@ -505,8 +506,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."
@@ -612,7 +613,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
@@ -687,7 +689,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(
@@ -797,6 +805,18 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io.tool_output('Use /help <question> for help, run "aider --help" to see cmd line args')
show = False
if args.show_release_notes is True:
show = True
elif args.show_release_notes is None and is_first_run:
io.tool_output()
show = io.confirm_ask("Would you like to see what's new in this version?")
if show:
io.tool_output(f"Opening release notes: {urls.release_notes}")
io.tool_output()
webbrowser.open(urls.release_notes)
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"
@@ -852,7 +872,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)
@@ -873,7 +894,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"
@@ -884,13 +924,8 @@ def check_and_load_imports(io, verbose=False):
io.tool_error(str(err))
io.tool_output("Error loading required imports. Did you install aider 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:
@@ -899,8 +934,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

@@ -161,6 +161,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",
@@ -629,7 +645,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"azure/o1-mini",
@@ -641,7 +656,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"o1-mini",
@@ -653,7 +667,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openai/o1-preview",
@@ -665,7 +678,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"azure/o1-preview",
@@ -677,7 +689,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"o1-preview",
@@ -689,7 +700,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/openai/o1-mini",
@@ -701,7 +711,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/openai/o1-preview",
@@ -713,7 +722,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/qwen/qwen-2.5-coder-32b-instruct",
@@ -762,6 +770,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:
@@ -809,6 +822,11 @@ class Model(ModelSettings):
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?
@@ -836,17 +854,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
@@ -868,17 +913,19 @@ 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
@@ -890,10 +937,12 @@ class Model(ModelSettings):
self.edit_format = "diff"
self.editor_edit_format = "editor-diff"
self.use_repo_map = True
return # <--
# use the defaults
if self.edit_format == "diff":
self.use_repo_map = True
return # <--
def __str__(self):
return self.name

View File

@@ -1,11 +0,0 @@
{
"openrouter/qwen/qwen-2.5-coder-32b-instruct": {
"max_tokens": 33792,
"max_input_tokens": 33792,
"max_output_tokens": 33792,
"input_cost_per_token": 0.00000018,
"output_cost_per_token": 0.00000018,
"litellm_provider": "openrouter",
"mode": "chat",
},
}

View File

@@ -12,3 +12,4 @@ 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"

View File

@@ -12,7 +12,9 @@ description: Release notes and stats on aider writing its own code.
The above
[stats are based on the git commit history](/docs/faq.html#how-are-the-aider-wrote-xx-of-code-stats-computed)
in the aider repo.
of the aider repo.
## Release notes
<!--[[[cog
# This page is a copy of HISTORY.md, adding the front matter above.
@@ -25,6 +27,23 @@ cog.out(text)
### main branch
- 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`.

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,7 +2143,7 @@
Paul Gauthier (aider): 201
start_tag: v0.49.0
total_lines: 324
- aider_percentage: 56.25
- aider_percentage: 56.18
aider_total: 450
end_date: '2024-08-20'
end_tag: v0.51.0
@@ -2170,6 +2178,8 @@
Paul Gauthier: 3
aider/utils.py:
Paul Gauthier (aider): 6
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
benchmark/benchmark.py:
Paul Gauthier: 7
benchmark/over_time.py:
@@ -2188,11 +2198,11 @@
Paul Gauthier: 15
Paul Gauthier (aider): 104
grand_total:
Paul Gauthier: 350
Paul Gauthier: 351
Paul Gauthier (aider): 450
start_tag: v0.50.0
total_lines: 800
- aider_percentage: 68.19
total_lines: 801
- aider_percentage: 68.1
aider_total: 521
end_date: '2024-08-23'
end_tag: v0.52.0
@@ -2231,6 +2241,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,11 +2262,11 @@
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
total_lines: 765
- aider_percentage: 58.61
aider_total: 405
end_date: '2024-08-27'
@@ -2328,7 +2340,7 @@
Paul Gauthier (aider): 405
start_tag: v0.52.0
total_lines: 691
- aider_percentage: 63.95
- aider_percentage: 63.75
aider_total: 204
end_date: '2024-08-28'
end_tag: v0.54.0
@@ -2364,6 +2376,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 +2390,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 +2464,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 +2494,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 +2533,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 +2544,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 +2593,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 +2614,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 +2700,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 +2730,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 +2772,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 +2789,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 +2831,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,12 +2842,12 @@
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'
@@ -2895,8 +2924,8 @@
kAIto47802: 4
start_tag: v0.60.0
total_lines: 1272
- aider_percentage: 84.0
aider_total: 63
- aider_percentage: 82.42
aider_total: 75
end_date: '2024-11-04'
end_tag: v0.62.0
file_counts:
@@ -2911,12 +2940,15 @@
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: 12
Paul Gauthier (aider): 63
Paul Gauthier: 16
Paul Gauthier (aider): 75
start_tag: v0.61.0
total_lines: 75
- aider_percentage: 55.16
total_lines: 91
- aider_percentage: 55.08
aider_total: 385
end_date: '2024-11-13'
end_tag: v0.63.0
@@ -2952,6 +2984,8 @@
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
@@ -2975,7 +3009,7 @@
Paul Gauthier: 1
grand_total:
Logan Attwood: 29
Paul Gauthier: 284
Paul Gauthier: 285
Paul Gauthier (aider): 385
start_tag: v0.62.0
total_lines: 698
total_lines: 699

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
@@ -274,7 +274,7 @@
- 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
@@ -297,7 +297,7 @@
- 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
@@ -623,7 +623,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 +671,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 +691,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 +699,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 +770,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 +796,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
@@ -946,7 +946,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 +973,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 +1113,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
@@ -1477,6 +1479,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 +1595,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
@@ -1615,6 +1619,7 @@
- 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
@@ -1773,32 +1778,10 @@
seconds_per_case: 18.3
total_cost: 0.0000
- dirname: 2024-11-09-10-57-11--Qwen2.5-Coder-32B-Instruct
test_cases: 133
model: Qwen2.5-Coder-32B-Instruct (whole)
edit_format: whole
commit_hash: ec9982a
pass_rate_1: 60.9
pass_rate_2: 73.7
percent_cases_well_formed: 100.0
error_outputs: 1
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 1
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 1
command: aider --model openai/Qwen2.5-Coder-32B-Instruct
date: 2024-11-09
versions: 0.59.2.dev
seconds_per_case: 26.6
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 (diff)
model: Qwen2.5-Coder-32B-Instruct
released: 2024-11-12
edit_format: diff
commit_hash: ec9982a
pass_rate_1: 59.4
@@ -1818,3 +1801,97 @@
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

View File

@@ -0,0 +1,93 @@
- dirname: 2024-11-09-11-09-15--Qwen2.5-Coder-32B-Instruct
test_cases: 133
model: HuggingFace weights via glhf.chat
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/Qwen2.5-Coder-32B-Instruct
date: 2024-11-09
versions: 0.59.2.dev
seconds_per_case: 22.5
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-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-09-30-14-09-43--qwen2.5-32b-whole-2
test_cases: 133
model: ollama/qwen2.5:32b
edit_format: whole
commit_hash: 765c4cb
pass_rate_1: 44.4
pass_rate_2: 54.1
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 9
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model ollama/qwen2.5:32b
date: 2024-09-30
versions: 0.58.1.dev
seconds_per_case: 134.9
total_cost: 0.0000

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,69 @@
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('quantChart').getContext('2d');
var chartData = {
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 site.data.quant %}
allData.push({
model: '{{ row.model }}',
pass_rate_2: {{ row.pass_rate_2 }}
});
{% endfor %}
allData.forEach(function(row) {
chartData.labels.push(row.model);
chartData.datasets[0].data.push(row.pass_rate_2);
});
new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'Aider coder 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
}
}
}
}
}
});
});

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

@@ -0,0 +1,43 @@
---
title: Quantization matters
excerpt: Open source LLMs are becoming very powerful, but pay attention to how you (or your provider) is quantizing the model. It can strongly 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 %}
# Quantization matters
Open source models like Qwen 2.5 32B are performing very well on
aider's code editing benchmark, rivaling closed source frontier models.
But pay attention to how your model is being quantized, as it
can strongly impact code editing skill.
Heavily quantized models are often used by cloud API providers
and local model servers like Ollama.
<canvas id="quantChart" width="800" height="450" style="margin: 20px 0"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
{% include quant-chart.js %}
</script>
The graph above compares 4 different versions of the Qwen 2.5 32B model,
served both locally and from cloud providers.
- The [HuggingFace weights](https://huggingface.co/Qwen/Qwen2.5-Coder-32B-Instruct) served via [glhf.chat](https://glhf.chat).
- The results from [OpenRouter's mix of providers](https://openrouter.ai/qwen/qwen-2.5-coder-32b-instruct/providers).
- Two Ollama models run locally.
The best version of the model rivals GPT-4o, while the worst performer
is more like GPT-3.5 Turbo.
## Choosing providers with OpenRouter
OpenRouter allows you to ignore specific providers in your
[preferences](https://openrouter.ai/settings/preferences).
This can be effective to exclude highly quantized or otherwise
undesirable providers.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 97 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -271,8 +271,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
@@ -314,6 +314,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
@@ -365,6 +368,9 @@
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
## Specify which editor to use for the /editor command
#editor: xxx
#################
# Voice Settings:

View File

@@ -270,8 +270,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=
@@ -300,6 +300,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
@@ -348,6 +351,9 @@
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## Specify which editor to use for the /editor command
#AIDER_EDITOR=
#################
# Voice Settings:

View File

@@ -55,8 +55,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 +68,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 +265,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
@@ -1057,7 +1113,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
@@ -1073,7 +1129,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
@@ -1089,7 +1145,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
@@ -1105,7 +1161,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
@@ -1121,7 +1177,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
@@ -1137,7 +1193,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
@@ -1153,7 +1209,7 @@ cog.out("```\n")
name: openrouter/openai/o1-mini
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
@@ -1169,7 +1225,7 @@ cog.out("```\n")
name: openrouter/openai/o1-preview
reminder: user
send_undo_reply: false
streaming: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false

View File

@@ -327,8 +327,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
@@ -370,6 +370,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
@@ -421,6 +424,9 @@ cog.outl("```")
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
## Specify which editor to use for the /editor command
#editor: xxx
#################
# Voice Settings:

View File

@@ -312,8 +312,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=
@@ -342,6 +342,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
@@ -390,6 +393,9 @@ cog.outl("```")
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=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

@@ -66,14 +66,15 @@ 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]
[--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] [--editor]
[--voice-format] [--voice-language]
```
@@ -510,8 +511,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`
@@ -561,6 +561,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
@@ -666,6 +673,10 @@ Aliases:
- `--fancy-input`
- `--no-fancy-input`
### `--editor VALUE`
Specify which editor to use for the /editor command
Environment variable: `AIDER_EDITOR`
## Voice Settings:
### `--voice-format VOICE_FORMAT`

View File

@@ -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.

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,81 +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');
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();
});
{% include edit-leaderboard.js %}
</script>
<style>
tr.selected {
@@ -158,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>
@@ -185,74 +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: {
y: {
beginAtZero: true
}
}
}
});
updateChart();
});
{% include refactor-leaderboard.js %}
</script>
@@ -318,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.')}")
]]]-->
November 11, 2024.
November 21, 2024.
<!--[[[end]]]-->
</p>

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/groq-beta
# List models available from xAI
aider --list-models groq/
```

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

View File

@@ -57,7 +57,6 @@ 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
@@ -91,11 +90,17 @@ cog.out(model_list)
- 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

@@ -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

@@ -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

@@ -5,6 +5,33 @@ from matplotlib import rc
from aider.dump import dump # noqa: 401
LABEL_FONT_SIZE = 16 # Font size for scatter plot dot labels
def get_legend_label(model):
model = model.lower()
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"
if "o1-preview" in model:
return "o1-preview"
return model
def get_model_color(model):
default = "lightblue"
@@ -12,6 +39,21 @@ def get_model_color(model):
if model == "gpt-4o-mini":
return default
if "qwen" in model.lower():
return "darkblue"
if "mistral" in model.lower():
return "cyan"
if "haiku" in model.lower():
return "pink"
if "deepseek" in model.lower():
return "brown"
if "sonnet" in model.lower():
return "orange"
if "-4o" in model:
return "purple"
@@ -59,7 +101,7 @@ def plot_over_time(yaml_file):
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
fig, ax = plt.subplots(figsize=(12, 8)) # Make figure square
print("Debug: Figure created. Plotting data...")
ax.grid(axis="y", zorder=0, lw=0.2)
@@ -73,39 +115,154 @@ def plot_over_time(yaml_file):
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"]
orange_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "orange"]
brown_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "brown"]
pink_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "pink"]
qwen_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "darkblue"]
mistral_points = [(d, r) for d, r, c in zip(dates, pass_rates, colors) if c == "cyan"]
# Plot lines for purple, red, and green points
# Create a mapping of colors to first points and labels
color_to_first_point = {}
color_to_label = {}
for date, rate, color, model in sorted(zip(dates, pass_rates, colors, models)):
if color not in color_to_first_point:
color_to_first_point[color] = (date, rate)
color_to_label[color] = get_legend_label(model)
# Plot lines and add labels at first 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 "purple" in color_to_first_point:
date, rate = color_to_first_point["purple"]
ax.annotate(
color_to_label["purple"],
(date, rate),
xytext=(10, 5),
textcoords="offset points",
color="purple",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
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 "red" in color_to_first_point:
date, rate = color_to_first_point["red"]
ax.annotate(
color_to_label["red"],
(date, rate),
xytext=(10, 5),
textcoords="offset points",
color="red",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
if green_points:
green_dates, green_rates = zip(*sorted(green_points))
ax.plot(green_dates, green_rates, c="green", alpha=0.5, linewidth=1)
if "green" in color_to_first_point:
date, rate = color_to_first_point["green"]
ax.annotate(
color_to_label["green"],
(date, rate),
xytext=(10, 5),
textcoords="offset points",
color="green",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
# Plot all points
ax.scatter(dates, pass_rates, c=colors, alpha=0.5, s=120)
if orange_points:
orange_dates, orange_rates = zip(*sorted(orange_points))
ax.plot(orange_dates, orange_rates, c="orange", alpha=0.5, linewidth=1)
if "orange" in color_to_first_point:
date, rate = color_to_first_point["orange"]
ax.annotate(
color_to_label["orange"],
(date, rate),
xytext=(10, 5),
textcoords="offset points",
color="orange",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
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",
)
if brown_points:
brown_dates, brown_rates = zip(*sorted(brown_points))
ax.plot(brown_dates, brown_rates, c="brown", alpha=0.5, linewidth=1)
if "brown" in color_to_first_point:
date, rate = color_to_first_point["brown"]
ax.annotate(
color_to_label["brown"],
(date, rate),
xytext=(10, -10),
textcoords="offset points",
color="brown",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
if pink_points:
pink_dates, pink_rates = zip(*sorted(pink_points))
ax.plot(pink_dates, pink_rates, c="pink", alpha=0.5, linewidth=1)
if "pink" in color_to_first_point:
date, rate = color_to_first_point["pink"]
ax.annotate(
color_to_label["pink"],
(date, rate),
xytext=(10, 5),
textcoords="offset points",
color="pink",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
if qwen_points:
qwen_dates, qwen_rates = zip(*sorted(qwen_points))
ax.plot(qwen_dates, qwen_rates, c="darkblue", alpha=0.5, linewidth=1)
if "darkblue" in color_to_first_point:
date, rate = color_to_first_point["darkblue"]
ax.annotate(
color_to_label["darkblue"],
(date, rate),
xytext=(10, 5),
textcoords="offset points",
color="darkblue",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
if mistral_points:
mistral_dates, mistral_rates = zip(*sorted(mistral_points))
ax.plot(mistral_dates, mistral_rates, c="cyan", alpha=0.5, linewidth=1)
if "cyan" in color_to_first_point:
date, rate = color_to_first_point["cyan"]
ax.annotate(
color_to_label["cyan"],
(date, rate),
xytext=(10, -10),
textcoords="offset points",
color="cyan",
alpha=0.8,
fontsize=LABEL_FONT_SIZE,
)
# Plot points without legend
for date, rate, color in zip(dates, pass_rates, colors):
ax.scatter([date], [rate], c=[color], alpha=0.5, s=120)
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
ax.set_ylim(30, 90) # 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)
plt.tight_layout(pad=1.0) # Adjust layout since we don't need room for legend anymore
print("Debug: Saving figures...")
plt.savefig("tmp_over_time.png")

View File

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

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,15 +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, it will be closed in 7 days.""" # noqa
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
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"
@@ -279,7 +291,7 @@ def handle_stale_closing(all_issues, auto_yes):
continue
# Add closing comment
comment_url = f"{GITHUB_API_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue['number']}/comments"
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}
)

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

@@ -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():

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,
):
# 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
with patch("subprocess.call") as mock_subprocess:
# 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

@@ -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

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,57 @@ 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_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()