Compare commits

...

376 Commits

Author SHA1 Message Date
Paul Gauthier
8159cbf7d3 set version to 0.82.4.dev 2025-05-05 20:23:46 -07:00
Paul Gauthier
c23e609902 version bump to 0.82.3 2025-05-05 20:23:43 -07:00
Paul Gauthier
2d9ea25273 fix: Add newline after "Reply in {user_lang}" reminder 2025-05-05 19:17:36 -07:00
Paul Gauthier
7773bbc908 copy 2025-05-05 19:13:49 -07:00
Paul Gauthier
72476f0967 bump deps 2025-05-05 19:05:11 -07:00
Paul Gauthier
a9883ccc25 copy 2025-05-05 19:03:32 -07:00
Paul Gauthier
3b9b93a8a4 Merge branch 'main' of github.com:Aider-AI/aider 2025-05-05 19:03:07 -07:00
Paul Gauthier
f90b7bfb09 better 2025-05-05 19:02:43 -07:00
paul-gauthier
5e7ef6c50e Merge pull request #3931 from elohmeier/main 2025-05-02 07:21:29 -07:00
Enno Richter
fdc7be1318 docs: update lint/test pre-commit shell script example to use "$@" for proper argument handling 2025-05-02 05:49:02 +02:00
paul-gauthier
f00c1bf61b Merge pull request #3930 from erykwieliczko/main 2025-05-01 20:03:17 -07:00
Eryk Wieliczko
09030de0b5 Show dates on "Release history" chart 2025-05-02 04:38:38 +02:00
Paul Gauthier
bdba0ca1c5 refactor: Move shell command prompts to shell.py, add final reminders 2025-05-01 17:31:22 -07:00
Paul Gauthier (aider)
e17c7d938c refactor: add normalize_language and improve get_user_language to return readable names 2025-05-01 17:29:14 -07:00
Paul Gauthier (aider)
433f2908a0 feat: add language normalization to convert locale codes to names using Babel or fallback map 2025-05-01 17:28:56 -07:00
Paul Gauthier
9fa5f5ace1 refactor: remove redundant dump call from prompt formatting in base_coder.py 2025-05-01 17:28:55 -07:00
Paul Gauthier
849a379a8c refactor: Move lazy/overeager prompts to final reminders in system prompt 2025-05-01 17:24:14 -07:00
Paul Gauthier
e205629a94 Merge branch 'main' of github.com:Aider-AI/aider 2025-04-28 07:53:31 -07:00
Paul Gauthier
9351f37935 add google-generativeai, bump deps 2025-04-28 07:53:20 -07:00
paul-gauthier
7d185bb710 Merge pull request #3898 from acro5piano/main
fix: add suffix "md" when opening editor in InputOutput class
2025-04-27 06:59:11 -07:00
Kay Gosho
07759813ed fix: add suffix "md" when opening editor in InputOutput class 2025-04-27 16:06:32 +09:00
Paul Gauthier
591d294052 feat: Print changed file path and check before reading content 2025-04-25 07:58:51 -07:00
Paul Gauthier (aider)
df1a0c5b8d style: Apply linter to aider/watch.py 2025-04-25 07:54:35 -07:00
Paul Gauthier (aider)
e743394537 feat: Skip scanning files larger than 1MB for AI comments 2025-04-25 07:54:32 -07:00
Paul Gauthier
22f140ac05 feat: Add common file patterns to default gitignore spec 2025-04-25 07:54:31 -07:00
Paul Gauthier (aider)
25a303935c fix: Add overeager setting to Gemini 2.5 Pro models in model-settings.yml 2025-04-24 19:51:35 -07:00
Paul Gauthier (aider)
3bf20d4f7a feat: Set gemini 2.5 pro models to overeager: true 2025-04-24 19:51:14 -07:00
Paul Gauthier
45413ce815 copy 2025-04-24 07:18:35 -07:00
Paul Gauthier
c56e4a08d3 copy 2025-04-20 19:53:32 -07:00
Paul Gauthier (aider)
80515b69c1 fix: Strip b/ prefix when a path is /dev/null in diffs 2025-04-20 17:34:36 -07:00
Paul Gauthier
303645cffa copy 2025-04-20 17:30:06 -07:00
Paul Gauthier
b3d32f65d3 fixed quote 2025-04-20 17:29:42 -07:00
Paul Gauthier
7c0aac7454 chore: Update Gemini flash model alias to preview version 2025-04-20 16:43:35 -07:00
Paul Gauthier
7719eae023 copy 2025-04-20 16:41:58 -07:00
Paul Gauthier
5e210c700d fix: Handle filenames starting with fences or triple backticks correctly 2025-04-20 16:36:36 -07:00
Paul Gauthier (aider)
c6ce871700 style: Apply linter to editblock_coder.py 2025-04-20 16:25:59 -07:00
Paul Gauthier (aider)
f28504a2eb fix: Properly handle filenames starting with triple backticks 2025-04-20 16:25:55 -07:00
Paul Gauthier
48733a315b fix: Handle filenames starting with fence chars in editblock coder 2025-04-20 16:25:54 -07:00
Paul Gauthier (aider)
16fbff8de1 Feat: Add gemini-2.5-flash-preview-04-17 as editor/weak model name 2025-04-20 16:04:04 -07:00
Paul Gauthier (aider)
bbab0cea5e feat: Add model settings for gemini-2.5-flash-preview-04-17 models 2025-04-20 16:01:03 -07:00
Paul Gauthier
19de93ae39 fix: Update weak model name for gemini-2.5-pro-exp-03-25 2025-04-20 15:58:54 -07:00
Paul Gauthier
230e5065c1 feat: Add gemini-2.5-flash-preview-04-17 model and leaderboard entry 2025-04-20 15:47:34 -07:00
Paul Gauthier
c94340d493 less ram 2025-04-20 13:18:57 -07:00
Paul Gauthier
ac1ff231e0 better prompt 2025-04-20 12:38:09 -07:00
Paul Gauthier (aider)
5423ffe518 feat: Add UnifiedDiffSimpleCoder to coders module 2025-04-20 11:34:10 -07:00
Paul Gauthier (aider)
ba4d613cbc feat: Give udiff-simple its own prompts, inheriting from udiff prompts 2025-04-20 11:32:42 -07:00
Paul Gauthier
ab11118c8a feat: Add simple prompts for unified diff coder 2025-04-20 11:32:41 -07:00
Paul Gauthier (aider)
3ca3f39f1d feat: Add UnifiedDiffSimpleCoder with simpler prompt for code edits 2025-04-20 11:31:55 -07:00
Paul Gauthier
8c3f167e8c feat: Add simple unified diff coder 2025-04-20 11:31:55 -07:00
Paul Gauthier (aider)
1a4d3927e7 feat: Add --thinking-tokens option to benchmark script 2025-04-20 11:29:33 -07:00
Paul Gauthier
20a29e5cd1 copy 2025-04-20 11:12:54 -07:00
Paul Gauthier
51e0fff822 cleanup metadata that is now in litellm 2025-04-20 11:12:20 -07:00
Paul Gauthier (aider)
13b3e75d0e style: Apply linting to clean_metadata.py 2025-04-20 11:11:01 -07:00
Paul Gauthier (aider)
de28178369 feat: Add dummy key to JSON dumps for diffing, then remove it. 2025-04-20 11:10:58 -07:00
Paul Gauthier (aider)
2f38cd184c style: Format clean_metadata.py with black linter 2025-04-20 11:08:57 -07:00
Paul Gauthier (aider)
d8caa76bc8 feat: Compare dicts directly to avoid spurious diffs in metadata cleaning 2025-04-20 11:08:53 -07:00
Paul Gauthier (aider)
506c3c928e refactor: Remove unused variable in find_block_lines function 2025-04-20 11:06:20 -07:00
Paul Gauthier (aider)
48ac1de8d3 fix: Remove unused variables and fix whitespace in clean_metadata.py 2025-04-20 11:05:56 -07:00
Paul Gauthier (aider)
ebfce5b0f2 style: Run linter on clean_metadata.py 2025-04-20 11:05:39 -07:00
Paul Gauthier (aider)
58f4db4e52 feat: Implement surgical removal of JSON blocks from metadata file 2025-04-20 11:05:36 -07:00
Paul Gauthier
ba2c4d1eb7 chore: Make clean_metadata.py executable 2025-04-20 11:05:35 -07:00
Paul Gauthier (aider)
6656b5d973 style: Apply linting to clean_metadata.py 2025-04-20 11:03:44 -07:00
Paul Gauthier (aider)
b4673fdc85 Refactor: Remove keys immediately in clean_metadata.py 2025-04-20 11:03:41 -07:00
Paul Gauthier (aider)
ce1266be68 style: Run linter on clean_metadata.py 2025-04-20 11:02:40 -07:00
Paul Gauthier (aider)
226108d05d feat: Prompt user to remove entries from model-metadata.json 2025-04-20 11:02:37 -07:00
Paul Gauthier (aider)
b2d541f1eb style: Fix line length in clean_metadata.py for flake8 compliance 2025-04-20 11:02:00 -07:00
Paul Gauthier (aider)
758020c574 fix: Flip diff order to be from aider -> litellm in script 2025-04-20 11:01:40 -07:00
Paul Gauthier (aider)
876569613b style: Apply linting to clean_metadata.py 2025-04-20 11:00:52 -07:00
Paul Gauthier (aider)
82b26daf37 feat: display matching entries side-by-side with diff highlighting 2025-04-20 11:00:49 -07:00
Paul Gauthier (aider)
be44b65095 style: Apply linting to clean_metadata.py 2025-04-20 11:00:03 -07:00
Paul Gauthier (aider)
8596f0d4a3 feat: Use json5 to load model metadata for lenient parsing 2025-04-20 11:00:00 -07:00
Paul Gauthier
19a94e5f15 fix: Update litellm_path to correctly locate JSON file 2025-04-20 10:59:59 -07:00
Paul Gauthier (aider)
7bde345b83 feat: Add script to find common models in metadata files. 2025-04-20 10:58:38 -07:00
Paul Gauthier
d45a5747ea feat: Add script to clean metadata from files 2025-04-20 10:58:37 -07:00
Paul Gauthier
e560ab61b6 copy 2025-04-20 10:48:39 -07:00
Paul Gauthier
84c3ac93ef copy 2025-04-20 10:37:14 -07:00
Paul Gauthier (aider)
7a50b7779a docs: Update boto3 install instructions for Bedrock 2025-04-20 10:34:13 -07:00
Paul Gauthier
328a3c3178 docs: Improve Amazon Bedrock setup instructions 2025-04-20 10:34:12 -07:00
Paul Gauthier (aider)
21fa54d792 Refactor: Update LLM docs to match gemini.md structure 2025-04-20 10:28:01 -07:00
Paul Gauthier
ec7ac60cfc copy 2025-04-20 08:54:44 -07:00
Paul Gauthier
c2d8d5dc82 set version to 0.82.3.dev 2025-04-20 08:26:25 -07:00
Paul Gauthier
20a7e3552c version bump to 0.82.2 2025-04-20 08:26:22 -07:00
Paul Gauthier
888168f044 copy 2025-04-20 08:21:33 -07:00
Paul Gauthier
851642a1bd copy 2025-04-20 08:13:04 -07:00
Paul Gauthier
f7bdebfba9 Merge branch 'main' of github.com:Aider-AI/aider 2025-04-19 18:50:34 -07:00
Paul Gauthier
a4d3222108 feat: Add openhands-lm-32b-v0.1 to polyglot leaderboard data 2025-04-19 11:27:50 -07:00
paul-gauthier
f1caab9de0 Merge pull request #3828 from zjy1412/main
fix: correctly detect edit blocks in diff-fenced mode
2025-04-19 10:03:31 -07:00
Paul Gauthier (aider)
c08336fdb0 feat: Update prompts to request one block per file in patches 2025-04-17 20:23:16 -07:00
Paul Gauthier (aider)
541b496d09 feat: Allow multiple update/delete actions for the same file in patch coder 2025-04-17 20:19:52 -07:00
Paul Gauthier
622bf349c5 chore: Add num_ctx and sleep to run_test_threaded.gather arguments 2025-04-17 20:08:57 -07:00
Paul Gauthier (aider)
05eaf82b36 feat: Pass verbose flag to Model class for detailed output 2025-04-17 20:02:31 -07:00
Paul Gauthier (aider)
5c8150fd16 fix: Change reasoning_effort type to string in benchmark script 2025-04-17 20:02:09 -07:00
Paul Gauthier (aider)
ec9327dcb4 style: Apply linter to benchmark.py 2025-04-17 20:01:30 -07:00
Paul Gauthier (aider)
8e689d35af Feat: Add --reasoning-effort switch to benchmark script 2025-04-17 20:01:26 -07:00
Paul Gauthier
50fd544070 Merge branch 'main' of github.com:Aider-AI/aider 2025-04-17 13:26:06 -07:00
paul-gauthier
4f8bd2e06d Merge pull request #3831 from VariousForks/main
docs: update editor usage instructions in multi-line guide
2025-04-17 11:46:57 -07:00
Greg OmniMind
6f1b6f5f31 docs: update editor usage instructions in multi-line guide
* Added keybinding `Ctrl-X Ctrl-E` for invoking editor via terminal compatibility.
* Enhances user ergonomics for terminals supporting this shortcut, streamlining workflow.
* Maintains reference to editor configuration documentation.
2025-04-17 20:42:34 +02:00
Paul Gauthier
bdfda399cb copy 2025-04-17 09:29:35 -07:00
Paul Gauthier
a08ffc3513 scale 2025-04-17 09:28:07 -07:00
Paul Gauthier
21beee2fe1 Merge branch 'arch-o3-41' 2025-04-17 08:29:47 -07:00
zjy1412
a564f94bf3 Added two test cases 2025-04-17 16:50:54 +08:00
zjy1412
9e54898866 fix: correctly detect edit blocks in diff-fenced mode 2025-04-17 14:30:13 +08:00
Paul Gauthier
739e01da95 copy 2025-04-16 19:10:24 -07:00
Paul Gauthier
3e0af2cc84 copy 2025-04-16 19:04:13 -07:00
Paul Gauthier
9ff13740f2 Merge branch 'main' into arch-o3-41 2025-04-16 19:02:45 -07:00
Paul Gauthier
00e5c33444 copy 2025-04-16 19:02:19 -07:00
Paul Gauthier
57abaf7500 add o3+4.1 2025-04-16 19:02:09 -07:00
Paul Gauthier (aider)
ed14be4e70 refactor: Use constant for max display cost cap in leaderboard table 2025-04-16 19:00:18 -07:00
Paul Gauthier
80909e17c7 set version to 0.82.2.dev 2025-04-16 18:16:55 -07:00
Paul Gauthier
52697ea884 version bump to 0.82.1 2025-04-16 18:16:52 -07:00
Paul Gauthier
9f01c8d0d6 no stream main o3 2025-04-16 18:16:33 -07:00
Paul Gauthier
e91d7e74ae copy 2025-04-16 18:12:22 -07:00
Paul Gauthier
20ca0463ea feat: Disable streaming for o3 models due to token issue 2025-04-16 18:12:04 -07:00
Paul Gauthier
5e40f469bf copy 2025-04-16 18:10:15 -07:00
Paul Gauthier
7f28d63c33 add o4-mini (high) 2025-04-16 17:24:55 -07:00
Paul Gauthier (aider)
bb1fa24971 feat: Add o4-mini model settings for openai, openrouter, and azure 2025-04-16 17:24:14 -07:00
Paul Gauthier
ffbbaa06d7 chore: Comment out reasoning_effort extra_params 2025-04-16 17:24:13 -07:00
Paul Gauthier (aider)
14e1b96f05 feat: Add azure/gpt-4.1-mini and azure/gpt-4.1 models 2025-04-16 15:45:41 -07:00
Paul Gauthier (aider)
d8c781b66b Feat: Add azure/o3 model settings 2025-04-16 15:44:57 -07:00
Paul Gauthier
2fbec8545c feat: Enable examples_as_sys_msg and set reasoning_effort to high 2025-04-16 15:44:56 -07:00
Paul Gauthier (aider)
b66901fc75 Feat: Add openai/o3 and openrouter/openai/o3 model settings 2025-04-16 15:00:43 -07:00
Paul Gauthier
d569bca520 cleanup 2025-04-16 15:00:32 -07:00
Paul Gauthier
efbefc669f add o3 2025-04-16 14:58:04 -07:00
Paul Gauthier (aider)
24805ff85d fix: Use $10 increments for cost ticks in leaderboard table 2025-04-14 22:02:11 -07:00
Paul Gauthier (aider)
8b917d5716 Refactor: Swap Select and Detail tabs in leaderboard UI 2025-04-14 21:27:45 -07:00
Paul Gauthier (aider)
3502f335ec style: Apply linter to udiff_coder.py 2025-04-14 21:27:10 -07:00
Paul Gauthier (aider)
758979e4f3 fix: Handle git diff prefixes in udiff file paths correctly 2025-04-14 21:27:06 -07:00
Paul Gauthier
8b5fc801da fix: Extract correct filename from unified diff hunk 2025-04-14 21:27:05 -07:00
Paul Gauthier
f5c4214c93 copy 2025-04-14 16:46:57 -07:00
Paul Gauthier
270e84287a copy 2025-04-14 16:32:26 -07:00
Paul Gauthier
daec7cf3f4 set version to 0.82.1.dev 2025-04-14 16:24:22 -07:00
Paul Gauthier
bb42d1e9a5 version bump to 0.82.0 2025-04-14 16:24:19 -07:00
Paul Gauthier (aider)
23f182aab3 feat: Dynamically adjust cost scale and ticks based on visible entries 2025-04-14 16:16:14 -07:00
Paul Gauthier
119fbc995c add gpt-4.1-nano 2025-04-14 16:00:42 -07:00
Paul Gauthier
3081f49179 copy 2025-04-14 15:52:10 -07:00
Paul Gauthier
8cf1874453 added gpt-4.1 and mini 2025-04-14 15:52:06 -07:00
Paul Gauthier (aider)
31b4bd5bcf feat: Apply generic settings for gpt-4.1 and gpt-4.1-mini models 2025-04-14 15:47:01 -07:00
Paul Gauthier
71d1591cc1 cleanup 2025-04-14 15:43:45 -07:00
Paul Gauthier (aider)
134a2d60fe style: Apply linter to patch_flex_coder.py 2025-04-14 15:35:39 -07:00
Paul Gauthier (aider)
152b8912ae refactor: Adapt PatchFlexCoder to use (path, ParsedEdit) tuples 2025-04-14 15:35:35 -07:00
Paul Gauthier (aider)
36f23c101d feat: Add PatchFlexCoder to coders init 2025-04-14 15:33:30 -07:00
Paul Gauthier (aider)
0e40510295 fix: Shorten long comment line in patch_flex_coder.py 2025-04-14 15:32:32 -07:00
Paul Gauthier (aider)
db0d0768d7 style: Remove unused import and reorder imports 2025-04-14 15:32:26 -07:00
Paul Gauthier (aider)
c68cade9f2 Refactor: Use do_replace in PatchFlexCoder instead of flexible_search 2025-04-14 15:32:22 -07:00
Paul Gauthier (aider)
14928727eb refactor: Remove unused remap arg and editblock_strategies var 2025-04-14 15:31:07 -07:00
Paul Gauthier (aider)
67b9345929 fix: Address linting errors in patch_coder and search_replace 2025-04-14 15:30:56 -07:00
Paul Gauthier (aider)
dae1a376a2 fix: Shorten comment to avoid exceeding line length limit. 2025-04-14 15:30:02 -07:00
Paul Gauthier (aider)
1e359f1dcf fix: Improve error message for invalid add file line in diff 2025-04-14 15:29:50 -07:00
Paul Gauthier (aider)
1c54857422 fix: Improve handling of interleaved +/- lines in patch parsing 2025-04-14 15:29:46 -07:00
Paul Gauthier (aider)
0f78a0ac5c style: Fix linting errors in patch_flex_coder.py 2025-04-14 15:29:30 -07:00
Paul Gauthier (aider)
4e1e77890b style: Run linter on patch_flex_coder.py 2025-04-14 15:29:14 -07:00
Paul Gauthier (aider)
5573cdfba1 feat: Create PatchFlexCoder using flexible search and replace for updates 2025-04-14 15:29:10 -07:00
Paul Gauthier
14028d3758 copy 2025-04-14 15:22:22 -07:00
Paul Gauthier
3ab673b398 copy 2025-04-14 15:17:10 -07:00
Paul Gauthier (aider)
861f51f6c3 fix: Define EditResult after PatchAction to resolve flake8 error 2025-04-14 15:08:41 -07:00
Paul Gauthier (aider)
64f5d0d388 refactor: Adapt PatchCoder to return List[Tuple[str, PatchAction]] 2025-04-14 15:08:28 -07:00
Paul Gauthier (aider)
9059af8d5f style: Reorder imports in aider/coders/__init__.py 2025-04-14 15:02:28 -07:00
Paul Gauthier (aider)
c3a543b99d feat: Add PatchCoder to the list of available coders 2025-04-14 15:02:25 -07:00
Paul Gauthier (aider)
c85cd783e5 feat: Use PatchPrompts class in PatchCoder 2025-04-14 15:01:36 -07:00
Paul Gauthier (aider)
af2d241c99 feat: Connect PatchCoder with PatchPrompts 2025-04-14 15:01:22 -07:00
Paul Gauthier (aider)
30839a5273 style: Run linter on patch_prompts.py 2025-04-14 14:58:50 -07:00
Paul Gauthier (aider)
8baa99b7ef refactor: Update PatchPrompts to use V4A diff format 2025-04-14 14:58:46 -07:00
Paul Gauthier
d1e5572343 feat: Add patch prompts for aider coders 2025-04-14 14:52:03 -07:00
Paul Gauthier (aider)
96aa648e17 chore: Fix linting issues: remove unused import, shorten long lines 2025-04-14 14:45:24 -07:00
Paul Gauthier (aider)
1ae5f23dc8 style: Run linter on patch_coder.py 2025-04-14 14:45:14 -07:00
Paul Gauthier (aider)
f565f72679 refactor: Integrate core logic from apply_patch.py into PatchCoder 2025-04-14 14:45:09 -07:00
Paul Gauthier (aider)
78e76648d0 feat: Add openai/gpt-4.1-mini and openrouter/openai/gpt-4.1-mini models 2025-04-14 14:42:20 -07:00
Paul Gauthier
8e1e2210dd feat: Add model settings for gpt-4.1-mini 2025-04-14 14:42:20 -07:00
Paul Gauthier (aider)
e8c43c36d7 fix: Shorten long comment line in patch_coder.py 2025-04-14 14:37:03 -07:00
Paul Gauthier (aider)
97e2a7bae0 fix: Correct spacing in patch_coder.py for accurate matching 2025-04-14 14:36:54 -07:00
Paul Gauthier (aider)
6b75a578ac style: Fix linting errors in patch_coder.py 2025-04-14 14:36:42 -07:00
Paul Gauthier (aider)
8b9238ebc9 style: Run linter on patch_coder.py 2025-04-14 14:36:27 -07:00
Paul Gauthier (aider)
8cc8027b40 feat: Create PatchCoder for applying patch-formatted code edits 2025-04-14 14:36:24 -07:00
Paul Gauthier (aider)
ffb743e108 feat: Add openai/gpt-4.1 and openrouter/openai/gpt-4.1 model settings 2025-04-14 14:26:48 -07:00
Paul Gauthier
0f805752d3 feat: Add gpt-4.1 model settings 2025-04-14 14:26:18 -07:00
Paul Gauthier (aider)
4e9de4d51b style: Add margin below leaderboard title for better spacing 2025-04-14 14:08:52 -07:00
Paul Gauthier (aider)
a4e9539040 feat: Dynamically update leaderboard title based on view mode 2025-04-14 14:04:35 -07:00
Paul Gauthier
0c383dfb11 copy 2025-04-13 13:55:34 -07:00
Paul Gauthier (aider)
11d2b7ca98 style: Adjust tear line height and position in leaderboard table 2025-04-13 13:54:37 -07:00
Paul Gauthier (aider)
e38be2f280 feat: Add dashed tear line to leaderboard bar transition 2025-04-13 13:54:03 -07:00
Paul Gauthier (aider)
febdd3c0d0 style: Extend striped cap on leaderboard bars to 15% 2025-04-13 13:52:32 -07:00
Paul Gauthier (aider)
0b08ca64a8 feat: Add diagonal stripes to large cost bars for hazard pattern 2025-04-13 13:50:59 -07:00
Paul Gauthier (aider)
0f8e7fbd34 feat: Remove cost bar tear line, keep dark end cap 2025-04-13 13:44:23 -07:00
Paul Gauthier (aider)
1a080ba71c feat: Remove numeric labels below cost bars in leaderboard table 2025-04-13 13:43:32 -07:00
Paul Gauthier (aider)
1622531d85 feat: Remove cost exceeded marker from leaderboard table 2025-04-13 13:42:35 -07:00
Paul Gauthier
7d0a9c7233 fix: Adjust cost tear marker position in leaderboards 2025-04-13 13:42:34 -07:00
Paul Gauthier (aider)
53a64c88ad feat: Color the cost bar past the tear marker darker blue 2025-04-13 13:37:56 -07:00
Paul Gauthier (aider)
27b51d51d8 feat: Draw tear across cost bar for exceeded costs on leaderboard 2025-04-13 13:37:01 -07:00
Paul Gauthier
bec35e0538 docs: Shorten "Cost (max $50)" to "Cost" in leaderboards table header 2025-04-13 13:37:00 -07:00
Paul Gauthier (aider)
f65e6a3bb1 feat: Limit cost bar to $50, mark bars exceeding, add tick labels 2025-04-13 13:35:47 -07:00
Paul Gauthier (aider)
fd94f1a5f9 fix: Remove log scale from leaderboard cost column header 2025-04-13 13:34:11 -07:00
Paul Gauthier (aider)
09fc037d4d feat: stop using log-scale for costs on the leaderboard 2025-04-13 13:34:06 -07:00
Paul Gauthier (aider)
cf0e6dac61 style: Set height on table rows instead of min-height on cells 2025-04-13 12:44:02 -07:00
Paul Gauthier (aider)
3b10e3bcb5 style: Use min-height for leaderboard table data cells 2025-04-13 12:43:18 -07:00
Paul Gauthier (aider)
4c17784444 style: Set consistent row height in leaderboards table 2025-04-13 12:41:28 -07:00
Paul Gauthier
6616f0886d copy 2025-04-13 11:59:09 -07:00
Paul Gauthier (aider)
dcafab2764 style: Improve leaderboard layout on narrow screens 2025-04-13 11:58:03 -07:00
Paul Gauthier
3b6146301f fix: Improve leaderboard table layout for better readability 2025-04-13 11:58:02 -07:00
Paul Gauthier
42e09b3c7f docs: Improve leaderboard column header for edit format 2025-04-13 11:52:48 -07:00
Paul Gauthier (aider)
73da42bee6 feat: Use percent_cases_well_formed for leaderboard conform rate 2025-04-13 11:51:24 -07:00
Paul Gauthier (aider)
415b1cf5f0 feat: Update label for conform_rate_2 to be more descriptive 2025-04-13 11:50:45 -07:00
Paul Gauthier (aider)
c011285904 feat: Add % conform and edit format columns to leaderboard table 2025-04-13 11:50:09 -07:00
Paul Gauthier
4314b4fefb copy 2025-04-13 11:22:53 -07:00
Paul Gauthier (aider)
d686f6844d style: Apply left border only to the first column in view mode 2025-04-13 11:08:49 -07:00
Paul Gauthier (aider)
65a0e5f771 style: Apply left border and subtle background to highlighted rows 2025-04-13 11:08:18 -07:00
Paul Gauthier
5ca6d8ce67 style: Change leaderboard highlight color to light yellow 2025-04-13 11:08:17 -07:00
Paul Gauthier (aider)
688c2b9ee5 style: Change leaderboard highlight color to light peach 2025-04-13 10:53:40 -07:00
Paul Gauthier (aider)
271f39505c style: Change view-highlighted background to light yellow 2025-04-13 10:53:11 -07:00
Paul Gauthier (aider)
3e8367ea3b style: Use light green for highlighted leaderboard rows 2025-04-13 10:52:21 -07:00
Paul Gauthier (aider)
67a1e52259 docs: Add kind words from kache (@yacineMTB) 2025-04-13 10:43:24 -07:00
Paul Gauthier
7561687b7b copy 2025-04-13 10:35:27 -07:00
Paul Gauthier
93fc7acbe3 copy 2025-04-13 10:34:33 -07:00
Paul Gauthier (aider)
72dc67950f docs: Fix link to reasoning settings documentation 2025-04-13 10:33:36 -07:00
Paul Gauthier (aider)
e2bebd1d51 docs: Note Grok 3 Mini supports --reasoning-effort flag 2025-04-13 10:33:11 -07:00
Paul Gauthier
03560d3386 docs: Add trailing newline to xai.md 2025-04-13 10:33:10 -07:00
Paul Gauthier (aider)
a3a3303a83 docs: List all Grok-3 and Grok-3-mini models in xai.md 2025-04-13 10:32:42 -07:00
Paul Gauthier
232a6f87d2 docs: Update xAI model names and usage instructions 2025-04-13 10:32:41 -07:00
Paul Gauthier (aider)
ab71ea0a65 feat: Add grok-3-fast and grok-3-mini-fast model configurations 2025-04-13 10:31:53 -07:00
Paul Gauthier (aider)
1302224f39 style: Make close button smaller and more compact 2025-04-13 09:54:18 -07:00
Paul Gauthier (aider)
733bf0dcdf feat: Add close button to hide leaderboard controls container 2025-04-13 09:52:32 -07:00
Paul Gauthier (aider)
4ed48178a9 fix: Improve leaderboard toggle button responsiveness on iOS Safari 2025-04-13 09:50:47 -07:00
Paul Gauthier
8cffb975d9 docs: Clarify Aider's LLM evaluation criteria and add polyglot link 2025-04-13 09:47:32 -07:00
Paul Gauthier
97b18797a4 copy 2025-04-13 09:16:18 -07:00
Paul Gauthier (aider)
579794b265 feat: Show only selected rows in 'View' mode if selections exist 2025-04-13 09:15:00 -07:00
Paul Gauthier (aider)
bea746595e feat: Hide first column in leaderboard table when in 'View' mode 2025-04-13 09:13:42 -07:00
Paul Gauthier (aider)
87711b048a feat: Implement three-state mode (View/Select/Detail) for leaderboard 2025-04-13 09:11:54 -07:00
Paul Gauthier
0b468ebd85 copy 2025-04-13 08:57:33 -07:00
Paul Gauthier
aefc250e30 move 2025-04-13 08:57:12 -07:00
Paul Gauthier (aider)
4a86fea86b refactor: Move script tags to markdown, include only js code 2025-04-13 08:56:36 -07:00
Paul Gauthier (aider)
fe6e2e1ea7 Refactor: Embed leaderboard script using Jekyll include tag 2025-04-13 08:55:44 -07:00
Paul Gauthier (aider)
09d90b9b70 Refactor: Move leaderboard table JS to external file for better caching. 2025-04-13 08:55:14 -07:00
Paul Gauthier
14eb7b46a2 feat: Add leaderboard table javascript file 2025-04-13 08:55:13 -07:00
Paul Gauthier (aider)
66077fe3a4 feat: Implement row highlighting in view mode for leaderboards 2025-04-13 08:52:58 -07:00
Paul Gauthier (aider)
d50cf806db feat: Add row click listener for checkbox toggle in select mode 2025-04-13 08:50:32 -07:00
Paul Gauthier (aider)
95edae9bd1 style: Style active leaderboard mode button with JS, remove CSS rule 2025-04-13 08:48:43 -07:00
Paul Gauthier (aider)
a6c35305ed style: Adjust active mode toggle button colors for contrast 2025-04-13 08:48:00 -07:00
Paul Gauthier (aider)
b382005a4c style: Remove inline background color from "View" button 2025-04-13 08:46:02 -07:00
Paul Gauthier (aider)
a71b90bdd6 feat: Implement toggle buttons for view mode selection 2025-04-13 08:44:49 -07:00
Paul Gauthier (aider)
d4a68c80bc feat: Replace dropdown with segmented button group for view mode 2025-04-13 08:44:36 -07:00
Paul Gauthier (aider)
fcf44cbebe fix: Only apply row-selected class in 'select' mode 2025-04-13 08:41:12 -07:00
Paul Gauthier (aider)
51d8cb063a feat: Simplify leaderboard modes to 'View' and 'Select' 2025-04-13 08:40:30 -07:00
Paul Gauthier (aider)
cdc86565cc Refactor: Update leaderboard dropdown option text for clarity 2025-04-13 08:39:05 -07:00
Paul Gauthier (aider)
1c54907b30 style: Improve leaderboard controls appearance with CSS styling 2025-04-13 08:38:13 -07:00
Paul Gauthier (aider)
b6d4246e18 feat: Replace segmented buttons with dropdown for view mode selection 2025-04-13 08:37:47 -07:00
Paul Gauthier (aider)
cc1a984c7e feat: Replace clear selection button with select all checkbox 2025-04-13 08:35:37 -07:00
Paul Gauthier (aider)
52d39657ab feat: Implement table view modes, row selection, and search filter 2025-04-13 08:33:14 -07:00
Paul Gauthier (aider)
363ec82a48 feat: Implement leaderboard view mode toggle (All/Select/Selected) 2025-04-13 08:32:54 -07:00
Paul Gauthier (aider)
f164b0e3eb style: Adjust font size of numbers in leaderboard bars 2025-04-13 08:12:10 -07:00
Paul Gauthier (aider)
3aaf7a69ec style: Adjust leaderboard number positioning in bar cells 2025-04-13 01:20:41 -07:00
Paul Gauthier (aider)
6d2828bc3c style: Update cost bar color in leaderboards docs 2025-04-13 00:46:57 -07:00
Paul Gauthier (aider)
dd6e2051a8 Style: Improve leaderboard table borders for visual clarity 2025-04-13 00:44:12 -07:00
Paul Gauthier (aider)
ef440972bb Refactor: Remove chart and add margin to post date in leaderboard 2025-04-13 00:42:37 -07:00
Paul Gauthier (aider)
da96888669 style: Hide command column on small screens in leaderboards 2025-04-13 00:41:44 -07:00
Paul Gauthier (aider)
75639059e1 style: Make toggle symbols more subtle by changing their color 2025-04-13 00:40:44 -07:00
Paul Gauthier (aider)
0a15dd311a feat: Use Unicode triangles for leaderboard toggle button 2025-04-13 00:40:19 -07:00
Paul Gauthier (aider)
434a1c6710 feat: Replace +/- with chevron icons for leaderboard details toggle 2025-04-13 00:39:24 -07:00
Paul Gauthier (aider)
f961eecab6 Feat: Add toggleable detail view to leaderboard table 2025-04-12 23:44:43 -07:00
Paul Gauthier (aider)
d33a571f7d Refactor: Remove edit-format column from leaderboards 2025-04-12 23:40:54 -07:00
Paul Gauthier
ea1239efef Docs: Clarify polyglot benchmark measures edits without intervention. 2025-04-12 23:40:53 -07:00
Paul Gauthier (aider)
19c7c7a9dc Docs: Make leaderboards intro text more concise 2025-04-12 23:37:16 -07:00
Paul Gauthier (aider)
49e4af4fab fix: Display '?' for zero or rounded-to-zero costs in leaderboards 2025-04-12 23:32:35 -07:00
Paul Gauthier (aider)
3e27c1bb17 feat: Only add cost ticks if the cost is greater than zero 2025-04-12 23:32:01 -07:00
Paul Gauthier (aider)
0f8d196741 style: Increase font size of leaderboard bar chart numbers 2025-04-12 23:30:29 -07:00
Paul Gauthier
4c45f0e44b style: Improve leaderboard bar chart tick visibility 2025-04-12 23:30:28 -07:00
Paul Gauthier (aider)
e39eef1ed7 style: Align ticks with bottom edge of leaderboard bars 2025-04-12 23:26:21 -07:00
Paul Gauthier
c9c7aea1c4 docs: Improve leaderboard cost visualization and table layout 2025-04-12 23:26:05 -07:00
Paul Gauthier (aider)
18ff9eb2b4 style: Make tick color lighter in leaderboards 2025-04-12 23:23:36 -07:00
Paul Gauthier (aider)
b2f3d2cd84 style: Improve visibility of ticks in leaderboard progress bars 2025-04-12 23:23:03 -07:00
Paul Gauthier (aider)
5e0832cb8b feat: Add percentage ticks to leaderboard percentage columns 2025-04-12 23:21:38 -07:00
Paul Gauthier (aider)
a14c0ccac6 style: Align cost-tick height with bar height in leaderboards 2025-04-12 23:20:56 -07:00
Paul Gauthier (aider)
278f90acdd fix: Add tick at base of cost column bars in leaderboards 2025-04-12 23:20:08 -07:00
Paul Gauthier (aider)
8e8b18e9a9 fix: Align ticks in bar table cells to 0%, 10%, 20%, etc. 2025-04-12 23:18:47 -07:00
Paul Gauthier (aider)
a277d74869 feat: Add dynamic cost ticks to leaderboards page cost bars 2025-04-12 23:14:21 -07:00
Paul Gauthier (aider)
7ca3b6455d feat: Add tick marks to leaderboard % correct and cost columns 2025-04-12 23:14:08 -07:00
Paul Gauthier (aider)
5ec6f69037 feat: Add tick marks to table bar graph cells 2025-04-12 23:13:04 -07:00
Paul Gauthier (aider)
39962ba5eb style: Remove internal cell borders from leaderboards table 2025-04-12 23:10:55 -07:00
Paul Gauthier (aider)
51fa1f9abd Refactor: Remove "Percent using correct edit format" column 2025-04-12 23:10:18 -07:00
Paul Gauthier
47af5d463c docs: Clarify cost column in leaderboards is log scale 2025-04-12 23:10:17 -07:00
Paul Gauthier (aider)
33f0b0b41c fix: Remove invalid Liquid comment from leaderboards page 2025-04-12 23:08:57 -07:00
Paul Gauthier (aider)
48038b1f5e feat: Use log scale for cost bar in leaderboards table 2025-04-12 23:08:28 -07:00
Paul Gauthier (aider)
323698d387 style: Remove box-shadow from bar graph numeric text container 2025-04-12 20:53:06 -07:00
Paul Gauthier (aider)
1f702beb74 style: Improve legibility of numbers in leaderboard table cells 2025-04-12 20:49:12 -07:00
Paul Gauthier
7d34c28af1 style: Reduce height of leaderboard progress bars 2025-04-12 20:47:02 -07:00
Paul Gauthier (aider)
d26be77010 feat: Hide cost bar if cost is 0 or unknown in leaderboards table 2025-04-12 20:45:29 -07:00
Paul Gauthier (aider)
3b96d1bd57 fix: Adjust bar-viz height in leaderboards page CSS 2025-04-12 20:43:07 -07:00
Paul Gauthier (aider)
48fd0e71d5 style: Increase bar height and fix colors in leaderboards 2025-04-12 20:42:58 -07:00
Paul Gauthier
bcb35ccf44 style: Reduce leaderboard bar height for better readability 2025-04-12 20:42:58 -07:00
Paul Gauthier (aider)
a663ff7fa8 style: Make leaderboard bars 2x taller 2025-04-12 20:40:46 -07:00
Paul Gauthier (aider)
813d34a0e9 style: Fix inconsistent bar heights in leaderboards table 2025-04-12 20:40:18 -07:00
Paul Gauthier (aider)
a4074a13c4 fix: Swap colors of leaderboard columns for correct display 2025-04-12 20:25:35 -07:00
Paul Gauthier (aider)
249f329b07 fix: Correct leaderboard bar colors and logic for accuracy 2025-04-12 20:24:51 -07:00
Paul Gauthier (aider)
cf160a8f84 fix: Swap colors of leaderboard columns 2 and 3 2025-04-12 20:23:45 -07:00
Paul Gauthier (aider)
4db963182d feat: Add color variation to cost bars in leaderboards 2025-04-12 20:21:38 -07:00
Paul Gauthier (aider)
199b59fdb9 feat: Improve table-as-bar-graph with color variation based on value 2025-04-12 20:21:08 -07:00
Paul Gauthier (aider)
2d09bfa0f3 feat: Implement dedicated bar element inside table cells for visualization 2025-04-12 20:15:28 -07:00
Paul Gauthier (aider)
729285e8a2 refactor: Move cost column in leaderboards table to be after percent 2025-04-12 20:13:05 -07:00
Paul Gauthier (aider)
afd17bd96a style: Improve leaderboard table styling with padding and bar adjustments 2025-04-12 20:11:09 -07:00
Paul Gauthier (aider)
380d8570dc fix: Remove visible Liquid comment from leaderboard page 2025-04-12 20:09:38 -07:00
Paul Gauthier (aider)
e711eaa810 feat: Add horizontal bar graphs to leaderboard numerical columns 2025-04-12 20:08:35 -07:00
Paul Gauthier
7dfdc2094e refactor: Use EditBlockFencedPrompts directly in EditorDiffFencedPrompts 2025-04-12 20:04:04 -07:00
Paul Gauthier (aider)
838646ac5b refactor: EditorDiffFencedCoder inherits from EditBlockFencedCoder 2025-04-12 19:57:10 -07:00
Paul Gauthier (aider)
507f07575b feat: Add diff-fenced to copy-paste edit format prefixing 2025-04-12 19:55:53 -07:00
Paul Gauthier (aider)
f5e8808770 feat: Add "diff-fenced" to editor edit format options. 2025-04-12 19:55:35 -07:00
Paul Gauthier (aider)
ae5b6e88a5 feat: Enable EditorDiffFencedCoder by adding it to __init__.py 2025-04-12 19:55:10 -07:00
Paul Gauthier (aider)
b45186dde0 feat: Add editor-diff-fenced coder and prompts classes 2025-04-12 19:52:43 -07:00
Paul Gauthier
38be8aa0da copy 2025-04-12 17:12:10 -07:00
Paul Gauthier (aider)
816d4ba206 docs: Add kind words from koleok to README 2025-04-12 17:10:29 -07:00
Paul Gauthier
ede59e4d2a docs: Fix typo in README quote from joseph stalzyn 2025-04-12 17:10:28 -07:00
Paul Gauthier (aider)
ce0931a3c8 docs: Add kind words from users to README 2025-04-12 17:08:37 -07:00
Paul Gauthier
a44e148818 feat: Add go_ahead_tip and rename_with_shell to editblock prompts 2025-04-12 17:04:12 -07:00
Paul Gauthier
71115c6558 feat: Add editor-diff and editor-whole edit formats 2025-04-12 16:44:13 -07:00
Paul Gauthier
8ae837e98b copy 2025-04-12 15:49:42 -07:00
Paul Gauthier
9518193d0a set version to 0.81.4.dev 2025-04-12 13:25:55 -07:00
Paul Gauthier
60a2b799e6 version bump to 0.81.3 2025-04-12 13:25:52 -07:00
Paul Gauthier
9d7dc00f25 copy 2025-04-12 08:58:50 -07:00
Paul Gauthier
882e7b6716 bump deps 2025-04-12 08:58:09 -07:00
Paul Gauthier
8ba29ee8e6 copy 2025-04-12 08:57:18 -07:00
Paul Gauthier
3f67c41759 copy 2025-04-12 08:09:46 -07:00
Paul Gauthier
7fbeafa1cf copy 2025-04-12 08:06:39 -07:00
Paul Gauthier
028257480b copy 2025-04-11 14:26:04 +12:00
Paul Gauthier
e42a0c45b6 Merge branch 'main' of github.com:Aider-AI/aider 2025-04-11 14:18:07 +12:00
Paul Gauthier
1e7f8549ff add grok3mini high 2025-04-11 14:11:39 +12:00
paul-gauthier
668de71f9d Merge pull request #3776 from peterhadlaw/master
Do not lowercase the _entirety_ of the commit message
2025-04-11 14:01:03 +12:00
Paul Gauthier
067245b810 chore: update grok model settings to remove/comment out params 2025-04-11 13:41:11 +12:00
Peter Hadlaw
8f236c69e1 fix: Do not lowercase the entirety of the commit message 2025-04-10 20:08:40 -05:00
Paul Gauthier
8ee33da114 copy 2025-04-11 09:08:06 +12:00
Paul Gauthier (aider)
2fedc2e699 feat: update openrouter badges to link to options menu 2025-04-11 08:38:22 +12:00
Paul Gauthier
1961543e2f set version to 0.81.3.dev 2025-04-11 08:37:59 +12:00
Paul Gauthier
b4f65734a5 version bump to 0.81.2 2025-04-11 08:37:56 +12:00
Paul Gauthier (aider)
0eb80553f6 style: Apply linter to versionbump.py 2025-04-11 08:37:37 +12:00
Paul Gauthier (aider)
110c63ae95 feat: Add --force flag to skip pre-push checks 2025-04-11 08:37:33 +12:00
Paul Gauthier
57304536bf copy 2025-04-11 08:23:16 +12:00
Paul Gauthier
a9ca5da139 feat: add grok-3-mini-beta to model settings with reasoning_effort 2025-04-11 08:22:44 +12:00
Paul Gauthier
947aebfbe0 copy 2025-04-11 08:13:15 +12:00
Paul Gauthier
fafc9268d4 feat: set grok-3-mini-beta edit_format to whole 2025-04-11 08:12:38 +12:00
Paul Gauthier
65a5d55436 feat: add grok-3-beta and grok-3-mini-beta model settings 2025-04-11 08:10:18 +12:00
Paul Gauthier (aider)
96b350400f feat: make highlight parameter case-insensitive in leaderboard 2025-04-11 07:28:01 +12:00
Paul Gauthier
7983b4caf2 copy 2025-04-11 07:25:10 +12:00
Paul Gauthier (aider)
e44122f1be fix: correct groq to grok typo in model settings yaml 2025-04-11 07:23:16 +12:00
Paul Gauthier (aider)
42618d7ec6 fix: correct groq to grok typos in model names and aliases 2025-04-11 07:23:05 +12:00
Paul Gauthier
1d0167bbf4 feat: add polyglot leaderboard entries for grok3 and optimus alpha 2025-04-11 07:17:56 +12:00
Paul Gauthier (aider)
43d4b21b23 feat: add "optimus" alias for openrouter model 2025-04-11 07:12:27 +12:00
Paul Gauthier (aider)
562171c548 feat: add grok3 alias for xai/groq-3-beta 2025-04-11 07:12:09 +12:00
Paul Gauthier (aider)
8dccecdd9f feat: add xai/groq-3-beta and xai/groq-3-mini-beta models 2025-04-11 07:10:23 +12:00
Paul Gauthier
940ae364d7 feat: add model settings for grok-3-beta, grok-3-mini-beta, optimus-alpha 2025-04-11 07:09:27 +12:00
Paul Gauthier (aider)
532bc454c5 feat: add openrouter/openrouter/optimus-alpha model metadata 2025-04-11 06:54:12 +12:00
Paul Gauthier (aider)
14ffe7782c feat: add openrouter/x-ai/grok-3-mini-beta model metadata 2025-04-11 06:37:33 +12:00
Paul Gauthier (aider)
2dd40fce44 feat: add openrouter/x-ai/grok-3-beta model metadata 2025-04-10 16:18:22 +12:00
Paul Gauthier (aider)
0c8bc46e28 fix: strip trailing } from urls extracted from error messages 2025-04-10 16:06:07 +12:00
Paul Gauthier
7d0dd29937 Merge branch 'main' of github.com:Aider-AI/aider 2025-04-08 18:33:41 +12:00
Paul Gauthier
349cd77821 copy 2025-04-08 08:10:21 +12:00
paul-gauthier
dc2d7b1dfe Merge pull request #3752 from tylersatre/main 2025-04-08 06:31:41 +12:00
Tyler Satre
be30329288 Update azure documentation 2025-04-07 11:04:15 -04:00
Paul Gauthier
71446d9f3c fix: get_file_mentions skips pure basenames with duplicates 2025-04-07 13:22:05 +12:00
Paul Gauthier (aider)
c9d4c8d09b fix: allow adding files by full path with existing basename 2025-04-07 13:19:25 +12:00
Paul Gauthier (aider)
c580ffdb70 test: add test for multiline backtick file mentions 2025-04-07 13:14:27 +12:00
Paul Gauthier
f46deb4eb7 improve diff-fenced prompts 2025-04-07 08:54:01 +12:00
Paul Gauthier
b3215bed48 copy 2025-04-07 08:13:22 +12:00
Paul Gauthier
2a9ab02753 chore: update polyglot leaderboard data 2025-04-07 08:12:37 +12:00
Paul Gauthier (aider)
0da586154d fix: quote values with '#' in sample aider.conf.yml config 2025-04-07 08:09:33 +12:00
Paul Gauthier
26d736551d Merge branch 'main' of github.com:Aider-AI/aider 2025-04-07 08:05:15 +12:00
paul-gauthier
9445a3118b Merge pull request #3733 from banjo/main 2025-04-06 07:28:56 +12:00
paul-gauthier
a2c46c7436 Merge pull request #3735 from KennyDizi/main 2025-04-06 07:20:22 +12:00
paul-gauthier
8df7a0960e Merge pull request #3736 from FelixLisczyk/tl-173 2025-04-06 07:19:30 +12:00
Felix Lisczyk
e7f35e7a35 Add Fireworks AI model 'deepseek-v3-0324' 2025-04-05 16:33:09 +02:00
Kenny Dizi
088e80e38b Add support model openrouter/google/gemini-2.5-pro-preview-03-25 2025-04-05 20:53:06 +07:00
Kenny Dizi
2d65c7f387 Remove trailing spaces 2025-04-05 20:51:11 +07:00
Anton Ödman
94db758eb7 fix: follow conventional commits examples by going all lowercase 2025-04-05 13:07:34 +02:00
Paul Gauthier
2bfb615d68 set version to 0.81.2.dev 2025-04-05 09:01:12 +13:00
Paul Gauthier
87275140f9 version bump to 0.81.1 2025-04-05 09:01:09 +13:00
Paul Gauthier
0672a68ba4 copy 2025-04-05 08:58:10 +13:00
Paul Gauthier (aider)
246e3ccfad refactor: Rename gemini-free alias to gemini-exp in MODEL_ALIASES 2025-04-05 08:56:56 +13:00
Paul Gauthier (aider)
b275ee919f feat: Update gemini model alias and add gemini-free alias 2025-04-05 08:56:35 +13:00
Paul Gauthier (aider)
eda796d5e0 feat: Add metadata and settings for gemini-2.5-pro-preview-03-25 2025-04-05 08:54:45 +13:00
Paul Gauthier
d1b3917309 copy 2025-04-04 22:08:49 +13:00
Paul Gauthier
ffee2b971f blame 2025-04-04 22:08:08 +13:00
85 changed files with 5482 additions and 1674 deletions

View File

@@ -1,5 +1,64 @@
# Release history
### main branch
- Add support for `gemini-2.5-flash-preview-04-17` models.
- Improved robustness of edit block parsing when filenames start with backticks or fences.
- Add new `udiff-simple` edit format, for Gemini 2.5 Pro.
- Update default weak/editor models for Gemini 2.5 Pro models to use `gemini-2.5-flash-preview-04-17`.
- Instruct models to reply in the user's detected system language.
- Fix parsing of diffs for newly created files (`--- /dev/null`).
- Add markdown syntax highlighting support when editing multi-line commit messages via `/commit`, by Kay Gosho.
- Set Gemini 2.5 Pro models to use the `overeager` prompt setting by default.
- Add common file types (`.svg`, `.pdf`) and IDE directories (`.idea/`, `.vscode/`, etc.) to the default list of ignored files for AI comment scanning (`--watch`).
- Skip scanning files larger than 1MB for AI comments (`--watch`).
- Aider wrote 67% of the code in this release.
### Aider v0.82.2
- Fix editing shell files with diff-fenced, by zjy1412.
- Improve robustness of patch application by allowing multiple update/delete actions for the same file within a single response.
- Update prompts to instruct LLMs to consolidate all edits for a given file into a single block within the patch.
### Aider v0.82.1
- Added support for `o3` and `o4-mini` including provider-specific versions for OpenAI, OpenRouter, and Azure.
- Added support for Azure specific `gpt-4.1` and `gpt-4.1-mini` models.
- Disabled streaming for `o3` models since you need identity verification to stream.
- Fixed handling of file paths in unified diffs, especially those generated by git.
### Aider v0.82.0
- Support for GPT 4.1, mini and nano.
- Added new `patch` edit format for OpenAI's GPT-4.1 model.
- Improved support for using architect mode with Gemini 2.5 Pro.
- Added new `editor-diff`, `editor-whole`, and `editor-diff-fenced` edit formats.
- Bugfix for automatically selecting the best edit format to use in architect mode.
- Added support for `grok-3-fast-beta` and `grok-3-mini-fast-beta` models.
- Aider wrote 92% of the code in this release.
### Aider v0.81.3
- Commit messages generated by aider are no longer forced to be entirely lowercase, by Peter Hadlaw.
- Updated default settings for Grok models.
### Aider v0.81.2
- Add support for `xai/grok-3-beta`, `xai/grok-3-mini-beta`, `openrouter/x-ai/grok-3-beta`, `openrouter/x-ai/grok-3-mini-beta`, and `openrouter/openrouter/optimus-alpha` models.
- Add alias "grok3" for `xai/grok-3-beta`.
- Add alias "optimus" for `openrouter/openrouter/optimus-alpha`.
- Fix URL extraction from error messages.
- Allow adding files by full path even if a file with the same basename is already in the chat.
- Fix quoting of values containing '#' in the sample `aider.conf.yml`.
- Add support for Fireworks AI model 'deepseek-v3-0324', by Felix Lisczyk.
- Commit messages generated by aider are now lowercase, by Anton Ödman.
### Aider v0.81.1
- Added support for the `gemini/gemini-2.5-pro-preview-03-25` model.
- Updated the `gemini` alias to point to `gemini/gemini-2.5-pro-preview-03-25`.
- Added the `gemini-exp` alias for `gemini/gemini-2.5-pro-exp-03-25`.
### Aider v0.81.0
- Added support for the `openrouter/openrouter/quasar-alpha` model.

View File

@@ -27,13 +27,13 @@ cog.out(text)
<a href="https://github.com/Aider-AI/aider/stargazers"><img alt="GitHub Stars" title="Total number of GitHub stars the Aider project has received"
src="https://img.shields.io/github/stars/Aider-AI/aider?style=flat-square&logo=github&color=f1c40f&labelColor=555555"/></a>
<a href="https://pypi.org/project/aider-chat/"><img alt="PyPI Downloads" title="Total number of installations via pip from PyPI"
src="https://img.shields.io/badge/📦%20Installs-1.8M-2ecc71?style=flat-square&labelColor=555555"/></a>
src="https://img.shields.io/badge/📦%20Installs-2.1M-2ecc71?style=flat-square&labelColor=555555"/></a>
<img alt="Tokens per week" title="Number of tokens processed weekly by Aider users"
src="https://img.shields.io/badge/📈%20Tokens%2Fweek-15B-3498db?style=flat-square&labelColor=555555"/>
<a href="https://openrouter.ai/"><img alt="OpenRouter Ranking" title="Aider's ranking among applications on the OpenRouter platform"
<a href="https://openrouter.ai/#options-menu"><img alt="OpenRouter Ranking" title="Aider's ranking among applications on the OpenRouter platform"
src="https://img.shields.io/badge/🏆%20OpenRouter-Top%2020-9b59b6?style=flat-square&labelColor=555555"/></a>
<a href="https://aider.chat/HISTORY.html"><img alt="Singularity" title="Percentage of the new code in Aider's last release written by Aider itself"
src="https://img.shields.io/badge/🔄%20Singularity-87%25-e74c3c?style=flat-square&labelColor=555555"/></a>
src="https://img.shields.io/badge/🔄%20Singularity-92%25-e74c3c?style=flat-square&labelColor=555555"/></a>
<!--[[[end]]]-->
</p>
@@ -140,6 +140,7 @@ See the [installation instructions](https://aider.chat/docs/install.html) and [u
## Kind Words From Users
- *"My life has changed... There's finally an AI coding tool that's good enough to keep up with me... Aider... It's going to rock your world."* — [Eric S. Raymond](https://x.com/esrtweet/status/1910809356381413593)
- *"The best free open source AI coding assistant."* — [IndyDevDan](https://youtu.be/YALpX8oOn78)
- *"The best AI coding assistant so far."* — [Matthew Berman](https://www.youtube.com/watch?v=df8afeb1FY8)
- *"Aider ... has easily quadrupled my coding productivity."* — [SOLAR_FIELDS](https://news.ycombinator.com/item?id=36212100)
@@ -167,6 +168,10 @@ See the [installation instructions](https://aider.chat/docs/install.html) and [u
- *"Aider is also my best friend."* — [jzn21](https://www.reddit.com/r/ChatGPTCoding/comments/1heuvuo/aider_vs_cline_vs_windsurf_vs_cursor/m27dcnb/)
- *"Try Aider, it's worth it."* — [jorgejhms](https://www.reddit.com/r/ChatGPTCoding/comments/1heuvuo/aider_vs_cline_vs_windsurf_vs_cursor/m27cp99/)
- *"I like aider :)"* — [Chenwei Cui](https://x.com/ccui42/status/1904965344999145698)
- *"Aider is the precision tool of LLM code gen. It is minimal, thoughtful and capable of surgical changes to your codebase all while keeping the developer in control."* — [Reilly Sweetland](https://x.com/rsweetland/status/1904963807237259586)
- *"Aider is the precision tool of LLM code gen... Minimal, thoughtful and capable of surgical changes to your codebase all while keeping the developer in control."* — [Reilly Sweetland](https://x.com/rsweetland/status/1904963807237259586)
- *"Cannot believe aider vibe coded a 650 LOC feature across service and cli today in 1 shot."* - [autopoietist](https://discord.com/channels/1131200896827654144/1131200896827654149/1355675042259796101)
- *"Oh no the secret is out! Yes, Aider is the best coding tool around. I highly, highly recommend it to anyone."* — [Joshua D Vander Hook](https://x.com/jodavaho/status/1911154899057795218)
- *"thanks to aider, i have started and finished three personal projects within the last two days"* — [joseph stalzyn](https://x.com/anitaheeder/status/1908338609645904160)
- *"Been using aider as my daily driver for over a year ... I absolutely love the tool, like beyond words."* — [koleok](https://discord.com/channels/1131200896827654144/1273248471394291754/1356727448372252783)
- *"aider is really cool"* — [kache (@yacineMTB)](https://x.com/yacineMTB/status/1911224442430124387)

View File

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

View File

@@ -143,7 +143,10 @@ class YamlHelpFormatter(argparse.HelpFormatter):
default = "true"
if default:
parts.append(f"#{switch}: {default}\n")
if "#" in default:
parts.append(f'#{switch}: "{default}"\n')
else:
parts.append(f"#{switch}: {default}\n")
elif action.nargs in ("*", "+") or isinstance(action, argparse._AppendAction):
parts.append(f"#{switch}: xxx")
parts.append("## Specify multiple values like this:")

View File

@@ -4,10 +4,13 @@ from .base_coder import Coder
from .context_coder import ContextCoder
from .editblock_coder import EditBlockCoder
from .editblock_fenced_coder import EditBlockFencedCoder
from .editor_diff_fenced_coder import EditorDiffFencedCoder
from .editor_editblock_coder import EditorEditBlockCoder
from .editor_whole_coder import EditorWholeFileCoder
from .help_coder import HelpCoder
from .patch_coder import PatchCoder
from .udiff_coder import UnifiedDiffCoder
from .udiff_simple import UnifiedDiffSimpleCoder
from .wholefile_coder import WholeFileCoder
# from .single_wholefile_func_coder import SingleWholeFileFunctionCoder
@@ -19,10 +22,13 @@ __all__ = [
EditBlockCoder,
EditBlockFencedCoder,
WholeFileCoder,
PatchCoder,
UnifiedDiffCoder,
UnifiedDiffSimpleCoder,
# SingleWholeFileFunctionCoder,
ArchitectCoder,
EditorEditBlockCoder,
EditorWholeFileCoder,
EditorDiffFencedCoder,
ContextCoder,
]

View File

@@ -32,4 +32,4 @@ Here are summaries of some files present in my git repo.
If you need to see the full contents of any files to answer my questions, ask me to *add them to the chat*.
"""
system_reminder = ""
system_reminder = "{final_reminders}"

View File

@@ -15,6 +15,13 @@ import time
import traceback
from collections import defaultdict
from datetime import datetime
# Optional dependency: used to convert locale codes (eg ``en_US``)
# into human-readable language names (eg ``English``).
try:
from babel import Locale # type: ignore
except ImportError: # Babel not installed we will fall back to a small mapping
Locale = None
from json.decoder import JSONDecodeError
from pathlib import Path
from typing import List
@@ -926,7 +933,7 @@ class Coder:
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(".',\"")
url = url.rstrip(".',\"}") # Added } to the characters to strip
self.io.offer_url(url)
return urls
@@ -1011,23 +1018,75 @@ class Coder:
]
self.cur_messages = []
def get_user_language(self):
if self.chat_language:
return self.chat_language
def normalize_language(self, lang_code):
"""
Convert a locale code such as ``en_US`` or ``fr`` into a readable
language name (e.g. ``English`` or ``French``). If Babel is
available it is used for reliable conversion; otherwise a small
built-in fallback map handles common languages.
"""
if not lang_code:
return None
# Probably already a language name
if (
len(lang_code) > 3
and "_" not in lang_code
and "-" not in lang_code
and lang_code[0].isupper()
):
return lang_code
# Preferred: Babel
if Locale is not None:
try:
loc = Locale.parse(lang_code.replace("-", "_"))
return loc.get_display_name("en").capitalize()
except Exception:
pass # Fall back to manual mapping
# Simple fallback for common languages
fallback = {
"en": "English",
"fr": "French",
"es": "Spanish",
"de": "German",
"it": "Italian",
"pt": "Portuguese",
"zh": "Chinese",
"ja": "Japanese",
"ko": "Korean",
"ru": "Russian",
}
return fallback.get(lang_code.split("_")[0].lower(), lang_code)
def get_user_language(self):
"""
Detect the user's language preference and return a human-readable
language name such as ``English``. Detection order:
1. ``self.chat_language`` if explicitly set
2. ``locale.getlocale()``
3. ``LANG`` / ``LANGUAGE`` / ``LC_ALL`` / ``LC_MESSAGES`` environment variables
"""
# Explicit override
if self.chat_language:
return self.normalize_language(self.chat_language)
# System locale
try:
lang = locale.getlocale()[0]
if lang:
return lang # Return the full language code, including country
return self.normalize_language(lang)
except Exception:
pass
pass # pragma: no cover
for env_var in ["LANG", "LANGUAGE", "LC_ALL", "LC_MESSAGES"]:
# Environment variables
for env_var in ("LANG", "LANGUAGE", "LC_ALL", "LC_MESSAGES"):
lang = os.environ.get(env_var)
if lang:
return lang.split(".")[
0
] # Return language and country, but remove encoding if present
lang = lang.split(".")[0] # Strip encoding if present
return self.normalize_language(lang)
return None
@@ -1079,23 +1138,28 @@ class Coder:
return platform_text
def fmt_system_prompt(self, prompt):
final_reminders = []
if self.main_model.lazy:
lazy_prompt = self.gpt_prompts.lazy_prompt
elif self.main_model.overeager:
lazy_prompt = self.gpt_prompts.overeager_prompt
else:
lazy_prompt = ""
final_reminders.append(self.gpt_prompts.lazy_prompt)
if self.main_model.overeager:
final_reminders.append(self.gpt_prompts.overeager_prompt)
user_lang = self.get_user_language()
if user_lang:
final_reminders.append(f"Reply in {user_lang}.\n")
platform_text = self.get_platform_info()
if self.suggest_shell_commands:
shell_cmd_prompt = self.gpt_prompts.shell_cmd_prompt.format(platform=platform_text)
shell_cmd_reminder = self.gpt_prompts.shell_cmd_reminder.format(platform=platform_text)
rename_with_shell = self.gpt_prompts.rename_with_shell
else:
shell_cmd_prompt = self.gpt_prompts.no_shell_cmd_prompt.format(platform=platform_text)
shell_cmd_reminder = self.gpt_prompts.no_shell_cmd_reminder.format(
platform=platform_text
)
rename_with_shell = ""
if self.chat_language:
language = self.chat_language
@@ -1109,13 +1173,17 @@ class Coder:
else:
quad_backtick_reminder = ""
final_reminders = "\n\n".join(final_reminders)
prompt = prompt.format(
fence=self.fence,
quad_backtick_reminder=quad_backtick_reminder,
lazy_prompt=lazy_prompt,
final_reminders=final_reminders,
platform=platform_text,
shell_cmd_prompt=shell_cmd_prompt,
rename_with_shell=rename_with_shell,
shell_cmd_reminder=shell_cmd_reminder,
go_ahead_tip=self.gpt_prompts.go_ahead_tip,
language=language,
)
@@ -1626,10 +1694,6 @@ class Coder:
mentioned_rel_fnames = set()
fname_to_rel_fnames = {}
for rel_fname in addable_rel_fnames:
# Skip files that share a basename with files already in chat
if os.path.basename(rel_fname) in existing_basenames:
continue
normalized_rel_fname = rel_fname.replace("\\", "/")
normalized_words = set(word.replace("\\", "/") for word in words)
if normalized_rel_fname in normalized_words:
@@ -1644,6 +1708,10 @@ class Coder:
fname_to_rel_fnames[fname].append(rel_fname)
for fname, rel_fnames in fname_to_rel_fnames.items():
# If the basename is already in chat, don't add based on a basename mention
if fname in existing_basenames:
continue
# If the basename mention is unique among addable files and present in the text
if len(rel_fnames) == 1 and fname in words:
mentioned_rel_fnames.add(rel_fnames[0])

View File

@@ -15,7 +15,9 @@ You always COMPLETELY IMPLEMENT the needed code!
"""
overeager_prompt = """Pay careful attention to the scope of the user's request.
Do what they ask, but no more."""
Do what they ask, but no more.
Do not improve, comment, fix or modify unrelated parts of the code in any way!
"""
example_messages = []
@@ -53,3 +55,6 @@ Do not edit these files!
shell_cmd_reminder = ""
no_shell_cmd_prompt = ""
no_shell_cmd_reminder = ""
rename_with_shell = ""
go_ahead_tip = ""

View File

@@ -412,7 +412,16 @@ def strip_filename(filename, fence):
return
start_fence = fence[0]
if filename.startswith(start_fence) or filename.startswith(triple_backticks):
if filename.startswith(start_fence):
candidate = filename[len(start_fence) :]
if candidate and ("." in candidate or "/" in candidate):
return candidate
return
if filename.startswith(triple_backticks):
candidate = filename[len(triple_backticks) :]
if candidate and ("." in candidate or "/" in candidate):
return candidate
return
filename = filename.rstrip(":")
@@ -454,7 +463,14 @@ def find_original_update_blocks(content, fence=DEFAULT_FENCE, valid_fnames=None)
"```csh",
"```tcsh",
]
next_is_editblock = i + 1 < len(lines) and head_pattern.match(lines[i + 1].strip())
# Check if the next line or the one after that is an editblock
next_is_editblock = (
i + 1 < len(lines)
and head_pattern.match(lines[i + 1].strip())
or i + 2 < len(lines)
and head_pattern.match(lines[i + 2].strip())
)
if any(line.strip().startswith(start) for start in shell_starts) and not next_is_editblock:
shell_content = []

View File

@@ -19,7 +19,7 @@ class EditBlockFencedPrompts(EditBlockPrompts):
Here are the *SEARCH/REPLACE* blocks:
{fence[0]}
{fence[0]}python
mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
@@ -29,7 +29,7 @@ from flask import Flask
>>>>>>> REPLACE
{fence[1]}
{fence[0]}
{fence[0]}python
mathweb/flask/app.py
<<<<<<< SEARCH
def factorial(n):
@@ -44,7 +44,7 @@ def factorial(n):
>>>>>>> REPLACE
{fence[1]}
{fence[0]}
{fence[0]}python
mathweb/flask/app.py
<<<<<<< SEARCH
return str(factorial(n))
@@ -68,7 +68,7 @@ mathweb/flask/app.py
Here are the *SEARCH/REPLACE* blocks:
{fence[0]}
{fence[0]}python
hello.py
<<<<<<< SEARCH
=======
@@ -79,7 +79,7 @@ def hello():
>>>>>>> REPLACE
{fence[1]}
{fence[0]}
{fence[0]}python
main.py
<<<<<<< SEARCH
def hello():
@@ -93,3 +93,51 @@ from hello import hello
""",
),
]
system_reminder = """
# *SEARCH/REPLACE block* Rules:
Every *SEARCH/REPLACE block* must use this format:
1. The opening fence and code language, eg: {fence[0]}python
2. The *FULL* file path alone on a line, verbatim. No bold asterisks, no quotes around it, no escaping of characters, etc.
3. The start of search block: <<<<<<< SEARCH
4. A contiguous chunk of lines to search for in the existing source code
5. The dividing line: =======
6. The lines to replace into the source code
7. The end of the replace block: >>>>>>> REPLACE
8. The closing fence: {fence[1]}
Use the *FULL* file path, as shown to you by the user.
{quad_backtick_reminder}
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 *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.
Include just the changing lines, and a few surrounding lines if needed for uniqueness.
Do not include long runs of unchanging lines in *SEARCH/REPLACE* blocks.
Only create *SEARCH/REPLACE* blocks for files that the user has added to the chat!
To move code within a file, use 2 *SEARCH/REPLACE* blocks: 1 to delete it from its current location, 1 to insert it in the new location.
Pay attention to which filenames the user wants you to edit, especially if they are asking you to create a new file.
If you want to put code in a new file, use a *SEARCH/REPLACE block* with:
- A new file path, including dir name if needed
- An empty `SEARCH` section
- The new file's contents in the `REPLACE` section
To rename files which have been added to the chat, use shell commands at the end of your response.
If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed.
The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks.
{final_reminders}
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_reminder}
"""

View File

@@ -1,5 +1,6 @@
# flake8: noqa: E501
from . import shell
from .base_prompts import CoderPrompts
@@ -7,7 +8,7 @@ class EditBlockPrompts(CoderPrompts):
main_system = """Act as an expert software developer.
Always use best practices when coding.
Respect and use existing conventions, libraries, etc that are already present in the code base.
{lazy_prompt}
{final_reminders}
Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
@@ -28,32 +29,6 @@ You can keep asking if you then decide you need to edit more files.
All changes to files must use this *SEARCH/REPLACE block* format.
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_prompt}
"""
shell_cmd_prompt = """
4. *Concisely* suggest any shell commands the user might want to run in ```bash blocks.
Just suggest shell commands this way, not example code.
Only suggest complete shell commands that are ready to execute, without placeholders.
Only suggest at most a few shell commands at a time, not more than 1-3, one per line.
Do not suggest multi-line shell commands.
All shell commands will run from the root directory of the user's project.
Use the appropriate shell based on the user's system info:
{platform}
Examples of when to suggest shell commands:
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.
- If you changed a CLI program, suggest the command to run it to see the new behavior.
- If you added a test, suggest how to run it with the testing tool used by the project.
- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations.
- If your code changes add new dependencies, suggest the command to install them.
- Etc.
"""
no_shell_cmd_prompt = """
Keep in mind these details about the user's platform and environment:
{platform}
"""
example_messages = [
dict(
@@ -181,23 +156,19 @@ If you want to put code in a new file, use a *SEARCH/REPLACE block* with:
- An empty `SEARCH` section
- The new file's contents in the `REPLACE` section
To rename files which have been added to the chat, use shell commands at the end of your response.
If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed.
The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks.
{lazy_prompt}
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{rename_with_shell}{go_ahead_tip}{final_reminders}ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_reminder}
"""
shell_cmd_reminder = """
Examples of when to suggest shell commands:
rename_with_shell = """To rename files which have been added to the chat, use shell commands at the end of your response.
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.
- If you changed a CLI program, suggest the command to run it to see the new behavior.
- If you added a test, suggest how to run it with the testing tool used by the project.
- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations.
- If your code changes add new dependencies, suggest the command to install them.
- Etc.
"""
go_ahead_tip = """If the user just says something like "ok" or "go ahead" or "do that" they probably want you to make SEARCH/REPLACE blocks for the code changes you just proposed.
The user will say when they've applied your edits. If they haven't explicitly confirmed the edits have been applied, they probably want proper SEARCH/REPLACE blocks.
"""
shell_cmd_prompt = shell.shell_cmd_prompt
no_shell_cmd_prompt = shell.no_shell_cmd_prompt
shell_cmd_reminder = shell.shell_cmd_reminder

View File

@@ -0,0 +1,9 @@
from .editblock_fenced_coder import EditBlockFencedCoder
from .editor_diff_fenced_prompts import EditorDiffFencedPrompts
class EditorDiffFencedCoder(EditBlockFencedCoder):
"A coder that uses search/replace blocks, focused purely on editing files."
edit_format = "editor-diff-fenced"
gpt_prompts = EditorDiffFencedPrompts()

View File

@@ -0,0 +1,11 @@
# flake8: noqa: E501
from .editblock_fenced_prompts import EditBlockFencedPrompts
class EditorDiffFencedPrompts(EditBlockFencedPrompts):
shell_cmd_prompt = ""
no_shell_cmd_prompt = ""
shell_cmd_reminder = ""
go_ahead_tip = ""
rename_with_shell = ""

View File

@@ -5,7 +5,7 @@ from .editblock_prompts import EditBlockPrompts
class EditorEditBlockPrompts(EditBlockPrompts):
main_system = """Act as an expert software developer who edits source code.
{lazy_prompt}
{final_reminders}
Describe each change with a *SEARCH/REPLACE block* per the examples below.
All changes to files must use this *SEARCH/REPLACE block* format.
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
@@ -14,3 +14,5 @@ ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
shell_cmd_prompt = ""
no_shell_cmd_prompt = ""
shell_cmd_reminder = ""
go_ahead_tip = ""
rename_with_shell = ""

View File

@@ -5,6 +5,6 @@ from .wholefile_prompts import WholeFilePrompts
class EditorWholeFilePrompts(WholeFilePrompts):
main_system = """Act as an expert software developer and make changes to source code.
{lazy_prompt}
{final_reminders}
Output a copy of each file that needs changes.
"""

706
aider/coders/patch_coder.py Normal file
View File

@@ -0,0 +1,706 @@
import pathlib
from dataclasses import dataclass, field
from enum import Enum
from typing import Dict, List, Optional, Tuple
from .base_coder import Coder
from .patch_prompts import PatchPrompts
# --------------------------------------------------------------------------- #
# Domain objects & Exceptions (Adapted from apply_patch.py)
# --------------------------------------------------------------------------- #
class DiffError(ValueError):
"""Any problem detected while parsing or applying a patch."""
class ActionType(str, Enum):
ADD = "Add"
DELETE = "Delete"
UPDATE = "Update"
@dataclass
class Chunk:
orig_index: int = -1 # Line number in the *original* file block where the change starts
del_lines: List[str] = field(default_factory=list)
ins_lines: List[str] = field(default_factory=list)
@dataclass
class PatchAction:
type: ActionType
path: str
# For ADD:
new_content: Optional[str] = None
# For UPDATE:
chunks: List[Chunk] = field(default_factory=list)
move_path: Optional[str] = None
# Type alias for the return type of get_edits
EditResult = Tuple[str, PatchAction]
@dataclass
class Patch:
actions: Dict[str, PatchAction] = field(default_factory=dict)
fuzz: int = 0 # Track fuzziness used during parsing
# --------------------------------------------------------------------------- #
# Helper functions (Adapted from apply_patch.py)
# --------------------------------------------------------------------------- #
def _norm(line: str) -> str:
"""Strip CR so comparisons work for both LF and CRLF input."""
return line.rstrip("\r")
def find_context_core(lines: List[str], context: List[str], start: int) -> Tuple[int, int]:
"""Finds context block, returns start index and fuzz level."""
if not context:
return start, 0
# Exact match
for i in range(start, len(lines) - len(context) + 1):
if lines[i : i + len(context)] == context:
return i, 0
# Rstrip match
norm_context = [s.rstrip() for s in context]
for i in range(start, len(lines) - len(context) + 1):
if [s.rstrip() for s in lines[i : i + len(context)]] == norm_context:
return i, 1 # Fuzz level 1
# Strip match
norm_context_strip = [s.strip() for s in context]
for i in range(start, len(lines) - len(context) + 1):
if [s.strip() for s in lines[i : i + len(context)]] == norm_context_strip:
return i, 100 # Fuzz level 100
return -1, 0
def find_context(lines: List[str], context: List[str], start: int, eof: bool) -> Tuple[int, int]:
"""Finds context, handling EOF marker."""
if eof:
# If EOF marker, first try matching at the very end
if len(lines) >= len(context):
new_index, fuzz = find_context_core(lines, context, len(lines) - len(context))
if new_index != -1:
return new_index, fuzz
# If not found at end, search from `start` as fallback
new_index, fuzz = find_context_core(lines, context, start)
return new_index, fuzz + 10_000 # Add large fuzz penalty if EOF wasn't at end
# Normal case: search from `start`
return find_context_core(lines, context, start)
def peek_next_section(lines: List[str], index: int) -> Tuple[List[str], List[Chunk], int, bool]:
"""
Parses one section (context, -, + lines) of an Update block.
Returns: (context_lines, chunks_in_section, next_index, is_eof)
"""
context_lines: List[str] = []
del_lines: List[str] = []
ins_lines: List[str] = []
chunks: List[Chunk] = []
mode = "keep" # Start by expecting context lines
start_index = index
while index < len(lines):
line = lines[index]
norm_line = _norm(line)
# Check for section terminators
if norm_line.startswith(
(
"@@",
"*** End Patch",
"*** Update File:",
"*** Delete File:",
"*** Add File:",
"*** End of File", # Special terminator
)
):
break
if norm_line == "***": # Legacy/alternative terminator? Handle just in case.
break
if norm_line.startswith("***"): # Invalid line
raise DiffError(f"Invalid patch line found in update section: {line}")
index += 1
last_mode = mode
# Determine line type and strip prefix
if line.startswith("+"):
mode = "add"
line_content = line[1:]
elif line.startswith("-"):
mode = "delete"
line_content = line[1:]
elif line.startswith(" "):
mode = "keep"
line_content = line[1:]
elif line.strip() == "": # Treat blank lines in patch as context ' '
mode = "keep"
line_content = "" # Keep it as a blank line
else:
# Assume lines without prefix are context if format is loose,
# but strict format requires ' '. Raise error for strictness.
raise DiffError(f"Invalid line prefix in update section: {line}")
# If mode changes from add/delete back to keep, finalize the previous chunk
if mode == "keep" and last_mode != "keep":
if del_lines or ins_lines:
chunks.append(
Chunk(
# orig_index is relative to the start of the *context* block found
orig_index=len(context_lines) - len(del_lines),
del_lines=del_lines,
ins_lines=ins_lines,
)
)
del_lines, ins_lines = [], []
# Collect lines based on mode
if mode == "delete":
del_lines.append(line_content)
context_lines.append(line_content) # Deleted lines are part of the original context
elif mode == "add":
ins_lines.append(line_content)
elif mode == "keep":
context_lines.append(line_content)
# Finalize any pending chunk at the end of the section
if del_lines or ins_lines:
chunks.append(
Chunk(
orig_index=len(context_lines) - len(del_lines),
del_lines=del_lines,
ins_lines=ins_lines,
)
)
# Check for EOF marker
is_eof = False
if index < len(lines) and _norm(lines[index]) == "*** End of File":
index += 1
is_eof = True
if index == start_index and not is_eof: # Should not happen if patch is well-formed
raise DiffError("Empty patch section found.")
return context_lines, chunks, index, is_eof
def identify_files_needed(text: str) -> List[str]:
"""Extracts file paths from Update and Delete actions."""
lines = text.splitlines()
paths = set()
for line in lines:
norm_line = _norm(line)
if norm_line.startswith("*** Update File: "):
paths.add(norm_line[len("*** Update File: ") :].strip())
elif norm_line.startswith("*** Delete File: "):
paths.add(norm_line[len("*** Delete File: ") :].strip())
return list(paths)
# --------------------------------------------------------------------------- #
# PatchCoder Class Implementation
# --------------------------------------------------------------------------- #
class PatchCoder(Coder):
"""
A coder that uses a custom patch format for code modifications,
inspired by the format described in tmp.gpt41edits.txt.
Applies patches using logic adapted from the reference apply_patch.py script.
"""
edit_format = "patch"
gpt_prompts = PatchPrompts()
def get_edits(self) -> List[EditResult]:
"""
Parses the LLM response content (containing the patch) into a list of
tuples, where each tuple contains the file path and the PatchAction object.
"""
content = self.partial_response_content
if not content or not content.strip():
return []
# Check for patch sentinels
lines = content.splitlines()
if (
len(lines) < 2
or not _norm(lines[0]).startswith("*** Begin Patch")
# Allow flexible end, might be EOF or just end of stream
# or _norm(lines[-1]) != "*** End Patch"
):
# Tolerate missing sentinels if content looks like a patch action
is_patch_like = any(
_norm(line).startswith(
("@@", "*** Update File:", "*** Add File:", "*** Delete File:")
)
for line in lines
)
if not is_patch_like:
# If it doesn't even look like a patch, return empty
self.io.tool_warning("Response does not appear to be in patch format.")
return []
# If it looks like a patch but lacks sentinels, try parsing anyway but warn.
self.io.tool_warning(
"Patch format warning: Missing '*** Begin Patch'/'*** End Patch' sentinels."
)
start_index = 0
else:
start_index = 1 # Skip "*** Begin Patch"
# Identify files needed for context lookups during parsing
needed_paths = identify_files_needed(content)
current_files: Dict[str, str] = {}
for rel_path in needed_paths:
abs_path = self.abs_root_path(rel_path)
try:
# Use io.read_text to handle potential errors/encodings
file_content = self.io.read_text(abs_path)
if file_content is None:
raise DiffError(
f"File referenced in patch not found or could not be read: {rel_path}"
)
current_files[rel_path] = file_content
except FileNotFoundError:
raise DiffError(f"File referenced in patch not found: {rel_path}")
except IOError as e:
raise DiffError(f"Error reading file {rel_path}: {e}")
try:
# Parse the patch text using adapted logic
patch_obj = self._parse_patch_text(lines, start_index, current_files)
# Convert Patch object actions dict to a list of tuples (path, action)
# for compatibility with the base Coder's prepare_to_edit method.
results = []
for path, action in patch_obj.actions.items():
results.append((path, action))
return results
except DiffError as e:
# Raise as ValueError for consistency with other coders' error handling
raise ValueError(f"Error parsing patch content: {e}")
except Exception as e:
# Catch unexpected errors during parsing
raise ValueError(f"Unexpected error parsing patch: {e}")
def _parse_patch_text(
self, lines: List[str], start_index: int, current_files: Dict[str, str]
) -> Patch:
"""
Parses patch content lines into a Patch object.
Adapted from the Parser class in apply_patch.py.
"""
patch = Patch()
index = start_index
fuzz_accumulator = 0
while index < len(lines):
line = lines[index]
norm_line = _norm(line)
if norm_line == "*** End Patch":
index += 1
break # Successfully reached end
# ---------- UPDATE ---------- #
if norm_line.startswith("*** Update File: "):
path = norm_line[len("*** Update File: ") :].strip()
index += 1
if not path:
raise DiffError("Update File action missing path.")
# Optional move target
move_to = None
if index < len(lines) and _norm(lines[index]).startswith("*** Move to: "):
move_to = _norm(lines[index])[len("*** Move to: ") :].strip()
index += 1
if not move_to:
raise DiffError("Move to action missing path.")
if path not in current_files:
raise DiffError(f"Update File Error - missing file content for: {path}")
file_content = current_files[path]
existing_action = patch.actions.get(path)
if existing_action is not None:
# Merge additional UPDATE block into the existing one
if existing_action.type != ActionType.UPDATE:
raise DiffError(f"Conflicting actions for file: {path}")
new_action, index, fuzz = self._parse_update_file_sections(
lines, index, file_content
)
existing_action.chunks.extend(new_action.chunks)
if move_to:
if existing_action.move_path and existing_action.move_path != move_to:
raise DiffError(f"Conflicting move targets for file: {path}")
existing_action.move_path = move_to
fuzz_accumulator += fuzz
else:
# First UPDATE block for this file
action, index, fuzz = self._parse_update_file_sections(
lines, index, file_content
)
action.path = path
action.move_path = move_to
patch.actions[path] = action
fuzz_accumulator += fuzz
continue
# ---------- DELETE ---------- #
elif norm_line.startswith("*** Delete File: "):
path = norm_line[len("*** Delete File: ") :].strip()
index += 1
if not path:
raise DiffError("Delete File action missing path.")
existing_action = patch.actions.get(path)
if existing_action:
if existing_action.type == ActionType.DELETE:
# Duplicate delete ignore the extra block
self.io.tool_warning(f"Duplicate delete action for file: {path} ignored.")
continue
else:
raise DiffError(f"Conflicting actions for file: {path}")
if path not in current_files:
raise DiffError(
f"Delete File Error - file not found: {path}"
) # Check against known files
patch.actions[path] = PatchAction(type=ActionType.DELETE, path=path)
continue
# ---------- ADD ---------- #
elif norm_line.startswith("*** Add File: "):
path = norm_line[len("*** Add File: ") :].strip()
index += 1
if not path:
raise DiffError("Add File action missing path.")
if path in patch.actions:
raise DiffError(f"Duplicate action for file: {path}")
# Check if file exists in the context provided (should not for Add).
# Note: We only have needed files, a full check requires FS access.
# if path in current_files:
# raise DiffError(f"Add File Error - file already exists: {path}")
action, index = self._parse_add_file_content(lines, index)
action.path = path # Ensure path is set
patch.actions[path] = action
continue
# If we are here, the line is unexpected
# Allow blank lines between actions
if not norm_line.strip():
index += 1
continue
raise DiffError(f"Unknown or misplaced line while parsing patch: {line}")
# Check if we consumed the whole input or stopped early
# Tolerate missing "*** End Patch" if we processed actions
# if index < len(lines) and _norm(lines[index-1]) != "*** End Patch":
# raise DiffError("Patch parsing finished unexpectedly before end of input.")
patch.fuzz = fuzz_accumulator
return patch
def _parse_update_file_sections(
self, lines: List[str], index: int, file_content: str
) -> Tuple[PatchAction, int, int]:
"""Parses all sections (@@, context, -, +) for a single Update File action."""
action = PatchAction(type=ActionType.UPDATE, path="") # Path set by caller
orig_lines = file_content.splitlines() # Use splitlines for consistency
current_file_index = 0 # Track position in original file content
total_fuzz = 0
while index < len(lines):
norm_line = _norm(lines[index])
# Check for terminators for *this* file update
if norm_line.startswith(
(
"*** End Patch",
"*** Update File:",
"*** Delete File:",
"*** Add File:",
)
):
break # End of this file's update section
# Handle @@ scope lines (optional)
scope_lines = []
while index < len(lines) and _norm(lines[index]).startswith("@@"):
scope_line_content = lines[index][len("@@") :].strip()
if scope_line_content: # Ignore empty @@ lines?
scope_lines.append(scope_line_content)
index += 1
# Find the scope in the original file if specified
if scope_lines:
# Simple scope finding: search from current position
# A more robust finder could handle nested scopes like the reference @@ @@
found_scope = False
temp_index = current_file_index
while temp_index < len(orig_lines):
# Check if all scope lines match sequentially from temp_index
match = True
for i, scope in enumerate(scope_lines):
if (
temp_index + i >= len(orig_lines)
or _norm(orig_lines[temp_index + i]).strip() != scope
):
match = False
break
if match:
current_file_index = temp_index + len(scope_lines)
found_scope = True
break
temp_index += 1
if not found_scope:
# Try fuzzy scope matching (strip whitespace)
temp_index = current_file_index
while temp_index < len(orig_lines):
match = True
for i, scope in enumerate(scope_lines):
if (
temp_index + i >= len(orig_lines)
or _norm(orig_lines[temp_index + i]).strip() != scope.strip()
):
match = False
break
if match:
current_file_index = temp_index + len(scope_lines)
found_scope = True
total_fuzz += 1 # Add fuzz for scope match difference
break
temp_index += 1
if not found_scope:
scope_txt = "\n".join(scope_lines)
raise DiffError(f"Could not find scope context:\n{scope_txt}")
# Peek and parse the next context/change section
context_block, chunks_in_section, next_index, is_eof = peek_next_section(lines, index)
# Find where this context block appears in the original file
found_index, fuzz = find_context(orig_lines, context_block, current_file_index, is_eof)
total_fuzz += fuzz
if found_index == -1:
ctx_txt = "\n".join(context_block)
marker = "*** End of File" if is_eof else ""
raise DiffError(
f"Could not find patch context {marker} starting near line"
f" {current_file_index}:\n{ctx_txt}"
)
# Adjust chunk original indices to be absolute within the file
for chunk in chunks_in_section:
# chunk.orig_index from peek is relative to context_block start
# We need it relative to the file start
chunk.orig_index += found_index
action.chunks.append(chunk)
# Advance file index past the matched context block
current_file_index = found_index + len(context_block)
# Advance line index past the processed section in the patch
index = next_index
return action, index, total_fuzz
def _parse_add_file_content(self, lines: List[str], index: int) -> Tuple[PatchAction, int]:
"""Parses the content (+) lines for an Add File action."""
added_lines: List[str] = []
while index < len(lines):
line = lines[index]
norm_line = _norm(line)
# Stop if we hit another action or end marker
if norm_line.startswith(
(
"*** End Patch",
"*** Update File:",
"*** Delete File:",
"*** Add File:",
)
):
break
# Expect lines to start with '+'
if not line.startswith("+"):
# Tolerate blank lines? Or require '+'? Reference implies '+' required.
if norm_line.strip() == "":
# Treat blank line as adding a blank line
added_lines.append("")
else:
raise DiffError(f"Invalid Add File line (missing '+'): {line}")
else:
added_lines.append(line[1:]) # Strip leading '+'
index += 1
action = PatchAction(type=ActionType.ADD, path="", new_content="\n".join(added_lines))
return action, index
def apply_edits(self, edits: List[PatchAction]):
"""
Applies the parsed PatchActions to the corresponding files.
"""
if not edits:
return
# Group edits by original path? Not strictly needed if processed sequentially.
# Edits are now List[Tuple[str, PatchAction]]
for _path_tuple_element, action in edits:
# action is the PatchAction object
# action.path is the canonical path within the action logic
full_path = self.abs_root_path(action.path)
path_obj = pathlib.Path(full_path)
try:
if action.type == ActionType.ADD:
# Check existence *before* writing
if path_obj.exists():
raise DiffError(f"ADD Error: File already exists: {action.path}")
if action.new_content is None:
# Parser should ensure this doesn't happen
raise DiffError(f"ADD change for {action.path} has no content")
self.io.tool_output(f"Adding {action.path}")
path_obj.parent.mkdir(parents=True, exist_ok=True)
# Ensure single trailing newline, matching reference behavior
content_to_write = action.new_content
if not content_to_write.endswith("\n"):
content_to_write += "\n"
self.io.write_text(full_path, content_to_write)
elif action.type == ActionType.DELETE:
self.io.tool_output(f"Deleting {action.path}")
if not path_obj.exists():
self.io.tool_warning(
f"DELETE Warning: File not found, skipping: {action.path}"
)
else:
path_obj.unlink()
elif action.type == ActionType.UPDATE:
if not path_obj.exists():
raise DiffError(f"UPDATE Error: File does not exist: {action.path}")
current_content = self.io.read_text(full_path)
if current_content is None:
# Should have been caught during parsing if file was needed
raise DiffError(f"Could not read file for UPDATE: {action.path}")
# Apply the update logic using the parsed chunks
new_content = self._apply_update(current_content, action, action.path)
target_full_path = (
self.abs_root_path(action.move_path) if action.move_path else full_path
)
target_path_obj = pathlib.Path(target_full_path)
if action.move_path:
self.io.tool_output(
f"Updating and moving {action.path} to {action.move_path}"
)
# Check if target exists before overwriting/moving
if target_path_obj.exists() and full_path != target_full_path:
self.io.tool_warning(
"UPDATE Warning: Target file for move already exists, overwriting:"
f" {action.move_path}"
)
else:
self.io.tool_output(f"Updating {action.path}")
# Ensure parent directory exists for target
target_path_obj.parent.mkdir(parents=True, exist_ok=True)
self.io.write_text(target_full_path, new_content)
# Remove original file *after* successful write to new location if moved
if action.move_path and full_path != target_full_path:
path_obj.unlink()
else:
# Should not happen
raise DiffError(f"Unknown action type encountered: {action.type}")
except (DiffError, FileNotFoundError, IOError, OSError) as e:
# Raise a ValueError to signal failure, consistent with other coders.
raise ValueError(f"Error applying action '{action.type}' to {action.path}: {e}")
except Exception as e:
# Catch unexpected errors during application
raise ValueError(
f"Unexpected error applying action '{action.type}' to {action.path}: {e}"
)
def _apply_update(self, text: str, action: PatchAction, path: str) -> str:
"""
Applies UPDATE chunks to the given text content.
Adapted from _get_updated_file in apply_patch.py.
"""
if action.type is not ActionType.UPDATE:
# Should not be called otherwise, but check for safety
raise DiffError("_apply_update called with non-update action")
orig_lines = text.splitlines() # Use splitlines to handle endings consistently
dest_lines: List[str] = []
current_orig_line_idx = 0 # Tracks index in orig_lines processed so far
# Sort chunks by their original index to apply them sequentially
sorted_chunks = sorted(action.chunks, key=lambda c: c.orig_index)
for chunk in sorted_chunks:
# chunk.orig_index is the absolute line number where the change starts
# (where the first deleted line was, or where inserted lines go if no deletes)
chunk_start_index = chunk.orig_index
if chunk_start_index < current_orig_line_idx:
# This indicates overlapping chunks or incorrect indices from parsing
raise DiffError(
f"{path}: Overlapping or out-of-order chunk detected."
f" Current index {current_orig_line_idx}, chunk starts at {chunk_start_index}."
)
# Add lines from original file between the last chunk and this one
dest_lines.extend(orig_lines[current_orig_line_idx:chunk_start_index])
# Verify that the lines to be deleted actually match the original file content
# (The parser should have used find_context, but double-check here)
num_del = len(chunk.del_lines)
actual_deleted_lines = orig_lines[chunk_start_index : chunk_start_index + num_del]
# Use the same normalization as find_context_core for comparison robustness
norm_chunk_del = [_norm(s).strip() for s in chunk.del_lines]
norm_actual_del = [_norm(s).strip() for s in actual_deleted_lines]
if norm_chunk_del != norm_actual_del:
# This indicates the context matching failed or the file changed since parsing
# Provide detailed error message
expected_str = "\n".join(f"- {s}" for s in chunk.del_lines)
actual_str = "\n".join(f" {s}" for s in actual_deleted_lines)
raise DiffError(
f"{path}: Mismatch applying patch near line {chunk_start_index + 1}.\n"
f"Expected lines to remove:\n{expected_str}\n"
f"Found lines in file:\n{actual_str}"
)
# Add the inserted lines from the chunk
dest_lines.extend(chunk.ins_lines)
# Advance the original line index past the lines processed (deleted lines)
current_orig_line_idx = chunk_start_index + num_del
# Add any remaining lines from the original file after the last chunk
dest_lines.extend(orig_lines[current_orig_line_idx:])
# Join lines and ensure a single trailing newline
result = "\n".join(dest_lines)
if result or orig_lines: # Add newline unless result is empty and original was empty
result += "\n"
return result

View File

@@ -0,0 +1,161 @@
# flake8: noqa: E501
from .base_prompts import CoderPrompts
from .editblock_prompts import EditBlockPrompts
class PatchPrompts(EditBlockPrompts):
# --------------------------------------------------------------------- #
# SYSTEM PROMPT
# --------------------------------------------------------------------- #
main_system = """Act as an expert software developer.
Always use best practices when coding.
Respect and use existing conventions, libraries, etc that are already present in the code base.
{final_reminders}
Take requests for changes to the supplied code.
If the request is ambiguous, ask questions.
Always reply to the user in {language}.
Once you understand the request you MUST:
1. Decide if you need to propose edits to any files that haven't been added to the chat. You can create new files without asking!
• If you need to propose edits to existing files not already added to the chat, you *MUST* tell the user their full path names and ask them to *add the files to the chat*.
• End your reply and wait for their approval.
• You can keep asking if you then decide you need to edit more files.
2. Think stepbystep and explain the needed changes in a few short sentences.
3. Describe the changes using the V4A diff format, enclosed within `*** Begin Patch` and `*** End Patch` markers.
IMPORTANT: Each file MUST appear only once in the patch.
Consolidate **all** edits for a given file into a single `*** [ACTION] File:` block.
{shell_cmd_prompt}
"""
# --------------------------------------------------------------------- #
# EXAMPLE MESSAGES
# --------------------------------------------------------------------- #
example_messages = [
# --- Example 1 ---------------------------------------------------- #
dict(
role="user",
content="Change get_factorial() to use math.factorial",
),
dict(
role="assistant",
content="""To make this change we need to modify `mathweb/flask/app.py`:
1. Import the `math` module.
2. Replace the custom recursive `factorial()` helper with `math.factorial`.
3. Update `get_factorial()` to call `math.factorial`.
Here is the patch:
*** Begin Patch
*** Update File: mathweb/flask/app.py
@@
-from flask import Flask
-
-from flask import Flask
+from flask import Flask
+import math
@@
-def factorial(n):
- "compute factorial"
-
- if n == 0:
- return 1
- else:
- return n * factorial(n-1)
+def factorial(n):
+ "compute factorial"
+
+ return math.factorial(n)
@@ def get_factorial(self, n):
- return str(factorial(n))
+ return str(math.factorial(n))
*** End Patch
""",
),
# --- Example 2 ---------------------------------------------------- #
dict(
role="user",
content="Refactor hello() into its own file.",
),
dict(
role="assistant",
content="""To make this change we need to modify `main.py` and create a new file `hello.py`:
1. Create `hello.py` with the `hello()` function.
2. Remove `hello()` from `main.py` and import it instead.
Here is the patch:
*** Begin Patch
*** Add File: hello.py
+# A simple function
+def hello():
+ "print a greeting"
+
+ print("hello")
*** Update File: main.py
@@
-def hello():
- "print a greeting"
-
- print("hello")
+from hello import hello
*** End Patch
""",
),
]
# --------------------------------------------------------------------- #
# SYSTEM REMINDER
# --------------------------------------------------------------------- #
system_reminder = """# V4A Diff Format Rules:
Your entire response containing the patch MUST start with `*** Begin Patch` on a line by itself.
Your entire response containing the patch MUST end with `*** End Patch` on a line by itself.
Use the *FULL* file path, as shown to you by the user.
{quad_backtick_reminder}
For each file you need to modify, start with a marker line:
*** [ACTION] File: [path/to/file]
Where `[ACTION]` is one of `Add`, `Update`, or `Delete`.
⇨ **Each file MUST appear only once in the patch.**
Consolidate all changes for that file into the same block.
If you are moving code within a file, include both the deletions and the
insertions as separate hunks inside this single `*** Update File:` block
(do *not* open a second block for the same file).
For `Update` actions, describe each snippet of code that needs to be changed using the following format:
1. Context lines: Include 3 lines of context *before* the change. These lines MUST start with a single space ` `.
2. Lines to remove: Precede each line to be removed with a minus sign `-`.
3. Lines to add: Precede each line to be added with a plus sign `+`.
4. Context lines: Include 3 lines of context *after* the change. These lines MUST start with a single space ` `.
Context lines MUST exactly match the existing file content, character for character, including indentation.
If a change is near the beginning or end of the file, include fewer than 3 context lines as appropriate.
If 3 lines of context is insufficient to uniquely identify the snippet, use `@@ [CLASS_OR_FUNCTION_NAME]` markers on their own lines *before* the context lines to specify the scope. You can use multiple `@@` markers if needed.
Do not include line numbers.
Only create patches for files that the user has added to the chat!
When moving code *within* a single file, keep everything inside one
`*** Update File:` block. Provide one hunk that deletes the code from its
original location and another hunk that inserts it at the new location.
For `Add` actions, use the `*** Add File: [path/to/new/file]` marker, followed by the lines of the new file, each preceded by a plus sign `+`.
For `Delete` actions, use the `*** Delete File: [path/to/file]` marker. No other lines are needed for the deletion.
{rename_with_shell}{go_ahead_tip}{final_reminders}ONLY EVER RETURN CODE IN THE SPECIFIED V4A DIFF FORMAT!
{shell_cmd_reminder}
"""

View File

@@ -235,20 +235,6 @@ Left
Left
"""
"""
ri = RelativeIndenter([example])
dump(example)
rel_example = ri.make_relative(example)
dump(repr(rel_example))
abs_example = ri.make_absolute(rel_example)
dump(abs_example)
sys.exit()
"""
def relative_indent(texts):
ri = RelativeIndenter(texts)
@@ -349,7 +335,7 @@ def lines_to_chars(lines, mapping):
return new_text
def dmp_lines_apply(texts, remap=True):
def dmp_lines_apply(texts):
debug = False
# debug = True
@@ -655,8 +641,6 @@ def proc(dname):
(dmp_lines_apply, all_preprocs),
]
_strategies = editblock_strategies # noqa: F841
short_names = dict(
search_and_replace="sr",
git_cherry_pick_osr_onto_o="cp_o",

37
aider/coders/shell.py Normal file
View File

@@ -0,0 +1,37 @@
shell_cmd_prompt = """
4. *Concisely* suggest any shell commands the user might want to run in ```bash blocks.
Just suggest shell commands this way, not example code.
Only suggest complete shell commands that are ready to execute, without placeholders.
Only suggest at most a few shell commands at a time, not more than 1-3, one per line.
Do not suggest multi-line shell commands.
All shell commands will run from the root directory of the user's project.
Use the appropriate shell based on the user's system info:
{platform}
Examples of when to suggest shell commands:
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.
- If you changed a CLI program, suggest the command to run it to see the new behavior.
- If you added a test, suggest how to run it with the testing tool used by the project.
- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations.
- If your code changes add new dependencies, suggest the command to install them.
- Etc.
""" # noqa
no_shell_cmd_prompt = """
Keep in mind these details about the user's platform and environment:
{platform}
""" # noqa
shell_cmd_reminder = """
Examples of when to suggest shell commands:
- If you changed a self-contained html file, suggest an OS-appropriate command to open a browser to view it to see the updated content.
- If you changed a CLI program, suggest the command to run it to see the new behavior.
- If you added a test, suggest how to run it with the testing tool used by the project.
- Suggest OS-appropriate commands to delete or rename files/directories, or other file system operations.
- If your code changes add new dependencies, suggest the command to install them.
- Etc.
""" # noqa

View File

@@ -45,6 +45,7 @@ other_hunks_applied = (
class UnifiedDiffCoder(Coder):
"""A coder that uses unified diff format for code modifications."""
edit_format = "udiff"
gpt_prompts = UnifiedDiffPrompts()
@@ -344,7 +345,16 @@ def process_fenced_block(lines, start_line_num):
if block[0].startswith("--- ") and block[1].startswith("+++ "):
# Extract the file path, considering that it might contain spaces
fname = block[1][4:].strip()
a_fname = block[0][4:].strip()
b_fname = block[1][4:].strip()
# Check if standard git diff prefixes are present (or /dev/null) and strip them
if (a_fname.startswith("a/") or a_fname == "/dev/null") and b_fname.startswith("b/"):
fname = b_fname[2:]
else:
# Otherwise, assume the path is as intended
fname = b_fname
block = block[2:]
else:
fname = None

View File

@@ -1,11 +1,12 @@
# flake8: noqa: E501
from . import shell
from .base_prompts import CoderPrompts
class UnifiedDiffPrompts(CoderPrompts):
main_system = """Act as an expert software developer.
{lazy_prompt}
{final_reminders}
Always use best practices when coding.
Respect and use existing conventions, libraries, etc that are already present in the code base.
@@ -106,5 +107,9 @@ To move code within a file, use 2 hunks: 1 to delete it from its current locatio
To make a new file, show a diff from `--- /dev/null` to `+++ path/to/new/file.ext`.
{lazy_prompt}
{final_reminders}
"""
shell_cmd_prompt = shell.shell_cmd_prompt
no_shell_cmd_prompt = shell.no_shell_cmd_prompt
shell_cmd_reminder = shell.shell_cmd_reminder

View File

@@ -0,0 +1,14 @@
from .udiff_coder import UnifiedDiffCoder
from .udiff_simple_prompts import UnifiedDiffSimplePrompts
class UnifiedDiffSimpleCoder(UnifiedDiffCoder):
"""
A coder that uses unified diff format for code modifications.
This variant uses a simpler prompt that doesn't mention specific
diff rules like using `@@ ... @@` lines or avoiding line numbers.
"""
edit_format = "udiff-simple"
gpt_prompts = UnifiedDiffSimplePrompts()

View File

@@ -0,0 +1,25 @@
from .udiff_prompts import UnifiedDiffPrompts
class UnifiedDiffSimplePrompts(UnifiedDiffPrompts):
"""
Prompts for the UnifiedDiffSimpleCoder.
Inherits from UnifiedDiffPrompts and can override specific prompts
if a simpler wording is desired for this edit format.
"""
example_messages = []
system_reminder = """# File editing rules:
Return edits similar to unified diffs that `diff -U0` would produce.
The user's patch tool needs CORRECT patches that apply cleanly against the current contents of the file!
Think carefully and make sure you include and mark all lines that need to be removed or changed as `-` lines.
Make sure you mark all new or modified lines with `+`.
Don't leave out any lines or the diff patch won't apply correctly.
To make a new file, show a diff from `--- /dev/null` to `+++ path/to/new/file.ext`.
{final_reminders}
""" # noqa

View File

@@ -10,7 +10,7 @@ If the request is ambiguous, ask questions.
Always reply to the user in {language}.
{lazy_prompt}
{final_reminders}
Once you understand the request you MUST:
1. Determine if any code changes are needed.
2. Explain any needed changes.
@@ -61,7 +61,7 @@ To suggest changes to a file you MUST return a *file listing* that contains the
*NEVER* skip, omit or elide content from a *file listing* using "..." or by adding comments like "... rest of code..."!
Create a new file you MUST return a *file listing* which includes an appropriate filename, including any appropriate path.
{lazy_prompt}
{final_reminders}
"""
redacted_edit_message = "No changes are needed."

View File

@@ -595,7 +595,7 @@ class InputOutput:
current_text = buffer.text
# Open the editor with the current text
edited_text = pipe_editor(input_data=current_text)
edited_text = pipe_editor(input_data=current_text, suffix="md")
# Replace the buffer with the edited text, strip any trailing newlines
buffer.text = edited_text.rstrip("\n")

View File

@@ -857,7 +857,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
)
if args.copy_paste and args.edit_format is None:
if main_model.edit_format in ("diff", "whole"):
if main_model.edit_format in ("diff", "whole", "diff-fenced"):
main_model.edit_format = "editor-" + main_model.edit_format
if args.verbose:

View File

@@ -88,11 +88,14 @@ MODEL_ALIASES = {
"3": "gpt-3.5-turbo",
# Other models
"deepseek": "deepseek/deepseek-chat",
"flash": "gemini/gemini-2.0-flash-exp",
"flash": "gemini/gemini-2.5-flash-preview-04-17",
"quasar": "openrouter/openrouter/quasar-alpha",
"r1": "deepseek/deepseek-reasoner",
"gemini-2.5-pro": "gemini/gemini-2.5-pro-exp-03-25",
"gemini": "gemini/gemini-2.5-pro-exp-03-25",
"gemini": "gemini/gemini-2.5-pro-preview-03-25",
"gemini-exp": "gemini/gemini-2.5-pro-exp-03-25",
"grok3": "xai/grok-3-beta",
"optimus": "openrouter/openrouter/optimus-alpha",
}
# Model metadata loaded from resources and user's files.
@@ -311,7 +314,11 @@ class Model(ModelSettings):
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:
if (
self.extra_model_settings
and self.extra_model_settings.extra_params
and self.extra_model_settings.name == "aider/extra_params"
):
# Initialize extra_params if it doesn't exist
if not self.extra_params:
self.extra_params = {}
@@ -331,10 +338,25 @@ class Model(ModelSettings):
self.use_repo_map = True
self.use_temperature = False
self.system_prompt_prefix = "Formatting re-enabled. "
self.system_prompt_prefix = "Formatting re-enabled. "
if "reasoning_effort" not in self.accepts_settings:
self.accepts_settings.append("reasoning_effort")
return # <--
if "gpt-4.1-mini" in model:
self.edit_format = "diff"
self.use_repo_map = True
self.reminder = "sys"
self.examples_as_sys_msg = False
return # <--
if "gpt-4.1" in model:
self.edit_format = "diff"
self.use_repo_map = True
self.reminder = "sys"
self.examples_as_sys_msg = False
return # <--
if "/o1-mini" in model:
self.use_repo_map = True
self.use_temperature = False
@@ -485,6 +507,8 @@ class Model(ModelSettings):
if not self.editor_edit_format:
self.editor_edit_format = self.editor_model.edit_format
if self.editor_edit_format in ("diff", "whole", "diff-fenced"):
self.editor_edit_format = "editor-" + self.editor_edit_format
return self.editor_model

View File

@@ -15,7 +15,7 @@ Use these for <type>: fix, feat, build, chore, ci, docs, style, refactor, perf,
Ensure the commit message:
- Starts with the appropriate prefix.
- Is in the imperative mood (e.g., \"Add feature\" not \"Added feature\" or \"Adding feature\").
- Is in the imperative mood (e.g., \"add feature\" not \"added feature\" or \"adding feature\").
- Does not exceed 72 characters.
Reply only with the one-line commit message, without any additional text, explanations, \

View File

@@ -15,22 +15,6 @@
//"supports_tool_choice": true,
"supports_prompt_caching": true
},
"openrouter/deepseek/deepseek-r1": {
"max_tokens": 8192,
"max_input_tokens": 64000,
"max_output_tokens": 8192,
"input_cost_per_token": 0.00000055,
"input_cost_per_token_cache_hit": 0.00000014,
"cache_read_input_token_cost": 0.00000014,
"cache_creation_input_token_cost": 0.0,
"output_cost_per_token": 0.00000219,
"litellm_provider": "openrouter",
"mode": "chat",
//"supports_function_calling": true,
"supports_assistant_prefill": true,
//"supports_tool_choice": true,
"supports_prompt_caching": true
},
"openrouter/deepseek/deepseek-r1:free": {
"max_tokens": 8192,
"max_input_tokens": 64000,
@@ -99,8 +83,8 @@
"output_cost_per_token": 0.000008,
"mode": "chat",
},
"fireworks_ai/accounts/fireworks/models/deepseek-v3": {
"max_tokens": 128000,
"fireworks_ai/accounts/fireworks/models/deepseek-v3-0324": {
"max_tokens": 160000,
"max_input_tokens": 100000,
"max_output_tokens": 8192,
"litellm_provider": "fireworks_ai",
@@ -108,54 +92,6 @@
"output_cost_per_token": 0.0000009,
"mode": "chat",
},
"o3-mini": {
"max_tokens": 100000,
"max_input_tokens": 200000,
"max_output_tokens": 100000,
"input_cost_per_token": 0.0000011,
"output_cost_per_token": 0.0000044,
"cache_read_input_token_cost": 0.00000055,
"litellm_provider": "openai",
"mode": "chat",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
"supports_vision": true,
"supports_prompt_caching": true,
"supports_system_messages": true,
"supports_response_schema": true
},
"openrouter/openai/o3-mini": {
"max_tokens": 100000,
"max_input_tokens": 200000,
"max_output_tokens": 100000,
"input_cost_per_token": 0.0000011,
"output_cost_per_token": 0.0000044,
"cache_read_input_token_cost": 0.00000055,
"litellm_provider": "openrouter",
"mode": "chat",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
"supports_vision": true,
"supports_prompt_caching": true,
"supports_system_messages": true,
"supports_response_schema": true
},
"openrouter/openai/o3-mini-high": {
"max_tokens": 100000,
"max_input_tokens": 200000,
"max_output_tokens": 100000,
"input_cost_per_token": 0.0000011,
"output_cost_per_token": 0.0000044,
"cache_read_input_token_cost": 0.00000055,
"litellm_provider": "openrouter",
"mode": "chat",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
"supports_vision": true,
"supports_prompt_caching": true,
"supports_system_messages": true,
"supports_response_schema": true
},
"openrouter/openrouter/quasar-alpha": {
"max_input_tokens": 1000000,
"max_output_tokens": 32000,
@@ -168,6 +104,14 @@
"supports_system_messages": true,
"supports_prompt_caching": true
},
"openrouter/openrouter/optimus-alpha": {
"max_input_tokens": 1000000,
"max_output_tokens": 32000,
"input_cost_per_token": 0.0,
"output_cost_per_token": 0.0,
"litellm_provider": "openrouter",
"mode": "chat"
},
"openrouter/openai/gpt-4o-mini": {
"max_tokens": 16384,
"max_input_tokens": 128000,
@@ -186,26 +130,6 @@
"supports_prompt_caching": true,
"supports_system_messages": true
},
"claude-3-7-sonnet-20250219": {
"max_tokens": 8192,
"max_input_tokens": 200000,
"max_output_tokens": 8192,
"input_cost_per_token": 0.000003,
"output_cost_per_token": 0.000015,
"cache_creation_input_token_cost": 0.00000375,
"cache_read_input_token_cost": 0.0000003,
"litellm_provider": "anthropic",
"mode": "chat",
"supports_function_calling": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 159,
"supports_assistant_prefill": true,
"supports_pdf_input": true,
"supports_prompt_caching": true,
"supports_response_schema": true,
"deprecation_date": "2025-10-01",
"supports_tool_choice": true
},
"anthropic/claude-3-7-sonnet-20250219": {
"max_tokens": 8192,
"max_input_tokens": 200000,
@@ -226,43 +150,6 @@
"deprecation_date": "2025-10-01",
"supports_tool_choice": true
},
"openrouter/anthropic/claude-3.7-sonnet": {
"max_tokens": 8192,
"max_input_tokens": 200000,
"max_output_tokens": 8192,
"input_cost_per_token": 0.000003,
"output_cost_per_token": 0.000015,
"cache_creation_input_token_cost": 0.00000375,
"cache_read_input_token_cost": 0.0000003,
"litellm_provider": "openrouter",
"mode": "chat",
"supports_function_calling": true,
"supports_vision": true,
"tool_use_system_prompt_tokens": 159,
"supports_assistant_prefill": true,
"supports_pdf_input": true,
"supports_prompt_caching": true,
"supports_response_schema": true,
"deprecation_date": "2025-10-01",
"supports_tool_choice": true
},
"gpt-4.5-preview": {
"max_tokens": 16384,
"max_input_tokens": 128000,
"max_output_tokens": 16384,
"input_cost_per_token": 0.000075,
"output_cost_per_token": 0.00015,
"cache_read_input_token_cost": 0.0000375,
"litellm_provider": "openai",
"mode": "chat",
"supports_function_calling": true,
"supports_parallel_function_calling": true,
"supports_response_schema": true,
"supports_vision": true,
"supports_prompt_caching": true,
"supports_system_messages": true,
"supports_tool_choice": true
},
"openai/gpt-4.5-preview": {
"max_tokens": 16384,
"max_input_tokens": 128000,
@@ -353,6 +240,78 @@
"supports_tool_choice": true,
"source": "https://cloud.google.com/vertex-ai/generative-ai/pricing"
},
"vertex_ai/gemini-2.5-pro-preview-03-25": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
"max_output_tokens": 64000,
"max_images_per_prompt": 3000,
"max_videos_per_prompt": 10,
"max_video_length": 1,
"max_audio_length_hours": 8.4,
"max_audio_per_prompt": 1,
"max_pdf_size_mb": 30,
"input_cost_per_image": 0,
"input_cost_per_video_per_second": 0,
"input_cost_per_audio_per_second": 0,
"input_cost_per_token": 0.00000125,
"input_cost_per_character": 0,
"input_cost_per_token_above_128k_tokens": 0,
"input_cost_per_character_above_128k_tokens": 0,
"input_cost_per_image_above_128k_tokens": 0,
"input_cost_per_video_per_second_above_128k_tokens": 0,
"input_cost_per_audio_per_second_above_128k_tokens": 0,
"output_cost_per_token": 0.000010,
"output_cost_per_character": 0,
"output_cost_per_token_above_128k_tokens": 0,
"output_cost_per_character_above_128k_tokens": 0,
"litellm_provider": "vertex_ai-language-models",
"mode": "chat",
"supports_system_messages": true,
"supports_function_calling": true,
"supports_vision": true,
"supports_audio_input": true,
"supports_video_input": true,
"supports_pdf_input": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"source": "https://cloud.google.com/vertex-ai/generative-ai/pricing"
},
"openrouter/google/gemini-2.5-pro-preview-03-25": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
"max_output_tokens": 64000,
"max_images_per_prompt": 3000,
"max_videos_per_prompt": 10,
"max_video_length": 1,
"max_audio_length_hours": 8.4,
"max_audio_per_prompt": 1,
"max_pdf_size_mb": 30,
"input_cost_per_image": 0,
"input_cost_per_video_per_second": 0,
"input_cost_per_audio_per_second": 0,
"input_cost_per_token": 0.00000125,
"input_cost_per_character": 0,
"input_cost_per_token_above_128k_tokens": 0,
"input_cost_per_character_above_128k_tokens": 0,
"input_cost_per_image_above_128k_tokens": 0,
"input_cost_per_video_per_second_above_128k_tokens": 0,
"input_cost_per_audio_per_second_above_128k_tokens": 0,
"output_cost_per_token": 0.000010,
"output_cost_per_character": 0,
"output_cost_per_token_above_128k_tokens": 0,
"output_cost_per_character_above_128k_tokens": 0,
"litellm_provider": "vertex_ai-language-models",
"mode": "chat",
"supports_system_messages": true,
"supports_function_calling": true,
"supports_vision": true,
"supports_audio_input": true,
"supports_video_input": true,
"supports_pdf_input": true,
"supports_response_schema": true,
"supports_tool_choice": true,
"source": "https://cloud.google.com/vertex-ai/generative-ai/pricing"
},
"openrouter/google/gemini-2.5-pro-exp-03-25:free": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
@@ -367,9 +326,9 @@
"input_cost_per_video_per_second": 0,
"input_cost_per_audio_per_second": 0,
"input_cost_per_token": 0,
"input_cost_per_character": 0,
"input_cost_per_token_above_128k_tokens": 0,
"input_cost_per_character_above_128k_tokens": 0,
"input_cost_per_character": 0,
"input_cost_per_token_above_128k_tokens": 0,
"input_cost_per_character_above_128k_tokens": 0,
"input_cost_per_image_above_128k_tokens": 0,
"input_cost_per_video_per_second_above_128k_tokens": 0,
"input_cost_per_audio_per_second_above_128k_tokens": 0,
@@ -389,7 +348,43 @@
"supports_tool_choice": true,
"source": "https://cloud.google.com/vertex-ai/generative-ai/pricing"
},
"openrouter/google/gemini-2.0-flash-exp:free": {
"openrouter/x-ai/grok-3-beta": {
"max_tokens": 131072,
"max_input_tokens": 131072,
"max_output_tokens": 131072,
"input_cost_per_token": 0.000003,
"output_cost_per_token": 0.000015,
"litellm_provider": "openrouter",
"mode": "chat"
},
"openrouter/x-ai/grok-3-mini-beta": {
"max_tokens": 131072,
"max_input_tokens": 131072,
"max_output_tokens": 131072,
"input_cost_per_token": 0.0000003,
"output_cost_per_token": 0.0000005,
"litellm_provider": "openrouter",
"mode": "chat"
},
"openrouter/x-ai/grok-3-fast-beta": {
"max_tokens": 131072,
"max_input_tokens": 131072,
"max_output_tokens": 131072,
"input_cost_per_token": 0.000005,
"output_cost_per_token": 0.000025,
"litellm_provider": "openrouter",
"mode": "chat"
},
"openrouter/x-ai/grok-3-mini-fast-beta": {
"max_tokens": 131072,
"max_input_tokens": 131072,
"max_output_tokens": 131072,
"input_cost_per_token": 0.0000006,
"output_cost_per_token": 0.000004,
"litellm_provider": "openrouter",
"mode": "chat"
},
"openrouter/google/gemini-2.0-flash-exp:free": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
"max_output_tokens": 8192,

View File

@@ -817,7 +817,7 @@
use_temperature: false
editor_model_name: openrouter/deepseek/deepseek-chat
editor_edit_format: editor-diff
- name: fireworks_ai/accounts/fireworks/models/deepseek-r1
edit_format: diff
weak_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3
@@ -838,6 +838,14 @@
extra_params:
max_tokens: 128000
- name: fireworks_ai/accounts/fireworks/models/deepseek-v3-0324
edit_format: diff
use_repo_map: true
reminder: sys
examples_as_sys_msg: true
extra_params:
max_tokens: 160000
- name: openai/o3-mini
edit_format: diff
weak_model_name: gpt-4o-mini
@@ -847,7 +855,7 @@
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: o3-mini
edit_format: diff
weak_model_name: gpt-4o-mini
@@ -897,7 +905,7 @@
examples_as_sys_msg: true
editor_model_name: gpt-4o
editor_edit_format: editor-diff
- name: openai/gpt-4.5-preview
edit_format: diff
weak_model_name: gpt-4o-mini
@@ -942,30 +950,439 @@
- name: gemini/gemma-3-27b-it
use_system_prompt: false
- name: openrouter/google/gemma-3-27b-it:free
use_system_prompt: false
- name: openrouter/google/gemma-3-27b-it
use_system_prompt: false
- name: gemini/gemini-2.5-pro-exp-03-25
- name: gemini/gemini-2.5-pro-preview-03-25
overeager: true
edit_format: diff-fenced
use_repo_map: true
weak_model_name: gemini/gemini-2.0-flash
- name: gemini/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
use_repo_map: true
overeager: true
weak_model_name: gemini/gemini-2.5-flash-preview-04-17
- name: openrouter/google/gemini-2.5-pro-exp-03-25:free
edit_format: diff-fenced
overeager: true
use_repo_map: true
weak_model_name: openrouter/google/gemini-2.0-flash-exp:free
- name: vertex_ai/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
use_repo_map: true
# Need metadata for this one...
#weak_model_name: vertex_ai/gemini-2.0-flash
weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
overeager: true
editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: vertex_ai/gemini-2.5-pro-preview-03-25
edit_format: diff-fenced
use_repo_map: true
weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
overeager: true
editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: openrouter/openrouter/quasar-alpha
use_repo_map: true
edit_format: diff
examples_as_sys_msg: true
- name: openrouter/x-ai/grok-3-beta
use_repo_map: true
edit_format: diff
- name: xai/grok-3-beta
use_repo_map: true
edit_format: diff
- name: openrouter/x-ai/grok-3-mini-beta
use_repo_map: true
edit_format: whole
accepts_settings:
- reasoning_effort
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: xai/grok-3-mini-beta
use_repo_map: true
edit_format: whole
accepts_settings:
- reasoning_effort
#extra_params:
# extra_body:
# reasoning_effort: low
- name: openrouter/x-ai/grok-3-fast-beta
use_repo_map: true
edit_format: diff
- name: xai/grok-3-fast-beta
use_repo_map: true
edit_format: diff
- name: openrouter/x-ai/grok-3-mini-fast-beta
use_repo_map: true
edit_format: whole
accepts_settings:
- reasoning_effort
- name: xai/grok-3-mini-fast-beta
use_repo_map: true
edit_format: whole
accepts_settings:
- reasoning_effort
- name: openrouter/openrouter/optimus-alpha
use_repo_map: true
edit_format: diff
examples_as_sys_msg: true
- name: gpt-4.1
edit_format: diff
weak_model_name: gpt-4.1-mini
use_repo_map: true
reminder: sys # user: 52.x%/96.9%
examples_as_sys_msg: false # true: 51.6% correct, 95.6% well formed; false: 52.4%/98.2%
editor_model_name: gpt-4.1-mini
- name: openai/gpt-4.1
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
reminder: sys
examples_as_sys_msg: false
editor_model_name: openai/gpt-4.1-mini
- name: azure/gpt-4.1
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
reminder: sys
examples_as_sys_msg: false
editor_model_name: azure/gpt-4.1-mini
- name: openrouter/openai/gpt-4.1
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
reminder: sys
examples_as_sys_msg: false
editor_model_name: openrouter/openai/gpt-4.1-mini
- name: gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
examples_as_sys_msg: false # false: 32.x%/92.4% (60+ malformed responses); true: 31.7/90.2/60+
- name: openai/gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
examples_as_sys_msg: false
- name: azure/gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
examples_as_sys_msg: false
- name: openrouter/openai/gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
examples_as_sys_msg: false
- name: o3
streaming: false
edit_format: diff
weak_model_name: gpt-4.1-mini
use_repo_map: true
editor_model_name: gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openai/o3
streaming: false
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openrouter/openai/o3
streaming: false
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: azure/o3
streaming: false
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
- name: o4-mini
edit_format: diff
weak_model_name: gpt-4.1-mini
use_repo_map: true
use_temperature: false
editor_model_name: gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
examples_as_sys_msg: true
#extra_params:
# extra_body:
# reasoning_effort: high
- name: gemini/gemini-2.5-flash-preview-04-17
edit_format: diff
use_repo_map: true
accepts_settings: ["thinking_tokens"]
- name: gemini-2.5-flash-preview-04-17
edit_format: diff
use_repo_map: true
accepts_settings: ["thinking_tokens"]
- name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
edit_format: diff
use_repo_map: true
accepts_settings: ["thinking_tokens"]

View File

@@ -34,6 +34,8 @@ def load_gitignores(gitignore_paths: list[Path]) -> Optional[PathSpec]:
"__pycache__/", # Python cache dir
".DS_Store", # macOS metadata
"Thumbs.db", # Windows thumbnail cache
"*.svg",
"*.pdf",
# IDE files
".idea/", # JetBrains IDEs
".vscode/", # VS Code
@@ -64,7 +66,9 @@ class FileWatcher:
"""Watches source files for changes and AI comments"""
# Compiled regex pattern for AI comments
ai_comment_pattern = re.compile(r"(?:#|//|--|;+) *(ai\b.*|ai\b.*|.*\bai[?!]?) *$", re.IGNORECASE)
ai_comment_pattern = re.compile(
r"(?:#|//|--|;+) *(ai\b.*|ai\b.*|.*\bai[?!]?) *$", re.IGNORECASE
)
def __init__(self, coder, gitignores=None, verbose=False, analytics=None, root=None):
self.coder = coder
@@ -93,15 +97,19 @@ class FileWatcher:
rel_path = path_abs.relative_to(self.root)
if self.verbose:
dump(rel_path)
print("Changed", rel_path)
if self.gitignore_spec and self.gitignore_spec.match_file(
rel_path.as_posix() + ("/" if path_abs.is_dir() else "")
):
return False
# Check file size before reading content
if path_abs.is_file() and path_abs.stat().st_size > 1 * 1024 * 1024: # 1MB limit
return False
if self.verbose:
dump("ok", rel_path)
print("Checking", rel_path)
# Check if file contains AI markers
try:

View File

@@ -24,6 +24,65 @@ cog.out(text)
]]]-->
### main branch
- Add support for `gemini-2.5-flash-preview-04-17` models.
- Improved robustness of edit block parsing when filenames start with backticks or fences.
- Add new `udiff-simple` edit format, for Gemini 2.5 Pro.
- Update default weak/editor models for Gemini 2.5 Pro models to use `gemini-2.5-flash-preview-04-17`.
- Instruct models to reply in the user's detected system language.
- Fix parsing of diffs for newly created files (`--- /dev/null`).
- Add markdown syntax highlighting support when editing multi-line commit messages via `/commit`, by Kay Gosho.
- Set Gemini 2.5 Pro models to use the `overeager` prompt setting by default.
- Add common file types (`.svg`, `.pdf`) and IDE directories (`.idea/`, `.vscode/`, etc.) to the default list of ignored files for AI comment scanning (`--watch`).
- Skip scanning files larger than 1MB for AI comments (`--watch`).
- Aider wrote 67% of the code in this release.
### Aider v0.82.2
- Fix editing shell files with diff-fenced, by zjy1412.
- Improve robustness of patch application by allowing multiple update/delete actions for the same file within a single response.
- Update prompts to instruct LLMs to consolidate all edits for a given file into a single block within the patch.
### Aider v0.82.1
- Added support for `o3` and `o4-mini` including provider-specific versions for OpenAI, OpenRouter, and Azure.
- Added support for Azure specific `gpt-4.1` and `gpt-4.1-mini` models.
- Disabled streaming for `o3` models since you need identity verification to stream.
- Fixed handling of file paths in unified diffs, especially those generated by git.
### Aider v0.82.0
- Support for GPT 4.1, mini and nano.
- Added new `patch` edit format for OpenAI's GPT-4.1 model.
- Improved support for using architect mode with Gemini 2.5 Pro.
- Added new `editor-diff`, `editor-whole`, and `editor-diff-fenced` edit formats.
- Bugfix for automatically selecting the best edit format to use in architect mode.
- Added support for `grok-3-fast-beta` and `grok-3-mini-fast-beta` models.
- Aider wrote 92% of the code in this release.
### Aider v0.81.3
- Commit messages generated by aider are no longer forced to be entirely lowercase, by Peter Hadlaw.
- Updated default settings for Grok models.
### Aider v0.81.2
- Add support for `xai/grok-3-beta`, `xai/grok-3-mini-beta`, `openrouter/x-ai/grok-3-beta`, `openrouter/x-ai/grok-3-mini-beta`, and `openrouter/openrouter/optimus-alpha` models.
- Add alias "grok3" for `xai/grok-3-beta`.
- Add alias "optimus" for `openrouter/openrouter/optimus-alpha`.
- Fix URL extraction from error messages.
- Allow adding files by full path even if a file with the same basename is already in the chat.
- Fix quoting of values containing '#' in the sample `aider.conf.yml`.
- Add support for Fireworks AI model 'deepseek-v3-0324', by Felix Lisczyk.
- Commit messages generated by aider are now lowercase, by Anton Ödman.
### Aider v0.81.1
- Added support for the `gemini/gemini-2.5-pro-preview-03-25` model.
- Updated the `gemini` alias to point to `gemini/gemini-2.5-pro-preview-03-25`.
- Added the `gemini-exp` alias for `gemini/gemini-2.5-pro-exp-03-25`.
### Aider v0.81.0
- Added support for the `openrouter/openrouter/quasar-alpha` model.

View File

@@ -4410,3 +4410,93 @@
Vasil Markoukin: 129
start_tag: v0.79.0
total_lines: 2115
- aider_percentage: 85.55
aider_total: 225
end_date: '2025-04-04'
end_tag: v0.81.0
file_counts:
.github/workflows/check_pypi_version.yml:
Paul Gauthier: 11
Paul Gauthier (aider): 75
.github/workflows/windows_check_pypi_version.yml:
Paul Gauthier: 4
Paul Gauthier (aider): 86
aider/__init__.py:
Paul Gauthier: 1
aider/coders/base_coder.py:
Paul Gauthier (aider): 4
aider/exceptions.py:
Paul Gauthier: 6
Paul Gauthier (aider): 12
aider/main.py:
Paul Gauthier (aider): 40
aider/models.py:
Paul Gauthier (aider): 2
aider/resources/model-settings.yml:
Paul Gauthier: 9
Paul Gauthier (aider): 1
aider/website/_includes/leaderboard.js:
Paul Gauthier (aider): 5
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
aider/website/index.html:
Paul Gauthier: 3
tests/basic/test_exceptions.py:
Paul Gauthier: 3
grand_total:
Paul Gauthier: 38
Paul Gauthier (aider): 225
start_tag: v0.80.0
total_lines: 263
- aider_percentage: 91.85
aider_total: 1567
end_date: '2025-04-14'
end_tag: v0.82.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/args_formatter.py:
Paul Gauthier (aider): 4
aider/coders/__init__.py:
Paul Gauthier (aider): 4
aider/coders/base_coder.py:
Paul Gauthier: 4
Paul Gauthier (aider): 5
aider/coders/editor_diff_fenced_coder.py:
Paul Gauthier (aider): 9
aider/coders/patch_coder.py:
Paul Gauthier (aider): 679
aider/coders/search_replace.py:
Paul Gauthier (aider): 1
aider/main.py:
Paul Gauthier (aider): 1
aider/models.py:
Paul Gauthier: 1
Paul Gauthier (aider): 25
aider/resources/model-settings.yml:
Felix Lisczyk: 13
Paul Gauthier: 37
Paul Gauthier (aider): 68
aider/website/_includes/leaderboard.js:
Paul Gauthier: 38
Paul Gauthier (aider): 6
aider/website/_includes/leaderboard_table.js:
Paul Gauthier (aider): 518
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 15
Paul Gauthier (aider): 209
aider/website/index.html:
Paul Gauthier: 28
scripts/homepage.py:
Paul Gauthier (aider): 2
scripts/versionbump.py:
Paul Gauthier (aider): 11
tests/basic/test_coder.py:
Paul Gauthier: 2
Paul Gauthier (aider): 25
grand_total:
Felix Lisczyk: 13
Paul Gauthier: 126
Paul Gauthier (aider): 1567
start_tag: v0.81.0
total_lines: 1706

View File

@@ -643,7 +643,7 @@
exhausted_context_windows: 0
test_timeouts: 1
total_tests: 225
command: "aider --model anthropic/claude-3-7-sonnet-20250219 # plus yml config"
command: "aider --model anthropic/claude-3-7-sonnet-20250219 --thinking-tokens 32k"
date: 2025-02-24
versions: 0.75.1.dev
seconds_per_case: 105.2
@@ -807,31 +807,31 @@
seconds_per_case: 290.0
total_cost: 1.1164
- dirname: 2025-03-25-19-46-45--gemini-25-pro-exp-diff-fenced
- dirname: 2025-04-12-04-55-50--gemini-25-pro-diff-fenced
test_cases: 225
model: Gemini 2.5 Pro exp-03-25
model: Gemini 2.5 Pro Preview 03-25
edit_format: diff-fenced
commit_hash: 33413ec
pass_rate_1: 39.1
commit_hash: 0282574
pass_rate_1: 40.9
pass_rate_2: 72.9
pass_num_1: 88
pass_num_1: 92
pass_num_2: 164
percent_cases_well_formed: 89.8
error_outputs: 30
num_malformed_responses: 30
num_with_malformed_responses: 23
user_asks: 57
percent_cases_well_formed: 92.4
error_outputs: 21
num_malformed_responses: 21
num_with_malformed_responses: 17
user_asks: 69
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
test_timeouts: 2
total_tests: 225
command: aider --model gemini/gemini-2.5-pro-exp-03-25
date: 2025-03-25
versions: 0.78.1.dev
seconds_per_case: 47.1
total_cost: 0.0000
command: aider --model gemini/gemini-2.5-pro-preview-03-25
date: 2025-04-12
versions: 0.81.3.dev
seconds_per_case: 45.3
total_cost: 6.3174
- dirname: 2025-03-29-05-24-55--chatgpt4o-mar28-diff
test_cases: 225
@@ -883,4 +883,344 @@
date: 2025-04-04
versions: 0.80.5.dev
seconds_per_case: 14.8
total_cost: 0.0000
total_cost: 0.0000
- dirname: 2025-04-06-08-39-52--llama-4-maverick-17b-128e-instruct-polyglot-whole
test_cases: 225
model: Llama 4 Maverick
edit_format: whole
commit_hash: 9445a31
pass_rate_1: 4.4
pass_rate_2: 15.6
pass_num_1: 10
pass_num_2: 35
percent_cases_well_formed: 99.1
error_outputs: 12
num_malformed_responses: 2
num_with_malformed_responses: 2
user_asks: 248
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 4
total_tests: 225
command: aider --model nvidia_nim/meta/llama-4-maverick-17b-128e-instruct
date: 2025-04-06
versions: 0.81.2.dev
seconds_per_case: 20.5
total_cost: 0.0000
- dirname: 2025-04-10-04-21-31--grok3-diff-exuser
test_cases: 225
model: Grok 3 Beta
edit_format: diff
commit_hash: 2dd40fc-dirty
pass_rate_1: 22.2
pass_rate_2: 53.3
pass_num_1: 50
pass_num_2: 120
percent_cases_well_formed: 99.6
error_outputs: 1
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 68
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
total_tests: 225
command: aider --model openrouter/x-ai/grok-3-beta
date: 2025-04-10
versions: 0.81.2.dev
seconds_per_case: 15.3
total_cost: 11.0338
- dirname: 2025-04-10-18-47-24--grok3-mini-whole-exuser
test_cases: 225
model: Grok 3 Mini Beta (low)
edit_format: whole
commit_hash: 14ffe77-dirty
pass_rate_1: 11.1
pass_rate_2: 34.7
pass_num_1: 25
pass_num_2: 78
percent_cases_well_formed: 100.0
error_outputs: 3
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 73
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 5
total_tests: 225
command: aider --model openrouter/x-ai/grok-3-mini-beta
date: 2025-04-10
versions: 0.81.2.dev
seconds_per_case: 35.1
total_cost: 0.7856
- dirname: 2025-04-10-23-59-02--xai-grok3-mini-whole-high
test_cases: 225
model: Grok 3 Mini Beta (high)
edit_format: whole
commit_hash: 8ee33da-dirty
pass_rate_1: 17.3
pass_rate_2: 49.3
pass_num_1: 39
pass_num_2: 111
percent_cases_well_formed: 99.6
error_outputs: 1
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 64
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
total_tests: 225
command: aider --model xai/grok-3-mini-beta --reasoning-effort high
date: 2025-04-10
versions: 0.81.3.dev
seconds_per_case: 79.1
total_cost: 0.7346
- dirname: 2025-04-10-19-02-44--oalpha-diff-exsys
test_cases: 225
model: Optimus Alpha
edit_format: diff
commit_hash: 532bc45-dirty
pass_rate_1: 21.3
pass_rate_2: 52.9
pass_num_1: 48
pass_num_2: 119
percent_cases_well_formed: 97.3
error_outputs: 7
num_malformed_responses: 6
num_with_malformed_responses: 6
user_asks: 182
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 3
total_tests: 225
command: aider --model openrouter/openrouter/optimus-alpha
date: 2025-04-10
versions: 0.81.2.dev
seconds_per_case: 18.4
total_cost: 0.0000
- dirname: 2025-04-14-21-05-54--gpt41-diff-exuser
test_cases: 225
model: gpt-4.1
edit_format: diff
commit_hash: 7a87db5-dirty
pass_rate_1: 20.0
pass_rate_2: 52.4
pass_num_1: 45
pass_num_2: 118
percent_cases_well_formed: 98.2
error_outputs: 6
num_malformed_responses: 5
num_with_malformed_responses: 4
user_asks: 171
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 5
total_tests: 225
command: aider --model gpt-4.1
date: 2025-04-14
versions: 0.81.4.dev
seconds_per_case: 20.5
total_cost: 9.8556
- dirname: 2025-04-14-21-27-53--gpt41mini-diff
test_cases: 225
model: gpt-4.1-mini
edit_format: diff
commit_hash: ffb743e-dirty
pass_rate_1: 11.1
pass_rate_2: 32.4
pass_num_1: 25
pass_num_2: 73
percent_cases_well_formed: 92.4
error_outputs: 64
num_malformed_responses: 62
num_with_malformed_responses: 17
user_asks: 159
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 2
test_timeouts: 2
total_tests: 225
command: aider --model gpt-4.1-mini
date: 2025-04-14
versions: 0.81.4.dev
seconds_per_case: 19.5
total_cost: 1.9918
- dirname: 2025-04-14-22-46-01--gpt41nano-diff
test_cases: 225
model: gpt-4.1-nano
edit_format: whole
commit_hash: 71d1591-dirty
pass_rate_1: 3.1
pass_rate_2: 8.9
pass_num_1: 7
pass_num_2: 20
percent_cases_well_formed: 94.2
error_outputs: 20
num_malformed_responses: 20
num_with_malformed_responses: 13
user_asks: 316
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 8
total_tests: 225
command: aider --model gpt-4.1-nano
date: 2025-04-14
versions: 0.81.4.dev
seconds_per_case: 12.0
total_cost: 0.4281
- dirname: 2025-04-16-21-20-55--o3-high-diff-temp0-exsys
test_cases: 225
model: o3 (high)
edit_format: diff
commit_hash: 24805ff-dirty
pass_rate_1: 36.9
pass_rate_2: 79.6
pass_num_1: 83
pass_num_2: 179
percent_cases_well_formed: 95.1
error_outputs: 11
num_malformed_responses: 11
num_with_malformed_responses: 11
user_asks: 110
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 2
total_tests: 225
command: aider --model o3
date: 2025-04-16
versions: 0.82.1.dev
seconds_per_case: 113.8
total_cost: 111.0325
- dirname: 2025-04-16-22-01-58--o4-mini-high-diff-exsys
test_cases: 225
model: o4-mini (high)
edit_format: diff
commit_hash: b66901f-dirty
pass_rate_1: 19.6
pass_rate_2: 72.0
pass_num_1: 44
pass_num_2: 162
percent_cases_well_formed: 90.7
error_outputs: 26
num_malformed_responses: 24
num_with_malformed_responses: 21
user_asks: 66
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 1
test_timeouts: 2
total_tests: 225
command: aider --model o4-mini
date: 2025-04-16
versions: 0.82.1.dev
seconds_per_case: 176.5
total_cost: 19.6399
- dirname: 2025-04-17-01-20-35--o3-mini-high-diff-arch
test_cases: 225
model: o3 (high) + gpt-4.1
edit_format: architect
commit_hash: 80909e1-dirty
editor_model: gpt-4.1
editor_edit_format: editor-diff
pass_rate_1: 36.0
pass_rate_2: 82.7
pass_num_1: 81
pass_num_2: 186
percent_cases_well_formed: 100.0
error_outputs: 9
num_malformed_responses: 0
num_with_malformed_responses: 0
user_asks: 166
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 0
total_tests: 225
command: aider --model o3 --architect
date: 2025-04-17
versions: 0.82.2.dev
seconds_per_case: 110.0
total_cost: 69.2921
- dirname: 2025-04-19-14-43-04--o4-mini-patch
test_cases: 225
model: openhands-lm-32b-v0.1
edit_format: whole
commit_hash: c08336f
pass_rate_1: 4.0
pass_rate_2: 10.2
pass_num_1: 9
pass_num_2: 23
percent_cases_well_formed: 95.1
error_outputs: 55
num_malformed_responses: 41
num_with_malformed_responses: 11
user_asks: 166
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 11
total_tests: 225
command: aider --model openrouter/all-hands/openhands-lm-32b-v0.1
date: 2025-04-19
versions: 0.82.2.dev
seconds_per_case: 195.6
total_cost: 0.0000
- dirname: 2025-04-20-19-54-31--flash25-diff-no-think
test_cases: 225
model: gemini-2.5-flash-preview-04-17 (default)
edit_format: diff
commit_hash: 7fcce5d-dirty
pass_rate_1: 21.8
pass_rate_2: 47.1
pass_num_1: 49
pass_num_2: 106
percent_cases_well_formed: 85.3
error_outputs: 60
num_malformed_responses: 55
num_with_malformed_responses: 33
user_asks: 82
lazy_comments: 1
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 5
test_timeouts: 4
total_tests: 225
command: aider --model gemini/gemini-2.5-flash-preview-04-17
date: 2025-04-20
versions: 0.82.3.dev
seconds_per_case: 50.1
total_cost: 1.8451

View File

@@ -27,7 +27,7 @@ document.addEventListener('DOMContentLoaded', function () {
labels: labels,
datasets: [{
label: 'Aider\'s percent of new code by release',
data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.aider_percentage }}, lines: {{ row.aider_total }} },{% endfor %}],
data: [{% for row in site.data.blame %}{ x: '{{ row.end_tag }}', y: {{ row.aider_percentage }}, lines: {{ row.aider_total }}, end_date: '{{ row.end_date }}' },{% endfor %}],
backgroundColor: 'rgba(54, 162, 235, 0.8)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
@@ -88,6 +88,10 @@ document.addEventListener('DOMContentLoaded', function () {
var value = context.parsed.y || 0;
var lines = context.raw.lines || 0;
return `${label}: ${Math.round(value)}% (${lines} lines)`;
},
afterLabel: function(context) {
let date = context.raw.end_date || 'n/a';
return `Date: ` + date;
}
}
},

View File

@@ -1,10 +1,13 @@
If you already have python 3.8-3.13 installed, you can get started quickly like this:
If you already have python 3.8-3.13 installed, you can get started quickly like this.
First, install aider:
{% include install.md %}
Start working with aider on your codebase:
```bash
python -m pip install aider-install
aider-install
# Change directory into your codebase
cd /to/your/project

View File

@@ -0,0 +1,5 @@
```bash
python -m pip install aider-install
aider-install
```

View File

@@ -17,14 +17,14 @@ document.addEventListener('DOMContentLoaded', function () {
backgroundColor: function(context) {
const row = allData[context.dataIndex];
if (row && row.edit_format === 'whole') {
return diagonalPattern;
return redDiagonalPattern; // Use red pattern for highlighted whole format
}
const label = leaderboardData.labels[context.dataIndex] || '';
return (label && label.includes(HIGHLIGHT_MODEL)) ? 'rgba(255, 99, 132, 0.2)' : 'rgba(54, 162, 235, 0.2)';
return (label && HIGHLIGHT_MODEL && label.toLowerCase().includes(HIGHLIGHT_MODEL.toLowerCase())) ? '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(HIGHLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)';
return (label && HIGHLIGHT_MODEL && label.toLowerCase().includes(HIGHLIGHT_MODEL.toLowerCase())) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)';
},
borderWidth: 1
}, {
@@ -78,11 +78,13 @@ document.addEventListener('DOMContentLoaded', function () {
leaderboardChart.render();
}
// Use displayedData in the backgroundColor callback instead of allData
// Update backgroundColor and borderColor for the main dataset based on displayedData
leaderboardData.datasets[0].backgroundColor = function(context) {
const row = displayedData[context.dataIndex];
const label = leaderboardData.labels[context.dataIndex] || '';
if (label && label.includes(HIGHLIGHT_MODEL)) {
const isHighlighted = label && HIGHLIGHT_MODEL && label.toLowerCase().includes(HIGHLIGHT_MODEL.toLowerCase());
if (isHighlighted) {
if (row && row.edit_format === 'whole') return redDiagonalPattern;
else return 'rgba(255, 99, 132, 0.2)';
} else if (row && row.edit_format === 'whole') {

View File

@@ -0,0 +1,515 @@
document.addEventListener('DOMContentLoaded', function() {
let currentMode = 'view'; // 'view', 'select', 'detail'
let selectedRows = new Set(); // Store indices of selected rows
const MAX_DISPLAY_COST_CAP = 75; // Define the constant here
const allMainRows = document.querySelectorAll('tr[id^="main-row-"]');
const allDetailsRows = document.querySelectorAll('tr[id^="details-"]');
const searchInput = document.getElementById('editSearchInput');
const modeViewButton = document.getElementById('mode-view-btn');
const modeDetailButton = document.getElementById('mode-detail-btn');
const modeSelectButton = document.getElementById('mode-select-btn');
const modeButtons = [modeViewButton, modeSelectButton, modeDetailButton];
const selectAllCheckbox = document.getElementById('select-all-checkbox');
const leaderboardTitle = document.getElementById('leaderboard-title'); // Get title element
const defaultTitle = "Aider polyglot coding leaderboard";
const filteredTitle = "Aider polyglot coding benchmark results (selected)";
function applySearchFilter() {
const searchTerm = searchInput.value.toLowerCase();
allMainRows.forEach(row => {
const textContent = row.textContent.toLowerCase();
const detailsRow = document.getElementById(row.id.replace('main-row-', 'details-'));
const matchesSearch = textContent.includes(searchTerm);
if (matchesSearch) {
row.classList.remove('hidden-by-search');
if (detailsRow) detailsRow.classList.remove('hidden-by-search');
} else {
row.classList.add('hidden-by-search');
if (detailsRow) detailsRow.classList.add('hidden-by-search');
}
});
// After applying search filter, re-apply view mode filter and update select-all state
updateTableView(currentMode);
if (currentMode === 'select') {
updateSelectAllCheckboxState();
}
// Update cost bars and ticks since visible rows may have changed
updateCostBars();
updateCostTicks();
}
function getVisibleMainRows() {
// Helper to get rows currently visible (not hidden by search or mode)
return Array.from(allMainRows).filter(row =>
!row.classList.contains('hidden-by-search') && !row.classList.contains('hidden-by-mode')
);
}
function updateSelectAllCheckboxState() {
// Update the header checkbox based on the selection state of *visible* rows
if (currentMode !== 'select') return; // Only relevant in select mode
const visibleRows = getVisibleMainRows();
const visibleRowCount = visibleRows.length;
const selectedVisibleRowCount = visibleRows.filter(row => selectedRows.has(row.querySelector('.row-selector')?.dataset.rowIndex)).length;
if (visibleRowCount === 0) {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = false;
} else if (selectedVisibleRowCount === visibleRowCount) {
selectAllCheckbox.checked = true;
selectAllCheckbox.indeterminate = false;
} else if (selectedVisibleRowCount > 0) {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = true;
} else {
selectAllCheckbox.checked = false;
selectAllCheckbox.indeterminate = false;
}
}
function updateTableView(mode) {
currentMode = mode; // Update global state ('view', 'select', 'detail')
// Update button styles first
modeButtons.forEach(btn => {
btn.classList.remove('active');
// Reset specific styles potentially added by .active
btn.style.backgroundColor = '';
btn.style.color = '';
});
let activeButton;
if (mode === 'view') activeButton = modeViewButton;
else if (mode === 'select') activeButton = modeSelectButton;
else if (mode === 'detail') activeButton = modeDetailButton;
activeButton.classList.add('active');
activeButton.style.backgroundColor = '#e7f3ff'; // Use selected row highlight blue
activeButton.style.color = '#495057'; // Use dark text for contrast on light blue
// Get the first header cell (for the toggle/checkbox column)
const firstHeaderCell = document.querySelector('table thead th:first-child');
// Show/hide header checkbox based on mode
selectAllCheckbox.style.display = mode === 'select' ? 'inline-block' : 'none';
allMainRows.forEach(row => {
const rowIndex = row.querySelector('.row-selector')?.dataset.rowIndex;
const toggleButton = row.querySelector('.toggle-details');
const selectorCheckbox = row.querySelector('.row-selector');
const firstCell = row.querySelector('td:first-child'); // Get the first cell of the main row
const detailsRow = document.getElementById(`details-${rowIndex}`);
const isSelected = selectedRows.has(rowIndex);
// Reset visibility classes before applying mode logic
row.classList.remove('hidden-by-mode');
if (detailsRow) detailsRow.classList.remove('hidden-by-mode');
// Show/hide the first column (header and data cells) based on mode
if (firstHeaderCell) {
firstHeaderCell.style.display = mode === 'view' ? 'none' : '';
}
if (firstCell) {
firstCell.style.display = mode === 'view' ? 'none' : '';
}
// Apply mode-specific logic
if (mode === 'view') { // --- VIEW MODE ---
toggleButton.style.display = 'none'; // Hide toggle in view mode
selectorCheckbox.style.display = 'none';
row.classList.remove('row-selected'); // Ensure no selection highlight
// view-highlighted is handled by row click listener
// In 'view' mode, hide row if selections exist AND this row is NOT selected
if (selectedRows.size > 0 && !isSelected) {
row.classList.add('hidden-by-mode');
if (detailsRow) detailsRow.classList.add('hidden-by-mode');
} else {
// Ensure row is not hidden by mode if it's selected or no selections exist
// This is handled by the reset at the start of the loop:
// row.classList.remove('hidden-by-mode');
// if (detailsRow) detailsRow.classList.remove('hidden-by-mode');
}
// Always hide details row content in view mode regardless of visibility class
if (detailsRow) {
detailsRow.style.display = 'none';
}
} else if (mode === 'select') { // --- SELECT MODE ---
toggleButton.style.display = 'none';
selectorCheckbox.style.display = 'inline-block';
selectorCheckbox.checked = isSelected;
row.classList.toggle('row-selected', isSelected);
row.classList.remove('view-highlighted'); // Clear view highlight when switching to select
// Always hide details row in select mode
if (detailsRow) detailsRow.style.display = 'none';
// In 'select' mode, no rows should be hidden based on selection status
row.classList.remove('hidden-by-mode');
if (detailsRow) detailsRow.classList.remove('hidden-by-mode');
} else { // --- DETAIL MODE --- (mode === 'detail')
toggleButton.style.display = 'inline-block'; // Show toggle
selectorCheckbox.style.display = 'none';
row.classList.remove('row-selected'); // Clear selection highlight
row.classList.remove('view-highlighted'); // Clear view highlight when switching to detail
// Details row visibility is controlled by the toggle button state, don't force hide/show here
// Ensure main row is visible if not hidden by search
row.classList.remove('hidden-by-mode');
if (detailsRow) {
detailsRow.classList.remove('hidden-by-mode');
// Preserve existing display state (controlled by toggle) unless hidden by search
if (detailsRow.classList.contains('hidden-by-search')) {
detailsRow.style.display = 'none';
}
}
}
// Ensure rows hidden by search remain hidden regardless of mode
if (row.classList.contains('hidden-by-search')) {
row.style.display = 'none';
if (detailsRow) detailsRow.style.display = 'none';
} else if (!row.classList.contains('hidden-by-mode')) {
// Make row visible if not hidden by search or mode
row.style.display = ''; // Or 'table-row' if needed, but '' usually works
} else {
// Row is hidden by mode, ensure it's hidden
row.style.display = 'none';
if (detailsRow) detailsRow.style.display = 'none';
}
});
// Update the leaderboard title based on mode and selection
if (leaderboardTitle) {
if (currentMode === 'view' && selectedRows.size > 0) {
leaderboardTitle.textContent = filteredTitle;
} else {
leaderboardTitle.textContent = defaultTitle;
}
}
// Update the select-all checkbox state after updating the view
updateSelectAllCheckboxState();
// Update cost bars and ticks since visible/selected rows may have changed
updateCostBars();
updateCostTicks();
}
// --- Existing Initializations ---
// Add percentage ticks
const percentCells = document.querySelectorAll('.bar-cell:not(.cost-bar-cell)');
percentCells.forEach(cell => {
// Add ticks at 0%, 10%, 20%, ..., 100%
for (let i = 0; i <= 100; i += 10) {
const tick = document.createElement('div');
tick.className = 'percent-tick';
tick.style.left = `${i}%`;
cell.appendChild(tick);
}
});
// Function to calculate the appropriate max display cost based on visible/selected entries
function calculateDisplayMaxCost() {
// Get the appropriate set of rows based on the current mode and selection state
let rowsToConsider;
if (currentMode === 'view' && selectedRows.size > 0) {
// In view mode with selections, only consider selected rows
rowsToConsider = Array.from(allMainRows).filter(row => {
const rowIndex = row.querySelector('.row-selector')?.dataset.rowIndex;
return rowIndex && selectedRows.has(rowIndex) && !row.classList.contains('hidden-by-search');
});
} else {
// In other modes or without selections, consider all visible rows
rowsToConsider = getVisibleMainRows();
}
// Find the maximum cost among the rows to consider
let maxCost = 0;
rowsToConsider.forEach(row => {
const costBar = row.querySelector('.cost-bar');
if (costBar) {
const cost = parseFloat(costBar.dataset.cost || '0');
if (cost > maxCost) maxCost = cost;
}
});
// Cap at MAX_DISPLAY_COST_CAP if any entries exceed that amount, otherwise use actual max
return maxCost > MAX_DISPLAY_COST_CAP ? MAX_DISPLAY_COST_CAP : Math.max(1, maxCost); // Ensure at least 1 to avoid division by zero
}
// Process cost bars with dynamic scale
function updateCostBars() {
const costBars = document.querySelectorAll('.cost-bar');
const currentMaxDisplayCost = calculateDisplayMaxCost();
// Remove existing special indicators first
document.querySelectorAll('.dark-section, .tear-line').forEach(el => el.remove());
costBars.forEach(bar => {
const cost = parseFloat(bar.dataset.cost);
if (cost > 0) {
// Calculate percentage based on the dynamic display max
const percent = Math.min(cost, currentMaxDisplayCost) / currentMaxDisplayCost * 100;
// Clamp percentage between 0 and 100
bar.style.width = Math.max(0, Math.min(100, percent)) + '%';
// Mark bars that exceed the limit (only if our display max is capped at 50)
if (currentMaxDisplayCost === MAX_DISPLAY_COST_CAP && cost > MAX_DISPLAY_COST_CAP) {
// Create a darker section at the end with diagonal stripes
const darkSection = document.createElement('div');
darkSection.className = 'bar-viz dark-section';
darkSection.style.width = '15%'; // From 85% to 100%
darkSection.style.left = '85%';
darkSection.style.backgroundColor = 'rgba(13, 110, 253, 0.6)'; // Darker blue
darkSection.style.borderRight = '1px solid rgba(13, 110, 253, 0.8)';
darkSection.style.zIndex = '1';
// Add diagonal stripes with CSS background
darkSection.style.backgroundImage = 'repeating-linear-gradient(45deg, rgba(255,255,255,0.3), rgba(255,255,255,0.3) 5px, transparent 5px, transparent 10px)';
bar.parentNode.appendChild(darkSection);
// Add a dashed "tear line" at the transition point
const tearLine = document.createElement('div');
tearLine.className = 'tear-line';
tearLine.style.position = 'absolute';
tearLine.style.left = '85%';
// Center the tear line vertically and make it 1.5x as tall as the bar
tearLine.style.top = '50%';
tearLine.style.transform = 'translateY(-50%)';
tearLine.style.height = '54px'; // 1.5x the bar height (36px)
tearLine.style.width = '2px';
tearLine.style.backgroundColor = 'white';
tearLine.style.borderLeft = '2px dashed rgba(0, 0, 0, 0.3)';
tearLine.style.zIndex = '2'; // Above the bar
bar.parentNode.appendChild(tearLine);
}
} else {
// Set width to 0 if cost is 0 or negative
bar.style.width = '0%';
}
});
}
// Call this initially to set up the bars
updateCostBars();
// Update cost ticks dynamically based on current max display cost
function updateCostTicks() {
const costCells = document.querySelectorAll('.cost-bar-cell');
if (costCells.length === 0) return;
const currentMaxDisplayCost = calculateDisplayMaxCost();
// Remove existing ticks first
document.querySelectorAll('.cost-tick').forEach(tick => tick.remove());
// Generate appropriate tick values based on current max
let tickValues = [];
// Always use $10 increments, regardless of the max
const maxTickValue = Math.ceil(currentMaxDisplayCost / 10) * 10; // Round up to nearest $10
for (let i = 0; i <= maxTickValue; i += 10) {
tickValues.push(i);
}
// Calculate percentage positions for each tick
const tickPercentages = tickValues.map(tickCost => {
return (tickCost / currentMaxDisplayCost) * 100;
});
// Add tick divs to each cost cell
costCells.forEach(cell => {
const costBar = cell.querySelector('.cost-bar');
// Use optional chaining and provide '0' as fallback if costBar or dataset.cost is missing
const cost = parseFloat(costBar?.dataset?.cost || '0');
// Only add ticks if the cost is actually greater than 0
if (cost > 0) {
tickPercentages.forEach((percent, index) => {
// Ensure percentage is within valid range
if (percent >= 0 && percent <= 100) {
const tick = document.createElement('div');
tick.className = 'cost-tick';
tick.style.left = `${percent}%`;
cell.appendChild(tick);
}
});
}
});
}
// Call this initially to set up the ticks
updateCostTicks();
// --- New Event Listeners ---
// Listener for mode toggle buttons
modeButtons.forEach(button => {
button.addEventListener('click', function(event) {
const newMode = this.dataset.mode;
if (newMode !== currentMode) {
// Update active button style
modeButtons.forEach(btn => {
btn.classList.remove('active');
// Reset specific styles potentially added by .active
btn.style.backgroundColor = '';
btn.style.color = '';
});
this.classList.add('active');
// Apply active styles directly as inline styles might interfere
this.style.backgroundColor = '#e7f3ff'; // Use selected row highlight blue
this.style.color = '#495057'; // Use dark text for contrast on light blue
// Update table view and apply filters
updateTableView(newMode);
applySearchFilter(); // Re-apply search filter when mode changes
}
});
});
// Listener for row selector checkboxes (using event delegation on table body)
const tableBody = document.querySelector('table tbody');
tableBody.addEventListener('change', function(event) {
if (event.target.classList.contains('row-selector') && currentMode === 'select') {
const checkbox = event.target;
const rowIndex = checkbox.dataset.rowIndex;
const mainRow = checkbox.closest('tr');
if (checkbox.checked) {
selectedRows.add(rowIndex);
mainRow.classList.add('row-selected');
} else {
selectedRows.delete(rowIndex);
mainRow.classList.remove('row-selected');
}
// Update select-all checkbox state
updateSelectAllCheckboxState();
// Update cost bars and ticks if in view mode, as selection affects what's shown
if (currentMode === 'view') {
updateCostBars();
updateCostTicks();
}
}
}); // End of tableBody listener
// Listener for Select All checkbox
selectAllCheckbox.addEventListener('change', function() {
if (currentMode !== 'select') return;
const isChecked = selectAllCheckbox.checked;
// Select/deselect only the rows that are currently visible
const visibleRows = getVisibleMainRows();
visibleRows.forEach(row => {
const checkbox = row.querySelector('.row-selector');
const rowIndex = checkbox?.dataset.rowIndex;
if (!checkbox || !rowIndex) return; // Skip if no checkbox/index found
// Only change state if it differs from target state
if (checkbox.checked !== isChecked) {
checkbox.checked = isChecked;
row.classList.toggle('row-selected', isChecked);
if (isChecked) {
selectedRows.add(rowIndex);
} else {
selectedRows.delete(rowIndex);
}
}
});
// After bulk change, ensure the selectAll checkbox state is correct (not indeterminate)
updateSelectAllCheckboxState();
// Update cost bars and ticks after selection changes
updateCostBars();
updateCostTicks();
});
// Listener for search input
searchInput.addEventListener('input', applySearchFilter);
// Add toggle functionality for details (Modified to respect modes)
const toggleButtons = document.querySelectorAll('.toggle-details');
toggleButtons.forEach(button => {
button.addEventListener('click', function() {
// Only allow toggling in 'detail' mode
if (currentMode !== 'detail') return;
const targetId = this.getAttribute('data-target');
const targetRow = document.getElementById(targetId);
const mainRow = this.closest('tr'); // Get the main row associated with this button
if (targetRow && !mainRow.classList.contains('hidden-by-mode') && !mainRow.classList.contains('hidden-by-search')) {
const isVisible = targetRow.style.display !== 'none';
targetRow.style.display = isVisible ? 'none' : 'table-row';
this.textContent = isVisible ? '▶' : '▼';
}
});
});
// Listener for clicking anywhere on a row
tableBody.addEventListener('click', function(event) {
const clickedRow = event.target.closest('tr');
// Ensure it's a main row and not a details row or header/footer
if (!clickedRow || !clickedRow.id.startsWith('main-row-')) return;
// --- START conditional logic ---
if (currentMode === 'select') {
// --- SELECT MODE LOGIC (Existing) ---
// Find the checkbox within this row
const checkbox = clickedRow.querySelector('.row-selector');
if (!checkbox) return; // No checkbox found in this row
// If the click was directly on the checkbox or its label (if any),
// let the default behavior and the 'change' event listener handle it.
// Otherwise, toggle the checkbox state programmatically.
if (event.target !== checkbox && event.target.tagName !== 'LABEL' /* Add if you use labels */) {
checkbox.checked = !checkbox.checked;
// Manually trigger the change event to update state and UI
checkbox.dispatchEvent(new Event('change', { bubbles: true }));
}
// --- END SELECT MODE LOGIC ---
} else if (currentMode === 'view') {
// --- VIEW MODE LOGIC (New) ---
// Don't highlight if the click was on the details toggle button
if (event.target.classList.contains('toggle-details')) {
return;
}
// Toggle the highlight class on the clicked row
clickedRow.classList.toggle('view-highlighted');
// --- END VIEW MODE LOGIC ---
}
// --- END conditional logic ---
});
// --- Initial Setup ---
updateTableView('view'); // Initialize view to 'view' mode
applySearchFilter(); // Apply initial search filter (if any text is pre-filled or just to set initial state)
// Close button functionality
const closeControlsBtn = document.getElementById('close-controls-btn');
if (closeControlsBtn) {
closeControlsBtn.addEventListener('click', function() {
const controlsContainer = document.getElementById('controls-container');
if (controlsContainer) {
controlsContainer.style.display = 'none';
}
});
}
});

View File

@@ -4,7 +4,7 @@ You can send long, multi-line messages in the chat in a few ways:
- Or, start with `{tag` (where "tag" is any sequence of letters/numbers) and end with `tag}`. This is useful when you need to include closing braces `}` in your message.
- Use Meta-ENTER to start a new line without sending the message (Esc+ENTER in some environments).
- Use `/paste` to paste text from the clipboard into the chat.
- Use the `/editor` command to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
- Use the `/editor` command (or press `Ctrl-X Ctrl-E` if your terminal allows) to open your editor to create the next chat message. See [editor configuration docs](/docs/config/editor.html) for more info.
- Use multiline-mode, which swaps the function of Meta-Enter and Enter, so that Enter inserts a newline, and Meta-Enter submits your command. To enable multiline mode:
- Use the `/multiline-mode` command to toggle it during a session.
- Use the `--multiline` switch.

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

View File

@@ -446,7 +446,7 @@ code, pre, .code-block {
}
.testimonial-text::before {
content: "\201C"; /* Opening fancy quote */
content: "\201C\00A0"; /* Opening fancy quote */
color: var(--primary);
margin-right: 4px;
vertical-align: -0.3em;

File diff suppressed because it is too large Load Diff

View File

@@ -171,19 +171,19 @@
#stream: true
## Set the color for user input (default: #00cc00)
#user-input-color: #00cc00
#user-input-color: "#00cc00"
## Set the color for tool output (default: None)
#tool-output-color: "xxx"
## Set the color for tool error messages (default: #FF2222)
#tool-error-color: #FF2222
#tool-error-color: "#FF2222"
## Set the color for tool warning messages (default: #FFA500)
#tool-warning-color: #FFA500
#tool-warning-color: "#FFA500"
## Set the color for assistant output (default: #0088ff)
#assistant-output-color: #0088ff
#assistant-output-color: "#0088ff"
## Set the color for the completion menu (default: terminal's default text color)
#completion-menu-color: "xxx"

View File

@@ -117,40 +117,6 @@ For example:
These settings will be merged with any model-specific settings, with the
`aider/extra_params` settings taking precedence for any direct conflicts.
### Controlling o1 reasoning effort
You need this chunk of yaml:
```
extra_params:
extra_body:
reasoning_effort: high
```
This is a full entry for o1 with that setting, obtained by finding the default
entry in the list below and adding the above `extra_params` entry:
```
- name: o1
edit_format: diff
weak_model_name: gpt-4o-mini
use_repo_map: true
send_undo_reply: false
lazy: false
reminder: user
examples_as_sys_msg: false
cache_control: false
caches_by_default: false
use_system_prompt: true
use_temperature: false
streaming: false
editor_model_name: gpt-4o
editor_edit_format: editor-diff
extra_params:
extra_body:
reasoning_effort: high
```
### Default model settings
Below are all the pre-configured model settings to give a sense for the settings which are supported.
@@ -280,6 +246,18 @@ cog.out("```\n")
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25
cache_control: true
- name: azure/gpt-4.1
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
reminder: sys
editor_model_name: azure/gpt-4.1-mini
- name: azure/gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
- name: azure/o1
edit_format: diff
weak_model_name: azure/gpt-4o-mini
@@ -308,6 +286,18 @@ cog.out("```\n")
editor_model_name: azure/gpt-4o
editor_edit_format: editor-diff
- name: azure/o3
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
streaming: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: azure/o3-mini
edit_format: diff
weak_model_name: azure/gpt-4o-mini
@@ -319,6 +309,66 @@ cog.out("```\n")
accepts_settings:
- reasoning_effort
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: azure/o4-mini
edit_format: diff
weak_model_name: azure/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: azure/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
edit_format: diff
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
@@ -569,6 +619,14 @@ cog.out("```\n")
extra_params:
max_tokens: 128000
- name: fireworks_ai/accounts/fireworks/models/deepseek-v3-0324
edit_format: diff
use_repo_map: true
reminder: sys
examples_as_sys_msg: true
extra_params:
max_tokens: 160000
- name: fireworks_ai/accounts/fireworks/models/qwq-32b
edit_format: diff
weak_model_name: fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct
@@ -582,6 +640,12 @@ cog.out("```\n")
editor_edit_format: editor-diff
reasoning_tag: think
- name: gemini-2.5-flash-preview-04-17
edit_format: diff
use_repo_map: true
accepts_settings:
- thinking_tokens
- name: gemini/gemini-1.5-flash-002
- name: gemini/gemini-1.5-flash-exp-0827
@@ -610,10 +674,23 @@ cog.out("```\n")
edit_format: diff
use_repo_map: true
- name: gemini/gemini-2.5-flash-preview-04-17
edit_format: diff
use_repo_map: true
accepts_settings:
- thinking_tokens
- name: gemini/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
weak_model_name: gemini/gemini-2.5-flash-preview-04-17
use_repo_map: true
overeager: true
- name: gemini/gemini-2.5-pro-preview-03-25
edit_format: diff-fenced
weak_model_name: gemini/gemini-2.0-flash
use_repo_map: true
overeager: true
- name: gemini/gemini-exp-1114
edit_format: diff
@@ -704,6 +781,18 @@ cog.out("```\n")
use_repo_map: true
reminder: sys
- name: gpt-4.1
edit_format: diff
weak_model_name: gpt-4.1-mini
use_repo_map: true
reminder: sys
editor_model_name: gpt-4.1-mini
- name: gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
- name: gpt-4.5-preview
edit_format: diff
weak_model_name: gpt-4o-mini
@@ -790,6 +879,18 @@ cog.out("```\n")
editor_model_name: gpt-4o
editor_edit_format: editor-diff
- name: o3
edit_format: diff
weak_model_name: gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
streaming: false
editor_model_name: gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: o3-mini
edit_format: diff
weak_model_name: gpt-4o-mini
@@ -801,6 +902,30 @@ cog.out("```\n")
accepts_settings:
- reasoning_effort
- name: o4-mini
edit_format: diff
weak_model_name: gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openai/gpt-4.1
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
reminder: sys
editor_model_name: openai/gpt-4.1-mini
- name: openai/gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
- name: openai/gpt-4.5-preview
edit_format: diff
weak_model_name: gpt-4o-mini
@@ -870,6 +995,18 @@ cog.out("```\n")
editor_model_name: openai/gpt-4o
editor_edit_format: editor-diff
- name: openai/o3
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
streaming: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openai/o3-mini
edit_format: diff
weak_model_name: gpt-4o-mini
@@ -881,6 +1018,66 @@ cog.out("```\n")
accepts_settings:
- reasoning_effort
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openai/o4-mini
edit_format: diff
weak_model_name: openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openrouter/anthropic/claude-3-opus
edit_format: diff
weak_model_name: openrouter/anthropic/claude-3-5-haiku
@@ -1023,6 +1220,7 @@ cog.out("```\n")
edit_format: diff-fenced
weak_model_name: openrouter/google/gemini-2.0-flash-exp:free
use_repo_map: true
overeager: true
- name: openrouter/google/gemma-3-27b-it
use_system_prompt: false
@@ -1035,6 +1233,18 @@ cog.out("```\n")
weak_model_name: openrouter/meta-llama/llama-3-70b-instruct
examples_as_sys_msg: true
- name: openrouter/openai/gpt-4.1
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
reminder: sys
editor_model_name: openrouter/openai/gpt-4.1-mini
- name: openrouter/openai/gpt-4.1-mini
edit_format: diff
use_repo_map: true
reminder: sys
- name: openrouter/openai/gpt-4o
edit_format: diff
weak_model_name: openrouter/openai/gpt-4o-mini
@@ -1075,6 +1285,18 @@ cog.out("```\n")
editor_model_name: openrouter/openai/gpt-4o
editor_edit_format: editor-diff
- name: openrouter/openai/o3
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
streaming: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openrouter/openai/o3-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4o-mini
@@ -1097,6 +1319,71 @@ cog.out("```\n")
accepts_settings:
- reasoning_effort
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openrouter/openai/o4-mini
edit_format: diff
weak_model_name: openrouter/openai/gpt-4.1-mini
use_repo_map: true
examples_as_sys_msg: true
use_temperature: false
editor_model_name: openrouter/openai/gpt-4.1
editor_edit_format: editor-diff
system_prompt_prefix: 'Formatting re-enabled. '
accepts_settings:
- reasoning_effort
- name: openrouter/openrouter/optimus-alpha
edit_format: diff
use_repo_map: true
examples_as_sys_msg: true
- name: openrouter/openrouter/quasar-alpha
edit_format: diff
use_repo_map: true
@@ -1109,6 +1396,24 @@ cog.out("```\n")
editor_model_name: openrouter/qwen/qwen-2.5-coder-32b-instruct
editor_edit_format: editor-diff
- name: openrouter/x-ai/grok-3-beta
edit_format: diff
use_repo_map: true
- name: openrouter/x-ai/grok-3-fast-beta
edit_format: diff
use_repo_map: true
- name: openrouter/x-ai/grok-3-mini-beta
use_repo_map: true
accepts_settings:
- reasoning_effort
- name: openrouter/x-ai/grok-3-mini-fast-beta
use_repo_map: true
accepts_settings:
- reasoning_effort
- name: vertex_ai-anthropic_models/vertex_ai/claude-3-7-sonnet@20250219
edit_format: diff
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
@@ -1122,6 +1427,12 @@ cog.out("```\n")
accepts_settings:
- thinking_tokens
- name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
edit_format: diff
use_repo_map: true
accepts_settings:
- thinking_tokens
- name: vertex_ai/claude-3-5-haiku@20241022
edit_format: diff
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
@@ -1172,11 +1483,39 @@ cog.out("```\n")
- name: vertex_ai/gemini-2.5-pro-exp-03-25
edit_format: diff-fenced
weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
use_repo_map: true
overeager: true
editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: vertex_ai/gemini-2.5-pro-preview-03-25
edit_format: diff-fenced
weak_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
use_repo_map: true
overeager: true
editor_model_name: vertex_ai-language-models/gemini-2.5-flash-preview-04-17
- name: vertex_ai/gemini-pro-experimental
edit_format: diff-fenced
use_repo_map: true
- name: xai/grok-3-beta
edit_format: diff
use_repo_map: true
- name: xai/grok-3-fast-beta
edit_format: diff
use_repo_map: true
- name: xai/grok-3-mini-beta
use_repo_map: true
accepts_settings:
- reasoning_effort
- name: xai/grok-3-mini-fast-beta
use_repo_map: true
accepts_settings:
- reasoning_effort
```
<!--[[[end]]]-->

View File

@@ -225,19 +225,19 @@ cog.outl("```")
#stream: true
## Set the color for user input (default: #00cc00)
#user-input-color: #00cc00
#user-input-color: "#00cc00"
## Set the color for tool output (default: None)
#tool-output-color: "xxx"
## Set the color for tool error messages (default: #FF2222)
#tool-error-color: #FF2222
#tool-error-color: "#FF2222"
## Set the color for tool warning messages (default: #FFA500)
#tool-warning-color: #FFA500
#tool-warning-color: "#FFA500"
## Set the color for assistant output (default: #0088ff)
#assistant-output-color: #0088ff
#assistant-output-color: "#0088ff"
## Set the color for the completion menu (default: terminal's default text color)
#completion-menu-color: "xxx"

View File

@@ -79,10 +79,13 @@ for alias, model in sorted(MODEL_ALIASES.items()):
- `4-turbo`: gpt-4-1106-preview
- `4o`: gpt-4o
- `deepseek`: deepseek/deepseek-chat
- `flash`: gemini/gemini-2.0-flash-exp
- `gemini`: gemini/gemini-2.5-pro-exp-03-25
- `flash`: gemini/gemini-2.5-flash-preview-04-17
- `gemini`: gemini/gemini-2.5-pro-preview-03-25
- `gemini-2.5-pro`: gemini/gemini-2.5-pro-exp-03-25
- `gemini-exp`: gemini/gemini-2.5-pro-exp-03-25
- `grok3`: xai/grok-3-beta
- `haiku`: claude-3-5-haiku-20241022
- `optimus`: openrouter/openrouter/optimus-alpha
- `opus`: claude-3-opus-20240229
- `quasar`: openrouter/openrouter/quasar-alpha
- `r1`: deepseek/deepseek-reasoner

View File

@@ -264,12 +264,15 @@ tr:hover { background-color: #f5f5f5; }
</style>
<table>
<tr><th>Model Name</th><th class='right'>Total Tokens</th><th class='right'>Percent</th></tr>
<tr><td>gemini/gemini-2.5-pro-exp-03-25</td><td class='right'>900,070</td><td class='right'>83.0%</td></tr>
<tr><td>anthropic/claude-3-7-sonnet-20250219</td><td class='right'>144,371</td><td class='right'>13.3%</td></tr>
<tr><td>openrouter/openrouter/quasar-alpha</td><td class='right'>25,535</td><td class='right'>2.4%</td></tr>
<tr><td>openrouter/deepseek/deepseek-chat-v3-0324:free</td><td class='right'>11,324</td><td class='right'>1.0%</td></tr>
<tr><td>openrouter/REDACTED</td><td class='right'>1,755</td><td class='right'>0.2%</td></tr>
<tr><td>vertex_ai/REDACTED</td><td class='right'>1,739</td><td class='right'>0.2%</td></tr>
<tr><td>gemini/gemini-2.5-pro-exp-03-25</td><td class='right'>1,826,168</td><td class='right'>83.3%</td></tr>
<tr><td>o3</td><td class='right'>239,619</td><td class='right'>10.9%</td></tr>
<tr><td>openrouter/anthropic/claude-3.7-sonnet</td><td class='right'>56,318</td><td class='right'>2.6%</td></tr>
<tr><td>gemini/gemini-2.5-flash-preview-04-17</td><td class='right'>18,645</td><td class='right'>0.9%</td></tr>
<tr><td>gemini/gemini-2.5-pro-preview-03-25</td><td class='right'>16,524</td><td class='right'>0.8%</td></tr>
<tr><td>o4-mini</td><td class='right'>16,499</td><td class='right'>0.8%</td></tr>
<tr><td>xai/grok-3-fast-beta</td><td class='right'>10,288</td><td class='right'>0.5%</td></tr>
<tr><td>None</td><td class='right'>8,001</td><td class='right'>0.4%</td></tr>
<tr><td>gemini/REDACTED</td><td class='right'>606</td><td class='right'>0.0%</td></tr>
</table>
{: .note :}
@@ -287,6 +290,16 @@ 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.
## Why did aider ignore/discard its proposed edits after it asked to add a new file to the chat?
If aider prompts you to add a new file to the chat and you say yes,
it will re-submit the original request.
The fact that the LLM's reply indicated that it needed to see another file (and you said yes)
is often a sign that the LLM should have been able to see/edit that file in the first place.
Without access to it, there is increased chance that it's done a bad implementation of the requested change.
Often LLMs will hallucinate content for the files they needed but didn't have.
So aider re-submits the original request in this situation.
## Why does aider sometimes stop highlighting code in its replies?
Aider displays the markdown responses that are coming back from the LLM.

View File

@@ -128,6 +128,6 @@ mod_dates = [get_last_modified_date(file) for file in files]
latest_mod_date = max(mod_dates)
cog.out(f"{latest_mod_date.strftime('%B %d, %Y.')}")
]]]-->
March 31, 2025.
April 12, 2025.
<!--[[[end]]]-->
</p>

View File

@@ -8,100 +8,261 @@ has_children: true
# Aider LLM Leaderboards
Aider works best with LLMs which are good at *editing* code, not just good at writing
code.
To evaluate an LLM's editing skill, aider uses benchmarks that
assess a model's ability to consistently follow the system prompt
to successfully edit code.
Aider excels with LLMs skilled at writing and *editing* code,
and uses benchmarks to
evaluate an LLM's ability to follow instructions and edit code successfully without
human intervention.
[Aider's polyglot benchmark](https://aider.chat/2024/12/21/polyglot.html#the-polyglot-benchmark) tests LLMs on 225 challenging Exercism coding exercises across C++, Go, Java, JavaScript, Python, and Rust.
The leaderboards report the results from a number of popular LLMs.
While [aider can connect to almost any LLM](/docs/llms.html),
it works best with models that score well on the benchmarks.
<h2 id="leaderboard-title">Aider polyglot coding leaderboard</h2>
## Polyglot leaderboard
[Aider's polyglot benchmark](https://aider.chat/2024/12/21/polyglot.html#the-polyglot-benchmark)
asks the LLM to edit source files to complete 225 coding exercises
from Exercism.
It contains exercises in many popular programming languages:
C++, Go, Java, JavaScript, Python and Rust.
The 225 exercises were purposely selected to be the *hardest*
that Exercism offered in those languages, to provide
a strong coding challenge to LLMs.
This benchmark measures the LLM's coding ability in popular languages,
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;">
<div id="controls-container" style="display: flex; align-items: center; width: 100%; max-width: 800px; margin: 10px auto; gap: 10px; box-sizing: border-box; padding: 0 5px; position: relative;">
<input type="text" id="editSearchInput" placeholder="Search..." style="flex-grow: 1; padding: 8px; border: 1px solid #ddd; border-radius: 4px;">
<div id="view-mode-toggle" style="display: inline-flex; border: 1px solid #ccc; border-radius: 4px;">
<button id="mode-view-btn" class="mode-button active" data-mode="view" style="padding: 8px 8px; border: none; border-radius: 3px 0 0 3px; cursor: pointer; font-size: 14px; line-height: 1.5; min-width: 50px;">View</button>
<button id="mode-select-btn" class="mode-button" data-mode="select" style="padding: 8px 8px; border: none; background-color: #f8f9fa; border-radius: 0; cursor: pointer; border-left: 1px solid #ccc; font-size: 14px; line-height: 1.5; min-width: 50px;">Select</button>
<button id="mode-detail-btn" class="mode-button" data-mode="detail" style="padding: 8px 8px; border: none; background-color: #f8f9fa; border-radius: 0 3px 3px 0; cursor: pointer; border-left: 1px solid #ccc; font-size: 14px; line-height: 1.5; min-width: 50px;">Detail</button>
</div>
<button id="close-controls-btn" style="width: 18px; height: 18px; padding: 0; border: 1px solid #ddd; border-radius: 50%; background-color: transparent; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 12px; margin-left: 4px; color: #999;">×</button>
</div>
<table style="width: 100%; max-width: 800px; margin: auto; border-collapse: collapse; box-shadow: 0 2px 4px rgba(0,0,0,0.1); font-size: 14px;">
<thead style="background-color: #f2f2f2;">
<tr>
<th style="padding: 8px; width: 40px; text-align: center; vertical-align: middle;">
<input type="checkbox" id="select-all-checkbox" style="display: none; cursor: pointer; vertical-align: middle;">
</th> <!-- Header checkbox added here -->
<th style="padding: 8px; text-align: left;">Model</th>
<th style="padding: 8px; text-align: center;">Percent correct</th>
<th style="padding: 8px; text-align: center;">Percent using correct edit format</th>
<th style="padding: 8px; text-align: left;">Command</th>
<th style="padding: 8px; text-align: center;">Edit format</th>
<th style="padding: 8px; text-align: center;">Cost</th>
<th style="padding: 8px; text-align: center; width: 25%">Percent correct</th>
<th style="padding: 8px; text-align: center; width: 25%">Cost</th>
<th style="padding: 8px; text-align: left;" class="col-command">Command</th>
<th style="padding: 8px; text-align: center; width: 10%" class="col-conform">Correct edit format</th>
<th style="padding: 8px; text-align: left; width: 10%" class="col-edit-format">Edit Format</th>
</tr>
</thead>
<tbody>
{% assign max_cost = 0 %}
{% for row in site.data.polyglot_leaderboard %}
{% if row.total_cost > max_cost %}
{% assign max_cost = row.total_cost %}
{% endif %}
{% endfor %}
{% if max_cost == 0 %}{% assign max_cost = 1 %}{% endif %}
{% assign edit_sorted = site.data.polyglot_leaderboard | sort: 'pass_rate_2' | reverse %}
{% for row in edit_sorted %}
<tr style="border-bottom: 1px solid #ddd;">
<td style="padding: 8px;">{{ row.model }}</td>
<td style="padding: 8px; text-align: center;">{{ row.pass_rate_2 }}%</td>
<td style="padding: 8px; text-align: center;">{{ row.percent_cases_well_formed }}%</td>
<td style="padding: 8px;"><code>{{ row.command }}</code></td>
<td style="padding: 8px; text-align: center;">{{ row.edit_format }}</td>
<td style="padding: 8px; text-align: center;">{% if row.total_cost == 0 %}?{% else %}${{ row.total_cost | times: 1.0 | round: 2 }}{% endif %}</td>
{% for row in edit_sorted %} {% comment %} Add loop index for unique IDs {% endcomment %}
{% assign row_index = forloop.index0 %}
<tr id="main-row-{{ row_index }}">
<td style="padding: 8px; text-align: center; vertical-align: middle;">
<button class="toggle-details" data-target="details-{{ row_index }}" style="background: none; border: none; cursor: pointer; font-size: 16px; padding: 0; vertical-align: middle;">▶</button>
<input type="checkbox" class="row-selector" data-row-index="{{ row_index }}" style="display: none; cursor: pointer; vertical-align: middle;">
</td>
<td style="padding: 8px;"><span>{{ row.model }}</span></td>
<td class="bar-cell">
<div class="bar-viz" style="width: {{ row.pass_rate_2 }}%; background-color: rgba(40, 167, 69, 0.3); border-right: 1px solid rgba(40, 167, 69, 0.5);"></div>
<span>{{ row.pass_rate_2 }}%</span>
</td>
<td class="bar-cell cost-bar-cell">
{% if row.total_cost > 0 %}
<div class="bar-viz cost-bar" data-cost="{{ row.total_cost }}" data-max-cost="{{ max_cost }}" style="width: 0%; background-color: rgba(13, 110, 253, 0.3); border-right: 1px solid rgba(13, 110, 253, 0.5);"></div>
{% endif %}
{% assign rounded_cost = row.total_cost | times: 1.0 | round: 2 %}
<span>{% if row.total_cost == 0 or rounded_cost == 0.00 %}{% else %}${{ rounded_cost }}{% endif %}</span>
</td>
<td style="padding: 8px;" class="col-command"><span><code>{{ row.command }}</code></span></td>
<td style="padding: 8px; text-align: center;" class="col-conform"><span>{{ row.percent_cases_well_formed }}%</span></td>
<td style="padding: 8px;" class="col-edit-format"><span>{{ row.edit_format }}</span></td>
</tr>
<tr class="details-row" id="details-{{ row_index }}" style="display: none; background-color: #f9f9f9;">
<td colspan="7" style="padding: 15px; border-bottom: 1px solid #ddd;">
<ul style="margin: 0; padding-left: 20px; list-style: none; border-bottom: 1px solid #ddd;">
{% for pair in row %}
{% if pair[1] != "" and pair[1] != nil %}
<li><strong>
{% if pair[0] == 'percent_cases_well_formed' %}
Percent cases well formed
{% else %}
{{ pair[0] | replace: '_', ' ' | capitalize }}
{% endif %}
:</strong>
{% if pair[0] == 'command' %}<code>{{ pair[1] }}</code>{% else %}{{ pair[1] }}{% endif %}
</li>
{% endif %}
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
### Aider polyglot benchmark results
<canvas id="editChart" width="800" height="450" style="margin-top: 20px"></canvas>
<script src="https://unpkg.com/patternomaly/dist/patternomaly.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
{% assign data_source = edit_sorted %}
{% assign pass_rate_field = "pass_rate_2" %}
{% assign highlight_model = "xxxxxx" %}
{% include leaderboard.js %}
</script>
<style>
#leaderboard-title {
margin-bottom: 20px; /* Add space below the title */
}
tr.selected {
color: #0056b3;
}
table {
table-layout: fixed;
}
thead {
border-top: 1px solid #ddd; /* Add top border to header */
}
td, th {
border: none; /* Remove internal cell borders */
word-wrap: break-word;
overflow-wrap: break-word;
vertical-align: middle; /* Ensure consistent vertical alignment */
}
td:nth-child(3), td:nth-child(4) {
font-size: 12px;
tbody tr {
height: 50px; /* Set a minimum height for all data rows */
}
/* Hide command and edit format columns on mobile */
td.col-command { /* Command column */
font-size: 12px; /* Keep font size adjustment for command column if desired, or remove */
}
/* Hide new columns first on smaller screens */
@media screen and (max-width: 991px) {
th.col-conform, td.col-conform,
th.col-edit-format, td.col-edit-format {
display: none;
}
/* Increase width of Percent correct and Cost columns when others are hidden */
th:nth-child(3), td:nth-child(3), /* Percent correct */
th:nth-child(4), td:nth-child(4) { /* Cost */
width: 33% !important; /* Override inline style */
}
}
/* Hide command column on even smaller screens */
@media screen and (max-width: 767px) {
th:nth-child(4), td:nth-child(4), /* Command column */
th:nth-child(5), td:nth-child(5) { /* Edit format column */
th.col-command, td.col-command { /* Command column */
display: none;
}
}
/* --- Control Styles --- */
#controls-container {
margin-bottom: 20px; /* Add some space below controls */
}
#editSearchInput, #view-mode-select {
padding: 8px 12px; /* Consistent padding */
border: 1px solid #ccc; /* Slightly softer border */
border-radius: 4px;
font-size: 14px; /* Match table font size */
height: 38px; /* Match height */
box-sizing: border-box; /* Include padding/border in height */
}
.bar-cell {
position: relative; /* Positioning context for the bar */
padding: 8px;
/* text-align: center; Removed */
overflow: hidden; /* Prevent bar from overflowing cell boundaries if needed */
}
.cost-bar-cell {
background-image: none; /* Remove default gradient for cost cells */
}
.percent-tick, .cost-tick {
position: absolute;
top: 50%;
transform: translateY(10px);
height: 8px; /* Short tick */
width: 1px;
background-color: rgba(170, 170, 170, 0.5);
z-index: 2; /* Above the bar but below the text */
}
.bar-viz {
position: absolute;
left: 0;
top: 50%; /* Position at the middle of the cell */
transform: translateY(-50%); /* Center the bar vertically */
z-index: 1; /* Above background, below ticks and text */
height: 36px;
border-radius: 0 2px 2px 0; /* Slightly rounded end corners */
/* Width and colors are set inline via style attribute */
}
/* Add a tooltip class for showing cost information on hover */
.cost-bar-cell:hover .bar-viz[style*="background-image"] {
animation: stripe-animation 2s linear infinite;
}
@keyframes stripe-animation {
0% { background-position: 0 0; }
100% { background-position: 20px 0; }
}
.bar-cell span {
position: absolute; /* Position relative to the cell */
left: 5px; /* Position slightly inside the left edge */
top: 50%; /* Center vertically */
transform: translateY(-50%); /* Adjust vertical centering */
z-index: 3; /* Ensure text is above everything else */
background-color: rgba(255, 255, 255, 0.7); /* Semi-transparent white background */
padding: 0 4px; /* Add padding around the text */
border-radius: 3px; /* Rounded corners for the text background */
font-size: 14px; /* Adjust font size for the numbers */
}
.toggle-details {
color: #888; /* Make toggle symbol more subtle */
transition: color 0.2s; /* Smooth transition on hover */
}
/* Style for selected rows */
tr.row-selected > td {
background-color: #e7f3ff; /* Example light blue highlight */
}
/* Ensure checkbox is vertically aligned if needed */
.row-selector {
vertical-align: middle;
}
/* Hide rows not matching the filter */
tr.hidden-by-mode {
display: none !important; /* Use important to override other display styles if necessary */
}
tr.hidden-by-search {
display: none !important;
}
/* --- Mode Toggle Button Styles --- */
#view-mode-toggle {
height: 38px; /* Match input height */
box-sizing: border-box;
flex-shrink: 0; /* Prevent toggle from shrinking on small screens */
}
.mode-button {
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
white-space: nowrap; /* Prevent text wrapping */
}
.mode-button:not(.active) {
background-color: #f8f9fa; /* Light grey background */
color: #495057; /* Dark grey text */
}
.mode-button:not(.active):hover {
background-color: #e2e6ea; /* Slightly darker grey on hover */
}
/* Style for highlighted rows in view mode */
tr.view-highlighted > td {
background-color: #fffef5; /* Very light yellow/cream */
/* Border moved to specific cell below */
}
/* Apply border and adjust padding ONLY for the first *visible* cell (Model name) in view mode */
tr.view-highlighted > td:nth-child(2) {
border-left: 4px solid #ffc107; /* Warning yellow border */
/* Original padding is 8px. Subtract border width. */
padding-left: 4px;
}
</style>
<script>
{% include leaderboard_table.js %}
</script>
<p class="post-date">
<p class="post-date" style="margin-top: 20px;">
By Paul Gauthier,
last updated
<!--[[[cog
@@ -124,6 +285,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.')}")
]]]-->
April 04, 2025.
April 20, 2025.
<!--[[[end]]]-->
</p>

View File

@@ -73,6 +73,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.')}")
]]]-->
March 31, 2025.
April 12, 2025.
<!--[[[end]]]-->
</p>

View File

@@ -98,7 +98,7 @@ if result.returncode == 0:
date = datetime.datetime.fromtimestamp(timestamp)
cog.out(f"{date.strftime('%B %d, %Y.')}")
]]]-->
March 31, 2025.
April 12, 2025.
<!--[[[end]]]-->
</p>

View File

@@ -16,9 +16,10 @@ description: Aider can connect to most LLMs for AI pair programming.
Aider works best with these models, which are skilled at editing code:
- [Gemini 2.5 Pro](/docs/llms/gemini.html)
- [DeepSeek R1 and V3](/docs/llms/deepseek.html)
- [Claude 3.7 Sonnet](/docs/llms/anthropic.html)
- [OpenAI o1, o3-mini and GPT-4o](/docs/llms/openai.html)
- [OpenAI o3, o4-mini and GPT-4.1](/docs/llms/openai.html)
## Free models
@@ -26,10 +27,8 @@ Aider works best with these models, which are skilled at editing code:
Aider works with a number of **free** API providers:
- Google's [Gemini 1.5 Pro](/docs/llms/gemini.html) works with aider, with
code editing capabilities similar to GPT-3.5.
- You can use [Llama 3 70B on Groq](/docs/llms/groq.html) which is comparable to GPT-3.5 in code editing performance.
- Cohere also offers free API access to their [Command-R+ model](/docs/llms/cohere.html), which works with aider as a *very basic* coding assistant.
- [OpenRouter offers free access to many models](https://openrouter.ai/models/?q=free), with limitations on daily usage.
- Google's [Gemini 2.5 Pro Exp](/docs/llms/gemini.html) works very well with aider.
## Local models
{: .no_toc }

View File

@@ -10,21 +10,26 @@ To work with Anthropic's models, you need to provide your
either in the `ANTHROPIC_API_KEY` environment variable or
via the `--anthropic-api-key` command line switch.
Aider has some built in shortcuts for the most popular Anthropic models and
has been tested and benchmarked to work well with them:
First, install aider:
{% include install.md %}
Then configure your API keys:
```
python -m pip install -U aider-chat
export ANTHROPIC_API_KEY=<key> # Mac/Linux
setx ANTHROPIC_API_KEY <key> # Windows, restart shell after setx
```
Start working with aider and Anthropic on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
# Aider uses Claude 3.7 Sonnet by default
aider
# Claude 3 Opus
aider --model claude-3-opus-20240229
# List models available from Anthropic
aider --list-models anthropic/
```

View File

@@ -7,21 +7,32 @@ nav_order: 500
Aider can connect to the OpenAI models on Azure.
```
python -m pip install -U aider-chat
First, install aider:
{% include install.md %}
Then configure your API keys and endpoint:
```
# Mac/Linux:
export AZURE_API_KEY=<key>
export AZURE_API_VERSION=2023-05-15
export AZURE_API_VERSION=2024-12-01-preview
export AZURE_API_BASE=https://myendpt.openai.azure.com
# Windows
setx AZURE_API_KEY <key>
setx AZURE_API_VERSION 2023-05-15
setx AZURE_API_VERSION 2024-12-01-preview
setx AZURE_API_BASE https://myendpt.openai.azure.com
# ... restart your shell after setx commands
```
aider --model azure/<your_deployment_name>
Start working with aider and Azure on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
aider --model azure/<your_model_deployment_name>
# List models available from Azure
aider --list-models azure/
@@ -29,3 +40,9 @@ aider --list-models azure/
Note that aider will also use environment variables
like `AZURE_OPENAI_API_xxx`.
The `aider --list-models azure/` command will list all models that aider supports through Azure, not the models that are available for the provided endpoint.
When setting the model to use with `--model azure/<your_model_deployment_name>`, `<your_model_deployment_name>` is likely just the name of the model you have deployed to the endpoint for example `o3-mini` or `gpt-4o`. The screenshow below shows `o3-mini` and `gpt-4o` deployments in the Azure portal done under the `myendpt` resource.
![example azure deployment](/assets/azure-deployment.png)

View File

@@ -6,8 +6,6 @@ nav_order: 560
# Amazon Bedrock
Aider can connect to models provided by Amazon Bedrock.
You will need to have an AWS account with access to the Bedrock service.
To configure Aider to use the Amazon Bedrock API, you need to set up your AWS credentials.
This can be done using the AWS CLI or by setting environment variables.
@@ -37,6 +35,14 @@ feature, you will receive an error message like the following:
anthropic.claude-3-7-sonnet-20250219-v1:0 with on-demand throughput isn\xe2\x80\x99t supported. Retry your
request with the ID or ARN of an inference profile that contains this model."}'
## Installation and Configuration
First, install aider:
{% include install.md %}
Next, configure your AWS credentials. This can be done using the AWS CLI or by setting environment variables.
## AWS CLI Configuration
If you haven't already, install the [AWS CLI](https://aws.amazon.com/cli/) and configure it with your credentials:
@@ -49,7 +55,7 @@ This will prompt you to enter your AWS Access Key ID, Secret Access Key, and def
## Environment Variables
Alternatively, you can set the following environment variables:
You can set the following environment variables:
```bash
export AWS_REGION=your_preferred_region
@@ -75,32 +81,15 @@ $env:AWS_SECRET_ACCESS_KEY = 'your_secret_key'
$env:AWS_REGION = 'us-west-2' # Put whichever AWS region that you'd like, that the Bedrock service supports.
```
## Install boto3
The AWS Bedrock provider requires the `boto3` package in order to function correctly:
```bash
pip install boto3
```
To use aider installed via `pipx` with AWS Bedrock, you must add the `boto3` dependency to aider's virtual environment by running
```bash
pipx inject aider-chat boto3
```
You must install `boto3` dependency to aider's virtual environment installed via one-liner or uv by running
```bash
uv tool run --from aider-chat pip install boto3
```
## Running Aider with Bedrock
## Get Started
Once your AWS credentials are set up, you can run Aider with the `--model` command line switch, specifying the Bedrock model you want to use:
```bash
# Change directory into your codebase
cd /to/your/project
aider --model bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0
```
@@ -121,6 +110,20 @@ aider --list-models bedrock/
Make sure you have access to these models in your AWS account before attempting to use them with Aider.
## Install boto3
You may need to install the `boto3` package.
```bash
# If you installed with aider-install or `uv tool`
uv tool run --from aider-chat pip install boto3
# Or with pipx...
pipx inject aider-chat boto3
# Or with pip
pip install -U boto3
```
# More info
For more information on Amazon Bedrock and its models, refer to the [official AWS documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/what-is-bedrock.html).

View File

@@ -10,13 +10,22 @@ Their Command-R+ model works well with aider
as a *very basic* coding assistant.
You'll need a [Cohere API key](https://dashboard.cohere.com/welcome/login).
To use **Command-R+**:
First, install aider:
{% include install.md %}
Then configure your API keys:
```
python -m pip install -U aider-chat
export COHERE_API_KEY=<key> # Mac/Linux
setx COHERE_API_KEY <key> # Windows, restart shell after setx
```
Start working with aider and Cohere on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
aider --model command-r-plus-08-2024

View File

@@ -9,11 +9,22 @@ Aider can connect to the DeepSeek.com API.
To work with DeepSeek's models, you need to set the `DEEPSEEK_API_KEY` environment variable with your [DeepSeek API key](https://platform.deepseek.com/api_keys).
The DeepSeek Chat V3 model has a top score on aider's code editing benchmark.
```
python -m pip install -U aider-chat
First, install aider:
{% include install.md %}
Then configure your API keys:
```
export DEEPSEEK_API_KEY=<key> # Mac/Linux
setx DEEPSEEK_API_KEY <key> # Windows, restart shell after setx
```
Start working with aider and DeepSeek on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
# Use DeepSeek Chat v3
aider --model deepseek/deepseek-chat

View File

@@ -7,22 +7,43 @@ nav_order: 300
You'll need a [Gemini API key](https://aistudio.google.com/app/u/2/apikey).
```
python -m pip install -U aider-chat
First, install aider:
# You may need to install google-generativeai
pip install -U google-generativeai
{% include install.md %}
# Or with pipx...
pipx inject aider-chat google-generativeai
Then configure your API keys:
```bash
export GEMINI_API_KEY=<key> # Mac/Linux
setx GEMINI_API_KEY <key> # Windows, restart shell after setx
```
# You can run the Gemini 2.5 Pro model with:
aider --model gemini-2.5-pro
Start working with aider and Gemini on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
# You can run the Gemini 2.5 Pro model with this shortcut:
aider --model gemini
# You can run the Gemini 2.5 Pro Exp for free, with usage limits:
aider --model gemini-exp
# List models available from Gemini
aider --list-models gemini/
```
You may need to install the `google-generativeai` package.
```bash
# If you installed with aider-install or `uv tool`
uv tool run --from aider-chat pip install google-generativeai
# Or with pipx...
pipx inject aider-chat google-generativeai
# Or with pip
pip install -U google-generativeai
```

View File

@@ -10,13 +10,22 @@ The Llama 3 70B model works
well with aider and is comparable to GPT-3.5 in code editing performance.
You'll need a [Groq API key](https://console.groq.com/keys).
To use **Llama3 70B**:
First, install aider:
{% include install.md %}
Then configure your API keys:
```
python -m pip install -U aider-chat
export GROQ_API_KEY=<key> # Mac/Linux
setx GROQ_API_KEY <key> # Windows, restart shell after setx
```
Start working with aider and Groq on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
aider --model groq/llama3-70b-8192

View File

@@ -5,11 +5,15 @@ nav_order: 400
# LM Studio
To use LM Studio:
Aider can connect to models served by LM Studio.
First, install aider:
{% include install.md %}
Then configure your API key and endpoint:
```
python -m pip install -U aider-chat
# Must set a value here even if its a dummy value
export LM_STUDIO_API_KEY=dummy-api-key # Mac/Linux
setx LM_STUDIO_API_KEY dummy-api-key # Windows, restart shell after setx
@@ -17,12 +21,19 @@ setx LM_STUDIO_API_KEY dummy-api-key # Windows, restart shell after setx
# LM Studio default server URL is http://localhost:1234/v1
export LM_STUDIO_API_BASE=http://localhost:1234/v1 # Mac/Linux
setx LM_STUDIO_API_BASE http://localhost:1234/v1 # Windows, restart shell after setx
aider --model lm_studio/<your-model-name>
```
**Note:** Even though LM Studio doesn't require an API Key out of the box the `LM_STUDIO_API_KEY` must have a dummy value like `dummy-api-key` set or the client request will fail trying to send an empty `Bearer` token.
Start working with aider and LM Studio on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
aider --model lm_studio/<your-model-name>
```
See the [model warnings](warnings.html)
section for information on warnings which will occur
when working with models that aider is not familiar with.

View File

@@ -7,6 +7,19 @@ nav_order: 500
Aider can connect to local Ollama models.
First, install aider:
{% include install.md %}
Then configure your Ollama API endpoint (usually the default):
```bash
export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
```
Start working with aider and Ollama on your codebase:
```
# Pull the model
ollama pull <model>
@@ -14,11 +27,8 @@ ollama pull <model>
# Start your ollama server, increasing the context window to 8k tokens
OLLAMA_CONTEXT_LENGTH=8192 ollama serve
# In another terminal window...
python -m pip install -U aider-chat
export OLLAMA_API_BASE=http://127.0.0.1:11434 # Mac/Linux
setx OLLAMA_API_BASE http://127.0.0.1:11434 # Windows, restart shell after setx
# In another terminal window, change directory into your codebase
cd /to/your/project
aider --model ollama_chat/<model>
```

View File

@@ -7,10 +7,13 @@ nav_order: 500
Aider can connect to any LLM which is accessible via an OpenAI compatible API endpoint.
```
python -m pip install aider-install
aider-install
First, install aider:
{% include install.md %}
Then configure your API key and endpoint:
```
# Mac/Linux:
export OPENAI_API_BASE=<endpoint>
export OPENAI_API_KEY=<key>
@@ -19,6 +22,13 @@ export OPENAI_API_KEY=<key>
setx OPENAI_API_BASE <endpoint>
setx OPENAI_API_KEY <key>
# ... restart shell after setx commands
```
Start working with aider and your OpenAI compatible API on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
# Prefix the model name with openai/
aider --model openai/<model-name>

View File

@@ -10,27 +10,34 @@ To work with OpenAI's models, you need to provide your
either in the `OPENAI_API_KEY` environment variable or
via the `--api-key openai=<key>` command line switch.
Aider has some built in shortcuts for the most popular OpenAI models and
has been tested and benchmarked to work well with them:
First, install aider:
{% include install.md %}
Then configure your API keys:
```
python -m pip install -U aider-chat
export OPENAI_API_KEY=<key> # Mac/Linux
setx OPENAI_API_KEY <key> # Windows, restart shell after setx
```
Start working with aider and OpenAI on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
# o3-mini
aider --model o3-mini --api-key openai=<key>
aider --model o3-mini
# o1-mini
aider --model o1-mini --api-key openai=<key>
aider --model o1-mini
# GPT-4o
aider --model gpt-4o --api-key openai=<key>
aider --model gpt-4o
# List models available from OpenAI
aider --list-models openai/
# You can also store you API key in environment variables (or .env)
export OPENAI_API_KEY=<key> # Mac/Linux
setx OPENAI_API_KEY <key> # Windows, restart shell after setx
```
You can use `aider --model <model-name>` to use any other OpenAI model.

View File

@@ -8,11 +8,22 @@ nav_order: 500
Aider can connect to [models provided by OpenRouter](https://openrouter.ai/models?o=top-weekly):
You'll need an [OpenRouter API key](https://openrouter.ai/keys).
```
python -m pip install -U aider-chat
First, install aider:
{% include install.md %}
Then configure your API keys:
```
export OPENROUTER_API_KEY=<key> # Mac/Linux
setx OPENROUTER_API_KEY <key> # Windows, restart shell after setx
```
Start working with aider and OpenRouter on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
# Or any other open router model
aider --model openrouter/<provider>/<model>
@@ -23,16 +34,6 @@ aider --list-models openrouter/
In particular, many aider users access Sonnet via OpenRouter:
```
python -m pip install -U aider-chat
export OPENROUTER_API_KEY=<key> # Mac/Linux
setx OPENROUTER_API_KEY <key> # Windows, restart shell after setx
aider --model openrouter/anthropic/claude-3.7-sonnet
```
{: .tip }
If you get errors, check your
[OpenRouter privacy settings](https://openrouter.ai/settings/privacy).

View File

@@ -55,8 +55,8 @@ lines = run(
lines = ['- ' + line for line in lines.splitlines(keepends=True)]
cog.out(''.join(lines))
]]]-->
- ALEPHALPHA_API_KEY
- ALEPH_ALPHA_API_KEY
- ALEPHALPHA_API_KEY
- ANTHROPIC_API_KEY
- ANYSCALE_API_KEY
- AZURE_AI_API_KEY
@@ -66,15 +66,15 @@ cog.out(''.join(lines))
- CEREBRAS_API_KEY
- CLARIFAI_API_KEY
- CLOUDFLARE_API_KEY
- CO_API_KEY
- CODESTRAL_API_KEY
- COHERE_API_KEY
- CO_API_KEY
- DATABRICKS_API_KEY
- DEEPINFRA_API_KEY
- DEEPSEEK_API_KEY
- FIREWORKSAI_API_KEY
- FIREWORKS_AI_API_KEY
- FIREWORKS_API_KEY
- FIREWORKSAI_API_KEY
- GEMINI_API_KEY
- GROQ_API_KEY
- HUGGINGFACE_API_KEY

View File

@@ -13,6 +13,10 @@ or service account with permission to use the Vertex AI API.
With your chosen login method, the gcloud CLI should automatically set the
`GOOGLE_APPLICATION_CREDENTIALS` environment variable which points to the credentials file.
First, install aider:
{% include install.md %}
To configure Aider to use the Vertex AI API, you need to set `VERTEXAI_PROJECT` (the GCP project ID)
and `VERTEXAI_LOCATION` (the GCP region) [environment variables for Aider](/docs/config/dotenv.html).
@@ -27,9 +31,12 @@ VERTEXAI_PROJECT=my-project
VERTEXAI_LOCATION=us-east5
```
Then you can run aider with the `--model` command line switch, like this:
Start working with aider and Vertex AI on your codebase:
```
# Change directory into your codebase
cd /to/your/project
aider --model vertex_ai/claude-3-5-sonnet@20240620
```

View File

@@ -7,18 +7,47 @@ nav_order: 400
You'll need a [xAI API key](https://console.x.ai.).
To use xAI:
First, install aider:
```
python -m pip install -U aider-chat
{% include install.md %}
Then configure your API keys:
```bash
export XAI_API_KEY=<key> # Mac/Linux
setx XAI_API_KEY <key> # Windows, restart shell after setx
```
aider --model xai/grok-beta
Start working with aider and xAI on your codebase:
```bash
# Change directory into your codebase
cd /to/your/project
# Grok 3
aider --model xai/grok-3-beta
# Grok 3 fast (faster, more expensive)
aider --model xai/grok-3-fast-beta
# Grok 3 Mini
aider --model xai/grok-3-mini-beta
# Grok 3 Mini fast (faster, more expensive)
aider --model xai/grok-3-mini-fast-beta
# List models available from xAI
aider --list-models xai/
```
The Grok 3 Mini models support the `--reasoning-effort` flag.
See the [reasoning settings documentation](../config/reasoning.md) for details.
Example:
```bash
aider --model xai/grok-3-mini-beta --reasoning-effort high
```

View File

@@ -5,7 +5,29 @@ nav_order: 28
# Models and API keys
You need to tell aider which LLM to use and provide an API key.
Aider needs to know which LLM model you would like to work with and which keys
to provide when accessing it via API.
## Defaults
If you don't explicitly name a model, aider will try to select a model
for you to work with.
First, aider will check which
[keys you have provided via the environment, config files, or command line arguments](https://aider.chat/docs/config/api-keys.html).
Based on the available keys, aider will select the best model to use.
## OpenRouter
If you have not provided any keys, aider will offer to help you connect to
[OpenRouter](http://openrouter.ai)
which provides both free and paid access to most popular LLMs.
Once connected, aider will select the best model available on OpenRouter
based on whether you have a free or paid account there.
## Specifying model & key
You can also tell aider which LLM to use and provide an API key.
The easiest way is to use the `--model` and `--api-key`
command line arguments, like this:

View File

@@ -52,8 +52,8 @@ the script as your linter.
# Second attempt will not do anything and exit 0 unless there's a real problem beyond
# the code formatting that was completed.
pre-commit run --files $* >/dev/null \
|| pre-commit run --files $*
pre-commit run --files "$@" >/dev/null \
|| pre-commit run --files "$@"
```
## Testing

View File

@@ -69,23 +69,23 @@ cog.out(text)
]]]-->
<a href="https://github.com/Aider-AI/aider" class="github-badge badge-stars" title="Total number of GitHub stars the Aider project has received">
<span class="badge-label">⭐ GitHub Stars</span>
<span class="badge-value">31K</span>
<span class="badge-value">32K</span>
</a>
<a href="https://pypi.org/project/aider-chat/" class="github-badge badge-installs" title="Total number of installations via pip from PyPI">
<span class="badge-label">📦 Installs</span>
<span class="badge-value">1.8M</span>
<span class="badge-value">2.1M</span>
</a>
<div class="github-badge badge-tokens" title="Number of tokens processed weekly by Aider users">
<span class="badge-label">📈 Tokens/week</span>
<span class="badge-value">15B</span>
</div>
<a href="https://openrouter.ai/" class="github-badge badge-router" title="Aider's ranking among applications on the OpenRouter platform">
<a href="https://openrouter.ai/#options-menu" class="github-badge badge-router" title="Aider's ranking among applications on the OpenRouter platform">
<span class="badge-label">🏆 OpenRouter</span>
<span class="badge-value">Top 20</span>
</a>
<a href="/HISTORY.html" class="github-badge badge-coded" title="Percentage of the new code in Aider's last release written by Aider itself">
<span class="badge-label">🔄 Singularity</span>
<span class="badge-value">87%</span>
<span class="badge-value">92%</span>
</a>
<!--[[[end]]]-->
</div>
@@ -268,6 +268,11 @@ cog.out(text)
]]]-->
<script>
const testimonials = [
{
text: "My life has changed... There's finally an AI coding tool that's good enough to keep up with me... Aider... It's going to rock your world.",
author: "Eric S. Raymond",
link: "https://x.com/esrtweet/status/1910809356381413593"
},
{
text: "The best free open source AI coding assistant.",
author: "IndyDevDan",
@@ -404,7 +409,7 @@ const testimonials = [
link: "https://x.com/ccui42/status/1904965344999145698"
},
{
text: "Aider is the precision tool of LLM code gen. It is minimal, thoughtful and capable of surgical changes to your codebase all while keeping the developer in control.",
text: "Aider is the precision tool of LLM code gen... Minimal, thoughtful and capable of surgical changes to your codebase all while keeping the developer in control.",
author: "Reilly Sweetland",
link: "https://x.com/rsweetland/status/1904963807237259586"
},
@@ -412,6 +417,26 @@ const testimonials = [
text: "Cannot believe aider vibe coded a 650 LOC feature across service and cli today in 1 shot.",
author: "autopoietist",
link: "https://discord.com/channels/1131200896827654144/1131200896827654149/1355675042259796101"
},
{
text: "Oh no the secret is out! Yes, Aider is the best coding tool around. I highly, highly recommend it to anyone.",
author: "Joshua D Vander Hook",
link: "https://x.com/jodavaho/status/1911154899057795218"
},
{
text: "thanks to aider, i have started and finished three personal projects within the last two days",
author: "joseph stalzyn",
link: "https://x.com/anitaheeder/status/1908338609645904160"
},
{
text: "Been using aider as my daily driver for over a year ... I absolutely love the tool, like beyond words.",
author: "koleok",
link: "https://discord.com/channels/1131200896827654144/1273248471394291754/1356727448372252783"
},
{
text: "aider is really cool",
author: "kache (@yacineMTB)",
link: "https://x.com/yacineMTB/status/1911224442430124387"
}
];
</script>

View File

@@ -206,6 +206,12 @@ def main(
read_model_settings: str = typer.Option(
None, "--read-model-settings", help="Load aider model settings from YAML file"
),
reasoning_effort: Optional[str] = typer.Option(
None, "--reasoning-effort", help="Set reasoning effort for models that support it"
),
thinking_tokens: Optional[int] = typer.Option(
None, "--thinking-tokens", help="Set thinking tokens for models that support it"
),
exercises_dir: str = typer.Option(
EXERCISES_DIR_DEFAULT, "--exercises-dir", help="Directory with exercise files"
),
@@ -362,6 +368,8 @@ def main(
editor_edit_format,
num_ctx,
sleep,
reasoning_effort,
thinking_tokens,
)
all_results.append(results)
@@ -384,6 +392,10 @@ def main(
replay,
editor_model,
editor_edit_format,
num_ctx,
sleep,
reasoning_effort,
thinking_tokens,
)
all_results = run_test_threaded.gather(tqdm=True)
@@ -481,6 +493,8 @@ def summarize_results(dirname, stats_languages=None):
res.indentation_errors = 0
res.lazy_comments = 0
res.reasoning_effort = None
res.thinking_tokens = None
variants = defaultdict(set)
for results in all_results:
@@ -509,6 +523,9 @@ def summarize_results(dirname, stats_languages=None):
res.syntax_errors += results.get("syntax_errors", 0)
res.indentation_errors += results.get("indentation_errors", 0)
res.reasoning_effort = results.get("reasoning_effort")
res.thinking_tokens = results.get("thinking_tokens")
for key in "model edit_format commit_hash editor_model editor_edit_format".split():
val = results.get(key)
if val:
@@ -552,6 +569,11 @@ def summarize_results(dirname, stats_languages=None):
setattr(res, key, val)
console.print(f" {key}: {val}", style=style)
if res.reasoning_effort is not None:
print(f" reasoning_effort: {res.reasoning_effort}")
if res.thinking_tokens is not None:
print(f" thinking_tokens: {res.thinking_tokens}")
for i in range(tries):
print(f" pass_rate_{i + 1}: {percents[i]:.1f}")
for i in range(tries):
@@ -637,15 +659,14 @@ def get_replayed_content(replay_dname, test_dname):
def run_test(original_dname, testdir, *args, **kwargs):
try:
return run_test_real(original_dname, testdir, *args, **kwargs)
except Exception as err:
except Exception:
print("=" * 40)
print("Test failed")
print(err)
traceback.print_exc()
testdir = Path(testdir)
results_fname = testdir / ".aider.results.json"
results_fname.write_text(json.dumps(dict(exception=str(err))))
results_fname.write_text(json.dumps(dict(exception=traceback.format_exc())))
def run_test_real(
@@ -663,6 +684,8 @@ def run_test_real(
editor_edit_format,
num_ctx=None,
sleep=0,
reasoning_effort: Optional[str] = None,
thinking_tokens: Optional[int] = None,
read_model_settings=None,
):
if not os.path.isdir(testdir):
@@ -767,8 +790,15 @@ def run_test_real(
weak_model=weak_model_name,
editor_model=editor_model,
editor_edit_format=editor_edit_format,
verbose=verbose,
)
if reasoning_effort is not None:
main_model.set_reasoning_effort(reasoning_effort)
if thinking_tokens is not None:
main_model.set_thinking_tokens(thinking_tokens)
dump(main_model.max_chat_history_tokens)
if num_ctx:
@@ -919,6 +949,8 @@ def run_test_real(
syntax_errors=syntax_errors,
indentation_errors=indentation_errors,
lazy_comments=lazy_comments, # Add the count of pattern matches to the results
reasoning_effort=reasoning_effort,
thinking_tokens=thinking_tokens,
chat_hashes=list(
zip(
coder.chat_completion_call_hashes,

View File

@@ -2,8 +2,8 @@
docker run \
-it --rm \
--memory=25g \
--memory-swap=25g \
--memory=12g \
--memory-swap=12g \
--add-host=host.docker.internal:host-gateway \
-v `pwd`:/aider \
-v `pwd`/tmp.benchmarks/.:/benchmarks \

View File

@@ -4,7 +4,7 @@ aiohappyeyeballs==2.6.1
# via
# -c requirements/common-constraints.txt
# aiohttp
aiohttp==3.11.16
aiohttp==3.11.18
# via
# -c requirements/common-constraints.txt
# litellm
@@ -33,11 +33,15 @@ backoff==2.2.1
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
# posthog
beautifulsoup4==4.13.3
beautifulsoup4==4.13.4
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
certifi==2025.1.31
cachetools==5.5.2
# via
# -c requirements/common-constraints.txt
# google-auth
certifi==2025.4.26
# via
# -c requirements/common-constraints.txt
# httpcore
@@ -48,7 +52,7 @@ cffi==1.17.1
# -c requirements/common-constraints.txt
# sounddevice
# soundfile
charset-normalizer==3.4.1
charset-normalizer==3.4.2
# via
# -c requirements/common-constraints.txt
# requests
@@ -81,7 +85,7 @@ flake8==7.2.0
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
frozenlist==1.5.0
frozenlist==1.6.0
# via
# -c requirements/common-constraints.txt
# aiohttp
@@ -98,24 +102,73 @@ gitpython==3.1.44
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
google-ai-generativelanguage==0.6.15
# via
# -c requirements/common-constraints.txt
# google-generativeai
google-api-core[grpc]==2.24.2
# via
# -c requirements/common-constraints.txt
# google-ai-generativelanguage
# google-api-python-client
# google-generativeai
google-api-python-client==2.169.0
# via
# -c requirements/common-constraints.txt
# google-generativeai
google-auth==2.40.0
# via
# -c requirements/common-constraints.txt
# google-ai-generativelanguage
# google-api-core
# google-api-python-client
# google-auth-httplib2
# google-generativeai
google-auth-httplib2==0.2.0
# via
# -c requirements/common-constraints.txt
# google-api-python-client
google-generativeai==0.8.5
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
googleapis-common-protos==1.70.0
# via
# -c requirements/common-constraints.txt
# google-api-core
# grpcio-status
grep-ast==0.8.1
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
h11==0.14.0
grpcio==1.71.0
# via
# -c requirements/common-constraints.txt
# google-api-core
# grpcio-status
grpcio-status==1.71.0
# via
# -c requirements/common-constraints.txt
# google-api-core
h11==0.16.0
# via
# -c requirements/common-constraints.txt
# httpcore
httpcore==1.0.7
httpcore==1.0.9
# via
# -c requirements/common-constraints.txt
# httpx
httplib2==0.22.0
# via
# -c requirements/common-constraints.txt
# google-api-python-client
# google-auth-httplib2
httpx==0.28.1
# via
# -c requirements/common-constraints.txt
# litellm
# openai
huggingface-hub==0.30.1
huggingface-hub==0.30.2
# via
# -c requirements/common-constraints.txt
# tokenizers
@@ -152,11 +205,11 @@ jsonschema==4.23.0
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
# litellm
jsonschema-specifications==2024.10.1
jsonschema-specifications==2025.4.1
# via
# -c requirements/common-constraints.txt
# jsonschema
litellm==1.65.3
litellm==1.68.0
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
@@ -180,11 +233,7 @@ mixpanel==4.10.1
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
monotonic==1.6
# via
# -c requirements/common-constraints.txt
# posthog
multidict==6.3.2
multidict==6.4.3
# via
# -c requirements/common-constraints.txt
# aiohttp
@@ -198,7 +247,7 @@ numpy==1.26.4
# -c requirements/common-constraints.txt
# scipy
# soundfile
openai==1.70.0
openai==1.75.0
# via
# -c requirements/common-constraints.txt
# litellm
@@ -216,19 +265,19 @@ pexpect==4.9.0
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
pillow==11.1.0
pillow==11.2.1
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
pip==25.0.1
pip==25.1.1
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
posthog==3.23.0
posthog==4.0.1
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
prompt-toolkit==3.0.50
prompt-toolkit==3.0.51
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
@@ -237,6 +286,20 @@ propcache==0.3.1
# -c requirements/common-constraints.txt
# aiohttp
# yarl
proto-plus==1.26.1
# via
# -c requirements/common-constraints.txt
# google-ai-generativelanguage
# google-api-core
protobuf==5.29.4
# via
# -c requirements/common-constraints.txt
# google-ai-generativelanguage
# google-api-core
# google-generativeai
# googleapis-common-protos
# grpcio-status
# proto-plus
psutil==7.0.0
# via
# -c requirements/common-constraints.txt
@@ -245,6 +308,15 @@ ptyprocess==0.7.0
# via
# -c requirements/common-constraints.txt
# pexpect
pyasn1==0.6.1
# via
# -c requirements/common-constraints.txt
# pyasn1-modules
# rsa
pyasn1-modules==0.4.2
# via
# -c requirements/common-constraints.txt
# google-auth
pycodestyle==2.13.0
# via
# -c requirements/common-constraints.txt
@@ -253,12 +325,13 @@ pycparser==2.22
# via
# -c requirements/common-constraints.txt
# cffi
pydantic==2.11.2
pydantic==2.11.4
# via
# -c requirements/common-constraints.txt
# google-generativeai
# litellm
# openai
pydantic-core==2.33.1
pydantic-core==2.33.2
# via
# -c requirements/common-constraints.txt
# pydantic
@@ -278,6 +351,10 @@ pypandoc==1.15
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
pyparsing==3.2.3
# via
# -c requirements/common-constraints.txt
# httplib2
pyperclip==1.9.0
# via
# -c requirements/common-constraints.txt
@@ -307,6 +384,7 @@ regex==2024.11.6
requests==2.32.3
# via
# -c requirements/common-constraints.txt
# google-api-core
# huggingface-hub
# mixpanel
# posthog
@@ -320,6 +398,10 @@ rpds-py==0.24.0
# -c requirements/common-constraints.txt
# jsonschema
# referencing
rsa==4.9.1
# via
# -c requirements/common-constraints.txt
# google-auth
scipy==1.13.1
# via
# -c requirements/common-constraints.txt
@@ -351,7 +433,7 @@ soundfile==0.13.1
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
soupsieve==2.6
soupsieve==2.7
# via
# -c requirements/common-constraints.txt
# beautifulsoup4
@@ -366,6 +448,7 @@ tokenizers==0.21.1
tqdm==4.67.1
# via
# -c requirements/common-constraints.txt
# google-generativeai
# huggingface-hub
# openai
# via
@@ -379,7 +462,7 @@ tree-sitter-embedded-template==0.23.2
# via
# -c requirements/common-constraints.txt
# tree-sitter-language-pack
tree-sitter-language-pack==0.6.1
tree-sitter-language-pack==0.7.2
# via
# -c requirements/common-constraints.txt
# grep-ast
@@ -387,11 +470,12 @@ tree-sitter-yaml==0.7.0
# via
# -c requirements/common-constraints.txt
# tree-sitter-language-pack
typing-extensions==4.13.1
typing-extensions==4.13.2
# via
# -c requirements/common-constraints.txt
# anyio
# beautifulsoup4
# google-generativeai
# huggingface-hub
# openai
# pydantic
@@ -402,12 +486,16 @@ typing-inspection==0.4.0
# via
# -c requirements/common-constraints.txt
# pydantic
urllib3==2.3.0
uritemplate==4.1.1
# via
# -c requirements/common-constraints.txt
# google-api-python-client
urllib3==2.4.0
# via
# -c requirements/common-constraints.txt
# mixpanel
# requests
watchfiles==1.0.4
watchfiles==1.0.5
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
@@ -415,7 +503,7 @@ wcwidth==0.2.13
# via
# -c requirements/common-constraints.txt
# prompt-toolkit
yarl==1.18.3
yarl==1.20.0
# via
# -c requirements/common-constraints.txt
# aiohttp

View File

@@ -2,7 +2,7 @@
# uv pip compile --no-strip-extras --output-file=requirements/common-constraints.txt requirements/requirements.in requirements/requirements-browser.in requirements/requirements-dev.in requirements/requirements-help.in requirements/requirements-playwright.in
aiohappyeyeballs==2.6.1
# via aiohttp
aiohttp==3.11.16
aiohttp==3.11.18
# via
# huggingface-hub
# litellm
@@ -27,9 +27,9 @@ backoff==2.2.1
# via
# -r requirements/requirements.in
# posthog
banks==2.1.1
banks==2.1.2
# via llama-index-core
beautifulsoup4==4.13.3
beautifulsoup4==4.13.4
# via -r requirements/requirements.in
blinker==1.9.0
# via streamlit
@@ -39,7 +39,7 @@ cachetools==5.5.2
# via
# google-auth
# streamlit
certifi==2025.1.31
certifi==2025.4.26
# via
# httpcore
# httpx
@@ -50,7 +50,7 @@ cffi==1.17.1
# soundfile
cfgv==3.4.0
# via pre-commit
charset-normalizer==3.4.1
charset-normalizer==3.4.2
# via requests
click==8.1.8
# via
@@ -67,7 +67,7 @@ colorama==0.4.6
# via griffe
configargparse==1.7
# via -r requirements/requirements.in
contourpy==1.3.1
contourpy==1.3.2
# via matplotlib
cycler==0.12.1
# via matplotlib
@@ -79,7 +79,7 @@ deprecated==1.2.18
# llama-index-core
diff-match-patch==20241021
# via -r requirements/requirements.in
dill==0.3.9
dill==0.4.0
# via
# multiprocess
# pathos
@@ -105,7 +105,7 @@ flake8==7.2.0
# via -r requirements/requirements.in
fonttools==4.57.0
# via matplotlib
frozenlist==1.5.0
frozenlist==1.6.0
# via
# aiohttp
# aiosignal
@@ -120,34 +120,49 @@ gitpython==3.1.44
# via
# -r requirements/requirements.in
# streamlit
google-ai-generativelanguage==0.6.15
# via google-generativeai
google-api-core[grpc]==2.24.2
# via
# google-ai-generativelanguage
# google-api-python-client
# google-cloud-bigquery
# google-cloud-core
google-auth==2.38.0
# google-generativeai
google-api-python-client==2.169.0
# via google-generativeai
google-auth==2.40.0
# via
# google-ai-generativelanguage
# google-api-core
# google-api-python-client
# google-auth-httplib2
# google-cloud-bigquery
# google-cloud-core
# google-generativeai
google-auth-httplib2==0.2.0
# via google-api-python-client
google-cloud-bigquery==3.31.0
# via -r requirements/requirements-dev.in
google-cloud-core==2.4.3
# via google-cloud-bigquery
google-crc32c==1.7.1
# via google-resumable-media
google-generativeai==0.8.5
# via -r requirements/requirements.in
google-resumable-media==2.7.2
# via google-cloud-bigquery
googleapis-common-protos==1.69.2
googleapis-common-protos==1.70.0
# via
# google-api-core
# grpcio-status
greenlet==3.1.1
greenlet==3.2.1
# via
# playwright
# sqlalchemy
grep-ast==0.8.1
# via -r requirements/requirements.in
griffe==1.7.2
griffe==1.7.3
# via banks
grpcio==1.71.0
# via
@@ -155,22 +170,26 @@ grpcio==1.71.0
# grpcio-status
grpcio-status==1.71.0
# via google-api-core
h11==0.14.0
h11==0.16.0
# via httpcore
httpcore==1.0.7
httpcore==1.0.9
# via httpx
httplib2==0.22.0
# via
# google-api-python-client
# google-auth-httplib2
httpx==0.28.1
# via
# litellm
# llama-index-core
# openai
huggingface-hub[inference]==0.30.1
huggingface-hub[inference]==0.30.2
# via
# llama-index-embeddings-huggingface
# sentence-transformers
# tokenizers
# transformers
identify==2.6.9
identify==2.6.10
# via pre-commit
idna==3.10
# via
@@ -197,7 +216,7 @@ jinja2==3.1.6
# torch
jiter==0.9.0
# via openai
joblib==1.4.2
joblib==1.5.0
# via
# nltk
# scikit-learn
@@ -208,17 +227,17 @@ jsonschema==4.23.0
# -r requirements/requirements.in
# altair
# litellm
jsonschema-specifications==2024.10.1
jsonschema-specifications==2025.4.1
# via jsonschema
kiwisolver==1.4.8
# via matplotlib
litellm==1.65.3
litellm==1.68.0
# via -r requirements/requirements.in
llama-index-core==0.12.26
# via
# -r requirements/requirements-help.in
# llama-index-embeddings-huggingface
llama-index-embeddings-huggingface==0.5.2
llama-index-embeddings-huggingface==0.5.3
# via -r requirements/requirements-help.in
lox==0.13.0
# via -r requirements/requirements-dev.in
@@ -236,19 +255,17 @@ mdurl==0.1.2
# via markdown-it-py
mixpanel==4.10.1
# via -r requirements/requirements.in
monotonic==1.6
# via posthog
mpmath==1.3.0
# via sympy
multidict==6.3.2
multidict==6.4.3
# via
# aiohttp
# yarl
multiprocess==0.70.17
multiprocess==0.70.18
# via pathos
mypy-extensions==1.0.0
mypy-extensions==1.1.0
# via typing-inspect
narwhals==1.33.0
narwhals==1.38.0
# via altair
nest-asyncio==1.6.0
# via llama-index-core
@@ -274,7 +291,7 @@ numpy==1.26.4
# soundfile
# streamlit
# transformers
openai==1.70.0
openai==1.75.0
# via litellm
packaging==24.2
# via
@@ -292,7 +309,7 @@ pandas==2.2.3
# via
# -r requirements/requirements-dev.in
# streamlit
pathos==0.3.3
pathos==0.3.4
# via lox
pathspec==0.12.1
# via
@@ -300,14 +317,14 @@ pathspec==0.12.1
# grep-ast
pexpect==4.9.0
# via -r requirements/requirements.in
pillow==11.1.0
pillow==11.2.1
# via
# -r requirements/requirements.in
# llama-index-core
# matplotlib
# sentence-transformers
# streamlit
pip==25.0.1
pip==25.1.1
# via
# -r requirements/requirements.in
# pip-tools
@@ -317,29 +334,33 @@ platformdirs==4.3.7
# via
# banks
# virtualenv
playwright==1.51.0
playwright==1.52.0
# via -r requirements/requirements-playwright.in
pluggy==1.5.0
# via pytest
posthog==3.23.0
posthog==4.0.1
# via -r requirements/requirements.in
pox==0.3.5
pox==0.3.6
# via pathos
ppft==1.7.6.9
ppft==1.7.7
# via pathos
pre-commit==4.2.0
# via -r requirements/requirements-dev.in
prompt-toolkit==3.0.50
prompt-toolkit==3.0.51
# via -r requirements/requirements.in
propcache==0.3.1
# via
# aiohttp
# yarl
proto-plus==1.26.1
# via google-api-core
# via
# google-ai-generativelanguage
# google-api-core
protobuf==5.29.4
# via
# google-ai-generativelanguage
# google-api-core
# google-generativeai
# googleapis-common-protos
# grpcio-status
# proto-plus
@@ -348,7 +369,7 @@ psutil==7.0.0
# via -r requirements/requirements.in
ptyprocess==0.7.0
# via pexpect
pyarrow==19.0.1
pyarrow==20.0.0
# via streamlit
pyasn1==0.6.1
# via
@@ -360,19 +381,20 @@ pycodestyle==2.13.0
# via flake8
pycparser==2.22
# via cffi
pydantic==2.11.2
pydantic==2.11.4
# via
# banks
# google-generativeai
# litellm
# llama-index-core
# openai
pydantic-core==2.33.1
pydantic-core==2.33.2
# via pydantic
pydeck==0.9.1
# via streamlit
pydub==0.25.1
# via -r requirements/requirements.in
pyee==12.1.1
pyee==13.0.0
# via playwright
pyflakes==3.3.2
# via flake8
@@ -381,7 +403,9 @@ pygments==2.19.1
pypandoc==1.15
# via -r requirements/requirements.in
pyparsing==3.2.3
# via matplotlib
# via
# httplib2
# matplotlib
pyperclip==1.9.0
# via -r requirements/requirements.in
pyproject-hooks==1.2.0
@@ -439,7 +463,7 @@ rpds-py==0.24.0
# via
# jsonschema
# referencing
rsa==4.9
rsa==4.9.1
# via google-auth
safetensors==0.5.3
# via transformers
@@ -452,9 +476,9 @@ scipy==1.13.1
# sentence-transformers
semver==3.0.4
# via -r requirements/requirements-dev.in
sentence-transformers==4.0.2
sentence-transformers==4.1.0
# via llama-index-embeddings-huggingface
setuptools==78.1.0
setuptools==80.3.1
# via pip-tools
shellingham==1.5.4
# via typer
@@ -475,13 +499,13 @@ sounddevice==0.5.1
# via -r requirements/requirements.in
soundfile==0.13.1
# via -r requirements/requirements.in
soupsieve==2.6
soupsieve==2.7
# via beautifulsoup4
sqlalchemy[asyncio]==2.0.40
# via llama-index-core
streamlit==1.44.1
streamlit==1.45.0
# via -r requirements/requirements-browser.in
sympy==1.13.3
sympy==1.14.0
# via torch
tenacity==9.1.2
# via
@@ -507,13 +531,14 @@ tornado==6.4.2
# via streamlit
tqdm==4.67.1
# via
# google-generativeai
# huggingface-hub
# llama-index-core
# nltk
# openai
# sentence-transformers
# transformers
transformers==4.50.3
transformers==4.51.3
# via sentence-transformers
tree-sitter==0.24.0
# via tree-sitter-language-pack
@@ -521,17 +546,18 @@ tree-sitter-c-sharp==0.23.1
# via tree-sitter-language-pack
tree-sitter-embedded-template==0.23.2
# via tree-sitter-language-pack
tree-sitter-language-pack==0.6.1
tree-sitter-language-pack==0.7.2
# via grep-ast
tree-sitter-yaml==0.7.0
# via tree-sitter-language-pack
typer==0.15.2
typer==0.15.3
# via -r requirements/requirements-dev.in
typing-extensions==4.13.1
typing-extensions==4.13.2
# via
# altair
# anyio
# beautifulsoup4
# google-generativeai
# huggingface-hub
# llama-index-core
# openai
@@ -554,15 +580,17 @@ typing-inspection==0.4.0
# via pydantic
tzdata==2025.2
# via pandas
urllib3==2.3.0
uritemplate==4.1.1
# via google-api-python-client
urllib3==2.4.0
# via
# mixpanel
# requests
uv==0.6.12
uv==0.7.2
# via -r requirements/requirements-dev.in
virtualenv==20.30.0
virtualenv==20.31.1
# via pre-commit
watchfiles==1.0.4
watchfiles==1.0.5
# via -r requirements/requirements.in
wcwidth==0.2.13
# via prompt-toolkit
@@ -572,7 +600,7 @@ wrapt==1.17.2
# via
# deprecated
# llama-index-core
yarl==1.18.3
yarl==1.20.0
# via aiohttp
zipp==3.21.0
# via importlib-metadata

View File

@@ -17,11 +17,11 @@ cachetools==5.5.2
# via
# -c requirements/common-constraints.txt
# streamlit
certifi==2025.1.31
certifi==2025.4.26
# via
# -c requirements/common-constraints.txt
# requests
charset-normalizer==3.4.1
charset-normalizer==3.4.2
# via
# -c requirements/common-constraints.txt
# requests
@@ -50,7 +50,7 @@ jsonschema==4.23.0
# via
# -c requirements/common-constraints.txt
# altair
jsonschema-specifications==2024.10.1
jsonschema-specifications==2025.4.1
# via
# -c requirements/common-constraints.txt
# jsonschema
@@ -58,7 +58,7 @@ markupsafe==3.0.2
# via
# -c requirements/common-constraints.txt
# jinja2
narwhals==1.33.0
narwhals==1.38.0
# via
# -c requirements/common-constraints.txt
# altair
@@ -77,7 +77,7 @@ pandas==2.2.3
# via
# -c requirements/common-constraints.txt
# streamlit
pillow==11.1.0
pillow==11.2.1
# via
# -c requirements/common-constraints.txt
# streamlit
@@ -85,7 +85,7 @@ protobuf==5.29.4
# via
# -c requirements/common-constraints.txt
# streamlit
pyarrow==19.0.1
pyarrow==20.0.0
# via
# -c requirements/common-constraints.txt
# streamlit
@@ -123,7 +123,7 @@ smmap==5.0.2
# via
# -c requirements/common-constraints.txt
# gitdb
streamlit==1.44.1
streamlit==1.45.0
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-browser.in
@@ -139,7 +139,7 @@ tornado==6.4.2
# via
# -c requirements/common-constraints.txt
# streamlit
typing-extensions==4.13.1
typing-extensions==4.13.2
# via
# -c requirements/common-constraints.txt
# altair
@@ -149,7 +149,7 @@ tzdata==2025.2
# via
# -c requirements/common-constraints.txt
# pandas
urllib3==2.3.0
urllib3==2.4.0
# via
# -c requirements/common-constraints.txt
# requests

View File

@@ -8,7 +8,7 @@ cachetools==5.5.2
# via
# -c requirements/common-constraints.txt
# google-auth
certifi==2025.1.31
certifi==2025.4.26
# via
# -c requirements/common-constraints.txt
# requests
@@ -16,7 +16,7 @@ cfgv==3.4.0
# via
# -c requirements/common-constraints.txt
# pre-commit
charset-normalizer==3.4.1
charset-normalizer==3.4.2
# via
# -c requirements/common-constraints.txt
# requests
@@ -33,7 +33,7 @@ cogapp==3.4.1
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-dev.in
contourpy==1.3.1
contourpy==1.3.2
# via
# -c requirements/common-constraints.txt
# matplotlib
@@ -41,7 +41,7 @@ cycler==0.12.1
# via
# -c requirements/common-constraints.txt
# matplotlib
dill==0.3.9
dill==0.4.0
# via
# -c requirements/common-constraints.txt
# multiprocess
@@ -63,7 +63,7 @@ google-api-core[grpc]==2.24.2
# -c requirements/common-constraints.txt
# google-cloud-bigquery
# google-cloud-core
google-auth==2.38.0
google-auth==2.40.0
# via
# -c requirements/common-constraints.txt
# google-api-core
@@ -85,7 +85,7 @@ google-resumable-media==2.7.2
# via
# -c requirements/common-constraints.txt
# google-cloud-bigquery
googleapis-common-protos==1.69.2
googleapis-common-protos==1.70.0
# via
# -c requirements/common-constraints.txt
# google-api-core
@@ -99,7 +99,7 @@ grpcio-status==1.71.0
# via
# -c requirements/common-constraints.txt
# google-api-core
identify==2.6.9
identify==2.6.10
# via
# -c requirements/common-constraints.txt
# pre-commit
@@ -135,7 +135,7 @@ mdurl==0.1.2
# via
# -c requirements/common-constraints.txt
# markdown-it-py
multiprocess==0.70.17
multiprocess==0.70.18
# via
# -c requirements/common-constraints.txt
# pathos
@@ -160,15 +160,15 @@ pandas==2.2.3
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-dev.in
pathos==0.3.3
pathos==0.3.4
# via
# -c requirements/common-constraints.txt
# lox
pillow==11.1.0
pillow==11.2.1
# via
# -c requirements/common-constraints.txt
# matplotlib
pip==25.0.1
pip==25.1.1
# via
# -c requirements/common-constraints.txt
# pip-tools
@@ -184,11 +184,11 @@ pluggy==1.5.0
# via
# -c requirements/common-constraints.txt
# pytest
pox==0.3.5
pox==0.3.6
# via
# -c requirements/common-constraints.txt
# pathos
ppft==1.7.6.9
ppft==1.7.7
# via
# -c requirements/common-constraints.txt
# pathos
@@ -261,7 +261,7 @@ rich==14.0.0
# via
# -c requirements/common-constraints.txt
# typer
rsa==4.9
rsa==4.9.1
# via
# -c requirements/common-constraints.txt
# google-auth
@@ -269,7 +269,7 @@ semver==3.0.4
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-dev.in
setuptools==78.1.0
setuptools==80.3.1
# via
# -c requirements/common-constraints.txt
# pip-tools
@@ -281,11 +281,11 @@ six==1.17.0
# via
# -c requirements/common-constraints.txt
# python-dateutil
typer==0.15.2
typer==0.15.3
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-dev.in
typing-extensions==4.13.1
typing-extensions==4.13.2
# via
# -c requirements/common-constraints.txt
# typer
@@ -293,15 +293,15 @@ tzdata==2025.2
# via
# -c requirements/common-constraints.txt
# pandas
urllib3==2.3.0
urllib3==2.4.0
# via
# -c requirements/common-constraints.txt
# requests
uv==0.6.12
uv==0.7.2
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-dev.in
virtualenv==20.30.0
virtualenv==20.31.1
# via
# -c requirements/common-constraints.txt
# pre-commit

View File

@@ -4,7 +4,7 @@ aiohappyeyeballs==2.6.1
# via
# -c requirements/common-constraints.txt
# aiohttp
aiohttp==3.11.16
aiohttp==3.11.18
# via
# -c requirements/common-constraints.txt
# huggingface-hub
@@ -25,17 +25,17 @@ attrs==25.3.0
# via
# -c requirements/common-constraints.txt
# aiohttp
banks==2.1.1
banks==2.1.2
# via
# -c requirements/common-constraints.txt
# llama-index-core
certifi==2025.1.31
certifi==2025.4.26
# via
# -c requirements/common-constraints.txt
# httpcore
# httpx
# requests
charset-normalizer==3.4.1
charset-normalizer==3.4.2
# via
# -c requirements/common-constraints.txt
# requests
@@ -70,7 +70,7 @@ filetype==1.2.0
# via
# -c requirements/common-constraints.txt
# llama-index-core
frozenlist==1.5.0
frozenlist==1.6.0
# via
# -c requirements/common-constraints.txt
# aiohttp
@@ -81,19 +81,19 @@ fsspec==2025.3.2
# huggingface-hub
# llama-index-core
# torch
greenlet==3.1.1
greenlet==3.2.1
# via
# -c requirements/common-constraints.txt
# sqlalchemy
griffe==1.7.2
griffe==1.7.3
# via
# -c requirements/common-constraints.txt
# banks
h11==0.14.0
h11==0.16.0
# via
# -c requirements/common-constraints.txt
# httpcore
httpcore==1.0.7
httpcore==1.0.9
# via
# -c requirements/common-constraints.txt
# httpx
@@ -101,7 +101,7 @@ httpx==0.28.1
# via
# -c requirements/common-constraints.txt
# llama-index-core
huggingface-hub[inference]==0.30.1
huggingface-hub[inference]==0.30.2
# via
# -c requirements/common-constraints.txt
# llama-index-embeddings-huggingface
@@ -120,7 +120,7 @@ jinja2==3.1.6
# -c requirements/common-constraints.txt
# banks
# torch
joblib==1.4.2
joblib==1.5.0
# via
# -c requirements/common-constraints.txt
# nltk
@@ -130,7 +130,7 @@ llama-index-core==0.12.26
# -c requirements/common-constraints.txt
# -r requirements/requirements-help.in
# llama-index-embeddings-huggingface
llama-index-embeddings-huggingface==0.5.2
llama-index-embeddings-huggingface==0.5.3
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-help.in
@@ -146,12 +146,12 @@ mpmath==1.3.0
# via
# -c requirements/common-constraints.txt
# sympy
multidict==6.3.2
multidict==6.4.3
# via
# -c requirements/common-constraints.txt
# aiohttp
# yarl
mypy-extensions==1.0.0
mypy-extensions==1.1.0
# via
# -c requirements/common-constraints.txt
# typing-inspect
@@ -182,7 +182,7 @@ packaging==24.2
# huggingface-hub
# marshmallow
# transformers
pillow==11.1.0
pillow==11.2.1
# via
# -c requirements/common-constraints.txt
# llama-index-core
@@ -196,12 +196,12 @@ propcache==0.3.1
# -c requirements/common-constraints.txt
# aiohttp
# yarl
pydantic==2.11.2
pydantic==2.11.4
# via
# -c requirements/common-constraints.txt
# banks
# llama-index-core
pydantic-core==2.33.1
pydantic-core==2.33.2
# via
# -c requirements/common-constraints.txt
# pydantic
@@ -237,7 +237,7 @@ scipy==1.13.1
# -c requirements/common-constraints.txt
# scikit-learn
# sentence-transformers
sentence-transformers==4.0.2
sentence-transformers==4.1.0
# via
# -c requirements/common-constraints.txt
# llama-index-embeddings-huggingface
@@ -249,7 +249,7 @@ sqlalchemy[asyncio]==2.0.40
# via
# -c requirements/common-constraints.txt
# llama-index-core
sympy==1.13.3
sympy==1.14.0
# via
# -c requirements/common-constraints.txt
# torch
@@ -282,11 +282,11 @@ tqdm==4.67.1
# nltk
# sentence-transformers
# transformers
transformers==4.50.3
transformers==4.51.3
# via
# -c requirements/common-constraints.txt
# sentence-transformers
typing-extensions==4.13.1
typing-extensions==4.13.2
# via
# -c requirements/common-constraints.txt
# anyio
@@ -308,7 +308,7 @@ typing-inspection==0.4.0
# via
# -c requirements/common-constraints.txt
# pydantic
urllib3==2.3.0
urllib3==2.4.0
# via
# -c requirements/common-constraints.txt
# requests
@@ -317,7 +317,7 @@ wrapt==1.17.2
# -c requirements/common-constraints.txt
# deprecated
# llama-index-core
yarl==1.18.3
yarl==1.20.0
# via
# -c requirements/common-constraints.txt
# aiohttp

View File

@@ -1,18 +1,18 @@
# This file was autogenerated by uv via the following command:
# uv pip compile --no-strip-extras --constraint=requirements/common-constraints.txt --output-file=requirements/requirements-playwright.txt requirements/requirements-playwright.in
greenlet==3.1.1
greenlet==3.2.1
# via
# -c requirements/common-constraints.txt
# playwright
playwright==1.51.0
playwright==1.52.0
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements-playwright.in
pyee==12.1.1
pyee==13.0.0
# via
# -c requirements/common-constraints.txt
# playwright
typing-extensions==4.13.1
typing-extensions==4.13.2
# via
# -c requirements/common-constraints.txt
# pyee

View File

@@ -28,6 +28,7 @@ watchfiles
socksio
pip
pillow
google-generativeai
# The proper dependency is networkx[default], but this brings
# in matplotlib and a bunch of other deps

258
scripts/clean_metadata.py Executable file
View File

@@ -0,0 +1,258 @@
#!/usr/bin/env python
import difflib
import json
import re
from pathlib import Path
import json5
def find_block_lines(lines, key_to_remove):
"""Finds the start and end line indices for a top-level key's block."""
start_line_idx = -1
# Regex to find the line starting the key definition, allowing for whitespace
# and ensuring it's the key we want (e.g., avoid matching "key1_extra": ...)
key_pattern = re.compile(r'^\s*"' + re.escape(key_to_remove) + r'"\s*:\s*{?')
for i, line in enumerate(lines):
if key_pattern.match(line.strip()):
start_line_idx = i
break
if start_line_idx == -1:
# Key might not start with '{' on the same line, check if it starts immediately after
key_pattern_no_brace = re.compile(r'^\s*"' + re.escape(key_to_remove) + r'"\s*:\s*$')
for i, line in enumerate(lines):
if key_pattern_no_brace.match(line.strip()):
# Look for the opening brace on the next non-empty/comment line
j = i + 1
while j < len(lines):
stripped_next_line = lines[j].strip()
if not stripped_next_line or stripped_next_line.startswith("//"):
j += 1
continue
if stripped_next_line.startswith("{"):
start_line_idx = i # Start from the key definition line
break
else:
# False alarm, the line after the key wasn't '{'
break
if start_line_idx != -1:
break
if start_line_idx == -1:
print(
f"Warning: Could not reliably find start line for '{key_to_remove}'. Skipping removal."
)
return None, None # Key block start not found clearly
brace_level = 0
in_string = False
block_started = False
end_line_idx = -1
# Start brace counting from the identified start line
for i in range(start_line_idx, len(lines)):
line = lines[i]
# Simple brace counting - might be fooled by braces in comments or strings
# This is a limitation of pure text processing without full parsing
for char_idx, char in enumerate(line):
# Rudimentary string detection
if char == '"':
# Check if preceded by an odd number of backslashes (escaped quote)
backslashes = 0
temp_idx = char_idx - 1
while temp_idx >= 0 and line[temp_idx] == "\\":
backslashes += 1
temp_idx -= 1
if backslashes % 2 == 0:
in_string = not in_string
if not in_string:
if char == "{":
brace_level += 1
block_started = True # Mark that we've entered the block
elif char == "}":
brace_level -= 1
# Check if the block ends *after* processing the entire line
if block_started and brace_level == 0:
end_line_idx = i
break
if end_line_idx == -1:
print(
f"Warning: Could not find end of block for '{key_to_remove}' starting at line"
f" {start_line_idx + 1}. Skipping removal."
)
return None, None # Block end not found
return start_line_idx, end_line_idx
def remove_block_surgically(file_path, key_to_remove):
"""Reads the file, removes the block for the key, writes back."""
try:
# Read with universal newlines, but keep track for writing
with open(file_path, "r") as f:
content = f.read()
lines = content.splitlines(keepends=True) # Keep original line endings
except Exception as e:
print(f"Error reading {file_path} for removal: {e}")
return False
start_idx, end_idx = find_block_lines(lines, key_to_remove)
if start_idx is None or end_idx is None:
return False # Error message already printed by find_block_lines
# Prepare the lines to be written, excluding the identified block
output_lines = lines[:start_idx] + lines[end_idx + 1 :]
# Note: Comma handling is omitted for simplicity. User may need manual fix.
try:
with open(file_path, "w") as f:
f.writelines(output_lines)
print(f"Successfully removed '{key_to_remove}' block and updated {file_path}.")
return True
except Exception as e:
print(f"Error writing updated data to {file_path} after removing {key_to_remove}: {e}")
return False
def main():
script_dir = Path(__file__).parent.resolve()
# Adjust path relative to the script's location in the aider repo
litellm_path = script_dir.parent / "../litellm/model_prices_and_context_window.json"
aider_path = script_dir / "../aider/resources/model-metadata.json"
if not litellm_path.exists():
print(f"Error: LiteLLM metadata file not found at {litellm_path}")
return
if not aider_path.exists():
print(f"Error: Aider metadata file not found at {aider_path}")
return
try:
with open(litellm_path, "r") as f:
litellm_data = json.load(f)
except json.JSONDecodeError as e:
print(f"Error decoding JSON from {litellm_path}: {e}")
return
except Exception as e:
print(f"Error reading {litellm_path}: {e}")
return
try:
# Use json5 for the aider metadata file as it might contain comments
with open(aider_path, "r") as f:
aider_data = json5.load(f)
except json.JSONDecodeError as e:
print(f"Error decoding JSON from {aider_path}: {e}")
return
except Exception as e:
print(f"Error reading {aider_path}: {e}")
return
litellm_keys = set(litellm_data.keys())
aider_keys = set(aider_data.keys())
common_keys = sorted(list(litellm_keys.intersection(aider_keys)))
removed_count = 0
if common_keys:
print("Comparing common models found in both files:\n")
for key in common_keys:
print(f"--- {key} (aider) ---")
print(f"+++ {key} (litellm) +++")
litellm_entry = litellm_data.get(key, {})
aider_entry = aider_data.get(key, {})
# Convert dicts to formatted JSON strings for comparison
# First, compare the dictionaries directly for semantic equality
if litellm_entry == aider_entry:
print(f"'{key}': Entries are semantically identical.")
print("\n" + "=" * 40)
print("-" * 40 + "\n") # Separator for the next model
continue # Skip diff and removal prompt for identical entries
# Generate unified diff
# If dictionaries differ, generate JSON strings to show the diff
# Add a dummy key to ensure the *real* last key gets a comma
litellm_entry_copy = litellm_entry.copy()
aider_entry_copy = aider_entry.copy()
dummy_key = "zzzdummykey"
litellm_entry_copy[dummy_key] = True
aider_entry_copy[dummy_key] = True
litellm_json_lines = json.dumps(
litellm_entry_copy, indent=4, sort_keys=True
).splitlines()
aider_json_lines = json.dumps(aider_entry_copy, indent=4, sort_keys=True).splitlines()
# Remove the dummy key line before diffing
litellm_json_filtered = [line for line in litellm_json_lines if dummy_key not in line]
aider_json_filtered = [line for line in aider_json_lines if dummy_key not in line]
diff = difflib.unified_diff(
aider_json_filtered,
litellm_json_filtered,
fromfile=f"{key} (aider)",
tofile=f"{key} (litellm)",
lineterm="",
n=max(len(litellm_json_filtered), len(aider_json_filtered)), # Show all lines
)
# Print the diff, skipping the header lines generated by unified_diff
diff_lines = list(diff)[2:]
if not diff_lines:
# This case should ideally not be reached if dict comparison was done first,
# but kept as a fallback.
print(
"(No textual differences found, though dictionaries might differ in type/order)"
)
else:
for line in diff_lines:
# Add color for better readability (optional, requires a library
# like 'termcolor' or manual ANSI codes)
# Simple +/- indication is standard for diffs
print(line)
print("\n" + "=" * 40)
# Ask user if they want to remove the entry from aider's metadata
response = (
input(f"Remove '{key}' from aider/resources/model-metadata.json? (y/N): ")
.strip()
.lower()
)
if response == "y":
# Perform surgical removal from the text file
if remove_block_surgically(aider_path, key):
removed_count += 1
# Optional: Also remove from the in-memory dict if needed later,
# but it's not strictly necessary if we reload or finish now.
# if key in aider_data: del aider_data[key]
else:
print(f"Failed to remove '{key}' block surgically.")
# Key might still be in aider_data if removal failed
else:
print(f"Keeping '{key}'.")
print("-" * 40 + "\n") # Separator for the next model
else:
print("No common models found between the two files.")
return # Exit if no common keys
# Final summary message
if removed_count > 0:
print(f"\nFinished comparing. A total of {removed_count} entr(y/ies) were removed.")
else:
print("\nFinished comparing. No entries were removed.")
if __name__ == "__main__":
main()

View File

@@ -288,7 +288,7 @@ src="https://img.shields.io/github/stars/Aider-AI/aider?style=flat-square&logo=g
src="https://img.shields.io/badge/📦%20Installs-{downloads_formatted}-2ecc71?style=flat-square&labelColor=555555"/></a>
<img alt="Tokens per week" title="{TOKENS_WEEKLY_TOOLTIP}"
src="https://img.shields.io/badge/📈%20Tokens%2Fweek-{TOKENS_PER_WEEK}-3498db?style=flat-square&labelColor=555555"/>
<a href="https://openrouter.ai/"><img alt="OpenRouter Ranking" title="{OPENROUTER_TOOLTIP}"
<a href="https://openrouter.ai/#options-menu"><img alt="OpenRouter Ranking" title="{OPENROUTER_TOOLTIP}"
src="https://img.shields.io/badge/🏆%20OpenRouter-Top%2020-9b59b6?style=flat-square&labelColor=555555"/></a>
<a href="https://aider.chat/HISTORY.html"><img alt="Singularity" title="{SINGULARITY_TOOLTIP}"
src="https://img.shields.io/badge/🔄%20Singularity-{aider_percent_rounded}%25-e74c3c?style=flat-square&labelColor=555555"/></a>""" # noqa
@@ -398,7 +398,7 @@ def get_badges_html():
<span class="badge-label">📈 Tokens/week</span>
<span class="badge-value">{TOKENS_PER_WEEK}</span>
</div>
<a href="https://openrouter.ai/" class="github-badge badge-router" title="{OPENROUTER_TOOLTIP}">
<a href="https://openrouter.ai/#options-menu" class="github-badge badge-router" title="{OPENROUTER_TOOLTIP}">
<span class="badge-label">🏆 OpenRouter</span>
<span class="badge-value">Top 20</span>
</a>

View File

@@ -81,15 +81,20 @@ def main():
parser.add_argument(
"--dry-run", action="store_true", help="Print each step without actually executing them"
)
parser.add_argument("--force", action="store_true", help="Skip pre-push checks")
args = parser.parse_args()
dry_run = args.dry_run
force = args.force
# Perform checks before proceeding
check_branch()
check_working_directory_clean()
check_main_branch_up_to_date()
check_ok_to_push()
# Perform checks before proceeding unless --force is used
if not force:
check_branch()
check_working_directory_clean()
check_main_branch_up_to_date()
check_ok_to_push()
else:
print("Skipping pre-push checks due to --force flag.")
new_version_str = args.new_version
if not re.match(r"^\d+\.\d+\.\d+$", new_version_str):

View File

@@ -194,8 +194,8 @@ class TestCoder(unittest.TestCase):
mock.return_value = set([str(fname1), str(fname2), str(fname3)])
coder.repo.get_tracked_files = mock
# Check that file mentions skip files with duplicate basenames
mentioned = coder.get_file_mentions(f"Check {fname2} and {fname3}")
# Check that file mentions of a pure basename skips files with duplicate basenames
mentioned = coder.get_file_mentions(f"Check {fname2.name} and {fname3}")
self.assertEqual(mentioned, {str(fname3)})
# Add a read-only file with same basename
@@ -366,6 +366,45 @@ class TestCoder(unittest.TestCase):
f"Failed to extract mentions from: {content}",
)
def test_get_file_mentions_multiline_backticks(self):
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=True)
coder = Coder.create(self.GPT35, None, io)
# Create test files
test_files = [
"swebench/harness/test_spec/python.py",
"swebench/harness/test_spec/javascript.py",
]
for fname in test_files:
fpath = Path(fname)
fpath.parent.mkdir(parents=True, exist_ok=True)
fpath.touch()
# Mock get_addable_relative_files to return our test files
coder.get_addable_relative_files = MagicMock(return_value=set(test_files))
# Input text with multiline backticked filenames
content = """
Could you please **add the following files to the chat**?
1. `swebench/harness/test_spec/python.py`
2. `swebench/harness/test_spec/javascript.py`
Once I have these, I can show you precisely how to do the thing.
"""
expected_mentions = {
"swebench/harness/test_spec/python.py",
"swebench/harness/test_spec/javascript.py",
}
mentioned_files = coder.get_file_mentions(content)
self.assertEqual(
mentioned_files,
expected_mentions,
f"Failed to extract mentions from multiline backticked content: {content}",
)
def test_get_file_mentions_path_formats(self):
with GitTemporaryDirectory():
io = InputOutput(pretty=False, yes=True)

View File

@@ -108,29 +108,6 @@ Hope you like it!
edits = list(eb.find_original_update_blocks(edit))
self.assertEqual(edits, [("foo.txt", "Two\n", "Tooooo\n")])
def test_find_original_update_blocks_mangled_filename_w_source_tag(self):
source = "source"
edit = """
Here's the change:
<%s>foo.txt
<<<<<<< SEARCH
One
=======
Two
>>>>>>> REPLACE
</%s>
Hope you like it!
""" % (source, source)
fence = ("<%s>" % source, "</%s>" % source)
with self.assertRaises(ValueError) as cm:
_edits = list(eb.find_original_update_blocks(edit, fence))
self.assertIn("missing filename", str(cm.exception))
def test_find_original_update_blocks_quote_below_filename(self):
edit = """
Here's the change:
@@ -181,10 +158,11 @@ Tooooo
oops!
>>>>>>> REPLACE
"""
with self.assertRaises(ValueError) as cm:
list(eb.find_original_update_blocks(edit))
_blocks = list(eb.find_original_update_blocks(edit))
self.assertIn("filename", str(cm.exception))
def test_find_original_update_blocks_no_final_newline(self):
@@ -575,6 +553,66 @@ Hope you like it!
edits = list(eb.find_original_update_blocks(edit, fence=quad_backticks))
self.assertEqual(edits, [("foo.txt", "", "Tooooo\n")])
# Test for shell script blocks with sh language identifier (issue #3785)
def test_find_original_update_blocks_with_sh_language_identifier(self):
# https://github.com/Aider-AI/aider/issues/3785
edit = """
Here's a shell script:
```sh
test_hello.sh
<<<<<<< SEARCH
=======
#!/bin/bash
# Check if exactly one argument is provided
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <argument>" >&2
exit 1
fi
# Echo the first argument
echo "$1"
exit 0
>>>>>>> REPLACE
```
"""
edits = list(eb.find_original_update_blocks(edit))
# Instead of comparing exact strings, check that we got the right file and structure
self.assertEqual(len(edits), 1)
self.assertEqual(edits[0][0], "test_hello.sh")
self.assertEqual(edits[0][1], "")
# Check that the content contains the expected shell script elements
result_content = edits[0][2]
self.assertIn("#!/bin/bash", result_content)
self.assertIn('if [ "$#" -ne 1 ];', result_content)
self.assertIn('echo "Usage: $0 <argument>"', result_content)
self.assertIn("exit 1", result_content)
self.assertIn('echo "$1"', result_content)
self.assertIn("exit 0", result_content)
# Test for C# code blocks with csharp language identifier
def test_find_original_update_blocks_with_csharp_language_identifier(self):
edit = """
Here's a C# code change:
```csharp
Program.cs
<<<<<<< SEARCH
Console.WriteLine("Hello World!");
=======
Console.WriteLine("Hello, C# World!");
>>>>>>> REPLACE
```
"""
edits = list(eb.find_original_update_blocks(edit))
search_text = 'Console.WriteLine("Hello World!");\n'
replace_text = 'Console.WriteLine("Hello, C# World!");\n'
self.assertEqual(edits, [("Program.cs", search_text, replace_text)])
if __name__ == "__main__":
unittest.main()