Compare commits

...

837 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
Paul Gauthier
abf804cf10 set version to 0.63.3.dev 2024-11-18 07:30:21 -08:00
Paul Gauthier
d7a195706f version bump to 0.63.2 2024-11-18 07:29:05 -08:00
Paul Gauthier
569370109a copy 2024-11-18 07:11:46 -08:00
Paul Gauthier
eae3f04c83 copy 2024-11-18 06:57:35 -08:00
Paul Gauthier (aider)
ee0987f331 feat: Update HISTORY.md with recent changes since v0.63.1 2024-11-18 06:57:04 -08:00
Paul Gauthier (aider)
bdafa842bd fix: Add missing time import for time.sleep() in write_text method 2024-11-15 16:23:37 -08:00
Paul Gauthier (aider)
76c7c2562c style: Format code with linter for improved readability 2024-11-15 16:23:26 -08:00
Paul Gauthier (aider)
f7de2234f2 fix: Handle different OSError types in write_text method 2024-11-15 16:23:21 -08:00
Paul Gauthier
c725c45726 Merge branch 'main' of github.com:Aider-AI/aider 2024-11-15 16:22:23 -08:00
paul-gauthier
383bef456d Merge pull request #2381 from mark-asymbl/write_text_file_lock_fix
Added io.py write_text exponential backoff to gracefully handle transient file locks
2024-11-15 16:21:40 -08:00
mw
7f48f3d01d Added write_text exponential backoff to
Discord thread ID: 1306776889762906123

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

The editor is determined as follows:

Look for the following environment variables, in order:

1. AIDER_EDITOR
2. VISUAL
3. EDITOR

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

Windows: notepad
OS X: vim
*nix: vi

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

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

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

NOTE: The editor used MUST block the process until the editor is closed -- the default editors all do this.
2024-11-03 20:18:57 -05:00
Paul Gauthier
0022c1a67e copy 2024-11-01 11:26:39 -07:00
Paul Gauthier
6a0380b8c0 copy 2024-11-01 09:46:27 -07:00
Paul Gauthier
305b4fee87 set version to 0.61.1.dev 2024-11-01 09:40:02 -07:00
Paul Gauthier
9e18fc55d3 version bump to 0.61.0 2024-11-01 09:38:46 -07:00
Paul Gauthier
ebc9a30cc6 copy 2024-11-01 09:23:37 -07:00
Paul Gauthier
f53f5927df Show friendly API error messages 2024-11-01 09:20:31 -07:00
Paul Gauthier (aider)
78a8d19ac5 fix: pass exception objects directly to check_and_open_urls 2024-11-01 09:12:50 -07:00
Paul Gauthier
bfa9dce1e0 refactor: improve API error messages and display format 2024-11-01 09:12:49 -07:00
Paul Gauthier (aider)
3b2f1f1e66 style: format long error messages with line breaks 2024-11-01 09:09:03 -07:00
Paul Gauthier (aider)
b2bcca967f refactor: update check_and_open_urls to handle exceptions with friendly messages 2024-11-01 09:08:57 -07:00
Paul Gauthier
929aeb22bf refactor: Update check_and_open_urls to handle exceptions with user-friendly messages 2024-11-01 09:08:56 -07:00
Paul Gauthier
66ad186edd start /save commands with /drop 2024-11-01 09:04:55 -07:00
Paul Gauthier
c098354a67 copy 2024-11-01 09:03:44 -07:00
Paul Gauthier (aider)
d67d319b31 style: fix whitespace and line spacing issues 2024-11-01 08:12:17 -07:00
Paul Gauthier (aider)
93639039d4 feat: disable spinner when stdout is not a tty 2024-11-01 08:12:13 -07:00
Paul Gauthier
789535cb85 feat: disable spinner animation when stdout is not a tty 2024-11-01 08:12:11 -07:00
Paul Gauthier
d8e1e823e7 update deps with chained constraints 2024-10-31 16:04:37 -07:00
Paul Gauthier (aider)
5b9fe6fee0 refactor: convert pip-compile script to use loop for requirements compilation 2024-10-31 16:03:12 -07:00
Paul Gauthier (aider)
91bc8cddf3 fix: add dependency constraints between requirements files 2024-10-31 16:02:33 -07:00
Paul Gauthier
392162ae84 copy 2024-10-31 15:33:17 -07:00
Paul Gauthier
0c4e4a123a pin pillow<11 to avoid regressing streamlit to ancient 1.22 2024-10-31 15:31:58 -07:00
Paul Gauthier (aider)
27711010a0 refactor: update --gui/--browser to use BooleanOptionalAction 2024-10-31 15:01:29 -07:00
Paul Gauthier
401967c27f refactor: convert browser flag to boolean argument 2024-10-31 15:01:26 -07:00
Paul Gauthier (aider)
d1b25b9a72 fix: remove duplicate test_cmd_read_only_with_image_file method 2024-10-31 15:00:21 -07:00
Paul Gauthier
df478e1f8f copy 2024-10-31 14:59:52 -07:00
Paul Gauthier (aider)
a459f0e130 test: add test for read-only command with image files 2024-10-31 14:59:46 -07:00
Paul Gauthier (aider)
66b6788990 test: add test for image file handling in read command 2024-10-31 14:59:22 -07:00
Paul Gauthier (aider)
624f9122ab style: fix whitespace in commands.py 2024-10-31 14:58:29 -07:00
Paul Gauthier (aider)
704350286c feat: allow /read command to work with images for vision models 2024-10-31 14:58:23 -07:00
Paul Gauthier (aider)
ec40ff5987 feat: prevent adding image files with /read command 2024-10-31 14:57:44 -07:00
Paul Gauthier
af7aaad903 fix: handle RecursionError during tree traversal in linter 2024-10-31 14:55:54 -07:00
Paul Gauthier
3794cf941f feat: add support for claude-3-5-sonnet-latest model 2024-10-31 14:53:50 -07:00
Paul Gauthier
72c1f25005 refactor: Move StringIO import to top of file 2024-10-31 14:49:16 -07:00
Paul Gauthier (aider)
c13536e641 style: move rich.columns import to top of file 2024-10-31 14:48:12 -07:00
Paul Gauthier (aider)
7a9988c060 style: fix linting issues in io.py 2024-10-31 14:45:35 -07:00
Paul Gauthier (aider)
b9939d4bd9 refactor: improve file list display with section headers 2024-10-31 14:45:31 -07:00
Paul Gauthier (aider)
b71a3148cf style: fix import order in io.py 2024-10-31 14:43:29 -07:00
Paul Gauthier (aider)
42abdb0a41 feat: add compact file listing using rich Columns when pretty=True 2024-10-31 14:43:25 -07:00
Paul Gauthier
4c39e92773 copy 2024-10-31 14:39:27 -07:00
Paul Gauthier
b7f7204c4e copy 2024-10-31 14:29:53 -07:00
Paul Gauthier (aider)
8f73c15f48 feat: skip analytics update in check mode 2024-10-31 14:16:34 -07:00
Paul Gauthier
17330e53c3 refactor: Improve error handling and URL processing in chat functionality 2024-10-31 14:13:36 -07:00
Paul Gauthier (aider)
3fcd79e165 style: fix line length and comment formatting 2024-10-31 14:03:33 -07:00
Paul Gauthier (aider)
750b12282f refactor: strip trailing punctuation from URLs before displaying 2024-10-31 14:03:27 -07:00
Paul Gauthier
94c5ff2fd2 refactor: simplify URL pattern matching and cleanup commented code 2024-10-31 14:03:26 -07:00
Paul Gauthier
85ad2826da test: add debug dump of URL pattern regex 2024-10-31 14:02:05 -07:00
Paul Gauthier
15c62e3e43 fix: improve URL pattern to handle trailing commas in links 2024-10-31 14:01:41 -07:00
Paul Gauthier (aider)
fea7134064 style: fix comment spacing and remove commented code 2024-10-31 14:01:28 -07:00
Paul Gauthier (aider)
da706d9eb8 fix: update URL regex to strip trailing punctuation 2024-10-31 14:01:21 -07:00
Paul Gauthier
9a37c0491d refactor: improve URL handling and error reporting in base coder 2024-10-31 14:01:20 -07:00
Paul Gauthier (aider)
1d3d6a589f style: remove unused Optional import 2024-10-31 13:52:50 -07:00
Paul Gauthier (aider)
c5a439e4e8 style: sort imports alphabetically in base_coder.py 2024-10-31 13:52:41 -07:00
Paul Gauthier (aider)
2b7584b651 refactor: extract URL checking logic into separate method 2024-10-31 13:52:37 -07:00
Paul Gauthier (aider)
1ef60b5a40 refactor: add URL checking function with browser open option 2024-10-31 13:52:24 -07:00
Paul Gauthier
b79321da51 chore: add TODO comments for URL handling refactoring 2024-10-31 13:52:22 -07:00
Paul Gauthier (aider)
6829b29ef4 feat: add error base class hierarchy to retry exception messages 2024-10-31 13:50:12 -07:00
Paul Gauthier
a9c0d20347 chore: add comment about error base class inspection 2024-10-31 13:50:11 -07:00
Paul Gauthier (aider)
25a906950c refactor: move webbrowser import to top of file 2024-10-31 13:48:28 -07:00
Paul Gauthier
740534dcff refactor: Move webbrowser import to top of file 2024-10-31 13:48:27 -07:00
Paul Gauthier (aider)
de65d86122 style: fix string quotes and line wrapping in error URL handling 2024-10-31 13:48:08 -07:00
Paul Gauthier (aider)
98bf9bd26d feat: add URL detection and viewer for error messages 2024-10-31 13:48:01 -07:00
Paul Gauthier
ade615c445 chore: Add TODO comment for URL handling in error messages 2024-10-31 13:48:00 -07:00
Paul Gauthier
d959e1c60d test: fix analytics disable test assertion for better clarity 2024-10-31 13:31:43 -07:00
Paul Gauthier (aider)
8d2f66fe34 test: add temp_data_dir fixture to all analytics tests 2024-10-31 13:28:31 -07:00
Paul Gauthier (aider)
66dc8dbccd style: remove unused MagicMock import 2024-10-31 13:22:59 -07:00
Paul Gauthier (aider)
b228bcab8c style: Fix linting issues in test_analytics.py 2024-10-31 13:22:50 -07:00
Paul Gauthier (aider)
ccbf1482c1 test: add comprehensive test suite for Analytics class 2024-10-31 13:22:47 -07:00
Paul Gauthier
f9a0946472 test: add basic analytics test suite 2024-10-31 13:22:45 -07:00
Paul Gauthier
faa80b7699 updated deps 2024-10-31 13:21:56 -07:00
Paul Gauthier
1eb2c724a5 copy 2024-10-31 13:15:33 -07:00
Paul Gauthier
c43e7f998e copy 2024-10-31 13:11:00 -07:00
Paul Gauthier
3e2454b84b cleanup 2024-10-31 11:49:17 -07:00
Paul Gauthier
2817766cf5 cleanup 2024-10-31 11:44:24 -07:00
Paul Gauthier
ba7656bc1c cleanup 2024-10-31 11:37:18 -07:00
Paul Gauthier
c14392a35a copy 2024-10-31 11:33:27 -07:00
Paul Gauthier
6bfb258473 copy 2024-10-31 11:31:32 -07:00
Paul Gauthier
1e872599fd copy 2024-10-31 11:02:04 -07:00
Paul Gauthier
c08b7f9c22 Merge branch 'main' into mixpanel 2024-10-31 10:09:36 -07:00
Paul Gauthier
6e4ccf8715 copy 2024-10-31 10:09:33 -07:00
Paul Gauthier (aider)
e4913669d4 refactor: simplify event method to use main_model attributes 2024-10-31 10:08:43 -07:00
Paul Gauthier
8e098752bd refactor: Use main_model attributes for weak and editor models in analytics 2024-10-31 10:08:41 -07:00
Paul Gauthier (aider)
6867dab89c style: remove trailing whitespace in analytics.py 2024-10-31 10:06:52 -07:00
Paul Gauthier (aider)
09a9fac91e refactor: extract model redaction logic and add model params 2024-10-31 10:05:10 -07:00
Paul Gauthier
2fd1681fab refactor: add weak_model and editor_model args to analytics event method 2024-10-31 10:05:08 -07:00
Paul Gauthier
ece91dc724 copy 2024-10-31 09:57:22 -07:00
Paul Gauthier
01bf154151 copy 2024-10-31 09:53:04 -07:00
Paul Gauthier
b5916981b3 copy 2024-10-30 20:19:47 -07:00
Paul Gauthier
a68b87272b copy 2024-10-30 20:19:08 -07:00
Paul Gauthier (aider)
88b55df1c6 chore: add privacy policy to update-docs script 2024-10-30 20:18:41 -07:00
Paul Gauthier (aider)
676c017eb1 feat: add git-based last updated date to privacy policy 2024-10-30 20:17:53 -07:00
Paul Gauthier
139b8a2d4a docs: add privacy policy document 2024-10-30 20:17:15 -07:00
Paul Gauthier
24c68928d6 feat: Add analytics tracking for model warnings 2024-10-30 14:34:27 -07:00
Paul Gauthier
f957111141 feat: Add model info manager import to analytics module 2024-10-30 14:30:14 -07:00
Paul Gauthier
e94e60b1d2 refactor: improve model name redaction in analytics and model info handling 2024-10-30 14:29:29 -07:00
Paul Gauthier (aider)
a565a63436 style: Fix import formatting in test_models.py 2024-10-30 13:21:47 -07:00
Paul Gauthier (aider)
a045bda171 refactor: update test to use ModelInfoManager instead of get_model_info 2024-10-30 13:21:43 -07:00
Paul Gauthier (aider)
a3d78e0944 style: split long URL string constant into multiple lines 2024-10-30 13:21:21 -07:00
Paul Gauthier
8082cbed98 refactor: rename get_model_flexible to get_model_from_cached_json_db 2024-10-30 13:21:19 -07:00
Paul Gauthier (aider)
aba8b5d00a style: fix linting issues and whitespace in models.py 2024-10-30 13:17:54 -07:00
Paul Gauthier (aider)
3d5a4d9303 refactor: encapsulate model info functionality into ModelInfoManager class 2024-10-30 13:17:49 -07:00
Paul Gauthier
a899b0e27e refactor: Extract model info handling into a dedicated class 2024-10-30 13:17:47 -07:00
Paul Gauthier
267872b7e4 feat: add opt-in analytics collection with privacy notice 2024-10-30 13:15:57 -07:00
Paul Gauthier (aider)
bd59a8debf refactor: extract analytics disable logic into dedicated method 2024-10-30 12:25:18 -07:00
Paul Gauthier
c0e137889c style: Update analytics refactoring comment with method name 2024-10-30 12:25:17 -07:00
Paul Gauthier
5b84b901b2 chore: add TODO comment for analytics refactoring 2024-10-30 12:24:39 -07:00
Paul Gauthier (aider)
059883abf7 feat: add asked_opt_in tracking to analytics 2024-10-30 12:17:17 -07:00
Paul Gauthier
0b622a6fd7 chore: add comment for analytics opt-in tracking implementation 2024-10-30 12:17:15 -07:00
Paul Gauthier
97989dd51a Merge branch 'main' into mixpanel 2024-10-30 12:06:38 -07:00
Paul Gauthier (aider)
d81c421bfe test: mock webbrowser.open in test setup 2024-10-30 12:04:43 -07:00
Paul Gauthier (aider)
bce586f510 fix: remove unused webbrowser import in test file 2024-10-30 12:00:12 -07:00
Paul Gauthier (aider)
a70b364842 style: fix import order and quote style in test file 2024-10-30 11:59:52 -07:00
Paul Gauthier (aider)
920e8da57c test: mock webbrowser.open in git index version test 2024-10-30 11:59:48 -07:00
Paul Gauthier (aider)
71a8b286dc style: fix linting issues in test_sanity_check_repo.py 2024-10-30 11:59:25 -07:00
Paul Gauthier (aider)
ee4decc50b fix: add missing urls import in test_sanity_check_repo.py 2024-10-30 11:59:21 -07:00
Paul Gauthier (aider)
63330aa833 style: fix line wrapping in test file 2024-10-30 11:59:08 -07:00
Paul Gauthier (aider)
15a0eb976f test: update git index version test to check confirm_ask call 2024-10-30 11:59:04 -07:00
Paul Gauthier
4f52ad385a copy 2024-10-30 11:52:09 -07:00
Paul Gauthier
cd1496f91b copy 2024-10-30 11:51:49 -07:00
Paul Gauthier (aider)
31babf39cd style: fix comment spacing in sanity_check_repo function 2024-10-30 11:42:50 -07:00
Paul Gauthier (aider)
fe3dbba1d9 feat: add browser URL launch with user confirmation prompt 2024-10-30 11:42:46 -07:00
Paul Gauthier
763724ed4e docs: add comment about prompting user for URL opening 2024-10-30 11:42:44 -07:00
Paul Gauthier
9e0e68caf9 copy 2024-10-30 11:41:39 -07:00
Paul Gauthier
52f697e513 style: remove extra blank line before main block 2024-10-30 11:41:11 -07:00
Paul Gauthier (aider)
aeca62bcf6 fix: remove unused import of urls module 2024-10-30 11:41:04 -07:00
Paul Gauthier
7e574bc214 refactor: improve documentation URL handling and error messages 2024-10-30 11:40:56 -07:00
Paul Gauthier (aider)
e9beb1336c style: fix line length in model warnings confirmation prompt 2024-10-30 11:34:24 -07:00
Paul Gauthier (aider)
4ac8386313 feat: add browser launch for model warnings documentation 2024-10-30 11:34:19 -07:00
Paul Gauthier
f0233455d2 feat: update model warning prompt to offer documentation link 2024-10-30 11:34:18 -07:00
Paul Gauthier
5c28dd039c pip compile 2024-10-30 09:41:57 -07:00
Paul Gauthier
26d1ab7a5f copy 2024-10-30 09:40:54 -07:00
Paul Gauthier
068fb38a5d Merge branch 'main' into mixpanel 2024-10-30 09:40:01 -07:00
Paul Gauthier
53e7eba00b copy 2024-10-30 06:39:48 -07:00
Paul Gauthier
854d908fe0 refactor: improve chat history file error handling and messaging 2024-10-30 06:37:59 -07:00
Paul Gauthier
ea3359fb4b test: adjust warning count assertion in model test 2024-10-30 06:33:31 -07:00
Paul Gauthier (aider)
55a2ba4bd6 style: Fix comment formatting in test_models.py 2024-10-30 06:32:22 -07:00
Paul Gauthier (aider)
20ca9c84c7 test: add warning message debug print in model test 2024-10-30 06:32:18 -07:00
Paul Gauthier
0d86124b15 test: add comment about tool warning args inspection 2024-10-30 06:32:17 -07:00
Paul Gauthier
554fa98c48 fix: simplify version check for dev mode 2024-10-30 06:30:11 -07:00
Paul Gauthier (aider)
eb92fa4f88 fix: handle TypeError when checking __version__ for dev mode 2024-10-30 06:26:50 -07:00
Paul Gauthier
0424e4b00a refactor: improve SQLite error handling and logging in tags cache 2024-10-29 15:09:22 -07:00
Paul Gauthier (aider)
adca062081 feat: improve SQLite error handling with original exception details 2024-10-29 15:05:16 -07:00
Paul Gauthier
ef0fcb8f38 refactor: Improve SQLite cache error handling and import organization 2024-10-29 15:04:00 -07:00
Paul Gauthier (aider)
0feed0047c style: fix whitespace and formatting in repomap.py 2024-10-29 14:59:55 -07:00
Paul Gauthier (aider)
7f027ff6e5 feat: add auto-recovery for corrupted tags cache 2024-10-29 14:59:50 -07:00
Paul Gauthier (aider)
e25a46c892 fix: wrap TAGS_CACHE length check in try/except block for SQLite errors 2024-10-29 14:58:00 -07:00
Paul Gauthier (aider)
68916b1186 feat: add error handling for SQLite tags cache operations 2024-10-29 14:55:43 -07:00
Paul Gauthier
e9771588e4 copy 2024-10-29 14:48:39 -07:00
Paul Gauthier
e1d55c82b1 refactor: Improve edit handling with dry run and path resolution 2024-10-29 14:31:12 -07:00
Paul Gauthier (aider)
5b6be29c1c chore: remove obsolete comment about path variable 2024-10-29 14:28:39 -07:00
Paul Gauthier
28d9f6f8da refactor: add dry run mode to apply_edits method 2024-10-29 14:28:38 -07:00
Paul Gauthier (aider)
3ccae4eff7 style: fix line length in test_commands.py 2024-10-29 14:19:53 -07:00
Paul Gauthier (aider)
3ad240a10e fix: normalize path separators in save/load tests for Windows compatibility 2024-10-29 14:19:47 -07:00
Paul Gauthier
87a31a583a refactor: remove unused comment in EditBlockCoder 2024-10-29 14:11:13 -07:00
Paul Gauthier (aider)
7553104433 refactor: handle updated edits array returned from apply_edits 2024-10-29 14:10:21 -07:00
Paul Gauthier
f9604633e6 fix: handle updated edits array in apply_edits return value 2024-10-29 14:10:19 -07:00
Paul Gauthier (aider)
eb9a73bdb0 fix: strip whitespace from file paths before resolving in test commands 2024-10-29 14:04:19 -07:00
Paul Gauthier (aider)
d75e75190d style: Fix regex string formatting in test commands 2024-10-29 14:03:46 -07:00
Paul Gauthier (aider)
94a49e601c refactor: use regex to normalize /add command spaces in tests 2024-10-29 14:03:40 -07:00
Paul Gauthier (aider)
3df3d86295 style: fix linting issues in test_commands.py 2024-10-29 14:02:43 -07:00
Paul Gauthier (aider)
63f8979f2b fix: normalize whitespace in command text assertions 2024-10-29 14:02:37 -07:00
Paul Gauthier
ad94e49ef5 test: fix failing test cases for save and load commands 2024-10-29 14:02:35 -07:00
Paul Gauthier
b40ff2a601 fix: improve o1 model detection with startswith check 2024-10-29 14:00:56 -07:00
Paul Gauthier
a4be01b474 refactor: move --load command execution before message processing 2024-10-29 13:59:41 -07:00
Paul Gauthier
c5dc44a73f style: simplify command execution output message 2024-10-29 13:59:04 -07:00
Paul Gauthier (aider)
358cbc9388 feat: add filename autocompletion to /load and /save commands 2024-10-29 13:58:25 -07:00
Paul Gauthier
2e5fa9dea4 style: align /add commands in history file for better readability 2024-10-29 13:58:23 -07:00
Paul Gauthier
717592463e feat: add --load option to execute commands from file on launch 2024-10-29 13:54:42 -07:00
Paul Gauthier (aider)
347a9f2a6d feat: add --load argument to execute commands from file 2024-10-29 13:53:19 -07:00
Paul Gauthier
d288122fab chore: add comment for load command implementation 2024-10-29 13:53:17 -07:00
Paul Gauthier (aider)
d1cf3d4600 refactor: conditionally set cursor shape only in vi mode 2024-10-29 13:50:40 -07:00
Paul Gauthier
5188872791 style: add comment about vi mode cursor config 2024-10-29 13:50:38 -07:00
Paul Gauthier
a57a06e8c7 Merge branch 'main' of github.com:Aider-AI/aider 2024-10-29 13:49:50 -07:00
Paul Gauthier (aider)
347ad34038 fix: update file path comparison in commands test to handle macOS prefix 2024-10-29 13:48:16 -07:00
Paul Gauthier (aider)
ccdd333ba3 fix: update test to use os.path.samefile for path comparison 2024-10-29 13:45:03 -07:00
Paul Gauthier (aider)
56f3220d4c fix: handle macOS /private/ prefix in file path tests 2024-10-29 13:21:31 -07:00
Paul Gauthier (aider)
26a85c2047 style: fix line length in test_commands.py 2024-10-29 13:20:49 -07:00
Paul Gauthier (aider)
f800ce1e5a test: use os.path.samefile for file path comparison in save/load test 2024-10-29 13:20:44 -07:00
Paul Gauthier
d4103cc271 chore: Remove unused comment in test file 2024-10-29 13:20:42 -07:00
Paul Gauthier (aider)
c3ba3b6f48 style: fix whitespace and comment formatting in test_commands.py 2024-10-29 13:19:15 -07:00
Paul Gauthier (aider)
be54df4084 refactor: improve path comparison in command tests using os.path.samefile 2024-10-29 13:19:09 -07:00
Paul Gauthier
d06c6f8557 style: improve clarity of comment in test_commands.py 2024-10-29 13:18:53 -07:00
Paul Gauthier
a876561ea0 test: add comment about parsing text in session file test 2024-10-29 13:17:50 -07:00
Paul Gauthier (aider)
6dc0b8d853 fix: use absolute paths for read-only files outside repo root 2024-10-29 13:14:37 -07:00
Paul Gauthier (aider)
460311d49e style: fix line continuation formatting in test file 2024-10-29 13:11:50 -07:00
Paul Gauthier (aider)
94396070e8 test: add test for saving and loading multiple external files 2024-10-29 13:11:44 -07:00
Paul Gauthier (aider)
4a3cb8dc95 fix: use platform-agnostic paths in test_commands.py 2024-10-29 13:11:00 -07:00
Paul Gauthier
f9005451fa test: add comment about Windows path separator issue in test_commands.py 2024-10-29 13:10:58 -07:00
paul-gauthier
16e292b1fd Merge pull request #2180 from kAIto47802/fix-o1-system-prompt 2024-10-29 13:03:35 -07:00
Paul Gauthier (aider)
7d37793765 style: fix linting issues by removing extra blank line 2024-10-29 12:54:12 -07:00
Paul Gauthier (aider)
9e9c162a16 style: fix indentation in test_cmd_save_and_load_with_external_file 2024-10-29 12:54:05 -07:00
Paul Gauthier (aider)
8d6db81a40 style: fix linting issues in test_commands.py 2024-10-29 12:53:27 -07:00
Paul Gauthier (aider)
425bd8932b test: add save/load test with external read-only file 2024-10-29 12:53:22 -07:00
Paul Gauthier
38820701be test: add comment for read-only file test case 2024-10-29 12:53:20 -07:00
Paul Gauthier
1bc74676ff copy 2024-10-29 12:49:16 -07:00
Paul Gauthier (aider)
0c37f002c9 style: remove extra newlines and fix trailing comma 2024-10-29 12:48:21 -07:00
Paul Gauthier (aider)
18c41b6128 refactor: move test_cmd_save_and_load to test_commands.py 2024-10-29 12:48:11 -07:00
Paul Gauthier
5876af4e94 test: add test for cmd_save and cmd_load functionality 2024-10-29 12:48:08 -07:00
Paul Gauthier (aider)
e1d145013a style: remove trailing newline in test_commands.py 2024-10-29 12:46:37 -07:00
Paul Gauthier (aider)
143eeff4da test: add tests for cmd_save and cmd_load commands 2024-10-29 12:46:31 -07:00
Paul Gauthier
3a7e4bac34 test: add TODO comment for cmd_save and cmd_load test coverage 2024-10-29 12:46:29 -07:00
Paul Gauthier (aider)
f5ca162576 style: fix whitespace and comment formatting 2024-10-29 12:43:56 -07:00
Paul Gauthier (aider)
dbefa6b010 feat: add /save command to store chat session file list 2024-10-29 12:43:51 -07:00
Paul Gauthier
79cdff6163 feat: add /save command to persist added files for /load 2024-10-29 12:43:49 -07:00
Paul Gauthier (aider)
b111fc357c fix: use IO encoding and handle decode errors in cmd_load 2024-10-29 12:42:33 -07:00
Paul Gauthier
2af48e159c feat: add encoding hint for file loading in commands 2024-10-29 12:42:31 -07:00
Paul Gauthier (aider)
6cec44e402 style: fix string quotes and whitespace in commands.py 2024-10-29 12:41:10 -07:00
Paul Gauthier (aider)
fc6c01a9a5 feat: add command to load and execute commands from file 2024-10-29 12:41:01 -07:00
Paul Gauthier
01439875af feat: add comment for future cmd_load implementation 2024-10-29 12:40:57 -07:00
kAIto47802
fcdf998fac Fix o1 settings 2024-10-29 08:47:24 +09:00
Paul Gauthier
ed4ad45e3d copy 2024-10-28 15:12:06 -07:00
Paul Gauthier
907c1dbe2b refactor: split error and retry messages in simple_send_with_retries 2024-10-28 15:10:27 -07:00
Paul Gauthier (aider)
3baad86afd refactor: consolidate error and retry messages into single print statement 2024-10-28 15:09:22 -07:00
Paul Gauthier (aider)
0351924628 test: update print call count assertions in sendchat tests 2024-10-28 15:09:11 -07:00
Paul Gauthier
29250f82ed test: fix print call count assertions in sendchat tests 2024-10-28 15:07:50 -07:00
Paul Gauthier
a819bf1d64 test: fix assertion errors in sendchat retry tests 2024-10-28 15:07:11 -07:00
Paul Gauthier (aider)
bc515cf74a refactor: add retry loop to simple_send_with_retries function 2024-10-28 15:05:07 -07:00
Paul Gauthier
f9c45432e6 refactor: Move retry logic from base_coder to sendchat module 2024-10-28 15:05:06 -07:00
Paul Gauthier
54d55c857b refactor: update retry exceptions to use openai instead of litellm 2024-10-28 14:40:42 -07:00
Paul Gauthier
8e2a4b47d6 fix: update litellm exception imports and error handling 2024-10-28 14:29:42 -07:00
Paul Gauthier (aider)
513f06be46 refactor: move retry_exceptions import to top of test file 2024-10-28 14:28:49 -07:00
Paul Gauthier
0fb79917ff test: add test for retry_exceptions function call 2024-10-28 14:28:48 -07:00
Paul Gauthier (aider)
cd133f95ee style: fix linting issues with whitespace and line breaks 2024-10-28 14:27:26 -07:00
Paul Gauthier (aider)
3d66b53791 test: add basic test for retry_exceptions function 2024-10-28 14:27:20 -07:00
Paul Gauthier
bf63e7045b refactor: simplify litellm exception imports 2024-10-28 14:27:19 -07:00
Paul Gauthier
e2dff0a74b #2120 2024-10-25 15:47:30 -07:00
Paul Gauthier (aider)
bf60e58d5b fix: use os.path.join for cross-platform path handling in tests 2024-10-25 10:57:04 -07:00
Paul Gauthier
e3a3a55dd5 fix: make file paths portable for Windows compatibility in tests 2024-10-25 10:57:03 -07:00
Paul Gauthier
1ed2eefff4 copy 2024-10-25 09:38:10 -07:00
Paul Gauthier
df65e87ef3 test: update InputOutput initialization with fancy_input param in tests 2024-10-25 09:24:52 -07:00
Paul Gauthier
ddb876d2fe only glob, not rglob for /read 2024-10-25 09:22:50 -07:00
Paul Gauthier
a080581329 refactor: improve file path handling with glob and rglob 2024-10-25 07:49:19 -07:00
Paul Gauthier (aider)
f70a82791b fix: handle absolute paths and globs in cmd_read_only 2024-10-25 07:43:31 -07:00
Paul Gauthier
5d3a60228c fix: use Path.rglob instead of glob.glob for recursive file matching 2024-10-25 07:43:29 -07:00
Paul Gauthier
fd820dbfe2 Merge branch 'main' of github.com:Aider-AI/aider 2024-10-25 07:41:02 -07:00
paul-gauthier
b911ceaa61 Merge pull request #2126 from webkonstantin/fix-read-only-from-working-dir
fix: Impossible to /read-only from another working directory
2024-10-25 07:40:57 -07:00
Paul Gauthier
9edf9b4186 refactor: extract get_rel_fname function for path resolution 2024-10-25 07:36:29 -07:00
Paul Gauthier
be74259df6 fix: add missing AnthropicError exception to retry list 2024-10-25 07:31:39 -07:00
Paul Gauthier
29293cc8ac fix: update import path for AnthropicError in retry_exceptions 2024-10-25 07:07:36 -07:00
Paul Gauthier
9e7995b730 bump deps 2024-10-25 06:55:47 -07:00
Konstantin L
ba9fdaa755 fix: Impossible to /read-only from another working directory 2024-10-25 10:59:23 +02:00
Paul Gauthier
dde2dee304 fix last test 2024-10-24 14:31:41 -07:00
Paul Gauthier (aider)
55a99143c2 test: set fancy_input=False in all InputOutput() test instances 2024-10-24 14:31:11 -07:00
Paul Gauthier
ba2bee61de test: fix confirm_ask_yes_no test by disabling fancy input 2024-10-24 14:31:09 -07:00
Paul Gauthier (aider)
5fd8fb15b9 fix: add fancy_input=False to all InputOutput test initializations 2024-10-24 14:27:53 -07:00
Paul Gauthier
8908a48b68 copy 2024-10-24 14:25:08 -07:00
Paul Gauthier (aider)
43fbda0faf feat: add --fancy-input flag to control input history and completion 2024-10-24 14:24:09 -07:00
Paul Gauthier (aider)
97a9c65125 feat: add fancy_input parameter to InputOutput class initialization 2024-10-24 14:23:24 -07:00
Paul Gauthier
8a63b1b3ce refactor: rename pretty flag to fancy_input for clarity 2024-10-24 14:23:22 -07:00
Paul Gauthier
3c658ac66f feat: set default reminder to "user" for gpt-4-1106-preview model 2024-10-24 14:08:51 -07:00
Paul Gauthier
055d529947 remove accepts_images 2024-10-24 14:08:06 -07:00
Paul Gauthier (aider)
9507f3c008 refactor: use main_model.info["supports_vision"] instead of accepts_images 2024-10-24 14:05:17 -07:00
Paul Gauthier
e0a1eefe0a copy 2024-10-24 14:01:00 -07:00
Paul Gauthier
ea37ba8346 set version to 0.60.2.dev 2024-10-24 13:59:43 -07:00
Paul Gauthier
8ea789c29d version bump to 0.60.1 2024-10-24 13:58:28 -07:00
Paul Gauthier
901e4397cb copy 2024-10-24 13:49:27 -07:00
Paul Gauthier (aider)
bcf781da73 feat: sort file lists alphabetically in format_files_for_input 2024-10-24 13:48:32 -07:00
Paul Gauthier
a68178fd1b refactor: sort files in format_files_for_input method 2024-10-24 13:48:31 -07:00
Paul Gauthier (aider)
e18b8b0a29 style: fix indentation in commands.py 2024-10-24 13:46:32 -07:00
Paul Gauthier (aider)
62ff822ee8 refactor: collect and sort expanded filenames before processing 2024-10-24 13:46:27 -07:00
Paul Gauthier
c9993dccc8 fix: remove stray comment and add sorting note in cmd_read 2024-10-24 13:46:25 -07:00
Paul Gauthier (aider)
6181fe5efa feat: sort filenames in cmd_read_only for consistent behavior 2024-10-24 13:44:52 -07:00
Paul Gauthier
dd6124fa64 refactor: sort filenames in cmd_read to match cmd_add behavior 2024-10-24 13:44:51 -07:00
Paul Gauthier (aider)
239302a219 feat: sort filenames before adding to chat 2024-10-24 13:43:01 -07:00
Paul Gauthier
e0949bff69 feat: sort filenames before adding them to chat 2024-10-24 13:42:59 -07:00
Paul Gauthier
e0c603c764 copy 2024-10-24 13:38:50 -07:00
Paul Gauthier
8f62f99db7 feat: add image support for Claude 3 models 2024-10-24 13:38:21 -07:00
Paul Gauthier (aider)
b46de7127d style: format Python code with black linter 2024-10-24 12:34:04 -07:00
Paul Gauthier (aider)
e9627cb3c6 feat: add --yes flag to auto-close duplicate issues without prompting 2024-10-24 12:34:01 -07:00
Paul Gauthier
eb8fdf483e feat: add --yes flag to issues script 2024-10-24 12:33:59 -07:00
Paul Gauthier
a6d5fa9cda copy 2024-10-22 14:40:14 -07:00
Paul Gauthier
1bef71f57a copy 2024-10-22 14:40:05 -07:00
Paul Gauthier
63c393e269 copy 2024-10-22 14:23:37 -07:00
Paul Gauthier
1efb0ba53e added new sonnet and o1 models to refac leaderboard 2024-10-22 14:17:36 -07:00
Paul Gauthier
4a3e6ef1e5 update sonnet model names since they are in litellm json now 2024-10-22 12:53:26 -07:00
Paul Gauthier (aider)
a800d219c7 feat: add ModelSettings for Claude 3.5 Sonnet v2 on Vertex AI 2024-10-22 12:51:21 -07:00
Paul Gauthier
7f962b5bb0 feat: add Claude 3.5 Sonnet model settings 2024-10-22 12:51:19 -07:00
Paul Gauthier
57642cf96c copy 2024-10-22 12:21:25 -07:00
Paul Gauthier
c2e49be096 set version to 0.60.1.dev 2024-10-22 11:35:38 -07:00
Paul Gauthier
c26b2e4859 version bump to 0.60.0 2024-10-22 11:34:28 -07:00
Paul Gauthier
9ce0757835 copy 2024-10-22 11:11:22 -07:00
Paul Gauthier
c80a032297 copy 2024-10-22 10:54:34 -07:00
Paul Gauthier
bd28d8f3fb corrected 1022 benchmark results 2024-10-22 10:52:35 -07:00
Paul Gauthier
748fd0cf12 copy 2024-10-22 10:49:29 -07:00
Paul Gauthier
ac6f495377 1022 should use 1022 as editor 2024-10-22 10:48:29 -07:00
Paul Gauthier
3b14eb98a5 copy 2024-10-22 10:43:08 -07:00
Paul Gauthier
914bf3d82b feat: add model metadata for Claude 3.5 Sonnet 2024-10-22 10:42:13 -07:00
Paul Gauthier
949b50bd69 fix 1122->1022 2024-10-22 10:36:30 -07:00
Paul Gauthier (aider)
d234d5e3ec feat: add resource model metadata to search path 2024-10-22 10:34:29 -07:00
Paul Gauthier
1b530f9200 copy 2024-10-22 10:10:09 -07:00
Paul Gauthier
3c4dad7eb4 use sonnet 1022 by default 2024-10-22 10:09:35 -07:00
Paul Gauthier
cfcb6656cb added claude-3-5-sonnet-20241022 benchmarks 2024-10-22 10:05:15 -07:00
Paul Gauthier
ae54ef57ae simplify format_files_for_input 2024-10-22 10:02:42 -07:00
Paul Gauthier
cb306b61cd added model settings for sonnet 1022 2024-10-22 09:38:32 -07:00
Paul Gauthier
46269f2e9b cleanup 2024-10-21 15:31:27 -07:00
Paul Gauthier
7c9f9be7d8 fix: remove trailing slash from index.md URLs in fname_to_url tests 2024-10-21 14:46:53 -07:00
Paul Gauthier (aider)
ef45fe1015 style: format code with black 2024-10-21 14:32:05 -07:00
Paul Gauthier (aider)
eaaf05d964 fix: handle Windows-style paths in fname_to_url function 2024-10-21 14:32:01 -07:00
Paul Gauthier (aider)
3ce1cfb908 refactor: remove unused imports in test_help.py 2024-10-21 14:28:50 -07:00
Paul Gauthier (aider)
9e0a9e919b style: apply linter formatting changes 2024-10-21 14:28:35 -07:00
Paul Gauthier (aider)
671f3078c1 test: add fname_to_url tests for Unix, Windows, and edge cases 2024-10-21 14:28:28 -07:00
Paul Gauthier (aider)
67d538a499 style: format code with linter 2024-10-21 14:23:11 -07:00
Paul Gauthier (aider)
b69d131810 refactor: improve robustness of fname_to_url function 2024-10-21 14:23:07 -07:00
Paul Gauthier
949b7ece36 chore: Add debug logging for filepath and node metadata 2024-10-21 14:23:05 -07:00
Paul Gauthier
d1e35bcdd1 refactor: update stale issue handling and edit block replacement logic 2024-10-21 12:02:29 -07:00
Paul Gauthier
34ec197199 copy 2024-10-21 10:46:15 -07:00
Paul Gauthier (aider)
5a1cf67ea3 ci: add permissions for stale issue workflow 2024-10-21 10:39:45 -07:00
Paul Gauthier
e427e2da05 do not stale prs 2024-10-21 10:37:43 -07:00
Paul Gauthier (aider)
2cfd4d719a feat: add manual trigger for stale issue closure workflow 2024-10-21 10:30:19 -07:00
Paul Gauthier
709633de72 Merge branch 'main' of github.com:Aider-AI/aider 2024-10-21 10:27:26 -07:00
Paul Gauthier
bf46f6dc8b only stale questions 2024-10-21 10:26:55 -07:00
Paul Gauthier (aider)
259a18f3dd chore: update stale workflow to mark issues as stale after 14 days 2024-10-21 10:25:45 -07:00
Paul Gauthier (aider)
4c3aea4bfc feat: add stale issue and PR workflow 2024-10-21 10:04:26 -07:00
Paul Gauthier
6c595c261c chore: add GitHub action to close stale issues and PRs 2024-10-21 10:04:24 -07:00
paul-gauthier
ecaf1e674d Merge pull request #1982 from jbellis/minimal_fileids
add format_files_for_input and compute_minimal_fileids to beautify the shown session context
2024-10-21 09:55:21 -07:00
Paul Gauthier
e76704e261 copy 2024-10-16 10:32:41 -07:00
Paul Gauthier
e092081c56 Merge branch 'main' of github.com:Aider-AI/aider 2024-10-16 10:17:42 -07:00
Paul Gauthier
4d6db0cb09 copy 2024-10-16 10:16:22 -07:00
Paul Gauthier
0729a725ad copy 2024-10-16 10:15:17 -07:00
Paul Gauthier
b7a884d81e feat: add Llama-3.1-Nemotron-70B model to edit leaderboard 2024-10-16 10:14:42 -07:00
Paul Gauthier
90e6941de5 slight tweak to wholefile prompt 2024-10-16 10:13:48 -07:00
paul-gauthier
c7a05d75fd Merge pull request #1927 from mbokinala/update-docs-pipx-boto3
docs: update instructions for AWS Bedrock pipx installation to include boto3 inject step
2024-10-15 13:21:34 -07:00
Manav Bokinala
ce253fec8f move pipx bedrock boto3 instructions to bedrock.md 2024-10-15 12:59:41 -07:00
Paul Gauthier
6bb9b2567f refactor: Centralize retry timeout and use consistent value 2024-10-15 12:25:05 -07:00
Paul Gauthier
26058c89fe fix pages deploy 2024-10-14 12:57:02 -07:00
Paul Gauthier
692f6a7b85 update linkchecker install 2024-10-14 11:22:05 -07:00
Paul Gauthier
163a29b026 copy 2024-10-14 11:01:00 -07:00
Paul Gauthier
06534fa91e copy 2024-10-14 10:59:42 -07:00
Paul Gauthier
bf45a14b30 feat: add Grok-2 and Grok-2-mini model results to leaderboard 2024-10-14 10:58:40 -07:00
Paul Gauthier
0a497b7fd7 copy 2024-10-10 19:19:54 -07:00
Paul Gauthier
e1f85aa19e copy 2024-10-10 15:24:41 -07:00
Paul Gauthier
2f307e46e2 Merge branch 'main' of github.com:Aider-AI/aider 2024-10-10 15:24:04 -07:00
Paul Gauthier
22203124e9 copy 2024-10-10 15:23:46 -07:00
Paul Gauthier
7e881927d6 cleanup 2024-10-10 15:22:06 -07:00
Paul Gauthier
a4e359daf4 cleanup 2024-10-10 15:08:18 -07:00
paul-gauthier
ef2c165399 Merge pull request #2005 from strayer/strayer/add-azure-o1-model-settings 2024-10-10 06:29:00 -07:00
Sven Grunewaldt
deb27f8f27 feat: Add new model settings for azure/o1-preview
Fixes litellm exceptions and incorrect model settings when using
o1-preview on Azure OpenAI.
2024-10-10 12:05:04 +02:00
fry69
e51d8a403f Merge pull request #2002 from fry69/help-cleanup
Cleanup.
2024-10-10 06:49:02 +02:00
fry69
27ddf8aeab fix: remove unreachable return statements 2024-10-10 06:46:10 +02:00
Jonathan Ellis
b915b1834d remove unused imports 2024-10-09 14:37:22 -05:00
fry69
cd3e0ae914 Merge pull request #1990 from fry69/clipboard-fix
Another quick fix
2024-10-09 14:08:00 +02:00
fry69
e820fea289 doc: fix leftover /clipboard mention 2024-10-09 14:06:30 +02:00
fry69
fc63faa737 Merge pull request #1987 from fry69/openrouter-haiku-fix
Quick emergency fix
2024-10-09 13:04:30 +02:00
fry69
65b50cdaee fix: correct weak model names for Sonnet-3.5 on OpenRouter 2024-10-09 12:50:44 +02:00
Jonathan Ellis
464c3e29e1 add format_files_for_input and compute_minimal_fileids 2024-10-08 22:29:46 -05:00
Paul Gauthier
f65bf9aee7 indent 2024-10-08 10:47:44 -07:00
Paul Gauthier
80f7e56785 initial 2024-10-08 10:39:30 -07:00
Paul Gauthier
0cb05dd001 initial 2024-10-08 10:38:36 -07:00
paul-gauthier
0fe5247d4c Merge pull request #1967 from fry69/chat-history-fix-try2
doc: fix wrong encapsulation
2024-10-07 16:33:01 -07:00
fry69
91a013afb3 doc: fix wrong encapsulation 2024-10-08 01:22:50 +02:00
fry69
3bc056a107 doc: fix wrong encapsulation 2024-10-08 01:22:01 +02:00
paul-gauthier
456c163cb9 Merge pull request #1966 from fry69/chat-history-fix 2024-10-07 15:54:19 -07:00
fry69
f3ff24e35a doc: clarify soft limit for chat history tokens 2024-10-08 00:51:04 +02:00
Paul Gauthier
1d2a3f573c fixes #1941 2024-10-07 13:05:40 -07:00
Paul Gauthier
cbdabd3ae9 fixes #1944 2024-10-07 13:05:28 -07:00
Paul Gauthier
c24ec7f230 fix: Handle additional Git errors in repo check 2024-10-07 12:52:38 -07:00
Paul Gauthier
3146d285bf fix gitignore test 2024-10-07 12:29:39 -07:00
Paul Gauthier (aider)
bde93903de feat: add .env to gitignore check and update process 2024-10-07 12:26:45 -07:00
Paul Gauthier
e487351c8d copy 2024-10-05 14:40:05 -07:00
Paul Gauthier
10ecb4b97f copy 2024-10-05 14:38:01 -07:00
Paul Gauthier (aider)
04a2cbb494 refactor: update regex patterns to match complete lines with optional whitespace 2024-10-05 12:31:23 -07:00
Manav Bokinala
30238dbbd5 docs: update instructions for pipx installation to include boto3 inject step 2024-10-04 20:05:33 -07:00
Paul Gauthier
0aad7b46f6 cleaner logic for load/save analytics.json 2024-08-16 11:28:13 -07:00
Paul Gauthier
62d8190733 copy 2024-08-16 11:04:54 -07:00
Paul Gauthier
4759297b67 disabled -> permanently_disabled 2024-08-16 11:03:14 -07:00
Paul Gauthier
607a9a8c86 track -> enable 2024-08-16 10:59:44 -07:00
Paul Gauthier
96b67ab26c copy 2024-08-16 10:45:14 -07:00
Paul Gauthier
93b8cb9cec Merge branch 'main' into mixpanel 2024-08-16 10:42:55 -07:00
Paul Gauthier (aider)
7b6ad16fdb fix: Preserve existing UUID when marking analytics as disabled 2024-08-13 14:22:39 -07:00
Paul Gauthier (aider)
b722572a28 style: format analytics.py file 2024-08-13 13:03:54 -07:00
Paul Gauthier (aider)
46489f1a46 feat: Add PostHog analytics integration 2024-08-13 13:03:51 -07:00
Paul Gauthier
d7a29c42b7 Merge branch 'main' into mixpanel 2024-08-13 13:01:43 -07:00
Paul Gauthier (aider)
1ebe5f8bd5 feat: add edit_format to event() call 2024-08-13 10:04:28 -07:00
Paul Gauthier
26fe63b7ac cleanup 2024-08-13 10:04:05 -07:00
Paul Gauthier
d2435c2e00 copy 2024-08-13 10:02:54 -07:00
Paul Gauthier
4d04a35e73 Merge branch 'main' into mixpanel 2024-08-13 09:52:50 -07:00
Paul Gauthier
cabad84521 tweak 2024-08-13 08:12:23 -07:00
Paul Gauthier
aeadf2f139 fix: Disable analytics by default and provide option to enable 2024-08-13 08:08:05 -07:00
Paul Gauthier
4ebbfa01b7 share last 1k analytics logs 2024-08-13 07:50:28 -07:00
Paul Gauthier
960b456e70 cleanup 2024-08-13 07:50:06 -07:00
Paul Gauthier (aider)
329514289d fix: Initialize Analytics instance with track=False if analytics is None 2024-08-13 07:45:35 -07:00
Paul Gauthier (aider)
03f14dfe47 feat: Create Analytics instance with track=False if analytics is None 2024-08-13 07:45:19 -07:00
Paul Gauthier (aider)
1c321df457 feat: Move analytics arguments to their own section 2024-08-13 07:23:46 -07:00
Paul Gauthier
8a21eb7804 handle new vars that accumulate tokens/costs for infinite output 2024-08-13 07:23:01 -07:00
Paul Gauthier
c1d4adbebf added mixpanel dep 2024-08-13 07:18:26 -07:00
Paul Gauthier
ef933c207b Merge branch 'main' into mixpanel 2024-08-13 07:17:13 -07:00
Paul Gauthier
08aaae4d36 initial 2024-08-13 07:16:35 -07:00
Paul Gauthier
f52265362f Merge branch 'main' into mixpanel 2024-08-13 07:09:34 -07:00
Paul Gauthier (aider)
00aa43d964 fix: Move imports to the top of the file in aider/analytics.py 2024-08-12 20:44:56 -07:00
Paul Gauthier (aider)
84489f16b5 refactor: Refactor data file name and mkdir operations 2024-08-12 20:44:42 -07:00
Paul Gauthier
e07194bbeb fix: Rename uuid_file to data_file for consistency 2024-08-12 20:44:41 -07:00
Paul Gauthier (aider)
1567d3e3d1 fix: Remove duplicate get_or_create_uuid method 2024-08-12 20:41:59 -07:00
Paul Gauthier (aider)
eca7a57138 style: Format code with linter 2024-08-12 20:41:17 -07:00
Paul Gauthier (aider)
64df0ad590 feat: Add --analytics-disable option to disable analytics tracking 2024-08-12 20:41:10 -07:00
Paul Gauthier
5a28d499a8 fix: Update the path for the Mixpanel UUID file 2024-08-12 20:41:09 -07:00
Paul Gauthier
4bad876f66 fix: Add event tracking for interactive help command 2024-08-12 20:36:51 -07:00
Paul Gauthier (aider)
1a8763d989 feat: Add --analytics-log argument and pass it to Analytics 2024-08-12 18:27:40 -07:00
Paul Gauthier (aider)
13eaf5e5ce style: Fix formatting in analytics.py 2024-08-12 18:26:11 -07:00
Paul Gauthier (aider)
82250db8af feat: Add logfile support to Analytics class 2024-08-12 18:26:08 -07:00
Paul Gauthier
85fa78f5a6 fix: Correct command execution logic 2024-08-12 18:23:51 -07:00
Paul Gauthier (aider)
9ed732959e fix: Remove unnecessary slice from event name in Commands.run 2024-08-12 18:22:51 -07:00
Paul Gauthier (aider)
860a36fe6c refactor: Extract command name from matching_commands[0][1:] 2024-08-12 18:22:36 -07:00
Paul Gauthier (aider)
01a9a8ffc4 feat: add event logging for command usage 2024-08-12 18:22:05 -07:00
Paul Gauthier
aa840f0e28 be careful logging main_models that are not in the model db 2024-08-12 18:20:35 -07:00
Paul Gauthier (aider)
a7a626423c fix: Remove properties argument from event method in Analytics class 2024-08-12 18:08:02 -07:00
Paul Gauthier
c2c9b60ea6 feat: Add main_model parameter to event method in analytics.py 2024-08-12 18:08:01 -07:00
Paul Gauthier (aider)
a6282818db fix: Add early return if self.mp is not set 2024-08-12 16:23:12 -07:00
Paul Gauthier (aider)
f563544761 style: Fix linter issues in analytics.py 2024-08-12 16:21:49 -07:00
Paul Gauthier (aider)
48a344bc6d feat: Add system information to all events 2024-08-12 16:21:46 -07:00
Paul Gauthier
f110e8c8db fix: Update Mixpanel project token 2024-08-12 16:21:45 -07:00
Paul Gauthier (aider)
65c0608d5c style: format code 2024-08-12 16:17:17 -07:00
Paul Gauthier (aider)
57ce0dca67 feat: add self.event() to calculate_and_show_tokens_and_cost 2024-08-12 16:17:11 -07:00
Paul Gauthier
4129065d6c fix: Add event attribute to Coder class 2024-08-12 16:17:10 -07:00
Paul Gauthier (aider)
d59fd508c2 style: Apply linter formatting to analytics.py 2024-08-12 16:16:42 -07:00
Paul Gauthier (aider)
62a5cf8dee feat: Handle numeric values in event properties 2024-08-12 16:16:39 -07:00
Paul Gauthier (aider)
6ec4e60058 feat: Add kwargs support to event() method 2024-08-12 16:14:11 -07:00
Paul Gauthier
087b3d4ffb feat: Rename track_event to event in aider/analytics.py 2024-08-12 16:14:10 -07:00
Paul Gauthier (aider)
7d3585bafe style: Fix formatting and linting issues in analytics.py 2024-08-12 16:11:23 -07:00
Paul Gauthier (aider)
1a49974f98 feat: add aider version number to all events 2024-08-12 16:11:20 -07:00
Paul Gauthier
b11c17dbd4 feat: Add optional analytics tracking 2024-08-12 16:10:20 -07:00
Paul Gauthier
474ac62391 feat: Add analytics field to Coder class 2024-08-12 16:08:58 -07:00
Paul Gauthier (aider)
6ee8a74d47 style: format code with linter 2024-08-12 16:07:15 -07:00
Paul Gauthier (aider)
121dd908a6 feat: Add Mixpanel project token to Analytics class 2024-08-12 16:07:12 -07:00
Paul Gauthier
2e1ac25ce2 feat: Add analytics module with Mixpanel integration 2024-08-12 16:07:11 -07:00
Paul Gauthier
b49ee06f23 feat: Add analytics.py module 2024-08-12 16:05:06 -07:00
100 changed files with 7484 additions and 1880 deletions

View File

@@ -70,15 +70,15 @@ jobs:
id: deployment
uses: actions/deploy-pages@v2
- name: Set up Python ${{ matrix.python-version }}
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
python-version: '3.12'
- name: Install linkchecker
run: |
python -m pip install --upgrade pip
pip install linkchecker
python -m pip install linkchecker
- name: Run linkchecker
run: |

View File

@@ -33,12 +33,9 @@ ensure that your contributions can be integrated smoothly.
## Licensing
By contributing to this project, you agree that your contributions
will be licensed under the Apache License 2.0. Additionally, you
understand and agree that contributions may be subject to a different
license, should the project maintainers decide to change the licensing
terms.
Before contributing a PR, please review our
[Individual Contributor License Agreement](https://aider.chat/docs/legal/contributor-agreement.html).
All contributors will be asked to complete the agreement as part of the PR process.
## Setting up a Development Environment
@@ -190,8 +187,8 @@ pytest
You can also run specific test files or test cases by providing the file path or test name:
```
pytest aider/tests/test_coder.py
pytest aider/tests/test_coder.py::TestCoder::test_specific_case
pytest tests/basic/test_coder.py
pytest tests/basic/test_coder.py::TestCoder::test_specific_case
```
#### Continuous Integration

View File

@@ -1,7 +1,108 @@
# Release history
### v0.59.0
### 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`.
- Updated dependency versions to pick up litellm fix for ollama models.
- Added exponential backoff retry when writing files to handle editor file locks.
- Updated Qwen 2.5 Coder 32B model configuration.
### Aider v0.63.1
- Fixed bug in git ignored file handling.
- Improved error handling for git operations.
### Aider v0.63.0
- Support for Qwen 2.5 Coder 32B.
- `/web` command just adds the page to the chat, without triggering an LLM response.
- Improved prompting for the user's preferred chat language.
- Improved handling of LiteLLM exceptions.
- Bugfix for double-counting tokens when reporting cache stats.
- Bugfix for the LLM creating new files.
- Other small bug fixes.
- Aider wrote 55% of the code in this release.
### Aider v0.62.0
- Full support for Claude 3.5 Haiku
- Scored 75% on [aider's code editing leaderboard](https://aider.chat/docs/leaderboards/).
- Almost as good as Sonnet at much lower cost.
- Launch with `--haiku` to use it.
- Easily apply file edits from ChatGPT, Claude or other web apps
- Chat with ChatGPT or Claude via their web app.
- Give it your source files and ask for the changes you want.
- Use the web app's "copy response" button to copy the entire reply from the LLM.
- Run `aider --apply-clipboard-edits file-to-edit.js`.
- Aider will edit your file with the LLM's changes.
- Bugfix for creating new files.
- Aider wrote 84% of the code in this release.
### Aider v0.61.0
- Load and save aider slash-commands to files:
- `/save <fname>` command will make a file of `/add` and `/read-only` commands that recreate the current file context in the chat.
- `/load <fname>` will replay the commands in the file.
- You can use `/load` to run any arbitrary set of slash-commands, not just `/add` and `/read-only`.
- Use `--load <fname>` to run a list of commands on launch, before the interactive chat begins.
- Anonymous, opt-in [analytics](https://aider.chat/docs/more/analytics.html) with no personal data sharing.
- Aider follows litellm's `supports_vision` attribute to enable image support for models.
- Bugfix for when diff mode flexibly handles the model using the wrong filename.
- Displays filenames in sorted order for `/add` and `/read-only`.
- New `--no-fancy-input` switch disables prompt toolkit input, now still available with `--no-pretty`.
- Override browser config with `--no-browser` or `--no-gui`.
- Offer to open documentation URLs when errors occur.
- Properly support all o1 models, regardless of provider.
- Improved layout of filenames above input prompt.
- Better handle corrupted repomap tags cache.
- Improved handling of API errors, especially when accessing the weak model.
- Aider wrote 68% of the code in this release.
### Aider v0.60.1
- Enable image support for Sonnet 10/22.
- Display filenames in sorted order.
### Aider v0.60.0
- Full support for Sonnet 10/22, the new SOTA model on aider's code editing benchmark.
- Aider uses Sonnet 10/22 by default.
- Improved formatting of added and read-only files above chat prompt, by @jbellis.
- Improved support for o1 models by more flexibly parsing their nonconforming code edit replies.
- Corrected diff edit format prompt that only the first match is replaced.
- Stronger whole edit format prompt asking for clean file names.
- Now offers to add `.env` to the `.gitignore` file.
- Ships with a small model metadata json file to handle models not yet updated in litellm.
- Model settings for o1 models on azure.
- Bugfix to properly include URLs in `/help` RAG results.
- Aider wrote 49% of the code in this release.
### Aider v0.59.1
- Check for obsolete `yes: true` in yaml config, show helpful error.
- Model settings for openrouter/anthropic/claude-3.5-sonnet:beta
### Aider v0.59.0
- Improvements to `/read-only`:
- Now supports shell-style auto-complete of the full file system.

View File

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

203
aider/analytics.py Normal file
View File

@@ -0,0 +1,203 @@
import json
import platform
import sys
import time
import uuid
from pathlib import Path
from mixpanel import Mixpanel
from posthog import Posthog
from aider import __version__
from aider.dump import dump # noqa: F401
from aider.models import model_info_manager
mixpanel_project_token = "6da9a43058a5d1b9f3353153921fb04d"
posthog_project_api_key = "phc_99T7muzafUMMZX15H8XePbMSreEUzahHbtWjy3l5Qbv"
posthog_host = "https://us.i.posthog.com"
class Analytics:
# providers
mp = None
ph = None
# saved
user_id = None
permanently_disable = None
asked_opt_in = None
# ephemeral
logfile = None
def __init__(self, logfile=None, permanently_disable=False):
self.logfile = logfile
self.get_or_create_uuid()
if self.permanently_disable or permanently_disable or not self.asked_opt_in:
self.disable(permanently_disable)
def enable(self):
if not self.user_id:
self.disable(False)
return
if self.permanently_disable:
self.disable(True)
return
if not self.asked_opt_in:
self.disable(False)
return
self.mp = Mixpanel(mixpanel_project_token)
self.ph = Posthog(project_api_key=posthog_project_api_key, host=posthog_host)
def disable(self, permanently):
self.mp = None
self.ph = None
if permanently:
self.asked_opt_in = True
self.permanently_disable = True
self.save_data()
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"
data_file.parent.mkdir(parents=True, exist_ok=True)
return data_file
def get_or_create_uuid(self):
self.load_data()
if self.user_id:
return
self.user_id = str(uuid.uuid4())
self.save_data()
def load_data(self):
data_file = self.get_data_file_path()
if data_file.exists():
try:
data = json.loads(data_file.read_text())
self.permanently_disable = data.get("permanently_disable")
self.user_id = data.get("uuid")
self.asked_opt_in = data.get("asked_opt_in", False)
except (json.decoder.JSONDecodeError, OSError):
self.disable(permanently=False)
def save_data(self):
data_file = self.get_data_file_path()
data = dict(
uuid=self.user_id,
permanently_disable=self.permanently_disable,
asked_opt_in=self.asked_opt_in,
)
# Allow exceptions; crash if we can't record permanently_disabled=True, etc
data_file.write_text(json.dumps(data, indent=4))
def get_system_info(self):
return {
"python_version": sys.version.split()[0],
"os_platform": platform.system(),
"os_release": platform.release(),
"machine": platform.machine(),
}
def _redact_model_name(self, model):
if not model:
return None
info = model_info_manager.get_model_from_cached_json_db(model.name)
if info:
return model.name
elif "/" in model.name:
return model.name.split("/")[0] + "/REDACTED"
return None
def event(self, event_name, main_model=None, **kwargs):
if not (self.mp or self.ph) and not self.logfile:
return
properties = {}
if main_model:
properties["main_model"] = self._redact_model_name(main_model)
properties["weak_model"] = self._redact_model_name(main_model.weak_model)
properties["editor_model"] = self._redact_model_name(main_model.editor_model)
properties.update(kwargs)
properties.update(self.get_system_info()) # Add system info to all events
# Handle numeric values
for key, value in properties.items():
if isinstance(value, (int, float)):
properties[key] = value
else:
properties[key] = str(value)
properties["aider_version"] = __version__
if self.mp:
self.mp.track(self.user_id, event_name, dict(properties))
if self.ph:
self.ph.capture(self.user_id, event_name, dict(properties))
if self.logfile:
log_entry = {
"event": event_name,
"properties": properties,
"user_id": self.user_id,
"time": int(time.time()),
}
with open(self.logfile, "a") as f:
json.dump(log_entry, f)
f.write("\n")
def __del__(self):
if self.ph:
self.ph.shutdown()

View File

@@ -58,7 +58,7 @@ def get_parser(default_config_files, git_root):
const=opus_model,
help=f"Use {opus_model} model for the main chat",
)
sonnet_model = "claude-3-5-sonnet-20240620"
sonnet_model = "claude-3-5-sonnet-20241022"
group.add_argument(
"--sonnet",
action="store_const",
@@ -66,6 +66,14 @@ def get_parser(default_config_files, git_root):
const=sonnet_model,
help=f"Use {sonnet_model} model for the main chat",
)
haiku_model = "claude-3-5-haiku-20241022"
group.add_argument(
"--haiku",
action="store_const",
dest="model",
const=haiku_model,
help=f"Use {haiku_model} model for the main chat",
)
gpt_4_model = "gpt-4-0613"
group.add_argument(
"--4",
@@ -237,8 +245,8 @@ def get_parser(default_config_files, git_root):
type=int,
default=None,
help=(
"Maximum number of tokens to use for chat history. If not specified, uses the model's"
" max_chat_history_tokens."
"Soft limit on tokens for chat history, after which summarization begins."
" If unspecified, defaults to the model's max_chat_history_tokens."
),
)
# This is a duplicate of the argument in the preparser and is a no-op by this time of
@@ -550,6 +558,25 @@ def get_parser(default_config_files, git_root):
)
##########
group = parser.add_argument_group("Analytics")
group.add_argument(
"--analytics",
action=argparse.BooleanOptionalAction,
default=None,
help="Enable/disable analytics for current session (default: random)",
)
group.add_argument(
"--analytics-log",
metavar="ANALYTICS_LOG_FILE",
help="Specify a file to log analytics events",
)
group.add_argument(
"--analytics-disable",
action="store_true",
help="Permanently disable analytics",
default=False,
)
group = parser.add_argument_group("Other Settings")
group.add_argument(
"--file",
@@ -593,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",
@@ -611,6 +644,12 @@ def get_parser(default_config_files, git_root):
metavar="FILE",
help="Apply the changes from the given file instead of running the chat (debug)",
)
group.add_argument(
"--apply-clipboard-edits",
action="store_true",
help="Apply clipboard contents as edits using the main model's editor format",
default=False,
)
group.add_argument(
"--yes-always",
action="store_true",
@@ -660,6 +699,11 @@ def get_parser(default_config_files, git_root):
" (disables chat mode)"
),
)
group.add_argument(
"--load",
metavar="LOAD_FILE",
help="Load and execute /commands from a file on launch",
)
group.add_argument(
"--encoding",
default="utf-8",
@@ -678,8 +722,8 @@ def get_parser(default_config_files, git_root):
group.add_argument(
"--gui",
"--browser",
action="store_true",
help="Run aider in your browser",
action=argparse.BooleanOptionalAction,
help="Run aider in your browser (default: False)",
default=False,
)
group.add_argument(
@@ -688,6 +732,16 @@ def get_parser(default_config_files, git_root):
default=True,
help="Enable/disable suggesting shell commands (default: True)",
)
group.add_argument(
"--fancy-input",
action=argparse.BooleanOptionalAction,
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")
@@ -719,7 +773,6 @@ def get_md_help():
parser.formatter_class = MarkdownHelpFormatter
return argparse.ArgumentParser.format_help(parser)
return parser.format_help()
def get_sample_yaml():
@@ -733,7 +786,6 @@ def get_sample_yaml():
parser.formatter_class = YamlHelpFormatter
return argparse.ArgumentParser.format_help(parser)
return parser.format_help()
def get_sample_dotenv():
@@ -747,7 +799,6 @@ def get_sample_dotenv():
parser.formatter_class = DotEnvFormatter
return argparse.ArgumentParser.format_help(parser)
return parser.format_help()
def main():

View File

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

View File

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

View File

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

View File

@@ -17,9 +17,12 @@ from collections import defaultdict
from datetime import datetime
from json.decoder import JSONDecodeError
from pathlib import Path
from typing import List
from aider import __version__, models, prompts, urls, utils
from aider.analytics import Analytics
from aider.commands import Commands
from aider.exceptions import LiteLLMExceptions
from aider.history import ChatSummary
from aider.io import ConfirmGroup, InputOutput
from aider.linter import Linter
@@ -27,7 +30,7 @@ from aider.llm import litellm
from aider.repo import ANY_GIT_ERROR, GitRepo
from aider.repomap import RepoMap
from aider.run_cmd import run_cmd
from aider.sendchat import retry_exceptions, send_completion
from aider.sendchat import RETRY_TIMEOUT, send_completion
from aider.utils import format_content, format_messages, format_tokens, is_image_file
from ..dump import dump # noqa: F401
@@ -258,12 +261,17 @@ class Coder:
commands=None,
summarizer=None,
total_cost=0.0,
analytics=None,
map_refresh="auto",
cache_prompts=False,
num_cache_warming_pings=0,
suggest_shell_commands=True,
chat_language=None,
):
# Fill in a dummy Analytics if needed, but it is never .enable()'d
self.analytics = analytics if analytics is not None else Analytics()
self.event = self.analytics.event
self.chat_language = chat_language
self.commit_before_message = []
self.aider_commit_hashes = set()
@@ -347,6 +355,9 @@ class Coder:
for fname in fnames:
fname = Path(fname)
if self.repo and self.repo.git_ignored_file(fname):
self.io.tool_warning(f"Skipping {fname} that matches gitignore spec.")
if self.repo and self.repo.ignored_file(fname):
self.io.tool_warning(f"Skipping {fname} that matches aiderignore spec.")
continue
@@ -679,7 +690,7 @@ class Coder:
return chat_files_messages
def get_images_message(self):
if not self.main_model.accepts_images:
if not self.main_model.info.get("supports_vision"):
return None
image_messages = []
@@ -782,18 +793,37 @@ class Coder:
self.num_reflections += 1
message = self.reflected_message
def check_for_urls(self, inp):
def check_and_open_urls(self, exc, friendly_msg=None):
"""Check exception for URLs, offer to open in a browser, with user-friendly error msgs."""
text = str(exc)
if friendly_msg:
self.io.tool_warning(text)
self.io.tool_error(f"{friendly_msg}")
else:
self.io.tool_error(text)
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*)")
urls = list(set(url_pattern.findall(text))) # Use set to remove duplicates
for url in urls:
url = url.rstrip(".',\"")
self.io.offer_url(url)
return urls
def check_for_urls(self, inp: str) -> List[str]:
"""Check input for URLs and offer to add them to the chat."""
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*[^\s,.])")
urls = list(set(url_pattern.findall(inp))) # Use set to remove duplicates
added_urls = []
group = ConfirmGroup(urls)
for url in urls:
if url not in self.rejected_urls:
url = url.rstrip(".',\"")
if self.io.confirm_ask(
"Add URL to the chat?", subject=url, group=group, allow_never=True
):
inp += "\n\n"
inp += self.commands.cmd_web(url)
inp += self.commands.cmd_web(url, return_content=True)
added_urls.append(url)
else:
self.rejected_urls.add(url)
@@ -929,12 +959,18 @@ class Coder:
platform=platform_text
)
if self.chat_language:
language = self.chat_language
else:
language = "the same language they are using"
prompt = prompt.format(
fence=self.fence,
lazy_prompt=lazy_prompt,
platform=platform_text,
shell_cmd_prompt=shell_cmd_prompt,
shell_cmd_reminder=shell_cmd_reminder,
language=language,
)
return prompt
@@ -1120,6 +1156,8 @@ class Coder:
retry_delay = 0.125
litellm_ex = LiteLLMExceptions()
self.usage_report = None
exhausted = False
interrupted = False
@@ -1128,24 +1166,37 @@ class Coder:
try:
yield from self.send(messages, functions=self.functions)
break
except retry_exceptions() as err:
self.io.tool_warning(str(err))
retry_delay *= 2
if retry_delay > 60:
except litellm_ex.exceptions_tuple() as err:
ex_info = litellm_ex.get_ex_info(err)
if ex_info.name == "ContextWindowExceededError":
exhausted = True
break
should_retry = ex_info.retry
if should_retry:
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
should_retry = False
if not should_retry:
self.mdstream = None
self.check_and_open_urls(err, ex_info.description)
break
err_msg = str(err)
if ex_info.description:
self.io.tool_warning(err_msg)
self.io.tool_error(ex_info.description)
else:
self.io.tool_error(err_msg)
self.io.tool_output(f"Retrying in {retry_delay:.1f} seconds...")
time.sleep(retry_delay)
continue
except KeyboardInterrupt:
interrupted = True
break
except litellm.ContextWindowExceededError:
# The input is overflowing the context window!
exhausted = True
break
except litellm.exceptions.BadRequestError as br_err:
self.io.tool_error(f"BadRequestError: {br_err}")
return
except FinishReasonLength:
# We hit the output limit!
if not self.main_model.info.get("supports_assistant_prefill"):
@@ -1161,9 +1212,10 @@ class Coder:
dict(role="assistant", content=self.multi_response_content, prefix=True)
)
except Exception as err:
self.io.tool_error(f"Unexpected error: {err}")
self.mdstream = None
lines = traceback.format_exception(type(err), err, err.__traceback__)
self.io.tool_error("".join(lines))
self.io.tool_warning("".join(lines))
self.io.tool_error(str(err))
return
finally:
if self.mdstream:
@@ -1193,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"
@@ -1247,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
@@ -1308,11 +1362,9 @@ class Coder:
res.append("- Use /clear to clear the chat history.")
res.append("- Break your code into smaller source files.")
res.append("")
res.append(f"For more info: {urls.token_limits}")
res = "".join([line + "\n" for line in res])
self.io.tool_error(res)
self.io.offer_url(urls.token_limits)
def lint_edited(self, fnames):
res = ""
@@ -1556,7 +1608,6 @@ class Coder:
completion.usage, "cache_creation_input_tokens"
):
self.message_tokens_sent += prompt_tokens
self.message_tokens_sent += cache_hit_tokens
self.message_tokens_sent += cache_write_tokens
else:
self.message_tokens_sent += prompt_tokens
@@ -1638,11 +1689,27 @@ class Coder:
self.usage_report = tokens_report + sep + cost_report
def show_usage_report(self):
if self.usage_report:
self.io.tool_output(self.usage_report)
self.message_cost = 0.0
self.message_tokens_sent = 0
self.message_tokens_received = 0
if not self.usage_report:
return
self.io.tool_output(self.usage_report)
prompt_tokens = self.message_tokens_sent
completion_tokens = self.message_tokens_received
self.event(
"message_send",
main_model=self.main_model,
edit_format=self.edit_format,
prompt_tokens=prompt_tokens,
completion_tokens=completion_tokens,
total_tokens=prompt_tokens + completion_tokens,
cost=self.message_cost,
total_cost=self.total_cost,
)
self.message_cost = 0.0
self.message_tokens_sent = 0
self.message_tokens_received = 0
def get_multi_response_content(self, final=False):
cur = self.multi_response_content or ""
@@ -1717,6 +1784,10 @@ class Coder:
self.check_for_dirty_commit(path)
return True
if self.repo and self.repo.git_ignored_file(path):
self.io.tool_warning(f"Skipping edits to {path} that matches gitignore spec.")
return
if not Path(full_path).exists():
if not self.io.confirm_ask("Create new file?", subject=path):
self.io.tool_output(f"Skipping edits to {path}")
@@ -1811,8 +1882,10 @@ class Coder:
edited = set()
try:
edits = self.get_edits()
edits = self.apply_edits_dry_run(edits)
edits = self.prepare_to_edit(edits)
edited = set(edit[0] for edit in edits)
self.apply_edits(edits)
except ValueError as err:
self.num_malformed_responses += 1
@@ -1940,6 +2013,9 @@ class Coder:
def apply_edits(self, edits):
return
def apply_edits_dry_run(self, edits):
return edits
def run_shell_commands(self):
if not self.suggest_shell_commands:
return ""
@@ -1985,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

@@ -35,29 +35,47 @@ class EditBlockCoder(Coder):
return edits
def apply_edits(self, edits):
def apply_edits_dry_run(self, edits):
return self.apply_edits(edits, dry_run=True)
def apply_edits(self, edits, dry_run=False):
failed = []
passed = []
updated_edits = []
for edit in edits:
path, original, updated = edit
full_path = self.abs_root_path(path)
content = self.io.read_text(full_path)
new_content = do_replace(full_path, content, original, updated, self.fence)
if not new_content:
new_content = None
if Path(full_path).exists():
content = self.io.read_text(full_path)
new_content = do_replace(full_path, content, original, updated, self.fence)
# If the edit failed, and
# this is not a "create a new file" with an empty original...
# https://github.com/Aider-AI/aider/issues/2258
if not new_content and original.strip():
# try patching any of the other files in the chat
for full_path in self.abs_fnames:
content = self.io.read_text(full_path)
new_content = do_replace(full_path, content, original, updated, self.fence)
if new_content:
path = self.get_rel_fname(full_path)
break
updated_edits.append((path, original, updated))
if new_content:
self.io.write_text(full_path, new_content)
if not dry_run:
self.io.write_text(full_path, new_content)
passed.append(edit)
else:
failed.append(edit)
if dry_run:
return updated_edits
if not failed:
return
@@ -365,9 +383,9 @@ def do_replace(fname, content, before_text, after_text, fence=None):
return new_content
HEAD = r"<{5,9} SEARCH"
DIVIDER = r"={5,9}"
UPDATED = r">{5,9} REPLACE"
HEAD = r"^<{5,9} SEARCH\s*$"
DIVIDER = r"^={5,9}\s*$"
UPDATED = r"^>{5,9} REPLACE\s*$"
HEAD_ERR = "<<<<<<< SEARCH"
DIVIDER_ERR = "======="

View File

@@ -11,7 +11,7 @@ Respect and use existing conventions, libraries, etc that are already present in
Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
Always reply to the user in the same language they are using.
Always reply to the user in {language}.
Once you understand the request you MUST:
@@ -159,8 +159,9 @@ Use the *FULL* file path, as shown to you by the user.
Every *SEARCH* section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, etc.
If the file contains code or other data wrapped/escaped in json/xml/quotes or other containers, you need to propose edits to the literal contents of the file, including the container markup.
*SEARCH/REPLACE* blocks will replace *all* matching occurrences.
Include enough lines to make the SEARCH blocks uniquely match the lines to change.
*SEARCH/REPLACE* blocks will *only* replace the first match occurrence.
Including multiple unique *SEARCH/REPLACE* blocks if needed.
Include enough lines in each SEARCH section to uniquely match each set of lines that need to change.
Keep *SEARCH/REPLACE* blocks concise.
Break large *SEARCH/REPLACE* blocks into a series of smaller blocks that each change a small portion of the file.

View File

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

View File

@@ -8,7 +8,7 @@ class WholeFilePrompts(CoderPrompts):
Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
Always reply to the user in the same language they are using.
Always reply to the user in {language}.
{lazy_prompt}
Once you understand the request you MUST:
@@ -52,7 +52,7 @@ path/to/filename.js
{fence[1]}
Every *file listing* MUST use this format:
- First line: the filename with any originally provided path
- First line: the filename with any originally provided path; no extra markup, punctuation, comments, etc. **JUST** the filename with path.
- Second line: opening {fence[0]}
- ... entire content of the file ...
- Final line: closing {fence[1]}

View File

@@ -14,6 +14,7 @@ from prompt_toolkit.completion import Completion, PathCompleter
from prompt_toolkit.document import Document
from aider import models, prompts, voice
from aider.editor import pipe_editor
from aider.format_settings import format_settings
from aider.help import Help, install_help_extra
from aider.llm import litellm
@@ -45,7 +46,15 @@ class Commands:
)
def __init__(
self, io, coder, voice_language=None, verify_ssl=True, args=None, parser=None, verbose=False
self,
io,
coder,
voice_language=None,
verify_ssl=True,
args=None,
parser=None,
verbose=False,
editor=None,
):
self.io = io
self.coder = coder
@@ -60,6 +69,7 @@ class Commands:
self.voice_language = voice_language
self.help = None
self.editor = editor
def cmd_model(self, args):
"Switch to a new LLM"
@@ -139,7 +149,7 @@ class Commands:
else:
self.io.tool_output("Please provide a partial model name to search for.")
def cmd_web(self, args):
def cmd_web(self, args, return_content=False):
"Scrape a webpage, convert to markdown and send in a message"
url = args.strip()
@@ -158,11 +168,16 @@ class Commands:
)
content = self.scraper.scrape(url) or ""
content = f"{url}:\n\n" + content
content = f"Here is the content of {url}:\n\n" + content
if return_content:
return content
self.io.tool_output("... done.")
self.io.tool_output("... added to chat.")
return content
self.coder.cur_messages += [
dict(role="user", content=content),
dict(role="assistant", content="Ok."),
]
def is_command(self, inp):
return inp[0] in "/!"
@@ -223,6 +238,7 @@ class Commands:
def run(self, inp):
if inp.startswith("!"):
self.coder.event("command_run")
return self.do_run("run", inp[1:])
res = self.matching_commands(inp)
@@ -230,9 +246,13 @@ class Commands:
return
matching_commands, first_word, rest_inp = res
if len(matching_commands) == 1:
return self.do_run(matching_commands[0][1:], rest_inp)
command = matching_commands[0][1:]
self.coder.event(f"command_{command}")
return self.do_run(command, rest_inp)
elif first_word in matching_commands:
return self.do_run(first_word[1:], rest_inp)
command = first_word[1:]
self.coder.event(f"command_{command}")
return self.do_run(command, rest_inp)
elif len(matching_commands) > 1:
self.io.tool_error(f"Ambiguous command: {', '.join(matching_commands)}")
else:
@@ -654,7 +674,7 @@ class Commands:
else:
try:
raw_matched_files = list(Path(self.coder.root).glob(pattern))
except IndexError:
except (IndexError, AttributeError):
raw_matched_files = []
except ValueError as err:
self.io.tool_error(f"Error matching {pattern}: {err}")
@@ -724,7 +744,7 @@ class Commands:
except OSError as e:
self.io.tool_error(f"Error creating file {fname}: {e}")
for matched_file in all_matched_files:
for matched_file in sorted(all_matched_files):
abs_file_path = self.coder.abs_root_path(matched_file)
if not abs_file_path.startswith(self.coder.root) and not is_image_file(matched_file):
@@ -733,6 +753,10 @@ class Commands:
)
continue
if self.coder.repo and self.coder.repo.git_ignored_file(matched_file):
self.io.tool_error(f"Can't add {matched_file} which is in gitignore")
continue
if abs_file_path in self.coder.abs_fnames:
self.io.tool_error(f"{matched_file} is already in the chat as an editable file")
continue
@@ -748,7 +772,9 @@ class Commands:
f"Cannot add {matched_file} as it's not part of the repository"
)
else:
if is_image_file(matched_file) and not self.coder.main_model.accepts_images:
if is_image_file(matched_file) and not self.coder.main_model.info.get(
"supports_vision"
):
self.io.tool_error(
f"Cannot add image file {matched_file} as the"
f" {self.coder.main_model.name} does not support images."
@@ -852,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
@@ -860,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"
@@ -961,6 +972,7 @@ class Commands:
self.basic_help()
return
self.coder.event("interactive help")
from aider.coders import Coder
if not self.help:
@@ -1163,25 +1175,41 @@ class Commands:
return
filenames = parse_quoted_filenames(args)
all_paths = []
# First collect all expanded paths
for pattern in filenames:
# Expand tilde for home directory
expanded_pattern = expanduser(pattern)
if os.path.isabs(expanded_pattern):
# For absolute paths, glob it
matches = list(glob.glob(expanded_pattern))
else:
# For relative paths and globs, use glob from the root directory
matches = list(Path(self.coder.root).glob(expanded_pattern))
expanded_paths = glob.glob(expanded_pattern, recursive=True)
if not expanded_paths:
if not matches:
self.io.tool_error(f"No matches found for: {pattern}")
continue
else:
all_paths.extend(matches)
for path in expanded_paths:
abs_path = self.coder.abs_root_path(path)
if os.path.isfile(abs_path):
self._add_read_only_file(abs_path, path)
elif os.path.isdir(abs_path):
self._add_read_only_directory(abs_path, path)
else:
self.io.tool_error(f"Not a file or directory: {abs_path}")
# Then process them in sorted order
for path in sorted(all_paths):
abs_path = self.coder.abs_root_path(path)
if os.path.isfile(abs_path):
self._add_read_only_file(abs_path, path)
elif os.path.isdir(abs_path):
self._add_read_only_directory(abs_path, path)
else:
self.io.tool_error(f"Not a file or directory: {abs_path}")
def _add_read_only_file(self, abs_path, original_name):
if is_image_file(original_name) and not self.coder.main_model.info.get("supports_vision"):
self.io.tool_error(
f"Cannot add image file {original_name} as the"
f" {self.coder.main_model.name} does not support images."
)
return
if abs_path in self.coder.abs_read_only_fnames:
self.io.tool_error(f"{original_name} is already in the chat as a read-only file")
return
@@ -1235,6 +1263,63 @@ class Commands:
output = f"{announcements}\n{settings}"
self.io.tool_output(output)
def completions_raw_load(self, document, complete_event):
return self.completions_raw_read_only(document, complete_event)
def cmd_load(self, args):
"Load and execute commands from a file"
if not args.strip():
self.io.tool_error("Please provide a filename containing commands to load.")
return
try:
with open(args.strip(), "r", encoding=self.io.encoding, errors="replace") as f:
commands = f.readlines()
except FileNotFoundError:
self.io.tool_error(f"File not found: {args}")
return
except Exception as e:
self.io.tool_error(f"Error reading file: {e}")
return
for cmd in commands:
cmd = cmd.strip()
if not cmd or cmd.startswith("#"):
continue
self.io.tool_output(f"\nExecuting: {cmd}")
self.run(cmd)
def completions_raw_save(self, document, complete_event):
return self.completions_raw_read_only(document, complete_event)
def cmd_save(self, args):
"Save commands to a file that can reconstruct the current chat session's files"
if not args.strip():
self.io.tool_error("Please provide a filename to save the commands to.")
return
try:
with open(args.strip(), "w", encoding=self.io.encoding) as f:
f.write("/drop\n")
# Write commands to add editable files
for fname in sorted(self.coder.abs_fnames):
rel_fname = self.coder.get_rel_fname(fname)
f.write(f"/add {rel_fname}\n")
# Write commands to add read-only files
for fname in sorted(self.coder.abs_read_only_fnames):
# Use absolute path for files outside repo root, relative path for files inside
if Path(fname).is_relative_to(self.coder.root):
rel_fname = self.coder.get_rel_fname(fname)
f.write(f"/read-only {rel_fname}\n")
else:
f.write(f"/read-only {fname}\n")
self.io.tool_output(f"Saved commands to {args.strip()}")
except Exception as e:
self.io.tool_error(f"Error saving commands to file: {e}")
def cmd_copy(self, args):
"Copy the last assistant message to the clipboard"
all_messages = self.coder.done_messages + self.coder.cur_messages
@@ -1276,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

81
aider/exceptions.py Normal file
View File

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

View File

@@ -40,24 +40,45 @@ def get_package_files():
def fname_to_url(filepath):
website = "website/"
index = "/index.md"
website = "website"
index = "index.md"
md = ".md"
docid = ""
if filepath.startswith("website/_includes/"):
pass
elif filepath.startswith(website):
docid = filepath[len(website) :]
# Convert backslashes to forward slashes for consistency
filepath = filepath.replace("\\", "/")
if filepath.endswith(index):
filepath = filepath[: -len(index)] + "/"
elif filepath.endswith(md):
filepath = filepath[: -len(md)] + ".html"
# Convert to Path object for easier manipulation
path = Path(filepath)
docid = "https://aider.chat/" + filepath
# Split the path into parts
parts = path.parts
return docid
# Find the 'website' part in the path
try:
website_index = [p.lower() for p in parts].index(website.lower())
except ValueError:
return "" # 'website' not found in the path
# Extract the part of the path starting from 'website'
relevant_parts = parts[website_index + 1 :]
# Handle _includes directory
if relevant_parts and relevant_parts[0].lower() == "_includes":
return ""
# Join the remaining parts
url_path = "/".join(relevant_parts)
# Handle index.md and other .md files
if url_path.lower().endswith(index.lower()):
url_path = url_path[: -len(index)]
elif url_path.lower().endswith(md.lower()):
url_path = url_path[: -len(md)] + ".html"
# Ensure the URL starts and ends with '/'
url_path = url_path.strip("/")
return f"https://aider.chat/{url_path}"
def get_index():

View File

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

View File

@@ -1,8 +1,11 @@
import base64
import os
import time
import webbrowser
from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime
from io import StringIO
from pathlib import Path
from prompt_toolkit.completion import Completer, Completion, ThreadedCompleter
@@ -15,6 +18,7 @@ from prompt_toolkit.shortcuts import CompleteStyle, PromptSession
from prompt_toolkit.styles import Style
from pygments.lexers import MarkdownLexer, guess_lexer_for_filename
from pygments.token import Token
from rich.columns import Columns
from rich.console import Console
from rich.markdown import Markdown
from rich.style import Style as RichStyle
@@ -192,6 +196,7 @@ class InputOutput:
dry_run=False,
llm_history_file=None,
editingmode=EditingMode.EMACS,
fancy_input=True,
):
self.never_prompts = set()
self.editingmode = editingmode
@@ -234,15 +239,16 @@ class InputOutput:
self.append_chat_history(f"\n# aider chat started at {current_time}\n\n")
self.prompt_session = None
if self.pretty:
if fancy_input:
# Initialize PromptSession
session_kwargs = {
"input": self.input,
"output": self.output,
"lexer": PygmentsLexer(MarkdownLexer),
"editing_mode": self.editingmode,
"cursor": ModalCursorShapeConfig(),
}
if self.editingmode == EditingMode.VI:
session_kwargs["cursor"] = ModalCursorShapeConfig()
if self.input_history_file is not None:
session_kwargs["history"] = FileHistory(self.input_history_file)
try:
@@ -328,14 +334,36 @@ class InputOutput:
self.tool_error("Use --encoding to set the unicode encoding.")
return
def write_text(self, filename, content):
def write_text(self, filename, content, max_retries=5, initial_delay=0.1):
"""
Writes content to a file, retrying with progressive backoff if the file is locked.
:param filename: Path to the file to write.
:param content: Content to write to the file.
:param max_retries: Maximum number of retries if a file lock is encountered.
:param initial_delay: Initial delay (in seconds) before the first retry.
"""
if self.dry_run:
return
try:
with open(str(filename), "w", encoding=self.encoding) as f:
f.write(content)
except OSError as err:
self.tool_error(f"Unable to write file {filename}: {err}")
delay = initial_delay
for attempt in range(max_retries):
try:
with open(str(filename), "w", encoding=self.encoding) as f:
f.write(content)
return # Successfully wrote the file
except PermissionError as err:
if attempt < max_retries - 1:
time.sleep(delay)
delay *= 2 # Exponential backoff
else:
self.tool_error(
f"Unable to write file {filename} after {max_retries} attempts: {err}"
)
raise
except OSError as err:
self.tool_error(f"Unable to write file {filename}: {err}")
raise
def rule(self):
if self.pretty:
@@ -358,7 +386,10 @@ class InputOutput:
rel_fnames = list(rel_fnames)
show = ""
if rel_fnames:
show = " ".join(rel_fnames) + "\n"
rel_read_only_fnames = [
get_rel_fname(fname, root) for fname in (abs_read_only_fnames or [])
]
show = self.format_files_for_input(rel_fnames, rel_read_only_fnames)
if edit_format:
show += edit_format
show += "> "
@@ -410,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:
@@ -432,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:
@@ -450,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:
@@ -477,6 +536,15 @@ class InputOutput:
hist = "\n" + content.strip() + "\n\n"
self.append_chat_history(hist)
def offer_url(self, url, prompt="Open URL for more info?"):
"""Offer to open a URL in the browser, returns True if opened."""
if url in self.never_prompts:
return False
if self.confirm_ask(prompt, subject=url, allow_never=True):
webbrowser.open(url)
return True
return False
def confirm_ask(
self,
question,
@@ -689,9 +757,55 @@ class InputOutput:
try:
with self.chat_history_file.open("a", encoding=self.encoding, errors="ignore") as f:
f.write(text)
except (PermissionError, OSError):
self.tool_error(
f"Warning: Unable to write to chat history file {self.chat_history_file}."
" Permission denied."
)
except (PermissionError, OSError) as err:
print(f"Warning: Unable to write to chat history file {self.chat_history_file}.")
print(err)
self.chat_history_file = None # Disable further attempts to write
def format_files_for_input(self, rel_fnames, rel_read_only_fnames):
if not self.pretty:
read_only_files = []
for full_path in sorted(rel_read_only_fnames or []):
read_only_files.append(f"{full_path} (read only)")
editable_files = []
for full_path in sorted(rel_fnames):
if full_path in rel_read_only_fnames:
continue
editable_files.append(f"{full_path}")
return "\n".join(read_only_files + editable_files) + "\n"
output = StringIO()
console = Console(file=output, force_terminal=False)
read_only_files = sorted(rel_read_only_fnames or [])
editable_files = [f for f in sorted(rel_fnames) if f not in rel_read_only_fnames]
if read_only_files:
files_with_label = ["Readonly:"] + read_only_files
read_only_output = StringIO()
Console(file=read_only_output, force_terminal=False).print(Columns(files_with_label))
read_only_lines = read_only_output.getvalue().splitlines()
console.print(Columns(files_with_label))
if editable_files:
files_with_label = editable_files
if read_only_files:
files_with_label = ["Editable:"] + editable_files
editable_output = StringIO()
Console(file=editable_output, force_terminal=False).print(Columns(files_with_label))
editable_lines = editable_output.getvalue().splitlines()
if len(read_only_lines) > 1 or len(editable_lines) > 1:
console.print()
console.print(Columns(files_with_label))
return output.getvalue()
def get_rel_fname(fname, root):
try:
return os.path.relpath(fname, root)
except ValueError:
return fname

View File

@@ -221,7 +221,12 @@ def basic_lint(fname, code):
tree = parser.parse(bytes(code, "utf-8"))
errors = traverse_tree(tree.root_node)
try:
errors = traverse_tree(tree.root_node)
except RecursionError:
print(f"Unable to lint {fname} due to RecursionError")
return
if not errors:
return

View File

@@ -5,13 +5,16 @@ import re
import sys
import threading
import traceback
import webbrowser
from pathlib import Path
import git
import importlib_resources
from dotenv import load_dotenv
from prompt_toolkit.enums import EditingMode
from aider import __version__, models, urls, utils
from aider.analytics import Analytics
from aider.args import get_parser
from aider.coders import Coder
from aider.commands import Commands, SwitchCoder
@@ -57,7 +60,7 @@ def guessed_wrong_repo(io, git_root, fnames, git_dname):
try:
check_repo = Path(GitRepo(io, fnames, git_dname).root).resolve()
except FileNotFoundError:
except (OSError,) + ANY_GIT_ERROR:
return
# we had no guess, rely on the "true" repo result
@@ -85,15 +88,25 @@ def make_new_repo(git_root, io):
def setup_git(git_root, io):
try:
cwd = Path.cwd()
except OSError:
cwd = None
repo = None
if git_root:
repo = git.Repo(git_root)
elif Path.cwd() == Path.home():
try:
repo = git.Repo(git_root)
except ANY_GIT_ERROR:
pass
elif cwd == Path.home():
io.tool_warning("You should probably run aider in a directory, not your home dir.")
return
elif io.confirm_ask("No git repo found, create one to track aider's changes (recommended)?"):
git_root = str(Path.cwd().resolve())
elif cwd and io.confirm_ask(
"No git repo found, create one to track aider's changes (recommended)?"
):
git_root = str(cwd.resolve())
repo = make_new_repo(git_root, io)
if not repo:
@@ -131,32 +144,39 @@ def check_gitignore(git_root, io, ask=True):
try:
repo = git.Repo(git_root)
if repo.ignored(".aider"):
if repo.ignored(".aider") and repo.ignored(".env"):
return
except ANY_GIT_ERROR:
pass
pat = ".aider*"
patterns = [".aider*", ".env"]
patterns_to_add = []
gitignore_file = Path(git_root) / ".gitignore"
if gitignore_file.exists():
content = io.read_text(gitignore_file)
if content is None:
return
if pat in content.splitlines():
return
existing_lines = content.splitlines()
for pat in patterns:
if pat not in existing_lines:
patterns_to_add.append(pat)
else:
content = ""
patterns_to_add = patterns
if ask and not io.confirm_ask(f"Add {pat} to .gitignore (recommended)?"):
if not patterns_to_add:
return
if ask and not io.confirm_ask(f"Add {', '.join(patterns_to_add)} to .gitignore (recommended)?"):
return
if content and not content.endswith("\n"):
content += "\n"
content += pat + "\n"
content += "\n".join(patterns_to_add) + "\n"
io.write_text(gitignore_file, content)
io.tool_output(f"Added {pat} to .gitignore")
io.tool_output(f"Added {', '.join(patterns_to_add)} to .gitignore")
def check_streamlit_install(io):
@@ -186,7 +206,10 @@ def launch_gui(args):
"--server.runOnSave=false",
]
if "-dev" in __version__:
# https://github.com/Aider-AI/aider/issues/2193
is_dev = "-dev" in str(__version__)
if is_dev:
print("Watching for file changes.")
else:
st_args += [
@@ -234,16 +257,23 @@ def parse_lint_cmds(lint_cmds, io):
return res
def generate_search_path_list(default_fname, git_root, command_line_file):
def generate_search_path_list(default_file, git_root, command_line_file):
files = []
default_file = Path(default_fname)
files.append(Path.home() / default_file) # homedir
if git_root:
files.append(Path(git_root) / default_file) # git root
files.append(default_file.resolve())
files.append(default_file)
if command_line_file:
files.append(command_line_file)
files = [Path(fn).resolve() for fn in files]
resolved_files = []
for fn in files:
try:
resolved_files.append(Path(fn).resolve())
except OSError:
pass
files = resolved_files
files.reverse()
uniq = []
for fn in files:
@@ -303,7 +333,13 @@ def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"):
def register_litellm_models(git_root, model_metadata_fname, io, verbose=False):
model_metatdata_files = generate_search_path_list(
model_metatdata_files = []
# Add the resource file path
resource_metadata = importlib_resources.files("aider.resources").joinpath("model-metadata.json")
model_metatdata_files.append(str(resource_metadata))
model_metatdata_files += generate_search_path_list(
".aider.model.metadata.json", git_root, model_metadata_fname
)
@@ -343,7 +379,7 @@ def sanity_check_repo(repo, io):
io.tool_error("Aider only works with git repos with version number 1 or 2.")
io.tool_output("You may be able to convert your repo: git update-index --index-version=2")
io.tool_output("Or run aider --no-git to proceed without using git.")
io.tool_output(urls.git_index_version)
io.offer_url(urls.git_index_version, "Open documentation url for more info?")
return False
io.tool_error("Unable to read git repository, it may be corrupt?")
@@ -404,6 +440,10 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
# Parse again to include any arguments that might have been defined in .env
args = parser.parse_args(argv)
if args.analytics_disable:
analytics = Analytics(permanently_disable=True)
print("Analytics have been permanently disabled.")
if not args.verify_ssl:
import httpx
@@ -453,6 +493,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
encoding=args.encoding,
llm_history_file=args.llm_history_file,
editingmode=editing_mode,
fancy_input=args.fancy_input,
)
io = get_io(args.pretty)
@@ -464,9 +505,35 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io = get_io(False)
io.tool_warning("Terminal does not support pretty output (UnicodeDecodeError)")
analytics = Analytics(logfile=args.analytics_log, permanently_disable=args.analytics_disable)
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."
)
io.tool_output(f"For more info: {urls.analytics}")
disable = not io.confirm_ask(
"Allow collection of anonymous analytics to help improve aider?"
)
analytics.asked_opt_in = True
if disable:
analytics.disable(permanently=True)
io.tool_output("Analytics have been permanently disabled.")
analytics.save_data()
io.tool_output()
# This is a no-op if the user has opted out
analytics.enable()
analytics.event("launched")
if args.gui and not return_coder:
if not check_streamlit_install(io):
return
analytics.event("gui session")
launch_gui(argv)
return
@@ -476,7 +543,14 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
all_files = args.files + (args.file or [])
fnames = [str(Path(fn).resolve()) for fn in all_files]
read_only_fnames = [str(Path(fn).resolve()) for fn in (args.read or [])]
read_only_fnames = []
for fn in args.read or []:
path = Path(fn).resolve()
if path.is_dir():
read_only_fnames.extend(str(f) for f in path.rglob("*") if f.is_file())
else:
read_only_fnames.append(str(path))
if len(all_files) > 1:
good = True
for fname in all_files:
@@ -539,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
@@ -561,7 +636,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if not args.model:
args.model = "gpt-4o-2024-08-06"
if os.environ.get("ANTHROPIC_API_KEY"):
args.model = "claude-3-5-sonnet-20240620"
args.model = "claude-3-5-sonnet-20241022"
main_model = models.Model(
args.model,
@@ -581,11 +656,12 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.show_model_warnings:
problem = models.sanity_check_models(io, main_model)
if problem:
analytics.event("model warning", main_model=main_model)
io.tool_output("You can skip this check with --no-show-model-warnings")
io.tool_output()
try:
if not io.confirm_ask("Proceed anyway?"):
return 1
io.offer_url(urls.model_warnings, "Open documentation url for more info?")
io.tool_output()
except KeyboardInterrupt:
return 1
@@ -613,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(
@@ -654,6 +736,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
test_cmd=args.test_cmd,
commands=commands,
summarizer=summarizer,
analytics=analytics,
map_refresh=args.map_refresh,
cache_prompts=args.cache_prompts,
map_mul_no_files=args.map_multiplier_no_files,
@@ -712,12 +795,28 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
coder.apply_updates()
return
if args.apply_clipboard_edits:
args.edit_format = main_model.editor_edit_format
args.message = "/paste"
if "VSCODE_GIT_IPC_HANDLE" in os.environ:
args.pretty = False
io.tool_output("VSCode terminal detected, pretty output has been disabled.")
io.tool_output('Use /help <question> for help, run "aider --help" to see cmd line args')
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"
@@ -727,6 +826,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io.tool_output(f"Cur working dir: {Path.cwd()}")
io.tool_output(f"Git working dir: {git_root}")
if args.load:
commands.cmd_load(args.load)
if args.message:
io.add_to_input_history(args.message)
io.tool_output()
@@ -752,6 +854,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.exit:
return
analytics.event("cli session", main_model=main_model, edit_format=main_model.edit_format)
while True:
try:
coder.run()
@@ -768,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)
@@ -789,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"
@@ -799,13 +923,9 @@ def check_and_load_imports(io, verbose=False):
except Exception as err:
io.tool_error(str(err))
io.tool_output("Error loading required imports. Did you install aider properly?")
io.tool_output("https://aider.chat/docs/install/install.html")
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:
@@ -814,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

@@ -13,7 +13,6 @@ import json5
import yaml
from PIL import Image
from aider import urls
from aider.dump import dump # noqa: F401
from aider.llm import litellm
@@ -53,9 +52,11 @@ ANTHROPIC_MODELS = """
claude-2
claude-2.1
claude-3-haiku-20240307
claude-3-5-haiku-20241022
claude-3-opus-20240229
claude-3-sonnet-20240229
claude-3-5-sonnet-20240620
claude-3-5-sonnet-20241022
"""
ANTHROPIC_MODELS = [ln.strip() for ln in ANTHROPIC_MODELS.splitlines() if ln.strip()]
@@ -69,7 +70,6 @@ class ModelSettings:
weak_model_name: Optional[str] = None
use_repo_map: bool = False
send_undo_reply: bool = False
accepts_images: bool = False
lazy: bool = False
reminder: str = "user"
examples_as_sys_msg: bool = False
@@ -125,7 +125,6 @@ MODEL_SETTINGS = [
"udiff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -134,7 +133,6 @@ MODEL_SETTINGS = [
"udiff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -143,7 +141,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
@@ -153,7 +150,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -162,7 +158,22 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
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",
),
@@ -171,7 +182,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
@@ -180,7 +190,6 @@ MODEL_SETTINGS = [
"gpt-4o-mini",
"whole",
weak_model_name="gpt-4o-mini",
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -188,7 +197,6 @@ MODEL_SETTINGS = [
"openai/gpt-4o-mini",
"whole",
weak_model_name="openai/gpt-4o-mini",
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -214,7 +222,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
reminder="sys",
),
ModelSettings(
@@ -243,29 +250,28 @@ MODEL_SETTINGS = [
ModelSettings(
"claude-3-opus-20240229",
"diff",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="claude-3-5-haiku-20241022",
use_repo_map=True,
),
ModelSettings(
"openrouter/anthropic/claude-3-opus",
"diff",
weak_model_name="openrouter/anthropic/claude-3-haiku",
weak_model_name="openrouter/anthropic/claude-3-5-haiku",
use_repo_map=True,
),
ModelSettings(
"claude-3-sonnet-20240229",
"whole",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="claude-3-5-haiku-20241022",
),
ModelSettings(
"claude-3-5-sonnet-20240620",
"diff",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="claude-3-5-haiku-20241022",
editor_model_name="claude-3-5-sonnet-20240620",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
@@ -278,7 +284,7 @@ MODEL_SETTINGS = [
ModelSettings(
"anthropic/claude-3-5-sonnet-20240620",
"diff",
weak_model_name="claude-3-haiku-20240307",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
editor_model_name="anthropic/claude-3-5-sonnet-20240620",
editor_edit_format="editor-diff",
use_repo_map=True,
@@ -292,6 +298,74 @@ MODEL_SETTINGS = [
cache_control=True,
reminder="user",
),
ModelSettings(
"anthropic/claude-3-5-sonnet-20241022",
"diff",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
editor_model_name="anthropic/claude-3-5-sonnet-20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
"max_tokens": 8192,
},
cache_control=True,
reminder="user",
),
ModelSettings(
"bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
"diff",
weak_model_name="bedrock/anthropic.claude-3-5-haiku-20241022-v1:0",
editor_model_name="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
"max_tokens": 8192,
},
cache_control=True,
reminder="user",
),
ModelSettings(
"anthropic/claude-3-5-sonnet-latest",
"diff",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
editor_model_name="anthropic/claude-3-5-sonnet-20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
"max_tokens": 8192,
},
cache_control=True,
reminder="user",
),
ModelSettings(
"claude-3-5-sonnet-20241022",
"diff",
weak_model_name="claude-3-5-haiku-20241022",
editor_model_name="claude-3-5-sonnet-20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
"max_tokens": 8192,
},
cache_control=True,
reminder="user",
),
ModelSettings(
"anthropic/claude-3-haiku-20240307",
"whole",
@@ -304,6 +378,52 @@ MODEL_SETTINGS = [
},
cache_control=True,
),
ModelSettings(
"anthropic/claude-3-5-haiku-20241022",
"diff",
weak_model_name="anthropic/claude-3-5-haiku-20241022",
use_repo_map=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
},
cache_control=True,
),
ModelSettings(
"bedrock/anthropic.claude-3-5-haiku-20241022-v1:0",
"diff",
weak_model_name="bedrock/anthropic.claude-3-5-haiku-20241022-v1:0",
use_repo_map=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
},
cache_control=True,
),
ModelSettings(
"claude-3-5-haiku-20241022",
"diff",
weak_model_name="claude-3-5-haiku-20241022",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
},
cache_control=True,
),
ModelSettings(
"vertex_ai/claude-3-5-haiku@20241022",
"diff",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
use_repo_map=True,
extra_params={
"max_tokens": 4096,
},
),
ModelSettings(
"claude-3-haiku-20240307",
"whole",
@@ -319,12 +439,11 @@ MODEL_SETTINGS = [
ModelSettings(
"openrouter/anthropic/claude-3.5-sonnet",
"diff",
weak_model_name="openrouter/anthropic/claude-3-haiku-20240307",
weak_model_name="openrouter/anthropic/claude-3-5-haiku",
editor_model_name="openrouter/anthropic/claude-3.5-sonnet",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"max_tokens": 8192,
},
@@ -334,12 +453,11 @@ MODEL_SETTINGS = [
ModelSettings(
"openrouter/anthropic/claude-3.5-sonnet:beta",
"diff",
weak_model_name="openrouter/anthropic/claude-3-haiku-20240307",
weak_model_name="openrouter/anthropic/claude-3-5-haiku:beta",
editor_model_name="openrouter/anthropic/claude-3.5-sonnet:beta",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"max_tokens": 8192,
},
@@ -351,12 +469,24 @@ MODEL_SETTINGS = [
ModelSettings(
"vertex_ai/claude-3-5-sonnet@20240620",
"diff",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
editor_model_name="vertex_ai/claude-3-5-sonnet@20240620",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"max_tokens": 8192,
},
reminder="user",
),
ModelSettings(
"vertex_ai/claude-3-5-sonnet-v2@20241022",
"diff",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
editor_model_name="vertex_ai/claude-3-5-sonnet-v2@20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"max_tokens": 8192,
},
@@ -365,13 +495,13 @@ MODEL_SETTINGS = [
ModelSettings(
"vertex_ai/claude-3-opus@20240229",
"diff",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
use_repo_map=True,
),
ModelSettings(
"vertex_ai/claude-3-sonnet@20240229",
"whole",
weak_model_name="vertex_ai/claude-3-haiku@20240307",
weak_model_name="vertex_ai/claude-3-5-haiku@20241022",
),
# Cohere
ModelSettings(
@@ -436,6 +566,11 @@ MODEL_SETTINGS = [
"diff-fenced",
use_repo_map=True,
),
ModelSettings(
"vertex_ai/gemini-pro-experimental",
"diff-fenced",
use_repo_map=True,
),
ModelSettings(
"gemini/gemini-1.5-flash-exp-0827",
"whole",
@@ -496,7 +631,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="openrouter/openai/gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
@@ -511,7 +645,17 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"azure/o1-mini",
"whole",
weak_model_name="azure/gpt-4o-mini",
editor_model_name="azure/gpt-4o",
editor_edit_format="editor-diff",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
),
ModelSettings(
"o1-mini",
@@ -523,7 +667,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openai/o1-preview",
@@ -535,7 +678,17 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"azure/o1-preview",
"diff",
weak_model_name="azure/gpt-4o-mini",
editor_model_name="azure/gpt-4o",
editor_edit_format="editor-diff",
use_repo_map=True,
reminder="user",
use_system_prompt=False,
use_temperature=False,
),
ModelSettings(
"o1-preview",
@@ -547,7 +700,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/openai/o1-mini",
@@ -559,7 +711,6 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/openai/o1-preview",
@@ -571,82 +722,98 @@ MODEL_SETTINGS = [
reminder="user",
use_system_prompt=False,
use_temperature=False,
streaming=False,
),
ModelSettings(
"openrouter/qwen/qwen-2.5-coder-32b-instruct",
"diff",
weak_model_name="openrouter/qwen/qwen-2.5-coder-32b-instruct",
editor_model_name="openrouter/qwen/qwen-2.5-coder-32b-instruct",
editor_edit_format="editor-diff",
use_repo_map=True,
),
]
model_info_url = (
"https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"
)
class ModelInfoManager:
MODEL_INFO_URL = (
"https://raw.githubusercontent.com/BerriAI/litellm/main/"
"model_prices_and_context_window.json"
)
CACHE_TTL = 60 * 60 * 24 # 24 hours
def __init__(self):
self.cache_dir = Path.home() / ".aider" / "caches"
self.cache_file = self.cache_dir / "model_prices_and_context_window.json"
self.content = None
self._load_cache()
def get_model_flexible(model, content):
info = content.get(model, dict())
if info:
return info
pieces = model.split("/")
if len(pieces) == 2:
info = content.get(pieces[1])
if info and info.get("litellm_provider") == pieces[0]:
return info
return dict()
def get_model_info(model):
if not litellm._lazy_module:
cache_dir = Path.home() / ".aider" / "caches"
cache_file = cache_dir / "model_prices_and_context_window.json"
def _load_cache(self):
try:
cache_dir.mkdir(parents=True, exist_ok=True)
use_cache = True
self.cache_dir.mkdir(parents=True, exist_ok=True)
if self.cache_file.exists():
cache_age = time.time() - self.cache_file.stat().st_mtime
if cache_age < self.CACHE_TTL:
self.content = json.loads(self.cache_file.read_text())
except OSError:
# If we can't create the cache directory, we'll skip using the cache
use_cache = False
if use_cache:
current_time = time.time()
cache_age = (
current_time - cache_file.stat().st_mtime if cache_file.exists() else float("inf")
)
if cache_age < 60 * 60 * 24:
try:
content = json.loads(cache_file.read_text())
res = get_model_flexible(model, content)
if res:
return res
except Exception as ex:
print(str(ex))
import requests
pass
def _update_cache(self):
try:
response = requests.get(model_info_url, timeout=5)
import requests
response = requests.get(self.MODEL_INFO_URL, timeout=5)
if response.status_code == 200:
content = response.json()
if use_cache:
try:
cache_file.write_text(json.dumps(content, indent=4))
except OSError:
# If we can't write to the cache file, we'll just skip caching
pass
res = get_model_flexible(model, content)
if res:
return res
self.content = response.json()
try:
self.cache_file.write_text(json.dumps(self.content, indent=4))
except OSError:
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:
self._update_cache()
if not self.content:
return dict()
info = self.content.get(model, dict())
if info:
return info
pieces = model.split("/")
if len(pieces) == 2:
info = self.content.get(pieces[1])
if info and info.get("litellm_provider") == pieces[0]:
return info
# If all else fails, do it the slow way...
try:
info = litellm.get_model_info(model)
return info
except Exception:
return dict()
def get_model_info(self, model):
cached_info = self.get_model_from_cached_json_db(model)
litellm_info = None
if litellm._lazy_module or not cached_info:
try:
litellm_info = litellm.get_model_info(model)
except Exception as ex:
if "model_prices_and_context_window.json" not in str(ex):
print(str(ex))
if litellm_info:
return litellm_info
return cached_info
model_info_manager = ModelInfoManager()
class Model(ModelSettings):
def __init__(self, model, weak_model=None, editor_model=None, editor_edit_format=None):
@@ -655,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?
@@ -680,19 +852,46 @@ class Model(ModelSettings):
self.get_editor_model(editor_model, editor_edit_format)
def get_model_info(self, model):
return get_model_info(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
@@ -714,16 +913,36 @@ 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 = None
self.reminder = "user"
return # <--
if model.startswith("o1-") or "/o1-" in model:
self.use_system_prompt = False
self.use_temperature = False
return # <--
if (
"qwen" in model
and "coder" in model
and ("2.5" in model or "2-5" in model)
and "32b" in model
):
"openrouter/qwen/qwen-2.5-coder-32b-instruct",
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
@@ -907,8 +1126,14 @@ def register_litellm_models(model_fnames):
continue
try:
with open(model_fname, "r") as model_def_file:
model_def = json5.load(model_def_file)
data = Path(model_fname).read_text()
if not data.strip():
continue
model_def = json5.loads(data)
if not model_def:
continue
# only load litellm if we have actual data
litellm._load_litellm()
litellm.register_model(model_def)
except Exception as e:
@@ -980,9 +1205,6 @@ def sanity_check_model(io, model):
for match in possible_matches:
io.tool_output(f"- {match}")
if show:
io.tool_output(f"For more info, see: {urls.model_warnings}")
return show
@@ -994,7 +1216,10 @@ def fuzzy_match_models(name):
model = model.lower()
if attrs.get("mode") != "chat":
continue
provider = (attrs["litellm_provider"] + "/").lower()
provider = attrs.get("litellm_provider", "").lower()
if not provider:
continue
provider += "/"
if model.startswith(provider):
fq_model = model

View File

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

View File

@@ -2,6 +2,7 @@ import colorsys
import math
import os
import random
import shutil
import sqlite3
import sys
import time
@@ -27,7 +28,7 @@ from tree_sitter_languages import get_language, get_parser # noqa: E402
Tag = namedtuple("Tag", "rel_fname fname line name kind".split())
SQLITE_ERRORS = (sqlite3.OperationalError, sqlite3.DatabaseError)
SQLITE_ERRORS = (sqlite3.OperationalError, sqlite3.DatabaseError, OSError)
class RepoMap:
@@ -166,13 +167,52 @@ class RepoMap:
# Just return the full fname.
return fname
def tags_cache_error(self, original_error=None):
"""Handle SQLite errors by trying to recreate cache, falling back to dict if needed"""
if self.verbose and original_error:
self.io.tool_warning(f"Tags cache error: {str(original_error)}")
if isinstance(getattr(self, "TAGS_CACHE", None), dict):
return
path = Path(self.root) / self.TAGS_CACHE_DIR
# Try to recreate the cache
try:
# Delete existing cache dir
if path.exists():
shutil.rmtree(path)
# Try to create new cache
new_cache = Cache(path)
# Test that it works
test_key = "test"
new_cache[test_key] = "test"
_ = new_cache[test_key]
del new_cache[test_key]
# If we got here, the new cache works
self.TAGS_CACHE = new_cache
return
except SQLITE_ERRORS as e:
# If anything goes wrong, warn and fall back to dict
self.io.tool_warning(
f"Unable to use tags cache at {path}, falling back to memory cache"
)
if self.verbose:
self.io.tool_warning(f"Cache recreation error: {str(e)}")
self.TAGS_CACHE = dict()
def load_tags_cache(self):
path = Path(self.root) / self.TAGS_CACHE_DIR
try:
self.TAGS_CACHE = Cache(path)
except SQLITE_ERRORS:
self.io.tool_warning(f"Unable to use tags cache, delete {path} to resolve.")
self.TAGS_CACHE = dict()
except SQLITE_ERRORS as e:
self.tags_cache_error(e)
def save_tags_cache(self):
pass
@@ -190,9 +230,18 @@ class RepoMap:
return []
cache_key = fname
val = self.TAGS_CACHE.get(cache_key) # Issue #1308
try:
val = self.TAGS_CACHE.get(cache_key) # Issue #1308
except SQLITE_ERRORS as e:
self.tags_cache_error(e)
val = self.TAGS_CACHE.get(cache_key)
if val is not None and val.get("mtime") == file_mtime:
return self.TAGS_CACHE[cache_key]["data"]
try:
return self.TAGS_CACHE[cache_key]["data"]
except SQLITE_ERRORS as e:
self.tags_cache_error(e)
return self.TAGS_CACHE[cache_key]["data"]
# miss!
data = list(self.get_tags_raw(fname, rel_fname))
@@ -201,8 +250,9 @@ class RepoMap:
try:
self.TAGS_CACHE[cache_key] = {"mtime": file_mtime, "data": data}
self.save_tags_cache()
except SQLITE_ERRORS:
pass
except SQLITE_ERRORS as e:
self.tags_cache_error(e)
self.TAGS_CACHE[cache_key] = {"mtime": file_mtime, "data": data}
return data
@@ -302,7 +352,13 @@ class RepoMap:
# https://networkx.org/documentation/stable/_modules/networkx/algorithms/link_analysis/pagerank_alg.html#pagerank
personalize = 100 / len(fnames)
if len(fnames) - len(self.TAGS_CACHE) > 100:
try:
cache_size = len(self.TAGS_CACHE)
except SQLITE_ERRORS as e:
self.tags_cache_error(e)
cache_size = len(self.TAGS_CACHE)
if len(fnames) - cache_size > 100:
self.io.tool_output(
"Initial repo scan can be slow in larger repos, but only happens once."
)
@@ -312,6 +368,8 @@ class RepoMap:
showing_bar = False
for fname in fnames:
if self.verbose:
self.io.tool_output(f"Processing {fname}")
if progress and not showing_bar:
progress()

View File

@@ -0,0 +1,3 @@
# This ensures that importlib_resources.files("aider.resources")
# doesn't raise ImportError, even if there are no other files in this
# dir.

View File

View File

@@ -1,9 +1,9 @@
import hashlib
import json
import backoff
import time
from aider.dump import dump # noqa: F401
from aider.exceptions import LiteLLMExceptions
from aider.llm import litellm
# from diskcache import Cache
@@ -13,37 +13,7 @@ CACHE_PATH = "~/.aider.send.cache.v1"
CACHE = None
# CACHE = Cache(CACHE_PATH)
def retry_exceptions():
import httpx
return (
httpx.ConnectError,
httpx.RemoteProtocolError,
httpx.ReadTimeout,
litellm.exceptions.APIConnectionError,
litellm.exceptions.APIError,
litellm.exceptions.RateLimitError,
litellm.exceptions.ServiceUnavailableError,
litellm.exceptions.Timeout,
litellm.exceptions.InternalServerError,
litellm.llms.anthropic.chat.AnthropicError,
)
def lazy_litellm_retry_decorator(func):
def wrapper(*args, **kwargs):
decorated_func = backoff.on_exception(
backoff.expo,
retry_exceptions(),
max_time=60,
on_backoff=lambda details: print(
f"{details.get('exception', 'Exception')}\nRetry in {details['wait']:.1f} seconds."
),
)(func)
return decorated_func(*args, **kwargs)
return wrapper
RETRY_TIMEOUT = 60
def send_completion(
@@ -54,8 +24,6 @@ def send_completion(
temperature=0,
extra_params=None,
):
from aider.llm import litellm
kwargs = dict(
model=model_name,
messages=messages,
@@ -88,18 +56,42 @@ def send_completion(
return hash_object, res
@lazy_litellm_retry_decorator
def simple_send_with_retries(model_name, messages, extra_params=None):
try:
kwargs = {
"model_name": model_name,
"messages": messages,
"functions": None,
"stream": False,
"extra_params": extra_params,
}
litellm_ex = LiteLLMExceptions()
_hash, response = send_completion(**kwargs)
return response.choices[0].message.content
except (AttributeError, litellm.exceptions.BadRequestError):
return
retry_delay = 0.125
while True:
try:
kwargs = {
"model_name": model_name,
"messages": messages,
"functions": None,
"stream": False,
"extra_params": extra_params,
}
_hash, response = send_completion(**kwargs)
if not response or not hasattr(response, "choices") or not response.choices:
return None
return response.choices[0].message.content
except litellm_ex.exceptions_tuple() as err:
ex_info = litellm_ex.get_ex_info(err)
print(str(err))
if ex_info.description:
print(ex_info.description)
should_retry = ex_info.retry
if should_retry:
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
should_retry = False
if not should_retry:
return None
print(f"Retrying in {retry_delay:.1f} seconds...")
time.sleep(retry_delay)
continue
except AttributeError:
return None

View File

@@ -10,3 +10,6 @@ llms = "https://aider.chat/docs/llms.html"
large_repos = "https://aider.chat/docs/faq.html#can-i-use-aider-in-a-large-mono-repo"
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

@@ -275,8 +275,12 @@ class Spinner:
self.start_time = time.time()
self.last_update = 0
self.visible = False
self.is_tty = sys.stdout.isatty()
def step(self):
if not self.is_tty:
return
current_time = time.time()
if not self.visible and current_time - self.start_time >= 0.5:
self.visible = True
@@ -292,7 +296,7 @@ class Spinner:
print(f"\r{self.text} {next(self.spinner_chars)}\r{self.text} ", end="", flush=True)
def end(self):
if self.visible:
if self.visible and self.is_tty:
print("\r" + " " * (len(self.text) + 3))

View File

@@ -1,7 +1,7 @@
---
title: Release history
parent: More info
nav_order: 999
nav_order: 900
highlight_image: /assets/blame.jpg
description: Release notes and stats on aider writing its own code.
---
@@ -10,6 +10,12 @@ description: Release notes and stats on aider writing its own code.
{% include blame.md %}
The above
[stats are based on the git commit history](/docs/faq.html#how-are-the-aider-wrote-xx-of-code-stats-computed)
of the aider repo.
## Release notes
<!--[[[cog
# This page is a copy of HISTORY.md, adding the front matter above.
text = open("HISTORY.md").read()
@@ -19,7 +25,108 @@ cog.out(text)
### v0.59.0
### 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`.
- Updated dependency versions to pick up litellm fix for ollama models.
- Added exponential backoff retry when writing files to handle editor file locks.
- Updated Qwen 2.5 Coder 32B model configuration.
### Aider v0.63.1
- Fixed bug in git ignored file handling.
- Improved error handling for git operations.
### Aider v0.63.0
- Support for Qwen 2.5 Coder 32B.
- `/web` command just adds the page to the chat, without triggering an LLM response.
- Improved prompting for the user's preferred chat language.
- Improved handling of LiteLLM exceptions.
- Bugfix for double-counting tokens when reporting cache stats.
- Bugfix for the LLM creating new files.
- Other small bug fixes.
- Aider wrote 55% of the code in this release.
### Aider v0.62.0
- Full support for Claude 3.5 Haiku
- Scored 75% on [aider's code editing leaderboard](https://aider.chat/docs/leaderboards/).
- Almost as good as Sonnet at much lower cost.
- Launch with `--haiku` to use it.
- Easily apply file edits from ChatGPT, Claude or other web apps
- Chat with ChatGPT or Claude via their web app.
- Give it your source files and ask for the changes you want.
- Use the web app's "copy response" button to copy the entire reply from the LLM.
- Run `aider --apply-clipboard-edits file-to-edit.js`.
- Aider will edit your file with the LLM's changes.
- Bugfix for creating new files.
- Aider wrote 84% of the code in this release.
### Aider v0.61.0
- Load and save aider slash-commands to files:
- `/save <fname>` command will make a file of `/add` and `/read-only` commands that recreate the current file context in the chat.
- `/load <fname>` will replay the commands in the file.
- You can use `/load` to run any arbitrary set of slash-commands, not just `/add` and `/read-only`.
- Use `--load <fname>` to run a list of commands on launch, before the interactive chat begins.
- Anonymous, opt-in [analytics](https://aider.chat/docs/more/analytics.html) with no personal data sharing.
- Aider follows litellm's `supports_vision` attribute to enable image support for models.
- Bugfix for when diff mode flexibly handles the model using the wrong filename.
- Displays filenames in sorted order for `/add` and `/read-only`.
- New `--no-fancy-input` switch disables prompt toolkit input, now still available with `--no-pretty`.
- Override browser config with `--no-browser` or `--no-gui`.
- Offer to open documentation URLs when errors occur.
- Properly support all o1 models, regardless of provider.
- Improved layout of filenames above input prompt.
- Better handle corrupted repomap tags cache.
- Improved handling of API errors, especially when accessing the weak model.
- Aider wrote 68% of the code in this release.
### Aider v0.60.1
- Enable image support for Sonnet 10/22.
- Display filenames in sorted order.
### Aider v0.60.0
- Full support for Sonnet 10/22, the new SOTA model on aider's code editing benchmark.
- Aider uses Sonnet 10/22 by default.
- Improved formatting of added and read-only files above chat prompt, by @jbellis.
- Improved support for o1 models by more flexibly parsing their nonconforming code edit replies.
- Corrected diff edit format prompt that only the first match is replaced.
- Stronger whole edit format prompt asking for clean file names.
- Now offers to add `.env` to the `.gitignore` file.
- Ships with a small model metadata json file to handle models not yet updated in litellm.
- Model settings for o1 models on azure.
- Bugfix to properly include URLs in `/help` RAG results.
- Aider wrote 49% of the code in this release.
### Aider v0.59.1
- Check for obsolete `yes: true` in yaml config, show helpful error.
- Model settings for openrouter/anthropic/claude-3.5-sonnet:beta
### Aider v0.59.0
- Improvements to `/read-only`:
- Now supports shell-style auto-complete of the full file system.

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,7 +2789,227 @@
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
total_lines: 228
- aider_percentage: 48.95
aider_total: 140
end_date: '2024-10-22'
end_tag: v0.60.0
file_counts:
.github/workflows/close-stale.yml:
Paul Gauthier: 5
Paul Gauthier (aider): 19
.github/workflows/pages.yml:
Paul Gauthier: 3
aider/__init__.py:
Paul Gauthier: 1
aider/args.py:
Paul Gauthier: 1
fry69: 2
aider/coders/base_coder.py:
Paul Gauthier: 2
aider/coders/editblock_coder.py:
Paul Gauthier (aider): 3
aider/commands.py:
Paul Gauthier: 1
aider/help.py:
Paul Gauthier: 1
Paul Gauthier (aider): 33
aider/io.py:
Jonathan Ellis: 10
Paul Gauthier: 7
aider/main.py:
Paul Gauthier: 20
Paul Gauthier (aider): 39
aider/models.py:
Paul Gauthier: 18
Sven Grunewaldt: 24
fry69: 16
aider/resources/__init__.py:
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:
Paul Gauthier: 1
tests/help/test_help.py:
Paul Gauthier: 4
Paul Gauthier (aider): 46
grand_total:
Jonathan Ellis: 10
Paul Gauthier: 94
Paul Gauthier (aider): 140
Sven Grunewaldt: 24
fry69: 18
start_tag: v0.59.0
total_lines: 286
- aider_percentage: 67.61
aider_total: 860
end_date: '2024-11-01'
end_tag: v0.61.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/analytics.py:
Paul Gauthier: 75
Paul Gauthier (aider): 89
aider/args.py:
Paul Gauthier: 5
Paul Gauthier (aider): 29
aider/coders/base_coder.py:
Paul Gauthier: 56
Paul Gauthier (aider): 43
aider/coders/editblock_coder.py:
Paul Gauthier: 14
aider/commands.py:
Paul Gauthier: 14
Paul Gauthier (aider): 86
aider/io.py:
Paul Gauthier: 12
Paul Gauthier (aider): 32
aider/linter.py:
Paul Gauthier: 6
aider/main.py:
Paul Gauthier: 48
Paul Gauthier (aider): 10
aider/models.py:
Paul Gauthier: 54
Paul Gauthier (aider): 63
kAIto47802: 4
aider/repomap.py:
Paul Gauthier: 12
Paul Gauthier (aider): 52
aider/sendchat.py:
Paul Gauthier: 23
Paul Gauthier (aider): 23
aider/urls.py:
Paul Gauthier: 2
aider/utils.py:
Paul Gauthier (aider): 6
scripts/issues.py:
Paul Gauthier (aider): 13
scripts/pip-compile.sh:
Paul Gauthier (aider): 13
scripts/update-docs.sh:
Paul Gauthier: 1
Paul Gauthier (aider): 5
tests/basic/test_analytics.py:
Paul Gauthier: 1
Paul Gauthier (aider): 99
tests/basic/test_commands.py:
Konstantin L: 34
Paul Gauthier: 45
Paul Gauthier (aider): 267
tests/basic/test_io.py:
Paul Gauthier: 2
Paul Gauthier (aider): 4
tests/basic/test_main.py:
Paul Gauthier (aider): 3
tests/basic/test_models.py:
Paul Gauthier: 3
Paul Gauthier (aider): 9
tests/basic/test_sanity_check_repo.py:
Paul Gauthier (aider): 6
tests/basic/test_sendchat.py:
Paul Gauthier (aider): 8
grand_total:
Konstantin L: 34
Paul Gauthier: 374
Paul Gauthier (aider): 860
kAIto47802: 4
start_tag: v0.60.0
total_lines: 1272
- aider_percentage: 82.42
aider_total: 75
end_date: '2024-11-04'
end_tag: v0.62.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/args.py:
Paul Gauthier (aider): 14
aider/coders/editblock_coder.py:
Paul Gauthier: 6
aider/main.py:
Paul Gauthier (aider): 4
aider/models.py:
Paul Gauthier: 5
Paul Gauthier (aider): 45
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 4
Paul Gauthier (aider): 12
grand_total:
Paul Gauthier: 16
Paul Gauthier (aider): 75
start_tag: v0.61.0
total_lines: 91
- aider_percentage: 55.08
aider_total: 385
end_date: '2024-11-13'
end_tag: v0.63.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/coders/architect_coder.py:
Paul Gauthier: 3
aider/coders/base_coder.py:
Paul Gauthier: 42
Paul Gauthier (aider): 1
aider/coders/editblock_coder.py:
Paul Gauthier: 4
aider/commands.py:
Paul Gauthier: 13
aider/exceptions.py:
Paul Gauthier: 72
Paul Gauthier (aider): 4
aider/io.py:
Paul Gauthier: 3
Paul Gauthier (aider): 23
aider/main.py:
Paul Gauthier: 9
Paul Gauthier (aider): 9
aider/models.py:
Logan Attwood: 29
Paul Gauthier: 50
Paul Gauthier (aider): 7
aider/repo.py:
Paul Gauthier: 7
aider/repomap.py:
Paul Gauthier: 4
aider/sendchat.py:
Paul Gauthier: 17
Paul Gauthier (aider): 4
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
scripts/issues.py:
Paul Gauthier: 4
Paul Gauthier (aider): 195
tests/basic/test_coder.py:
Paul Gauthier: 2
tests/basic/test_commands.py:
Paul Gauthier (aider): 20
tests/basic/test_editblock.py:
Paul Gauthier: 41
tests/basic/test_exceptions.py:
Paul Gauthier (aider): 65
tests/basic/test_main.py:
Paul Gauthier: 1
tests/basic/test_sanity_check_repo.py:
Paul Gauthier: 2
Paul Gauthier (aider): 2
tests/basic/test_sendchat.py:
Paul Gauthier: 8
Paul Gauthier (aider): 55
tests/scrape/test_scrape.py:
Paul Gauthier: 1
grand_total:
Logan Attwood: 29
Paul Gauthier: 285
Paul Gauthier (aider): 385
start_tag: v0.62.0
total_lines: 699

View File

@@ -1,7 +1,7 @@
- dirname: 2024-05-01-20-05-59--direct-opus-filenames-outside-fence
test_cases: 133
model: claude-3-opus-20240229
released: 2024-02-29
_released: 2024-02-29
edit_format: diff
commit_hash: f4b1797-dirty, f4b1797
pass_rate_1: 53.4
@@ -20,7 +20,7 @@
versions: 0.30.2-dev
seconds_per_case: 32.4
total_cost: 13.8395
- dirname: 2024-03-06-16-42-00--claude3-sonnet-whole
test_cases: 133
model: claude-3-sonnet-20240229
@@ -43,7 +43,7 @@
versions: 0.25.1-dev
seconds_per_case: 23.1
total_cost: 0.0000
- dirname: 2024-05-03-20-47-24--gemini-1.5-pro-diff-fenced
test_cases: 133
model: gemini-1.5-pro-latest
@@ -88,7 +88,7 @@
versions: 0.33.1-dev
seconds_per_case: 6.5
total_cost: 0.5032
- dirname: 2023-11-06-21-23-59--gpt-3.5-turbo-0301
test_cases: 133
model: gpt-3.5-turbo-0301
@@ -111,7 +111,7 @@
versions: 0.16.4-dev
seconds_per_case: 6.5
total_cost: 0.4822
- dirname: 2023-11-07-02-41-07--gpt-3.5-turbo-0613
test_cases: 133
model: gpt-3.5-turbo-0613
@@ -155,7 +155,7 @@
versions: 0.30.2-dev
seconds_per_case: 5.3
total_cost: 0.3261
- dirname: 2024-01-25-23-37-15--jan-exercism-gpt-4-0125-preview-udiff
test_cases: 133
model: gpt-4-0125-preview
@@ -178,7 +178,7 @@
versions: 0.22.1-dev
seconds_per_case: 44.8
total_cost: 14.6428
- dirname: 2024-05-04-15-07-30--redo-gpt-4-0314-diff-reminder-rules
test_cases: 133
model: gpt-4-0314
@@ -201,7 +201,7 @@
versions: 0.31.2-dev
seconds_per_case: 19.8
total_cost: 16.2689
- dirname: 2023-12-16-21-24-28--editblock-gpt-4-0613-actual-main
test_cases: 133
model: gpt-4-0613
@@ -228,7 +228,7 @@
- dirname: 2024-05-08-21-16-03--may-gpt-4-1106-preview-udiff
test_cases: 133
model: gpt-4-1106-preview
released: 2023-11-06
released: 2023-11-06
edit_format: udiff
commit_hash: 87664dc
pass_rate_1: 51.9
@@ -247,7 +247,7 @@
versions: 0.33.1-dev
seconds_per_case: 20.4
total_cost: 6.6061
- dirname: 2024-05-01-02-09-20--gpt-4-turbo-examples
test_cases: 133
model: gpt-4-turbo-2024-04-09 (udiff)
@@ -270,11 +270,11 @@
versions: 0.30.2-dev
seconds_per_case: 22.8
total_cost: 6.3337
- dirname: 2024-05-03-22-24-48--openrouter--llama3-diff-examples-sys-msg
test_cases: 132
model: llama3-70b-8192
released: 2024-04-18
_released: 2024-04-18
edit_format: diff
commit_hash: b5bb453
pass_rate_1: 38.6
@@ -293,11 +293,11 @@
versions: 0.31.2-dev
seconds_per_case: 14.5
total_cost: 0.4311
- dirname: 2024-05-06-18-31-08--command-r-plus-whole-final
test_cases: 133
model: command-r-plus
released: 2024-04-04
_released: 2024-04-04
edit_format: whole
commit_hash: fc3a43e-dirty
pass_rate_1: 21.8
@@ -316,11 +316,11 @@
versions: 0.31.2-dev
seconds_per_case: 22.9
total_cost: 2.7494
- dirname: 2024-05-07-20-32-37--qwen1.5-110b-chat-whole
test_cases: 133
model: qwen1.5-110b-chat
released: 2024-02-04
released: 2024-02-04
edit_format: whole
commit_hash: 70b1c0c
pass_rate_1: 30.8
@@ -339,7 +339,7 @@
versions: 0.31.2-dev
seconds_per_case: 46.9
total_cost: 0.0000
- dirname: 2024-05-07-20-57-04--wizardlm-2-8x22b-whole
test_cases: 133
model: WizardLM-2 8x22B
@@ -384,7 +384,7 @@
versions: 0.34.1-dev
seconds_per_case: 6.0
total_cost: 0.0000
- dirname: 2024-04-12-22-18-20--gpt-4-turbo-2024-04-09-plain-diff
test_cases: 33
model: gpt-4-turbo-2024-04-09 (diff)
@@ -547,7 +547,7 @@
- dirname: 2024-07-04-14-32-08--claude-3.5-sonnet-diff-continue
test_cases: 133
model: claude-3.5-sonnet
model: claude-3.5-sonnet-20240620
edit_format: diff
commit_hash: 35f21b5
pass_rate_1: 57.1
@@ -563,12 +563,12 @@
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --sonnet
command: aider --model claude-3.5-sonnet-20240620
date: 2024-07-04
versions: 0.42.1-dev
seconds_per_case: 17.6
total_cost: 3.6346
- dirname: 2024-07-01-21-41-48--haiku-whole
test_cases: 133
model: claude-3-haiku-20240307
@@ -623,7 +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
@@ -1131,7 +1133,7 @@
versions: 0.56.1.dev
seconds_per_case: 80.9
total_cost: 63.9190
- dirname: 2024-09-19-16-58-29--qwen2.5-coder:7b-instruct-q8_0
test_cases: 133
model: qwen2.5-coder:7b-instruct-q8_0
@@ -1154,7 +1156,7 @@
versions: 0.56.0
seconds_per_case: 9.3
total_cost: 0.0000
- dirname: 2024-09-20-20-20-19--qwen-2.5-72b-instruct-diff
test_cases: 133
model: qwen-2.5-72b-instruct (bf16)
@@ -1458,7 +1460,7 @@
versions: 0.58.1.dev
seconds_per_case: 63.7
total_cost: 0.0000
- dirname: 2024-10-01-16-50-09--hermes3-whole-4
test_cases: 133
model: ollama/hermes3
@@ -1477,6 +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
@@ -1495,4 +1498,400 @@
date: 2024-10-04
versions: 0.58.2.dev
seconds_per_case: 23.7
total_cost: 4.0641
total_cost: 4.0641
- dirname: 2024-10-05-20-03-10--dracarys-glhf-whole
test_cases: 133
model: Dracarys2-72B-Instruct
edit_format: whole
commit_hash: 04a2cbb
pass_rate_1: 55.6
pass_rate_2: 66.9
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: 0
command: (via glhf.chat)
date: 2024-10-05
versions: 0.59.2.dev
seconds_per_case: 46.7
total_cost: 0.0000
- dirname: 2024-10-13-21-33-42--grok2-whole
test_cases: 133
model: Grok-2
edit_format: whole
commit_hash: 0a497b7
pass_rate_1: 45.9
pass_rate_2: 58.6
percent_cases_well_formed: 98.5
error_outputs: 7
num_malformed_responses: 7
num_with_malformed_responses: 2
user_asks: 24
lazy_comments: 4
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model openrouter/x-ai/grok-2
date: 2024-10-13
versions: 0.59.2.dev
seconds_per_case: 34.6
total_cost: 0.0000
- dirname: 2024-10-13-23-58-44--grok2mini-whole
test_cases: 133
model: Grok-2-mini
edit_format: whole
commit_hash: 0a497b7-dirty, 0a497b7
pass_rate_1: 40.6
pass_rate_2: 54.9
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 8
lazy_comments: 2
syntax_errors: 2
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model openrouter/x-ai/grok-2-mini
date: 2024-10-13
versions: 0.59.2.dev
seconds_per_case: 32.1
total_cost: 0.0000
- dirname: 2024-10-16-15-55-37--nemotron-glhf-whole3
test_cases: 133
model: Llama-3.1-Nemotron-70B-Instruct-HF
edit_format: whole
commit_hash: 6bb9b25-dirty
pass_rate_1: 36.8
pass_rate_2: 54.9
percent_cases_well_formed: 99.2
error_outputs: 17
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 53
lazy_comments: 17
syntax_errors: 1
indentation_errors: 2
exhausted_context_windows: 0
test_timeouts: 3
command: (via glhf.chat)
date: 2024-10-16
versions: 0.59.2.dev
seconds_per_case: 64.9
total_cost: 0.0000
- 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
pass_rate_2: 84.2
percent_cases_well_formed: 99.2
error_outputs: 1
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 0
lazy_comments: 1
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --model anthropic/claude-3-5-sonnet-20241022
date: 2024-10-22
versions: 0.59.2.dev
seconds_per_case: 18.6
total_cost: 0.0000
- dirname: 2024-11-04-19-19-32--haiku35-diff-ex-as-sys-false
test_cases: 133
model: claude-3-5-haiku-20241022
released: 2024-10-22
edit_format: diff
commit_hash: 03bbdb0-dirty
pass_rate_1: 61.7
pass_rate_2: 75.2
percent_cases_well_formed: 95.5
error_outputs: 11
num_malformed_responses: 11
num_with_malformed_responses: 6
user_asks: 1
lazy_comments: 1
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
command: aider --model anthropic/claude-3-5-haiku-20241022
date: 2024-11-04
versions: 0.61.1.dev
seconds_per_case: 18.4
total_cost: 0.0000
- dirname: 2024-11-07-06-15-36--Qwen2.5.1-Coder-7B-Instruct-GGUF:Q8_0-32k-whole
test_cases: 133
model: ollama/Qwen2.5.1-Coder-7B-Instruct-GGUF:Q8_0-32k
edit_format: whole
commit_hash: e76704e
pass_rate_1: 52.6
pass_rate_2: 63.9
percent_cases_well_formed: 100.0
error_outputs: 0
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 4
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 1
command: aider --model ollama/Qwen2.5.1-Coder-7B-Instruct-GGUF:Q8_0-32k
date: 2024-11-07
versions: 0.59.2.dev
seconds_per_case: 18.2
total_cost: 0.0000
- dirname: 2024-10-29-00-29-09--Qwen2.5-Coder-0.5B-Instruct
test_cases: 133
model: Qwen2.5-Coder-0.5B-Instruct
edit_format: whole
commit_hash: 58bd375
pass_rate_1: 14.3
pass_rate_2: 14.3
percent_cases_well_formed: 100.0
error_outputs: 20
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 45
lazy_comments: 0
syntax_errors: 2
indentation_errors: 0
exhausted_context_windows: 20
test_timeouts: 2
command: aider --model openai/Qwen2.5-Coder-0.5B-Instruct
date: 2024-10-29
versions: 0.59.2.dev
seconds_per_case: 16.0
total_cost: 0.0000
- dirname: 2024-11-11-19-37-01--Qwen2.5-Coder-1.5B-Instruct
test_cases: 133
model: Qwen2.5-Coder-1.5B-Instruct
edit_format: whole
commit_hash: bb5681c
pass_rate_1: 28.6
pass_rate_2: 31.6
percent_cases_well_formed: 100.0
error_outputs: 5
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 13
lazy_comments: 2
syntax_errors: 1
indentation_errors: 0
exhausted_context_windows: 5
test_timeouts: 2
command: aider --model openai/Qwen2.5-Coder-1.5B-Instruct
date: 2024-11-11
versions: 0.59.2.dev
seconds_per_case: 27.4
total_cost: 0.0000
- dirname: 2024-11-04-02-25-32--Qwen2.5-Coder-3B-Instruct
test_cases: 133
model: Qwen2.5-Coder-3B-Instruct
edit_format: whole
commit_hash: 0ba3647
pass_rate_1: 33.8
pass_rate_2: 39.1
percent_cases_well_formed: 100.0
error_outputs: 4
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 3
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 4
test_timeouts: 6
command: aider --model openai/Qwen2.5-Coder-3B-Instruct
date: 2024-11-04
versions: 0.59.2.dev
seconds_per_case: 18.7
total_cost: 0.0000
- dirname: 2024-10-16-16-20-59--Qwen2.5-Coder-7B-Instruct
test_cases: 133
model: Qwen2.5-Coder-7B-Instruct
edit_format: whole
commit_hash: 92fe979-dirty
pass_rate_1: 51.9
pass_rate_2: 57.9
percent_cases_well_formed: 100.0
error_outputs: 2
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 2
test_timeouts: 5
command: aider --model openai/Qwen2.5-Coder-7B-Instruct
date: 2024-10-16
versions: 0.59.2.dev
seconds_per_case: 10.5
total_cost: 0.0000
- dirname: 2024-10-29-11-53-39--Qwen2.5-Coder-14B-Instruct
test_cases: 133
model: Qwen2.5-Coder-14B-Instruct
edit_format: whole
commit_hash: 58bd375
pass_rate_1: 58.6
pass_rate_2: 69.2
percent_cases_well_formed: 100.0
error_outputs: 3
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 2
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 3
test_timeouts: 0
command: aider --model openai/Qwen2.5-Coder-14B-Instruct
date: 2024-10-29
versions: 0.59.2.dev
seconds_per_case: 18.3
total_cost: 0.0000
- dirname: 2024-11-09-11-09-15--Qwen2.5-Coder-32B-Instruct
test_cases: 133
model: Qwen2.5-Coder-32B-Instruct
released: 2024-11-12
edit_format: diff
commit_hash: ec9982a
pass_rate_1: 59.4
pass_rate_2: 71.4
percent_cases_well_formed: 94.7
error_outputs: 17
num_malformed_responses: 17
num_with_malformed_responses: 7
user_asks: 1
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
command: aider --model openai/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-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

@@ -145,7 +145,7 @@
- dirname: 2024-07-01-18-30-33--refac-claude-3.5-sonnet-diff-not-lazy
test_cases: 89
model: claude-3.5-sonnet (diff)
model: claude-3.5-sonnet-20240620
edit_format: diff
commit_hash: 7396e38-dirty
pass_rate_1: 64.0
@@ -229,4 +229,70 @@
date: 2024-09-05
versions: 0.55.1.dev
seconds_per_case: 225.4
total_cost: 1.0338
total_cost: 1.0338
- dirname: 2024-10-22-19-57-27--refac-openrouter-sonnet-1022
test_cases: 89
model: claude-3-5-sonnet-20241022
edit_format: diff
commit_hash: 4a3e6ef
pass_rate_1: 92.1
percent_cases_well_formed: 91.0
error_outputs: 13
num_malformed_responses: 12
num_with_malformed_responses: 8
user_asks: 14
lazy_comments: 2
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
command: aider --sonnet
date: 2024-10-22
versions: 0.60.1.dev
seconds_per_case: 32.5
total_cost: 8.4644
- dirname: 2024-10-22-20-03-10--refac-o1mini
test_cases: 89
model: o1-mini
edit_format: diff
commit_hash: 4a3e6ef-dirty
pass_rate_1: 44.9
percent_cases_well_formed: 29.2
error_outputs: 151
num_malformed_responses: 150
num_with_malformed_responses: 63
user_asks: 28
lazy_comments: 2
syntax_errors: 5
indentation_errors: 4
exhausted_context_windows: 1
test_timeouts: 0
command: aider --model o1-mini
date: 2024-10-22
versions: 0.60.1.dev
seconds_per_case: 115.3
total_cost: 29.0492
- dirname: 2024-10-22-20-26-36--refac-o1preview
test_cases: 89
model: o1-preview
edit_format: diff
commit_hash: 4a3e6ef-dirty
pass_rate_1: 75.3
percent_cases_well_formed: 57.3
error_outputs: 75
num_malformed_responses: 74
num_with_malformed_responses: 38
user_asks: 19
lazy_comments: 2
syntax_errors: 2
indentation_errors: 3
exhausted_context_windows: 1
test_timeouts: 0
command: aider --model o1-preview
date: 2024-10-22
versions: 0.60.1.dev
seconds_per_case: 231.7
total_cost: 120.9850

View File

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

View File

@@ -0,0 +1,97 @@
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('editChart').getContext('2d');
const HIGHTLIGHT_MODEL = 'no no no no';
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: function(context) {
const label = context.chart.data.labels[context.dataIndex] || '';
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)';
},
borderColor: function(context) {
const label = context.chart.data.labels[context.dataIndex] || '';
return (label && label.includes(HIGHTLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)';
},
borderWidth: 1
}]
};
var allData = [];
{% for row in edit_sorted %}
allData.push({
model: '{{ row.model }}',
pass_rate_2: {{ row.pass_rate_2 }},
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
});
{% endfor %}
function updateChart() {
var selectedRows = document.querySelectorAll('tr.selected');
var showAll = selectedRows.length === 0;
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
allData.forEach(function(row, index) {
var rowElement = document.getElementById('edit-row-' + index);
if (showAll) {
rowElement.classList.remove('selected');
}
if (showAll || rowElement.classList.contains('selected')) {
leaderboardData.labels.push(row.model);
leaderboardData.datasets[0].data.push(row.pass_rate_2);
}
});
leaderboardChart.update();
}
var tableBody = document.querySelector('table tbody');
allData.forEach(function(row, index) {
var tr = tableBody.children[index];
tr.id = 'edit-row-' + index;
tr.style.cursor = 'pointer';
tr.onclick = function() {
this.classList.toggle('selected');
updateChart();
};
});
var leaderboardChart = new Chart(ctx, {
type: 'bar',
data: leaderboardData,
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
updateChart();
// Add search functionality for edit table
document.getElementById('editSearchInput').addEventListener('keyup', function() {
var searchWords = this.value.toLowerCase().split(' ').filter(word => word.length > 0);
var tableBody = document.querySelector('table:first-of-type tbody');
var rows = tableBody.getElementsByTagName('tr');
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
for (var i = 0; i < rows.length; i++) {
var rowText = rows[i].textContent;
if (searchWords.every(word => rowText.toLowerCase().includes(word))) {
rows[i].style.display = '';
leaderboardData.labels.push(allData[i].model);
leaderboardData.datasets[0].data.push(allData[i].pass_rate_2);
} else {
rows[i].style.display = 'none';
}
}
leaderboardChart.update();
});
});

View File

View File

@@ -1,5 +1,15 @@
You can send long, multi-line messages in the chat in a few ways:
- Paste a multi-line message directly into the chat.
- Enter `{` alone on the first line to start a multiline message and `}` alone on the last line to end it.
- Or, start with `{tag` (where "tag" is any sequence of letters/numbers) and end with `tag}`. This is useful when you need to include closing braces `}` in your message.
- Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
- Use `/clipboard` to paste text from the clipboard into the chat.
- 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

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

View File

@@ -0,0 +1,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

@@ -29,9 +29,12 @@
## Use claude-3-opus-20240229 model for the main chat
#opus: false
## Use claude-3-5-sonnet-20240620 model for the main chat
## Use claude-3-5-sonnet-20241022 model for the main chat
#sonnet: false
## Use claude-3-5-haiku-20241022 model for the main chat
#haiku: false
## Use gpt-4-0613 model for the main chat
#4: false
@@ -104,7 +107,7 @@
## Only work with models that have meta-data available (default: True)
#show-model-warnings: true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#max-chat-history-tokens: xxx
## Specify the .env file to load (default: .env in git root)
@@ -265,6 +268,18 @@
## Run tests and fix problems found
#test: false
############
# Analytics:
## Enable/disable analytics for current session (default: random)
#analytics: xxx
## Specify a file to log analytics events
#analytics-log: xxx
## Permanently disable analytics
#analytics-disable: false
#################
# Other Settings:
@@ -299,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
@@ -308,6 +326,9 @@
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Always say yes to every confirmation
#yes-always: false
@@ -329,18 +350,27 @@
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Load and execute /commands from a file on launch
#load: xxx
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx
## Run aider in your browser
## Run aider in your browser (default: False)
#gui: false
## Enable/disable suggesting shell commands (default: True)
#suggest-shell-commands: true
## 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

@@ -33,9 +33,12 @@
## Use claude-3-opus-20240229 model for the main chat
#AIDER_OPUS=
## Use claude-3-5-sonnet-20240620 model for the main chat
## Use claude-3-5-sonnet-20241022 model for the main chat
#AIDER_SONNET=
## Use claude-3-5-haiku-20241022 model for the main chat
#AIDER_HAIKU=
## Use gpt-4-0613 model for the main chat
#AIDER_4=
@@ -108,7 +111,7 @@
## Only work with models that have meta-data available (default: True)
#AIDER_SHOW_MODEL_WARNINGS=true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#AIDER_MAX_CHAT_HISTORY_TOKENS=
## Specify the .env file to load (default: .env in git root)
@@ -264,6 +267,18 @@
## Run tests and fix problems found
#AIDER_TEST=false
############
# Analytics:
## Enable/disable analytics for current session (default: random)
#AIDER_ANALYTICS=
## Specify a file to log analytics events
#AIDER_ANALYTICS_LOG=
## Permanently disable analytics
#AIDER_ANALYTICS_DISABLE=false
#################
# Other Settings:
@@ -285,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
@@ -294,6 +312,9 @@
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
@@ -315,15 +336,24 @@
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser
## Run aider in your browser (default: False)
#AIDER_GUI=false
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## 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)
@@ -81,8 +105,7 @@ cog.out(get_model_settings_as_yaml())
cog.out("```\n")
]]]-->
```yaml
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -98,8 +121,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -115,8 +137,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -132,8 +153,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -149,8 +169,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -166,8 +185,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -183,8 +201,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -200,8 +217,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -217,8 +233,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -234,8 +249,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -251,8 +265,39 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- 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
editor_edit_format: editor-diff
@@ -268,8 +313,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -285,8 +329,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -302,8 +345,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -319,8 +361,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -336,8 +377,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -353,8 +393,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -370,8 +409,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -387,8 +425,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -404,8 +441,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -420,9 +456,8 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: false
cache_control: false
weak_model_name: claude-3-5-haiku-20241022
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -437,9 +472,8 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku
- accepts_images: false
cache_control: false
weak_model_name: openrouter/anthropic/claude-3-5-haiku
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -454,9 +488,8 @@ cog.out("```\n")
use_repo_map: false
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: true
cache_control: true
weak_model_name: claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -474,9 +507,8 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: false
cache_control: true
weak_model_name: claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -494,9 +526,84 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: false
cache_control: true
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: anthropic/claude-3-5-sonnet-20241022
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
max_tokens: 8192
lazy: false
name: anthropic/claude-3-5-sonnet-20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
max_tokens: 8192
lazy: false
name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: anthropic/claude-3-5-sonnet-20241022
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
max_tokens: 8192
lazy: false
name: anthropic/claude-3-5-sonnet-latest
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: claude-3-5-sonnet-20241022
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
max_tokens: 8192
lazy: false
name: claude-3-5-sonnet-20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -514,8 +621,78 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
- accepts_images: false
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
lazy: false
name: anthropic/claude-3-5-haiku-20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-5-haiku-20241022
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
lazy: false
name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
lazy: false
name: claude-3-5-haiku-20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-5-haiku-20241022
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params:
max_tokens: 4096
lazy: false
name: vertex_ai/claude-3-5-haiku@20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: true
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -533,8 +710,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: true
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -550,9 +726,8 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku-20240307
- accepts_images: true
cache_control: true
weak_model_name: openrouter/anthropic/claude-3-5-haiku
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -568,9 +743,8 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku-20240307
- accepts_images: true
cache_control: false
weak_model_name: openrouter/anthropic/claude-3-5-haiku:beta
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -586,9 +760,25 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
- accepts_images: false
cache_control: false
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: vertex_ai/claude-3-5-sonnet-v2@20241022
examples_as_sys_msg: true
extra_params:
max_tokens: 8192
lazy: false
name: vertex_ai/claude-3-5-sonnet-v2@20241022
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -603,9 +793,8 @@ cog.out("```\n")
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
- accepts_images: false
cache_control: false
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -620,9 +809,8 @@ cog.out("```\n")
use_repo_map: false
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
- accepts_images: false
cache_control: false
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -638,8 +826,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: command-r-plus
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -655,8 +842,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: command-r-08-2024
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -672,8 +858,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: command-r-plus-08-2024
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -689,8 +874,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: groq/llama3-8b-8192
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -706,8 +890,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/meta-llama/llama-3-70b-instruct
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -723,8 +906,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -740,8 +922,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
@@ -757,8 +938,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
@@ -774,8 +954,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
@@ -791,8 +970,23 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
editor_model_name: null
examples_as_sys_msg: false
extra_params: null
lazy: false
name: vertex_ai/gemini-pro-experimental
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: null
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -808,8 +1002,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -826,8 +1019,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: true
edit_format: diff
editor_edit_format: null
@@ -844,8 +1036,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -862,8 +1053,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: true
edit_format: diff
editor_edit_format: null
@@ -880,8 +1070,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -897,8 +1086,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -914,8 +1102,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
@@ -926,13 +1113,28 @@ 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
weak_model_name: openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
editor_model_name: azure/gpt-4o
examples_as_sys_msg: false
extra_params: null
lazy: false
name: azure/o1-mini
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
weak_model_name: azure/gpt-4o-mini
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
@@ -943,13 +1145,12 @@ 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
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -960,13 +1161,28 @@ 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
weak_model_name: openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: azure/gpt-4o
examples_as_sys_msg: false
extra_params: null
lazy: false
name: azure/o1-preview
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: false
use_temperature: false
weak_model_name: azure/gpt-4o-mini
- cache_control: false
caches_by_default: false
edit_format: architect
editor_edit_format: editor-diff
@@ -977,13 +1193,12 @@ 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
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
@@ -994,13 +1209,12 @@ 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
weak_model_name: openrouter/openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -1011,11 +1225,27 @@ 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
weak_model_name: openrouter/openai/gpt-4o-mini
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct
examples_as_sys_msg: false
extra_params: null
lazy: false
name: openrouter/qwen/qwen-2.5-coder-32b-instruct
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct
```
<!--[[[end]]]-->

View File

@@ -85,9 +85,12 @@ cog.outl("```")
## Use claude-3-opus-20240229 model for the main chat
#opus: false
## Use claude-3-5-sonnet-20240620 model for the main chat
## Use claude-3-5-sonnet-20241022 model for the main chat
#sonnet: false
## Use claude-3-5-haiku-20241022 model for the main chat
#haiku: false
## Use gpt-4-0613 model for the main chat
#4: false
@@ -160,7 +163,7 @@ cog.outl("```")
## Only work with models that have meta-data available (default: True)
#show-model-warnings: true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#max-chat-history-tokens: xxx
## Specify the .env file to load (default: .env in git root)
@@ -321,6 +324,18 @@ cog.outl("```")
## Run tests and fix problems found
#test: false
############
# Analytics:
## Enable/disable analytics for current session (default: random)
#analytics: xxx
## Specify a file to log analytics events
#analytics-log: xxx
## Permanently disable analytics
#analytics-disable: false
#################
# Other Settings:
@@ -355,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
@@ -364,6 +382,9 @@ cog.outl("```")
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Always say yes to every confirmation
#yes-always: false
@@ -385,18 +406,27 @@ cog.outl("```")
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Load and execute /commands from a file on launch
#load: xxx
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx
## Run aider in your browser
## Run aider in your browser (default: False)
#gui: false
## Enable/disable suggesting shell commands (default: True)
#suggest-shell-commands: true
## 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

@@ -75,9 +75,12 @@ cog.outl("```")
## Use claude-3-opus-20240229 model for the main chat
#AIDER_OPUS=
## Use claude-3-5-sonnet-20240620 model for the main chat
## Use claude-3-5-sonnet-20241022 model for the main chat
#AIDER_SONNET=
## Use claude-3-5-haiku-20241022 model for the main chat
#AIDER_HAIKU=
## Use gpt-4-0613 model for the main chat
#AIDER_4=
@@ -150,7 +153,7 @@ cog.outl("```")
## Only work with models that have meta-data available (default: True)
#AIDER_SHOW_MODEL_WARNINGS=true
## Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#AIDER_MAX_CHAT_HISTORY_TOKENS=
## Specify the .env file to load (default: .env in git root)
@@ -306,6 +309,18 @@ cog.outl("```")
## Run tests and fix problems found
#AIDER_TEST=false
############
# Analytics:
## Enable/disable analytics for current session (default: random)
#AIDER_ANALYTICS=
## Specify a file to log analytics events
#AIDER_ANALYTICS_LOG=
## Permanently disable analytics
#AIDER_ANALYTICS_DISABLE=false
#################
# Other Settings:
@@ -327,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
@@ -336,6 +354,9 @@ cog.outl("```")
## Apply the changes from the given file instead of running the chat (debug)
#AIDER_APPLY=
## Apply clipboard contents as edits using the main model's editor format
#AIDER_APPLY_CLIPBOARD_EDITS=false
## Always say yes to every confirmation
#AIDER_YES_ALWAYS=
@@ -357,15 +378,24 @@ cog.outl("```")
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser
## Run aider in your browser (default: False)
#AIDER_GUI=false
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
## 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

@@ -26,12 +26,12 @@ cog.out(get_md_help())
]]]-->
```
usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--opus] [--sonnet] [--4] [--4o] [--mini] [--4-turbo]
[--35turbo] [--deepseek] [--o1-mini] [--o1-preview]
[--list-models] [--openai-api-base] [--openai-api-type]
[--openai-api-version] [--openai-api-deployment-id]
[--openai-organization-id] [--model-settings-file]
[--model-metadata-file]
[--opus] [--sonnet] [--haiku] [--4] [--4o] [--mini]
[--4-turbo] [--35turbo] [--deepseek] [--o1-mini]
[--o1-preview] [--list-models] [--openai-api-base]
[--openai-api-type] [--openai-api-version]
[--openai-api-deployment-id] [--openai-organization-id]
[--model-settings-file] [--model-metadata-file]
[--verify-ssl | --no-verify-ssl] [--edit-format]
[--architect] [--weak-model] [--editor-model]
[--editor-edit-format]
@@ -61,15 +61,19 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--commit] [--commit-prompt] [--dry-run | --no-dry-run]
[--skip-sanity-check-repo] [--lint] [--lint-cmd]
[--auto-lint | --no-auto-lint] [--test-cmd]
[--auto-test | --no-auto-test] [--test] [--file]
[--read] [--vim] [--chat-language] [--version]
[--just-check-update]
[--auto-test | --no-auto-test] [--test]
[--analytics | --no-analytics] [--analytics-log]
[--analytics-disable] [--file] [--read] [--vim]
[--chat-language] [--version] [--just-check-update]
[--check-update | --no-check-update]
[--show-release-notes | --no-show-release-notes]
[--install-main-branch] [--upgrade] [--apply]
[--yes-always] [-v] [--show-repo-map] [--show-prompts]
[--exit] [--message] [--message-file] [--encoding] [-c]
[--gui]
[--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] [--editor]
[--voice-format] [--voice-language]
```
@@ -101,9 +105,13 @@ Use claude-3-opus-20240229 model for the main chat
Environment variable: `AIDER_OPUS`
### `--sonnet`
Use claude-3-5-sonnet-20240620 model for the main chat
Use claude-3-5-sonnet-20241022 model for the main chat
Environment variable: `AIDER_SONNET`
### `--haiku`
Use claude-3-5-haiku-20241022 model for the main chat
Environment variable: `AIDER_HAIKU`
### `--4`
Use gpt-4-0613 model for the main chat
Environment variable: `AIDER_4`
@@ -223,7 +231,7 @@ Aliases:
- `--no-show-model-warnings`
### `--max-chat-history-tokens VALUE`
Maximum number of tokens to use for chat history. If not specified, uses the model's max_chat_history_tokens.
Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
Environment variable: `AIDER_MAX_CHAT_HISTORY_TOKENS`
### `--env-file ENV_FILE`
@@ -500,6 +508,24 @@ Run tests and fix problems found
Default: False
Environment variable: `AIDER_TEST`
## Analytics:
### `--analytics`
Enable/disable analytics for current session (default: random)
Environment variable: `AIDER_ANALYTICS`
Aliases:
- `--analytics`
- `--no-analytics`
### `--analytics-log ANALYTICS_LOG_FILE`
Specify a file to log analytics events
Environment variable: `AIDER_ANALYTICS_LOG`
### `--analytics-disable`
Permanently disable analytics
Default: False
Environment variable: `AIDER_ANALYTICS_DISABLE`
## Other Settings:
### `--file FILE`
@@ -535,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
@@ -552,6 +585,11 @@ Aliases:
Apply the changes from the given file instead of running the chat (debug)
Environment variable: `AIDER_APPLY`
### `--apply-clipboard-edits`
Apply clipboard contents as edits using the main model's editor format
Default: False
Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS`
### `--yes-always`
Always say yes to every confirmation
Environment variable: `AIDER_YES_ALWAYS`
@@ -594,6 +632,10 @@ Aliases:
- `--message-file MESSAGE_FILE`
- `-f MESSAGE_FILE`
### `--load LOAD_FILE`
Load and execute /commands from a file on launch
Environment variable: `AIDER_LOAD`
### `--encoding VALUE`
Specify the encoding for input and output (default: utf-8)
Default: utf-8
@@ -606,12 +648,14 @@ Aliases:
- `--config CONFIG_FILE`
### `--gui`
Run aider in your browser
Run aider in your browser (default: False)
Default: False
Environment variable: `AIDER_GUI`
Aliases:
- `--gui`
- `--no-gui`
- `--browser`
- `--no-browser`
### `--suggest-shell-commands`
Enable/disable suggesting shell commands (default: True)
@@ -621,6 +665,18 @@ Aliases:
- `--suggest-shell-commands`
- `--no-suggest-shell-commands`
### `--fancy-input`
Enable/disable fancy input with history and completion (default: True)
Default: True
Environment variable: `AIDER_FANCY_INPUT`
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

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

View File

@@ -1,6 +1,6 @@
---
parent: More info
nav_order: 800
nav_order: 100
description: Aider is tightly integrated with git.
---
@@ -22,9 +22,16 @@ This keeps your edits separate from aider's edits, and makes sure you never lose
## In-chat commands
Aider also allows you to use in-chat commands to `/diff` or `/undo` the last change.
To do more complex management of your git history, you cat use raw `git` commands,
either by using `/git` within the chat, or with standard git tools outside of aider.
Aider also allows you to use
[in-chat commands](/docs/usage/commands.html)
to perform git operations:
- `/diff` will show all the file changes since the last message you sent.
- `/undo` will undo and discard the last change.
- `/commit` to commit all dirty changes with a sensible commit message.
- `/git` will let you run raw git commands to do more complex management of your git history.
You can also manage your git history outside of aider with your preferred git tools.
## Disabling git integration
@@ -36,6 +43,8 @@ While it is not recommended, you can disable aider's use of git in a few ways:
## Commit messages
Aider sends the `--weak-model` a copy of the diffs and the chat history
and asks it to produce a commit message.
By default, aider creates commit messages which follow
[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
@@ -45,6 +54,7 @@ with the `--commit-prompt` option.
You can place that on the command line, or
[configure it via a config file or environment variables](https://aider.chat/docs/config.html).
## Commit attribution
Aider marks commits that it either authored or committed.

View File

@@ -9,6 +9,10 @@ nav_order: 10
- TOC
{:toc}
## Python version
Aider currently works with python 3.9-3.12.
## Install git
Make sure you have git installed.

View File

@@ -1,6 +1,6 @@
---
parent: More info
nav_order: 900
nav_order: 200
description: Aider supports pretty much all popular coding languages.
---
# Supported languages

View File

@@ -31,6 +31,8 @@ This measures the LLM's coding ability, and whether it can
write new code that integrates into existing code.
The model also has to successfully apply all its changes to the source file without human intervention.
<input type="text" id="editSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
<table style="width: 100%; max-width: 800px; margin: auto; border-collapse: collapse; box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 14px;">
<thead style="background-color: #f2f2f2;">
<tr>
@@ -58,79 +60,7 @@ The model also has to successfully apply all its changes to the source file with
<canvas id="editChart" width="800" height="450" style="margin-top: 20px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('editChart').getContext('2d');
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
};
var allData = [];
{% for row in edit_sorted %}
allData.push({
model: '{{ row.model }}',
pass_rate_2: {{ row.pass_rate_2 }},
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
});
{% endfor %}
function updateChart() {
var selectedRows = document.querySelectorAll('tr.selected');
var showAll = selectedRows.length === 0;
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
allData.forEach(function(row, index) {
var rowElement = document.getElementById('edit-row-' + index);
if (showAll) {
rowElement.classList.remove('selected');
}
if (showAll || rowElement.classList.contains('selected')) {
leaderboardData.labels.push(row.model);
leaderboardData.datasets[0].data.push(row.pass_rate_2);
}
});
leaderboardChart.update();
}
var tableBody = document.querySelector('table tbody');
allData.forEach(function(row, index) {
var tr = tableBody.children[index];
tr.id = 'edit-row-' + index;
tr.style.cursor = 'pointer';
tr.onclick = function() {
this.classList.toggle('selected');
updateChart();
};
});
var leaderboardChart = new Chart(ctx, {
type: 'bar',
data: leaderboardData,
options: {
scales: {
yAxes: [{
scaleLabel: {
display: true,
},
ticks: {
beginAtZero: true
}
}]
}
}
});
updateChart();
});
{% include edit-leaderboard.js %}
</script>
<style>
tr.selected {
@@ -156,6 +86,8 @@ The refactoring benchmark requires a large context window to
work with large source files.
Therefore, results are available for fewer models.
<input type="text" id="refacSearchInput" placeholder="Search..." style="width: 100%; max-width: 800px; margin: 10px auto; padding: 8px; display: block; border: 1px solid #ddd; border-radius: 4px;">
<table style="width: 100%; max-width: 800px; margin: auto; border-collapse: collapse; box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 14px;">
<thead style="background-color: #f2f2f2;">
<tr>
@@ -183,79 +115,7 @@ Therefore, results are available for fewer models.
<canvas id="refacChart" width="800" height="450" style="margin-top: 20px"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var ctx = document.getElementById('refacChart').getContext('2d');
var leaderboardData = {
labels: [],
datasets: [{
label: 'Percent completed correctly',
data: [],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
};
var allData = [];
{% for row in refac_sorted %}
allData.push({
model: '{{ row.model }}',
pass_rate_1: {{ row.pass_rate_1 }},
percent_cases_well_formed: {{ row.percent_cases_well_formed }}
});
{% endfor %}
function updateChart() {
var selectedRows = document.querySelectorAll('tr.selected');
var showAll = selectedRows.length === 0;
leaderboardData.labels = [];
leaderboardData.datasets[0].data = [];
allData.forEach(function(row, index) {
var rowElement = document.getElementById('refac-row-' + index);
if (showAll) {
rowElement.classList.remove('selected');
}
if (showAll || rowElement.classList.contains('selected')) {
leaderboardData.labels.push(row.model);
leaderboardData.datasets[0].data.push(row.pass_rate_1);
}
});
leaderboardChart.update();
}
var tableBody = document.querySelectorAll('table tbody')[1];
allData.forEach(function(row, index) {
var tr = tableBody.children[index];
tr.id = 'refac-row-' + index;
tr.style.cursor = 'pointer';
tr.onclick = function() {
this.classList.toggle('selected');
updateChart();
};
});
var leaderboardChart = new Chart(ctx, {
type: 'bar',
data: leaderboardData,
options: {
scales: {
yAxes: [{
scaleLabel: {
display: true,
},
ticks: {
beginAtZero: true
}
}]
}
}
});
updateChart();
});
{% include refactor-leaderboard.js %}
</script>
@@ -321,6 +181,6 @@ mod_dates = [get_last_modified_date(file) for file in files]
latest_mod_date = max(mod_dates)
cog.out(f"{latest_mod_date.strftime('%B %d, %Y.')}")
]]]-->
October 04, 2024.
November 21, 2024.
<!--[[[end]]]-->
</p>

View File

@@ -0,0 +1,111 @@
Individual Contributor License Agreement
Thank you for your interest in Aider AI LLC ("Aider AI").
To clarify the intellectual property license
granted with Contributions from any person or entity, Aider AI
must have on file a signed Contributor License Agreement ("CLA")
from each Contributor, indicating agreement with the license
terms below. This agreement is for your protection as a Contributor
as well as the protection of Aider AI and its users. It does not
change your rights to use your own Contributions for any other purpose.
Please complete and sign this Agreement. Read this document carefully
before signing and keep a copy for your records.
You accept and agree to the following terms and conditions for Your
Contributions (present and future) that you submit to Aider AI.
Except for the license granted herein to Aider AI and recipients
of software distributed by Aider AI, You reserve all right, title,
and interest in and to Your Contributions.
1. Definitions.
"You" (or "Your") shall mean the copyright owner or legal entity
authorized by the copyright owner that is making this Agreement
with Aider AI. For legal entities, the entity making a
Contribution and all other entities that control, are controlled
by, or are under common control with that entity are considered to
be a single Contributor. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"Contribution" shall mean any original work of authorship,
including any modifications or additions to an existing work, that
is intentionally submitted by You to Aider AI for inclusion
in, or documentation of, any of the products owned or managed by
Aider AI (the "Work"). For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written
communication sent to Aider AI or its representatives,
including but not limited to communication on electronic mailing
lists, source code control systems, and issue tracking systems that
are managed by, or on behalf of, Aider AI for the purpose of
discussing and improving the Work, but excluding communication that
is conspicuously marked or otherwise designated in writing by You
as "Not a Contribution."
2. Grant of Copyright License. Subject to the terms and conditions of
this Agreement, You hereby grant to Aider AI and to
recipients of software distributed by Aider AI a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare derivative works of,
publicly display, publicly perform, sublicense, and distribute Your
Contributions and such derivative works.
3. Grant of Patent License. Subject to the terms and conditions of
this Agreement, You hereby grant to Aider AI and to
recipients of software distributed by Aider AI a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the
Work, where such license applies only to those patent claims
licensable by You that are necessarily infringed by Your
Contribution(s) alone or by combination of Your Contribution(s)
with the Work to which such Contribution(s) was submitted. If any
entity institutes patent litigation against You or any other entity
(including a cross-claim or counterclaim in a lawsuit) alleging
that your Contribution, or the Work to which you have contributed,
constitutes direct or contributory patent infringement, then any
patent licenses granted to that entity under this Agreement for
that Contribution or Work shall terminate as of the date such
litigation is filed.
4. You represent that you are legally entitled to grant the above
license. If your employer(s) has rights to intellectual property
that you create that includes your Contributions, you represent
that you have received permission to make Contributions on behalf
of that employer, that your employer has waived such rights for
your Contributions to Aider AI, or that your employer has
executed a separate Corporate CLA with Aider AI.
5. You represent that each of Your Contributions is Your original
creation (see section 7 for submissions on behalf of others). You
represent that Your Contribution submissions include complete
details of any third-party license or other restriction (including,
but not limited to, related patents and trademarks) of which you
are personally aware and which are associated with any part of Your
Contributions.
6. You are not expected to provide support for Your Contributions,
except to the extent You desire to provide support. You may provide
support for free, for a fee, or not at all. Unless required by
applicable law or agreed to in writing, You provide Your
Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied, including, without
limitation, any warranties or conditions of TITLE, NON-
INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
7. Should You wish to submit work that is not Your original creation,
You may submit it to Aider AI separately from any
Contribution, identifying the complete details of its source and of
any license or other restriction (including, but not limited to,
related patents, trademarks, and license agreements) of which you
are personally aware, and conspicuously marking the work as
"Submitted on behalf of a third-party: [named here]".
8. You agree to notify Aider AI of any facts or circumstances of
which you become aware that would make these representations
inaccurate in any respect.

View File

@@ -0,0 +1,104 @@
---
parent: More info
nav_order: 500
---
# Privacy policy
[Aider AI LLC](/docs/faq.html#what-is-aider-ai-llc)
(“Aider,” “we,” “our,” and/or “us”) values the privacy of individuals who use our website, programming tools, and related services (collectively, our “Services”). This privacy policy (the “Privacy Policy”) explains how we collect, use, and disclose information from users of our Services. By using our Services, you agree to the collection, use, disclosure, and procedures this Privacy Policy describes.
### Information We Collect
We may collect a variety of information from or about you or your devices from various sources, as described below.
### A. Information You Provide to Us.
**Communications.** If you contact us directly, we may receive additional information about you, such as your name, email address, the contents of a message or attachments that you may send to us, and other information you choose to provide.
### B. Information We Collect When You Use Our Services.
**Device Information.** We may receive information about the device and software you use to access our Services, including IP address, device type, device identifiers, web browser type and version, and operating system version.
**Usage Information.** We may automatically receive information about your interactions with our Services, like the pages or other content you view, referrer information (the website you visited before coming to our Services), and the dates and times of your visits.
**Analytics Information.** If you use our programming tools, we may receive information about your interactions with the tools, such as how often certain features or commands are used, information about exceptions and errors, and which large language models are used. This information is associated with a randomly generated identifier, not any directly identifiable user information such as your name or email address. Please see the “Your Choices” section below for information on how to disable the collection of this information.
**Information from Cookies and Other Tracking Technologies.** We and our third-party partners may collect information about your activities on our Services using cookies, pixel tags, SDKs, or other tracking technologies. Our third-party partners, such as analytics and security partners, may also use these technologies to collect information about your online activities over time and across different services.
### How We Use the Information We Collect
We use the information we collect:
- To provide, maintain, improve, and enhance our Services;
- To understand and analyze how you use our Services and develop new products, services, features, and functionality;
- To communicate with you, provide you with updates and other information relating to our Services, provide information that you request, respond to comments and questions, and otherwise provide customer support;
- To generate anonymized or aggregate data containing only de-identified, non-personal information that we may use for any lawful purposes such as to publish reports;
- To find and prevent fraud and abuse, and respond to trust and safety issues that may arise;
- For compliance purposes, including enforcing our legal rights, or as may be required by applicable laws and regulations or requested by any judicial process or governmental agency; and
- For other purposes for which we provide specific notice at the time the information is collected.
### How We Disclose the Information We Collect
**Affiliates.** We may disclose any information we receive to our current or future affiliates for any of the purposes described in this Privacy Policy.
**Vendors and Service Providers.** We may disclose any information we receive to vendors and service providers retained in connection with the provision of our Services.
**Analytics Partners.** We may use analytics services to collect and process certain analytics data to improve our Services, such as by improving the ability of our programming tools to work with LLMs, edit code, and complete user requests.
**As Required By Law and Similar Disclosures.** We may access, preserve, and disclose your information if we believe doing so is required or appropriate to: (a) comply with law enforcement requests and legal process, such as a court order or subpoena; (b) respond to your requests; or (c) protect your, our, or others rights, property, or safety. For the avoidance of doubt, the disclosure of your information may occur if you post any objectionable content on or through the Services.
**Merger, Sale, or Other Asset Transfers.** We may transfer your information to service providers, advisors, potential transactional partners, or other third parties in connection with the consideration, negotiation, or completion of a corporate transaction in which we are acquired by or merged with another company or we sell, liquidate, or transfer all or a portion of our assets. The use of your information following any of these events will be governed by the provisions of this Privacy Policy in effect at the time the applicable information was collected.
**Consent.** We may also disclose your information with your permission.
### Your Choices
**Analytics Information.** You can turn off analytics collection when using our programming tools. Please visit this
[documentation page](/docs/more/analytics.html)
for more information about the data collected and your options.
### Third Parties
Our Services may contain links to other websites, products, or services that we do not own or operate. We are not responsible for the privacy practices of these third parties. Please be aware that this Privacy Policy does not apply to your activities on these third-party services or any information you disclose to these third parties. We encourage you to read their privacy policies before providing any information to them.
### Security
We make reasonable efforts to protect your information by using physical and electronic safeguards designed to improve the security of the information we maintain. However, because no electronic transmission or storage of information can be entirely secure, we can make no guarantees as to the security or privacy of your information.
### Childrens Privacy
We do not knowingly collect, maintain, or use personal information from children under 18 years of age, and no part of our Service(s) is directed to children. If you learn that a child has provided us with personal information in violation of this Privacy Policy, then you may alert us at [INSERT EMAIL ADDRESS].
### International Visitors
Our Services are hosted in the United States and intended for visitors located within the United States. If you choose to use the Services from the European Union or other regions of the world with laws governing data collection and use that may differ from U.S. law, then please note that you are transferring your personal information outside of those regions to the U.S. for storage and processing. We may also transfer your data from the U.S. to other countries or regions in connection with storage and processing of data, fulfilling your requests, and operating the Services. By providing any information, including personal information, on or to the Services, you consent to such transfer, storage, and processing.
### Changes to this Privacy Policy
We will post any adjustments to the Privacy Policy on this page, and the revised version will be effective when it is posted. If we materially change the ways in which we use or disclose personal information previously collected from you through the Services, we will notify you through the Services, by email, or other communication.
### Contact Information
If you have any questions, comments, or concerns about our processing activities, please email us at privacy@aider.chat.
----
<p class="post-date">
Last updated
<!--[[[cog
import subprocess
import datetime
result = subprocess.run(['git', 'log', '-1', '--format=%ct', 'aider/website/docs/legal/privacy.md'], capture_output=True, text=True)
if result.returncode == 0:
timestamp = int(result.stdout.strip())
date = datetime.datetime.fromtimestamp(timestamp)
cog.out(f"{date.strftime('%B %d, %Y.')}")
]]]-->
October 31, 2024.
<!--[[[end]]]-->
</p>

View File

@@ -39,6 +39,14 @@ export AWS_PROFILE=your-profile
You can add these to your
[.env file](/docs/config/dotenv.html).
## Bedrock with `pipx` installation
The AWS Bedrock provider requires the `boto3` package in order to function correctly. To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dependency to aider's virtual environment by running
```
pipx inject aider boto3
```
## Running Aider with Bedrock

View File

@@ -22,12 +22,18 @@ setx OPENAI_API_KEY <key> # Windows, restart shell after setx
# Aider uses gpt-4o by default (or use --4o)
aider
# GPT-4 Turbo (1106)
aider --4-turbo
# GPT-4o
aider --4o
# GPT-3.5 Turbo
aider --35-turbo
# o1-mini
aider --model o1-mini
# o1-preview
aider --model o1-preview
# List models available from OpenAI
aider --list-models openai/
```

View File

@@ -84,16 +84,17 @@ cog.out(''.join(lines))
- NVIDIA_NIM_API_KEY
- OLLAMA_API_KEY
- OPENAI_API_KEY
- OPENAI_LIKE_API_KEY
- OPENROUTER_API_KEY
- OR_API_KEY
- PALM_API_KEY
- PERPLEXITYAI_API_KEY
- PREDIBASE_API_KEY
- PROVIDER_API_KEY
- QDRANT_API_KEY
- REPLICATE_API_KEY
- TOGETHERAI_API_KEY
- VOLCENGINE_API_KEY
- VOYAGE_API_KEY
- XAI_API_KEY
- XINFERENCE_API_KEY
<!--[[[end]]]-->

View File

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

View File

@@ -0,0 +1,122 @@
---
parent: More info
nav_order: 500
description: Opt-in, anonymous, no personal info.
---
# Analytics
Aider can collect anonymous analytics to help
improve aider's ability to work with LLMs, edit code and complete user requests.
## Opt-in, anonymous, no personal info
Analytics are only collected if you agree and opt-in.
Aider respects your privacy and never collects your code, chat messages, keys or
personal info.
Aider collects information on:
- which LLMs are used and with how many tokens,
- which of aider's edit formats are used,
- how often features and commands are used,
- information about exceptions and errors,
- etc
These analytics are associated with an anonymous,
randomly generated UUID4 user identifier.
This information helps improve aider by identifying which models, edit formats,
features and commands are most used.
It also helps uncover bugs that users are experiencing, so that they can be fixed
in upcoming releases.
## Disabling analytics
You can opt out of analytics forever by running this command one time:
```
aider --analytics-disable
```
## Enabling analytics
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
Aider respects your privacy and never collects your code, prompts, chats, keys or any personal
info.
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 say "no", analytics will be permanently disabled.
## Details about data being collected
### Sample analytics data
To get a better sense of what type of data is collected, you can review some
[sample analytics logs](https://github.com/aider-ai/aider/blob/main/aider/website/assets/sample-analytics.jsonl).
These are the last 1,000 analytics events from the author's
personal use of aider, updated regularly.
### Analytics code
Since aider is open source, all the places where aider collects analytics
are visible in the source code.
They can be viewed using
[GitHub search](https://github.com/search?q=repo%3Aaider-ai%2Faider+%22.event%28%22&type=code).
### Logging and inspecting analytics
You can get a full log of the analytics that aider is collecting,
in case you would like to audit or inspect this data.
```
aider --analytics-log filename.jsonl
```
If you want to just log analytics without reporting them, you can do:
```
aider --analytics-log filename.jsonl --no-analytics
```
## Reporting issues
If you have concerns about any of the analytics that aider is collecting
or our data practices
please contact us by opening a
[GitHub Issue](https://github.com/aider-ai/aider/issues).
## Privacy policy
Please see aider's
[privacy policy](/docs/legal/privacy.html)
for more details.

View File

@@ -1,6 +1,6 @@
---
parent: More info
nav_order: 960
nav_order: 490
description: Aider uses various "edit formats" to let LLMs edit source files.
---

View File

@@ -1,6 +1,6 @@
---
parent: More info
nav_order: 920
nav_order: 480
description: Aider can handle "infinite output" from models that support prefill.
---
@@ -55,7 +55,11 @@ model_list = "\n".join(f"- {model}" for model in sorted(prefill_models))
cog.out(model_list)
]]]-->
- anthropic.claude-3-5-haiku-20241022-v1:0
- anthropic.claude-3-5-sonnet-20241022-v2:0
- claude-3-5-haiku-20241022
- claude-3-5-sonnet-20240620
- claude-3-5-sonnet-20241022
- claude-3-haiku-20240307
- claude-3-opus-20240229
- claude-3-sonnet-20240229
@@ -63,6 +67,7 @@ cog.out(model_list)
- codestral/codestral-latest
- deepseek-chat
- deepseek-coder
- eu.anthropic.claude-3-5-sonnet-20241022-v2:0
- mistral/codestral-2405
- mistral/codestral-latest
- mistral/codestral-mamba-latest
@@ -83,9 +88,19 @@ cog.out(model_list)
- mistral/open-mixtral-8x7b
- mistral/pixtral-12b-2409
- openrouter/anthropic/claude-3.5-sonnet
- us.anthropic.claude-3-5-haiku-20241022-v1:0
- us.anthropic.claude-3-5-sonnet-20241022-v2:0
- vertex_ai/claude-3-5-haiku
- vertex_ai/claude-3-5-haiku@20241022
- vertex_ai/claude-3-5-sonnet
- vertex_ai/claude-3-5-sonnet-v2
- vertex_ai/claude-3-5-sonnet-v2@20241022
- vertex_ai/claude-3-5-sonnet@20240620
- vertex_ai/claude-3-haiku
- vertex_ai/claude-3-haiku@20240307
- vertex_ai/claude-3-opus
- vertex_ai/claude-3-opus@20240229
- vertex_ai/claude-3-sonnet
- vertex_ai/claude-3-sonnet@20240229
<!--[[[end]]]-->

View File

@@ -1,7 +1,7 @@
---
parent: More info
highlight_image: /assets/robot-ast.png
nav_order: 900
nav_order: 300
description: Aider uses a map of your git repository to provide code context to LLMs.
---

View File

@@ -1,6 +1,6 @@
---
parent: More info
nav_order: 900
nav_order: 400
description: You can script aider via the command line or python.
---
@@ -95,3 +95,6 @@ io = InputOutput(yes=True)
coder = Coder.create(model=model, fnames=fnames, io=io)
```
{: .note }
The scripting API is not officially supported or documented and may
change without warning.

View File

@@ -19,7 +19,19 @@ LLM edits that are "almost" correctly formatted.
But sometimes the LLM just won't cooperate.
In these cases, here are some things you might try.
## Use a capable model
## Don't add too many files
Many LLMs now have very large context windows,
but filling them with irrelevant code or conversation
can confuse the model.
- Don't add too many files to the chat, *just* add the files you think need to be edited.
Aider also sends the LLM a [map of your entire git repo](https://aider.chat/docs/repomap.html), so other relevant code will be included automatically.
- Use `/drop` to remove files from the chat session which aren't needed for the task at hand. This will reduce distractions and may help the LLM produce properly formatted edits.
- Use `/clear` to remove the conversation history, again to help the LLM focus.
- Use `/tokens` to see how many tokens you are using for each message.
## Use a more capable model
If possible try using GPT-4o, Claude 3.5 Sonnet or Claude 3 Opus,
as they are the strongest and most capable models.
@@ -33,9 +45,9 @@ so editing errors are probably unavoidable.
Local models which have been quantized are even more likely to have problems
because they are not capable enough to follow aider's system prompts.
## Try the whole format
## Try the whole edit format
Run aider with `--edit-format whole` if the model is using a different edit format.
Run aider with `--edit-format whole` if were using a different edit format.
You can see which edit format it is using in the announce lines:
```
@@ -43,17 +55,6 @@ Aider v0.50.2-dev
Models: claude-3-5-sonnet-20240620 with ♾️ diff edit format
```
## Reduce distractions
Many LLMs now have very large context windows,
but filling them with irrelevant code or conversation
can confuse the model.
- Don't add too many files to the chat, *just* add the files you think need to be edited.
Aider also sends the LLM a [map of your entire git repo](https://aider.chat/docs/repomap.html), so other relevant code will be included automatically.
- Use `/drop` to remove files from the chat session which aren't needed for the task at hand. This will reduce distractions and may help the LLM produce properly formatted edits.
- Use `/clear` to remove the conversation history, again to help the LLM focus.
- Use `/tokens` to see how many tokens you are using for each message.
## More help

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,10 +31,12 @@ 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 |
| **/lint** | Lint and fix in-chat files or all dirty files if none in chat |
| **/load** | Load and execute commands from a file |
| **/ls** | List all known files and indicate which are included in the chat session |
| **/map** | Print out the current repository map |
| **/map-refresh** | Force a refresh of the repository map |
@@ -39,6 +48,7 @@ cog.out(get_help_md())
| **/report** | Report a problem by opening a GitHub Issue |
| **/reset** | Drop all files and clear the chat history |
| **/run** | Run a shell command and optionally add the output to the chat (alias: !) |
| **/save** | Save commands to a file that can reconstruct the current chat session's files |
| **/settings** | Print out the current settings |
| **/test** | Run a shell command and add the output to the chat on non-zero exit code |
| **/tokens** | Report on the number of tokens used by the current chat context |
@@ -67,6 +77,8 @@ The interactive prompt is built with [prompt-toolkit](https://github.com/prompt-
### Emacs
- `Up Arrow` : Scroll back through previously sent messages.
- `Down Arrow` : Scroll forward through previously sent messages.
- `Ctrl-A` : Move cursor to the start of the line.
- `Ctrl-B` : Move cursor back one character.
- `Ctrl-D` : Delete the character under the cursor.
@@ -83,6 +95,8 @@ The interactive prompt is built with [prompt-toolkit](https://github.com/prompt-
To use vi/vim keybindings, run aider with the `--vim` switch.
- `Up Arrow` : Scroll back through previously sent messages.
- `Down Arrow` : Scroll forward through previously sent messages.
- `Esc` : Switch to command mode.
- `i` : Switch to insert mode.
- `a` : Move cursor one character to the right and switch to insert mode.

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

@@ -4,15 +4,15 @@
#
# pip-compile --output-file=requirements.txt requirements/requirements.in
#
aiohappyeyeballs==2.4.0
aiohappyeyeballs==2.4.3
# via aiohttp
aiohttp==3.10.5
aiohttp==3.11.2
# via litellm
aiosignal==1.3.1
# via aiohttp
annotated-types==0.7.0
# via pydantic
anyio==4.6.0
anyio==4.6.2.post1
# via
# httpx
# openai
@@ -22,7 +22,9 @@ attrs==24.2.0
# jsonschema
# referencing
backoff==2.2.1
# via -r requirements/requirements.in
# via
# -r requirements/requirements.in
# posthog
beautifulsoup4==4.12.3
# via -r requirements/requirements.in
certifi==2024.8.30
@@ -34,13 +36,13 @@ cffi==1.17.1
# via
# sounddevice
# soundfile
charset-normalizer==3.3.2
charset-normalizer==3.4.0
# via requests
click==8.1.7
# via litellm
configargparse==1.7
# via -r requirements/requirements.in
diff-match-patch==20230430
diff-match-patch==20241021
# via -r requirements/requirements.in
diskcache==5.6.3
# via -r requirements/requirements.in
@@ -50,11 +52,11 @@ filelock==3.16.1
# via huggingface-hub
flake8==7.1.1
# via -r requirements/requirements.in
frozenlist==1.4.1
frozenlist==1.5.0
# via
# aiohttp
# aiosignal
fsspec==2024.9.0
fsspec==2024.10.0
# via huggingface-hub
gitdb==4.0.11
# via gitpython
@@ -64,11 +66,11 @@ grep-ast==0.3.3
# via -r requirements/requirements.in
h11==0.14.0
# via httpcore
httpcore==1.0.5
httpcore==1.0.6
# via httpx
httpx==0.27.2
# via openai
huggingface-hub==0.25.0
huggingface-hub==0.26.2
# via tokenizers
idna==3.10
# via
@@ -84,26 +86,30 @@ importlib-resources==6.4.5
# via -r requirements/requirements.in
jinja2==3.1.4
# via litellm
jiter==0.5.0
jiter==0.7.1
# via openai
json5==0.9.25
json5==0.9.28
# via -r requirements/requirements.in
jsonschema==4.23.0
# via
# -r requirements/requirements.in
# litellm
jsonschema-specifications==2023.12.1
jsonschema-specifications==2024.10.1
# via jsonschema
litellm==1.47.0
litellm==1.52.8
# via -r requirements/requirements.in
markdown-it-py==3.0.0
# via rich
markupsafe==2.1.5
markupsafe==3.0.2
# via jinja2
mccabe==0.7.0
# via flake8
mdurl==0.1.2
# via markdown-it-py
mixpanel==4.10.1
# via -r requirements/requirements.in
monotonic==1.6
# via posthog
multidict==6.1.0
# via
# aiohttp
@@ -114,9 +120,9 @@ numpy==1.26.4
# via
# -r requirements/requirements.in
# scipy
openai==1.47.0
openai==1.54.4
# via litellm
packaging==24.1
packaging==24.2
# via
# -r requirements/requirements.in
# huggingface-hub
@@ -128,9 +134,15 @@ pexpect==4.9.0
# via -r requirements/requirements.in
pillow==10.4.0
# via -r requirements/requirements.in
prompt-toolkit==3.0.47
posthog==3.7.0
# via -r requirements/requirements.in
psutil==6.0.0
prompt-toolkit==3.0.48
# via -r requirements/requirements.in
propcache==0.2.0
# via
# aiohttp
# yarl
psutil==6.1.0
# via -r requirements/requirements.in
ptyprocess==0.7.0
# via pexpect
@@ -150,10 +162,12 @@ pyflakes==3.2.0
# via flake8
pygments==2.18.0
# via rich
pypandoc==1.13
pypandoc==1.14
# via -r requirements/requirements.in
pyperclip==1.9.0
# via -r requirements/requirements.in
python-dateutil==2.9.0.post0
# via posthog
python-dotenv==1.0.1
# via litellm
pyyaml==6.0.2
@@ -164,21 +178,28 @@ referencing==0.35.1
# via
# jsonschema
# jsonschema-specifications
regex==2024.9.11
regex==2024.11.6
# via tiktoken
requests==2.32.3
# via
# huggingface-hub
# litellm
# mixpanel
# posthog
# tiktoken
rich==13.8.1
rich==13.9.4
# via -r requirements/requirements.in
rpds-py==0.20.0
rpds-py==0.21.0
# via
# jsonschema
# referencing
scipy==1.13.1
# via -r requirements/requirements.in
six==1.16.0
# via
# mixpanel
# posthog
# python-dateutil
smmap==5.0.1
# via gitdb
sniffio==1.3.1
@@ -186,19 +207,19 @@ sniffio==1.3.1
# anyio
# httpx
# openai
sounddevice==0.5.0
sounddevice==0.5.1
# via -r requirements/requirements.in
soundfile==0.12.1
# via -r requirements/requirements.in
soupsieve==2.6
# via beautifulsoup4
tiktoken==0.7.0
tiktoken==0.8.0
# via litellm
tokenizers==0.19.1
# via
# -r requirements/requirements.in
# litellm
tqdm==4.66.5
tqdm==4.67.0
# via
# huggingface-hub
# openai
@@ -215,10 +236,12 @@ typing-extensions==4.12.2
# pydantic
# pydantic-core
urllib3==2.2.3
# via requests
# via
# mixpanel
# requests
wcwidth==0.2.13
# via prompt-toolkit
yarl==1.11.1
yarl==1.17.1
# via aiohttp
zipp==3.20.2
zipp==3.21.0
# via importlib-metadata

View File

@@ -2,144 +2,212 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-browser.txt requirements/requirements-browser.in
#
altair==5.4.1
# via streamlit
attrs==24.2.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-help.txt
# jsonschema
# referencing
blinker==1.8.2
blinker==1.9.0
# via streamlit
cachetools==5.5.0
# via streamlit
certifi==2024.8.30
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
charset-normalizer==3.3.2
charset-normalizer==3.4.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
click==8.1.7
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
gitdb==4.0.11
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# gitpython
gitpython==3.1.43
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# streamlit
idna==3.10
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
jinja2==3.1.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# altair
# pydeck
jsonschema==4.23.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# altair
jsonschema-specifications==2023.12.1
jsonschema-specifications==2024.10.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# jsonschema
markdown-it-py==3.0.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# rich
markupsafe==2.1.5
markupsafe==3.0.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# jinja2
mdurl==0.1.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# markdown-it-py
narwhals==1.8.2
narwhals==1.13.5
# via altair
numpy==1.26.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# pandas
# pyarrow
# pydeck
# streamlit
packaging==24.1
packaging==24.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# altair
# streamlit
pandas==2.2.3
# via streamlit
# via
# -c requirements/requirements-dev.txt
# streamlit
pillow==10.4.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
protobuf==5.28.2
protobuf==5.28.3
# via streamlit
pyarrow==17.0.0
pyarrow==18.0.0
# via streamlit
pydeck==0.9.1
# via streamlit
pygments==2.18.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# rich
python-dateutil==2.9.0.post0
# via pandas
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# pandas
pytz==2024.2
# via pandas
# via
# -c requirements/requirements-dev.txt
# pandas
referencing==0.35.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# jsonschema
# jsonschema-specifications
requests==2.32.3
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# streamlit
rich==13.8.1
rich==13.9.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# streamlit
rpds-py==0.20.0
rpds-py==0.21.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# jsonschema
# referencing
six==1.16.0
# via python-dateutil
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# python-dateutil
smmap==5.0.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# gitdb
streamlit==1.38.0
streamlit==1.40.1
# via -r requirements/requirements-browser.in
tenacity==8.5.0
# via streamlit
# via
# -c requirements/requirements-help.txt
# streamlit
toml==0.10.2
# via streamlit
tornado==6.4.1
# via streamlit
typing-extensions==4.12.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# altair
# streamlit
tzdata==2024.1
# via pandas
tzdata==2024.2
# via
# -c requirements/requirements-dev.txt
# pandas
urllib3==2.2.3
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# requests
watchdog==4.0.2
# via -r requirements/requirements-browser.in

View File

@@ -2,26 +2,29 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in
# pip-compile --constraint=requirements.txt --output-file=requirements/requirements-dev.txt requirements/requirements-dev.in
#
alabaster==0.7.16
alabaster==1.0.0
# via sphinx
babel==2.16.0
# via sphinx
build==1.2.2
build==1.2.2.post1
# via pip-tools
certifi==2024.8.30
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
cfgv==3.4.0
# via pre-commit
charset-normalizer==3.3.2
charset-normalizer==3.4.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
click==8.1.7
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# pip-tools
# typer
@@ -29,30 +32,32 @@ codespell==2.3.0
# via -r requirements/requirements-dev.in
cogapp==3.4.1
# via -r requirements/requirements-dev.in
contourpy==1.3.0
contourpy==1.3.1
# via matplotlib
cycler==0.12.1
# via matplotlib
dill==0.3.8
dill==0.3.9
# via
# multiprocess
# pathos
distlib==0.3.8
distlib==0.3.9
# via virtualenv
docutils==0.20.1
docutils==0.21.2
# via
# sphinx
# sphinx-rtd-theme
filelock==3.16.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# virtualenv
fonttools==4.53.1
fonttools==4.55.0
# via matplotlib
identify==2.6.1
identify==2.6.2
# via pre-commit
idna==3.10
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
imagesize==1.4.1
@@ -63,6 +68,7 @@ iniconfig==2.0.0
# via pytest
jinja2==3.1.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# sphinx
kiwisolver==1.4.7
@@ -71,30 +77,35 @@ lox==0.12.0
# via -r requirements/requirements-dev.in
markdown-it-py==3.0.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# rich
markupsafe==2.1.5
markupsafe==3.0.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# jinja2
matplotlib==3.9.2
# via -r requirements/requirements-dev.in
mdurl==0.1.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# markdown-it-py
multiprocess==0.70.16
multiprocess==0.70.17
# via pathos
nodeenv==1.9.1
# via pre-commit
numpy==1.26.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# contourpy
# matplotlib
# pandas
packaging==24.1
packaging==24.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# build
# matplotlib
@@ -102,10 +113,11 @@ packaging==24.1
# sphinx
pandas==2.2.3
# via -r requirements/requirements-dev.in
pathos==0.3.2
pathos==0.3.3
# via lox
pillow==10.4.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# matplotlib
pip-tools==7.4.1
@@ -114,20 +126,21 @@ platformdirs==4.3.6
# via virtualenv
pluggy==1.5.0
# via pytest
pox==0.3.4
pox==0.3.5
# via pathos
ppft==1.7.6.8
ppft==1.7.6.9
# via pathos
pre-commit==3.8.0
pre-commit==4.0.1
# via -r requirements/requirements-dev.in
pygments==2.18.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# rich
# sphinx
pyparsing==3.1.4
pyparsing==3.2.0
# via matplotlib
pyproject-hooks==1.1.0
pyproject-hooks==1.2.0
# via
# build
# pip-tools
@@ -135,20 +148,25 @@ pytest==8.3.3
# via -r requirements/requirements-dev.in
python-dateutil==2.9.0.post0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# matplotlib
# pandas
pytz==2024.2
# via pandas
pyyaml==6.0.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# pre-commit
requests==2.32.3
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# sphinx
rich==13.8.1
rich==13.9.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# typer
semver==3.0.2
@@ -156,14 +174,17 @@ semver==3.0.2
shellingham==1.5.4
# via typer
six==1.16.0
# via python-dateutil
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# python-dateutil
snowballstemmer==2.2.0
# via sphinx
sphinx==7.4.7
sphinx==8.1.3
# via
# sphinx-rtd-theme
# sphinxcontrib-jquery
sphinx-rtd-theme==2.0.0
sphinx-rtd-theme==3.0.2
# via lox
sphinxcontrib-applehelp==2.0.0
# via sphinx
@@ -179,21 +200,23 @@ sphinxcontrib-qthelp==2.0.0
# via sphinx
sphinxcontrib-serializinghtml==2.0.0
# via sphinx
typer==0.12.5
typer==0.13.0
# via -r requirements/requirements-dev.in
typing-extensions==4.12.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# typer
tzdata==2024.1
tzdata==2024.2
# via pandas
urllib3==2.2.3
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# requests
virtualenv==20.26.5
virtualenv==20.27.1
# via pre-commit
wheel==0.44.0
wheel==0.45.0
# via pip-tools
# The following packages are considered to be unsafe in a requirements file:

View File

@@ -2,46 +2,58 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --output-file=requirements/requirements-help.txt requirements/requirements-help.in
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-dev.txt --output-file=requirements/requirements-help.txt requirements/requirements-help.in
#
aiohappyeyeballs==2.4.0
aiohappyeyeballs==2.4.3
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
aiohttp==3.10.5
aiohttp==3.11.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# huggingface-hub
# llama-index-core
aiosignal==1.3.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
annotated-types==0.7.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# pydantic
anyio==4.6.0
anyio==4.6.2.post1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# httpx
attrs==24.2.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
certifi==2024.8.30
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# httpcore
# httpx
# requests
charset-normalizer==3.3.2
charset-normalizer==3.4.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# requests
click==8.1.7
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# nltk
dataclasses-json==0.6.7
# via llama-index-core
@@ -51,17 +63,23 @@ dirtyjson==1.0.8
# via llama-index-core
filelock==3.16.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# torch
# transformers
frozenlist==1.4.1
filetype==1.2.0
# via llama-index-core
frozenlist==1.5.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
# aiosignal
fsspec==2024.9.0
fsspec==2024.10.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# huggingface-hub
# llama-index-core
@@ -72,18 +90,22 @@ greenlet==3.0.3
# sqlalchemy
h11==0.14.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# httpcore
httpcore==1.0.5
httpcore==1.0.6
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# httpx
httpx==0.27.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
huggingface-hub[inference]==0.25.0
huggingface-hub[inference]==0.26.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-embeddings-huggingface
# sentence-transformers
@@ -91,37 +113,42 @@ huggingface-hub[inference]==0.25.0
# transformers
idna==3.10
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# anyio
# httpx
# requests
# yarl
jinja2==3.1.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# torch
joblib==1.4.2
# via
# nltk
# scikit-learn
llama-index-core==0.11.11
llama-index-core==0.11.23
# via
# -r requirements/requirements-help.in
# llama-index-embeddings-huggingface
llama-index-embeddings-huggingface==0.3.1
# via -r requirements/requirements-help.in
markupsafe==2.1.5
markupsafe==3.0.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# jinja2
marshmallow==3.22.0
marshmallow==3.23.1
# via dataclasses-json
minijinja==2.2.0
# via huggingface-hub
mpmath==1.3.0
# via sympy
multidict==6.1.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
# yarl
@@ -131,6 +158,7 @@ nest-asyncio==1.6.0
# via llama-index-core
networkx==3.2.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
# torch
@@ -138,45 +166,64 @@ nltk==3.9.1
# via llama-index-core
numpy==1.26.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# llama-index-core
# scikit-learn
# scipy
# transformers
packaging==24.1
packaging==24.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# marshmallow
# transformers
pillow==10.4.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# llama-index-core
# sentence-transformers
propcache==0.2.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp
# yarl
pydantic==2.9.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
pydantic-core==2.23.4
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# pydantic
pyyaml==6.0.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# llama-index-core
# transformers
regex==2024.9.11
regex==2024.11.6
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# nltk
# tiktoken
# transformers
requests==2.32.3
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# llama-index-core
# tiktoken
@@ -187,17 +234,19 @@ scikit-learn==1.5.2
# via sentence-transformers
scipy==1.13.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# scikit-learn
# sentence-transformers
sentence-transformers==3.1.1
sentence-transformers==3.3.0
# via llama-index-embeddings-huggingface
sniffio==1.3.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# anyio
# httpx
sqlalchemy[asyncio]==2.0.35
sqlalchemy[asyncio]==2.0.36
# via
# llama-index-core
# sqlalchemy
@@ -207,18 +256,21 @@ tenacity==8.5.0
# via llama-index-core
threadpoolctl==3.5.0
# via scikit-learn
tiktoken==0.7.0
tiktoken==0.8.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# llama-index-core
tokenizers==0.19.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# transformers
torch==2.2.2
# via sentence-transformers
tqdm==4.66.5
tqdm==4.67.0
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# huggingface-hub
# llama-index-core
@@ -229,7 +281,9 @@ transformers==4.44.2
# via sentence-transformers
typing-extensions==4.12.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# huggingface-hub
# llama-index-core
# pydantic
@@ -243,13 +297,16 @@ typing-inspect==0.9.0
# llama-index-core
urllib3==2.2.3
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-dev.txt
# requests
wrapt==1.16.0
# via
# deprecated
# llama-index-core
yarl==1.11.1
yarl==1.17.1
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# aiohttp

View File

@@ -2,10 +2,11 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --output-file=requirements/requirements-playwright.txt requirements/requirements-playwright.in
# pip-compile --constraint=requirements.txt --constraint=requirements/requirements-browser.txt --constraint=requirements/requirements-dev.txt --constraint=requirements/requirements-help.txt --output-file=requirements/requirements-playwright.txt requirements/requirements-playwright.in
#
greenlet==3.0.3
# via
# -c requirements/requirements-help.txt
# -r requirements/requirements-playwright.in
# playwright
playwright==1.47.0
@@ -14,5 +15,9 @@ pyee==12.0.0
# via playwright
typing-extensions==4.12.2
# via
# -c requirements.txt
# -c requirements/../requirements.txt
# -c requirements/requirements-browser.txt
# -c requirements/requirements-dev.txt
# -c requirements/requirements-help.txt
# pyee

View File

@@ -17,13 +17,14 @@ sounddevice
soundfile
beautifulsoup4
PyYAML
Pillow
diff-match-patch
pypandoc
litellm
flake8
importlib_resources
pyperclip
posthog
mixpanel
pexpect
json5
psutil
@@ -55,3 +56,6 @@ numpy<2
# Going past this makes dependencies unresolvable
# Seems to be caused by sentence-transformers
tokenizers==0.19.1
# streamlit 1.39.0 depends on this, as far back as 1.22 which is ancient and doesn't have chat ui
Pillow<11

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

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

View File

@@ -3,16 +3,23 @@
# exit when any command fails
set -e
# First compile the base requirements
pip-compile \
requirements/requirements.in \
--output-file=requirements.txt \
$1
for SUFFIX in dev help browser playwright; do
# Then compile each additional requirements file in sequence
SUFFIXES=(dev help browser playwright)
CONSTRAINTS="--constraint=requirements.txt"
for SUFFIX in "${SUFFIXES[@]}"; do
pip-compile \
requirements/requirements-${SUFFIX}.in \
--output-file=requirements/requirements-${SUFFIX}.txt \
${CONSTRAINTS} \
$1
done
# Add this file as a constraint for the next iteration
CONSTRAINTS+=" --constraint=requirements/requirements-${SUFFIX}.txt"
done

View File

@@ -9,6 +9,10 @@ else
ARG=$1
fi
if [ "$ARG" != "--check" ]; then
tail -1000 ~/.aider/analytics.jsonl > aider/website/assets/sample-analytics.jsonl
fi
# README.md before index.md, because index.md uses cog to include README.md
cog $ARG \
README.md \
@@ -22,4 +26,5 @@ cog $ARG \
aider/website/docs/config/adv-model-settings.md \
aider/website/docs/leaderboards/index.md \
aider/website/docs/llms/other.md \
aider/website/docs/more/infinite-output.md
aider/website/docs/more/infinite-output.md \
aider/website/docs/legal/privacy.md

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

@@ -0,0 +1,139 @@
import json
import os
import tempfile
from pathlib import Path
from unittest.mock import patch
import pytest
from aider.analytics import Analytics
@pytest.fixture
def temp_analytics_file():
with tempfile.NamedTemporaryFile(delete=False) as f:
yield f.name
os.unlink(f.name)
@pytest.fixture
def temp_data_dir(monkeypatch):
with tempfile.TemporaryDirectory() as tmpdir:
temp_dir = Path(tmpdir)
monkeypatch.setattr(Path, "home", lambda: temp_dir)
yield temp_dir
def test_analytics_initialization(temp_data_dir):
analytics = Analytics(permanently_disable=True)
assert analytics.mp is None
assert analytics.ph is None
assert analytics.permanently_disable is True
assert analytics.user_id is not None
def test_analytics_enable_disable(temp_data_dir):
analytics = Analytics()
analytics.asked_opt_in = True
analytics.enable()
assert analytics.mp is not None
assert analytics.ph is not None
analytics.disable(permanently=False)
assert analytics.mp is None
assert analytics.ph is None
assert analytics.permanently_disable is not True
analytics.disable(permanently=True)
assert analytics.permanently_disable is True
def test_analytics_data_persistence(temp_data_dir):
analytics1 = Analytics()
user_id = analytics1.user_id
analytics2 = Analytics()
assert analytics2.user_id == user_id
def test_analytics_event_logging(temp_analytics_file, temp_data_dir):
analytics = Analytics(logfile=temp_analytics_file)
analytics.asked_opt_in = True
analytics.enable()
test_event = "test_event"
test_properties = {"test_key": "test_value"}
with patch.object(analytics.mp, "track") as mock_mp_track:
with patch.object(analytics.ph, "capture") as mock_ph_capture:
analytics.event(test_event, **test_properties)
mock_mp_track.assert_called_once()
mock_ph_capture.assert_called_once()
# Verify logfile
with open(temp_analytics_file) as f:
log_entry = json.loads(f.read().strip())
assert log_entry["event"] == test_event
assert "test_key" in log_entry["properties"]
def test_system_info(temp_data_dir):
analytics = Analytics()
sys_info = analytics.get_system_info()
assert "python_version" in sys_info
assert "os_platform" in sys_info
assert "os_release" in sys_info
assert "machine" in sys_info
def test_need_to_ask(temp_data_dir):
analytics = Analytics()
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(True) is False
analytics.permanently_disable = True
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

@@ -17,6 +17,8 @@ from aider.utils import GitTemporaryDirectory
class TestCoder(unittest.TestCase):
def setUp(self):
self.GPT35 = Model("gpt-3.5-turbo")
self.webbrowser_patcher = patch("aider.io.webbrowser.open")
self.mock_webbrowser = self.webbrowser_patcher.start()
def test_allowed_to_edit(self):
with GitTemporaryDirectory():

View File

@@ -1,5 +1,6 @@
import codecs
import os
import re
import shutil
import sys
import tempfile
@@ -33,7 +34,7 @@ class TestCommands(TestCase):
def test_cmd_add(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -48,7 +49,7 @@ class TestCommands(TestCase):
def test_cmd_copy(self):
# Initialize InputOutput and Coder instances
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -78,7 +79,7 @@ class TestCommands(TestCase):
def test_cmd_copy_with_cur_messages(self):
# Initialize InputOutput and Coder instances
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -108,7 +109,7 @@ class TestCommands(TestCase):
" cur_messages"
)
mock_tool_output.assert_any_call(expected_preview)
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -124,7 +125,7 @@ class TestCommands(TestCase):
mock_tool_error.assert_called_once_with("No assistant messages found to copy.")
def test_cmd_copy_pyperclip_exception(self):
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -147,7 +148,7 @@ class TestCommands(TestCase):
def test_cmd_add_bad_glob(self):
# https://github.com/Aider-AI/aider/issues/293
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -157,7 +158,7 @@ class TestCommands(TestCase):
def test_cmd_add_with_glob_patterns(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -183,7 +184,7 @@ class TestCommands(TestCase):
def test_cmd_add_no_match(self):
# yes=False means we will *not* create the file when it is not found
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -197,7 +198,7 @@ class TestCommands(TestCase):
def test_cmd_add_no_match_but_make_it(self):
# yes=True means we *will* create the file when it is not found
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -214,7 +215,7 @@ class TestCommands(TestCase):
def test_cmd_add_drop_directory(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -265,7 +266,7 @@ class TestCommands(TestCase):
def test_cmd_drop_with_glob_patterns(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -292,7 +293,7 @@ class TestCommands(TestCase):
def test_cmd_add_bad_encoding(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -308,7 +309,7 @@ class TestCommands(TestCase):
def test_cmd_git(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
with GitTemporaryDirectory() as tempdir:
# Create a file in the temporary directory
@@ -329,7 +330,7 @@ class TestCommands(TestCase):
def test_cmd_tokens(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -371,7 +372,7 @@ class TestCommands(TestCase):
os.chdir("subdir")
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -387,7 +388,7 @@ class TestCommands(TestCase):
def test_cmd_add_from_subdir_again(self):
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -413,7 +414,7 @@ class TestCommands(TestCase):
repo.git.add(fname)
repo.git.commit("-m", "initial")
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -432,7 +433,7 @@ class TestCommands(TestCase):
root.mkdir()
os.chdir(str(root))
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -455,7 +456,7 @@ class TestCommands(TestCase):
make_repo()
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -473,7 +474,7 @@ class TestCommands(TestCase):
def test_cmd_add_filename_with_special_chars(self):
with ChdirTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -498,7 +499,7 @@ class TestCommands(TestCase):
repo.git.add(A=True)
repo.git.commit("-m", "Initial commit")
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(Model("claude-3-5-sonnet-20240620"), None, io)
@@ -538,7 +539,7 @@ class TestCommands(TestCase):
def test_cmd_add_dirname_with_special_chars(self):
with ChdirTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -556,7 +557,7 @@ class TestCommands(TestCase):
def test_cmd_add_dirname_with_special_chars_git(self):
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -578,7 +579,7 @@ class TestCommands(TestCase):
def test_cmd_add_abs_filename(self):
with ChdirTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -593,7 +594,7 @@ class TestCommands(TestCase):
def test_cmd_add_quoted_filename(self):
with ChdirTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -621,7 +622,7 @@ class TestCommands(TestCase):
# leave a dirty `git rm`
repo.git.rm("one.txt")
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -642,9 +643,269 @@ class TestCommands(TestCase):
del commands
del repo
def test_cmd_save_and_load(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create some test files
test_files = {
"file1.txt": "Content of file 1",
"file2.py": "print('Content of file 2')",
"subdir/file3.md": "# Content of file 3",
}
for file_path, content in test_files.items():
full_path = Path(repo_dir) / file_path
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.write_text(content)
# Add some files as editable and some as read-only
commands.cmd_add("file1.txt file2.py")
commands.cmd_read_only("subdir/file3.md")
# Save the session to a file
session_file = "test_session.txt"
commands.cmd_save(session_file)
# Verify the session file was created and contains the expected commands
self.assertTrue(Path(session_file).exists())
with open(session_file, encoding=io.encoding) as f:
commands_text = f.read().splitlines()
# Convert paths to absolute for comparison
abs_file1 = str(Path("file1.txt").resolve())
abs_file2 = str(Path("file2.py").resolve())
abs_file3 = str(Path("subdir/file3.md").resolve())
# Check each line for matching paths using os.path.samefile
found_file1 = found_file2 = found_file3 = False
for line in commands_text:
if line.startswith("/add "):
path = Path(line[5:].strip()).resolve()
if os.path.samefile(str(path), abs_file1):
found_file1 = True
elif os.path.samefile(str(path), abs_file2):
found_file2 = True
elif line.startswith("/read-only "):
path = Path(line[11:]).resolve()
if os.path.samefile(str(path), abs_file3):
found_file3 = True
self.assertTrue(found_file1, "file1.txt not found in commands")
self.assertTrue(found_file2, "file2.py not found in commands")
self.assertTrue(found_file3, "file3.md not found in commands")
# Clear the current session
commands.cmd_reset("")
self.assertEqual(len(coder.abs_fnames), 0)
self.assertEqual(len(coder.abs_read_only_fnames), 0)
# Load the session back
commands.cmd_load(session_file)
# Verify files were restored correctly
added_files = {Path(coder.get_rel_fname(f)).as_posix() for f in coder.abs_fnames}
read_only_files = {
Path(coder.get_rel_fname(f)).as_posix() for f in coder.abs_read_only_fnames
}
self.assertEqual(added_files, {"file1.txt", "file2.py"})
self.assertEqual(read_only_files, {"subdir/file3.md"})
# Clean up
Path(session_file).unlink()
def test_cmd_save_and_load_with_external_file(self):
with tempfile.NamedTemporaryFile(mode="w", delete=False) as external_file:
external_file.write("External file content")
external_file_path = external_file.name
try:
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create some test files in the repo
test_files = {
"file1.txt": "Content of file 1",
"file2.py": "print('Content of file 2')",
}
for file_path, content in test_files.items():
full_path = Path(repo_dir) / file_path
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.write_text(content)
# Add some files as editable and some as read-only
commands.cmd_add(str(Path("file1.txt")))
commands.cmd_read_only(external_file_path)
# Save the session to a file
session_file = str(Path("test_session.txt"))
commands.cmd_save(session_file)
# Verify the session file was created and contains the expected commands
self.assertTrue(Path(session_file).exists())
with open(session_file, encoding=io.encoding) as f:
commands_text = f.read()
commands_text = re.sub(
r"/add +", "/add ", commands_text
) # Normalize add command spaces
self.assertIn("/add file1.txt", commands_text)
# Split commands and check each one
for line in commands_text.splitlines():
if line.startswith("/read-only "):
saved_path = line.split(" ", 1)[1]
if os.path.samefile(saved_path, external_file_path):
break
else:
self.fail(f"No matching read-only command found for {external_file_path}")
# Clear the current session
commands.cmd_reset("")
self.assertEqual(len(coder.abs_fnames), 0)
self.assertEqual(len(coder.abs_read_only_fnames), 0)
# Load the session back
commands.cmd_load(session_file)
# Verify files were restored correctly
added_files = {coder.get_rel_fname(f) for f in coder.abs_fnames}
read_only_files = {coder.get_rel_fname(f) for f in coder.abs_read_only_fnames}
self.assertEqual(added_files, {str(Path("file1.txt"))})
self.assertTrue(
any(os.path.samefile(external_file_path, f) for f in read_only_files)
)
# Clean up
Path(session_file).unlink()
finally:
os.unlink(external_file_path)
def test_cmd_save_and_load_with_multiple_external_files(self):
with (
tempfile.NamedTemporaryFile(mode="w", delete=False) as external_file1,
tempfile.NamedTemporaryFile(mode="w", delete=False) as external_file2,
):
external_file1.write("External file 1 content")
external_file2.write("External file 2 content")
external_file1_path = external_file1.name
external_file2_path = external_file2.name
try:
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create some test files in the repo
test_files = {
"internal1.txt": "Content of internal file 1",
"internal2.txt": "Content of internal file 2",
}
for file_path, content in test_files.items():
full_path = Path(repo_dir) / file_path
full_path.parent.mkdir(parents=True, exist_ok=True)
full_path.write_text(content)
# Add files as editable and read-only
commands.cmd_add(str(Path("internal1.txt")))
commands.cmd_read_only(external_file1_path)
commands.cmd_read_only(external_file2_path)
# Save the session to a file
session_file = str(Path("test_session.txt"))
commands.cmd_save(session_file)
# Verify the session file was created and contains the expected commands
self.assertTrue(Path(session_file).exists())
with open(session_file, encoding=io.encoding) as f:
commands_text = f.read()
commands_text = re.sub(
r"/add +", "/add ", commands_text
) # Normalize add command spaces
self.assertIn("/add internal1.txt", commands_text)
# Split commands and check each one
for line in commands_text.splitlines():
if line.startswith("/read-only "):
saved_path = line.split(" ", 1)[1]
if os.path.samefile(saved_path, external_file1_path):
break
else:
self.fail(f"No matching read-only command found for {external_file1_path}")
# Split commands and check each one
for line in commands_text.splitlines():
if line.startswith("/read-only "):
saved_path = line.split(" ", 1)[1]
if os.path.samefile(saved_path, external_file2_path):
break
else:
self.fail(f"No matching read-only command found for {external_file2_path}")
# Clear the current session
commands.cmd_reset("")
self.assertEqual(len(coder.abs_fnames), 0)
self.assertEqual(len(coder.abs_read_only_fnames), 0)
# Load the session back
commands.cmd_load(session_file)
# Verify files were restored correctly
added_files = {coder.get_rel_fname(f) for f in coder.abs_fnames}
read_only_files = {coder.get_rel_fname(f) for f in coder.abs_read_only_fnames}
self.assertEqual(added_files, {str(Path("internal1.txt"))})
self.assertTrue(
all(
any(os.path.samefile(external_path, fname) for fname in read_only_files)
for external_path in [external_file1_path, external_file2_path]
)
)
# Clean up
Path(session_file).unlink()
finally:
os.unlink(external_file1_path)
os.unlink(external_file2_path)
def test_cmd_read_only_with_image_file(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create a test image file
test_file = Path(repo_dir) / "test_image.jpg"
test_file.write_text("Mock image content")
# Test with non-vision model
commands.cmd_read_only(str(test_file))
self.assertEqual(len(coder.abs_read_only_fnames), 0)
# Test with vision model
vision_model = Model("gpt-4-vision-preview")
vision_coder = Coder.create(vision_model, None, io)
vision_commands = Commands(io, vision_coder)
vision_commands.cmd_read_only(str(test_file))
self.assertEqual(len(vision_coder.abs_read_only_fnames), 1)
self.assertTrue(
any(
os.path.samefile(str(test_file), fname)
for fname in vision_coder.abs_read_only_fnames
)
)
def test_cmd_read_only_with_glob_pattern(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -679,7 +940,7 @@ class TestCommands(TestCase):
def test_cmd_read_only_with_recursive_glob(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -706,7 +967,7 @@ class TestCommands(TestCase):
def test_cmd_read_only_with_nonexistent_glob(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -724,7 +985,7 @@ class TestCommands(TestCase):
def test_cmd_add_unicode_error(self):
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -742,7 +1003,7 @@ class TestCommands(TestCase):
def test_cmd_add_read_only_file(self):
with GitTemporaryDirectory():
# Initialize the Commands and InputOutput objects
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -797,7 +1058,7 @@ class TestCommands(TestCase):
def test_cmd_test_unbound_local_error(self):
with ChdirTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -807,14 +1068,16 @@ 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():
repo = git.Repo()
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
from aider.coders import Coder
coder = Coder.create(self.GPT35, None, io)
@@ -839,7 +1102,7 @@ class TestCommands(TestCase):
def test_cmd_undo_with_dirty_files_not_in_last_commit(self):
with GitTemporaryDirectory() as repo_dir:
repo = git.Repo(repo_dir)
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -887,7 +1150,7 @@ class TestCommands(TestCase):
def test_cmd_undo_with_newly_committed_file(self):
with GitTemporaryDirectory() as repo_dir:
repo = git.Repo(repo_dir)
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -923,7 +1186,7 @@ class TestCommands(TestCase):
def test_cmd_undo_on_first_commit(self):
with GitTemporaryDirectory() as repo_dir:
repo = git.Repo(repo_dir)
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -949,6 +1212,26 @@ class TestCommands(TestCase):
del commands
del repo
def test_cmd_add_gitignored_file(self):
with GitTemporaryDirectory():
# Create a .gitignore file
gitignore = Path(".gitignore")
gitignore.write_text("*.ignored\n")
# Create a file that matches the gitignore pattern
ignored_file = Path("test.ignored")
ignored_file.write_text("This should be ignored")
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Try to add the ignored file
commands.cmd_add(str(ignored_file))
# Verify the file was not added
self.assertEqual(len(coder.abs_fnames), 0)
def test_cmd_add_aiderignored_file(self):
with GitTemporaryDirectory():
repo = git.Repo()
@@ -991,7 +1274,7 @@ class TestCommands(TestCase):
def test_cmd_read_only(self):
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -1021,14 +1304,54 @@ class TestCommands(TestCase):
)
)
def test_cmd_read_only_from_working_dir(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
# Create a subdirectory and a test file within it
subdir = Path(repo_dir) / "subdir"
subdir.mkdir()
test_file = subdir / "test_read_only_file.txt"
test_file.write_text("Test content")
# Change the current working directory to the subdirectory
os.chdir(subdir)
# Test the /read-only command using git_root referenced name
commands.cmd_read_only(os.path.join("subdir", "test_read_only_file.txt"))
# Check if the file was added to abs_read_only_fnames
self.assertTrue(
any(
os.path.samefile(str(test_file.resolve()), fname)
for fname in coder.abs_read_only_fnames
)
)
# Test dropping the read-only file using git_root referenced name
commands.cmd_drop(os.path.join("subdir", "test_read_only_file.txt"))
# Check if the file was removed from abs_read_only_fnames
self.assertFalse(
any(
os.path.samefile(str(test_file.resolve()), fname)
for fname in coder.abs_read_only_fnames
)
)
def test_cmd_read_only_with_external_file(self):
with tempfile.NamedTemporaryFile(mode="w", delete=False) as external_file:
external_file.write("External file content")
external_file_path = external_file.name
try:
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
with GitTemporaryDirectory() as repo_dir:
# Create a test file in the repo
repo_file = Path(repo_dir) / "repo_file.txt"
repo_file.write_text("Repo file content")
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -1059,7 +1382,7 @@ class TestCommands(TestCase):
def test_cmd_read_only_with_multiple_files(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -1090,7 +1413,7 @@ class TestCommands(TestCase):
def test_cmd_read_only_with_tilde_path(self):
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=False)
io = InputOutput(pretty=False, fancy_input=False, yes=False)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -1125,7 +1448,7 @@ class TestCommands(TestCase):
def test_cmd_diff(self):
with GitTemporaryDirectory() as repo_dir:
repo = git.Repo(repo_dir)
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -1189,7 +1512,7 @@ class TestCommands(TestCase):
self.assertIn("+Final modified content", diff_output)
def test_cmd_ask(self):
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -1208,7 +1531,7 @@ class TestCommands(TestCase):
def test_cmd_lint_with_dirty_file(self):
with GitTemporaryDirectory() as repo_dir:
repo = git.Repo(repo_dir)
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)
@@ -1245,7 +1568,7 @@ class TestCommands(TestCase):
def test_cmd_reset(self):
with GitTemporaryDirectory() as repo_dir:
io = InputOutput(pretty=False, yes=True)
io = InputOutput(pretty=False, fancy_input=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
commands = Commands(io, coder)

View File

@@ -10,6 +10,7 @@ from aider.coders import editblock_coder as eb
from aider.dump import dump # noqa: F401
from aider.io import InputOutput
from aider.models import Model
from aider.utils import ChdirTemporaryDirectory
class TestUtils(unittest.TestCase):
@@ -296,6 +297,28 @@ These changes replace the `subprocess.run` patches with `subprocess.check_output
result = eb.replace_most_similar_chunk(whole, part, replace)
self.assertEqual(result, expected_output)
def test_replace_multiple_matches(self):
"only replace first occurrence"
whole = "line1\nline2\nline1\nline3\n"
part = "line1\n"
replace = "new_line\n"
expected_output = "new_line\nline2\nline1\nline3\n"
result = eb.replace_most_similar_chunk(whole, part, replace)
self.assertEqual(result, expected_output)
def test_replace_multiple_matches_missing_whitespace(self):
"only replace first occurrence"
whole = " line1\n line2\n line1\n line3\n"
part = "line1\n"
replace = "new_line\n"
expected_output = " new_line\n line2\n line1\n line3\n"
result = eb.replace_most_similar_chunk(whole, part, replace)
self.assertEqual(result, expected_output)
def test_replace_part_with_just_some_missing_leading_whitespace(self):
whole = " line1\n line2\n line3\n"
part = " line1\n line2\n"
@@ -319,6 +342,46 @@ These changes replace the `subprocess.run` patches with `subprocess.check_output
result = eb.replace_most_similar_chunk(whole, part, replace)
self.assertEqual(result, expected_output)
def test_create_new_file_with_other_file_in_chat(self):
# https://github.com/Aider-AI/aider/issues/2258
with ChdirTemporaryDirectory():
# Create a few temporary files
file1 = "file.txt"
with open(file1, "w", encoding="utf-8") as f:
f.write("one\ntwo\nthree\n")
files = [file1]
# Initialize the Coder object with the mocked IO and mocked repo
coder = Coder.create(
self.GPT35, "diff", use_git=False, io=InputOutput(yes=True), fnames=files
)
def mock_send(*args, **kwargs):
coder.partial_response_content = f"""
Do this:
newfile.txt
<<<<<<< SEARCH
=======
creating a new file
>>>>>>> REPLACE
"""
coder.partial_response_function_call = dict()
return []
coder.send = mock_send
coder.run(with_message="hi")
content = Path(file1).read_text(encoding="utf-8")
self.assertEqual(content, "one\ntwo\nthree\n")
content = Path("newfile.txt").read_text(encoding="utf-8")
self.assertEqual(content, "creating a new file\n")
def test_full_edit(self):
# Create a few temporary files
_, file1 = tempfile.mkstemp()
@@ -482,9 +545,7 @@ two
Hope you like it!
"""
edits = list(
eb.find_original_update_blocks(edit, valid_fnames=["path/to/a/file1.txt"])
)
edits = list(eb.find_original_update_blocks(edit, valid_fnames=["path/to/a/file1.txt"]))
self.assertEqual(
edits,
[

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

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

View File

@@ -14,7 +14,7 @@ from aider.utils import ChdirTemporaryDirectory
class TestInputOutput(unittest.TestCase):
def test_no_color_environment_variable(self):
with patch.dict(os.environ, {"NO_COLOR": "1"}):
io = InputOutput()
io = InputOutput(fancy_input=False)
self.assertFalse(io.pretty)
def test_autocompleter_get_command_completions(self):
@@ -107,7 +107,7 @@ class TestInputOutput(unittest.TestCase):
@patch("builtins.input", return_value="test input")
def test_get_input_is_a_directory_error(self, mock_input):
io = InputOutput(pretty=False) # Windows tests throw UnicodeDecodeError
io = InputOutput(pretty=False, fancy_input=False) # Windows tests throw UnicodeDecodeError
root = "/"
rel_fnames = ["existing_file.txt"]
addable_rel_fnames = ["new_file.txt"]
@@ -121,7 +121,7 @@ class TestInputOutput(unittest.TestCase):
@patch("builtins.input")
def test_confirm_ask_explicit_yes_required(self, mock_input):
io = InputOutput(pretty=False)
io = InputOutput(pretty=False, fancy_input=False)
# Test case 1: explicit_yes_required=True, self.yes=True
io.yes = True
@@ -153,7 +153,7 @@ class TestInputOutput(unittest.TestCase):
@patch("builtins.input")
def test_confirm_ask_with_group(self, mock_input):
io = InputOutput(pretty=False)
io = InputOutput(pretty=False, fancy_input=False)
group = ConfirmGroup()
# Test case 1: No group preference, user selects 'All'
@@ -195,7 +195,7 @@ class TestInputOutput(unittest.TestCase):
@patch("builtins.input")
def test_confirm_ask_yes_no(self, mock_input):
io = InputOutput(pretty=False)
io = InputOutput(pretty=False, fancy_input=False)
# Test case 1: User selects 'Yes'
mock_input.return_value = "y"
@@ -220,7 +220,7 @@ class TestInputOutput(unittest.TestCase):
@patch("builtins.input", side_effect=["d"])
def test_confirm_ask_allow_never(self, mock_input):
io = InputOutput(pretty=False)
io = InputOutput(pretty=False, fancy_input=False)
# First call: user selects "Don't ask again"
result = io.confirm_ask("Are you sure?", allow_never=True)

View File

@@ -32,6 +32,8 @@ class TestMain(TestCase):
os.environ["HOME"] = self.homedir_obj.name
self.input_patcher = patch("builtins.input", return_value=None)
self.mock_input = self.input_patcher.start()
self.webbrowser_patcher = patch("aider.io.webbrowser.open")
self.mock_webbrowser = self.webbrowser_patcher.start()
def tearDown(self):
os.chdir(self.original_cwd)
@@ -40,9 +42,10 @@ class TestMain(TestCase):
os.environ.clear()
os.environ.update(self.original_env)
self.input_patcher.stop()
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())
@@ -138,7 +141,7 @@ class TestMain(TestCase):
gitignore.write_text("one\ntwo\n")
check_gitignore(cwd, io)
self.assertEqual("one\ntwo\n.aider*\n", gitignore.read_text())
self.assertEqual("one\ntwo\n.aider*\n.env\n", gitignore.read_text())
del os.environ["GIT_CONFIG_GLOBAL"]
def test_main_args(self):
@@ -329,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)
@@ -337,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)
@@ -378,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

@@ -1,12 +1,20 @@
import unittest
from unittest.mock import ANY, MagicMock, patch
from aider.models import Model, get_model_info, sanity_check_model, sanity_check_models
from aider.models import (
ANTHROPIC_BETA_HEADER,
Model,
ModelInfoManager,
register_models,
sanity_check_model,
sanity_check_models,
)
class TestModels(unittest.TestCase):
def test_get_model_info_nonexistent(self):
info = get_model_info("non-existent-model")
manager = ModelInfoManager()
info = manager.get_model_info("non-existent-model")
self.assertEqual(info, {})
def test_max_context_tokens(self):
@@ -73,12 +81,68 @@ class TestModels(unittest.TestCase):
result
) # 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
self.assertGreaterEqual(mock_io.tool_warning.call_count, 2) # Expect two warnings
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
self.assertTrue(
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()

View File

@@ -6,6 +6,7 @@ from unittest import mock
import pytest
from git import GitError, Repo
from aider import urls
from aider.main import sanity_check_repo
@@ -99,7 +100,8 @@ def test_detached_head_state(create_repo, mock_io):
mock_io.tool_output.assert_not_called()
def test_git_index_version_greater_than_2(create_repo, mock_io):
@mock.patch("webbrowser.open")
def test_git_index_version_greater_than_2(mock_browser, create_repo, mock_io):
repo_path, repo = create_repo
# Set the git index version to 3
set_git_index_version(str(repo_path), 3)
@@ -125,7 +127,10 @@ def test_git_index_version_greater_than_2(create_repo, mock_io):
"You may be able to convert your repo: git update-index --index-version=2"
)
mock_io.tool_output.assert_any_call("Or run aider --no-git to proceed without using git.")
mock_io.tool_output.assert_any_call("https://github.com/Aider-AI/aider/issues/211")
mock_io.offer_url.assert_any_call(
urls.git_index_version,
"Open documentation url for more info?",
)
def test_bare_repository(create_repo, mock_io, tmp_path):

View File

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

View File

@@ -4,7 +4,7 @@ from unittest.mock import MagicMock
import aider
from aider.coders import Coder
from aider.commands import Commands
from aider.help import Help
from aider.help import Help, fname_to_url
from aider.io import InputOutput
from aider.models import Model
@@ -54,6 +54,53 @@ class TestHelp(unittest.TestCase):
# Assert that there are more than 5 <doc> entries
self.assertGreater(result.count("<doc"), 5)
def test_fname_to_url_unix(self):
# Test relative Unix-style paths
self.assertEqual(fname_to_url("website/docs/index.md"), "https://aider.chat/docs")
self.assertEqual(
fname_to_url("website/docs/usage.md"), "https://aider.chat/docs/usage.html"
)
self.assertEqual(fname_to_url("website/_includes/header.md"), "")
# Test absolute Unix-style paths
self.assertEqual(
fname_to_url("/home/user/project/website/docs/index.md"), "https://aider.chat/docs"
)
self.assertEqual(
fname_to_url("/home/user/project/website/docs/usage.md"),
"https://aider.chat/docs/usage.html",
)
self.assertEqual(fname_to_url("/home/user/project/website/_includes/header.md"), "")
def test_fname_to_url_windows(self):
# Test relative Windows-style paths
self.assertEqual(fname_to_url(r"website\docs\index.md"), "https://aider.chat/docs")
self.assertEqual(
fname_to_url(r"website\docs\usage.md"), "https://aider.chat/docs/usage.html"
)
self.assertEqual(fname_to_url(r"website\_includes\header.md"), "")
# Test absolute Windows-style paths
self.assertEqual(
fname_to_url(r"C:\Users\user\project\website\docs\index.md"), "https://aider.chat/docs"
)
self.assertEqual(
fname_to_url(r"C:\Users\user\project\website\docs\usage.md"),
"https://aider.chat/docs/usage.html",
)
self.assertEqual(fname_to_url(r"C:\Users\user\project\website\_includes\header.md"), "")
def test_fname_to_url_edge_cases(self):
# Test paths that don't contain 'website'
self.assertEqual(fname_to_url("/home/user/project/docs/index.md"), "")
self.assertEqual(fname_to_url(r"C:\Users\user\project\docs\index.md"), "")
# Test empty path
self.assertEqual(fname_to_url(""), "")
# Test path with 'website' in the wrong place
self.assertEqual(fname_to_url("/home/user/website_project/docs/index.md"), "")
if __name__ == "__main__":
unittest.main()

View File

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