Compare commits

...

1047 Commits

Author SHA1 Message Date
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
Paul Gauthier
b9a80f9c8c set version to 0.81.1.dev 2025-04-04 22:02:37 +13:00
Paul Gauthier
980f673ce2 version bump to 0.81.0 2025-04-04 22:02:34 +13:00
Paul Gauthier
55767a0003 copy 2025-04-04 21:56:25 +13:00
Paul Gauthier
fb44bebe40 copy 2025-04-04 21:53:47 +13:00
Paul Gauthier (aider)
b79f072499 feat: Add alias "quasar" for openrouter/openrouter/quasar-alpha 2025-04-04 21:53:12 +13:00
Paul Gauthier (aider)
d65a2e8b51 fix: Exclude double quotes from detected URLs 2025-04-04 21:48:17 +13:00
Paul Gauthier (aider)
e0b42d51db fix: Do not retry litellm.APIError for insufficient credits. 2025-04-04 21:45:56 +13:00
Paul Gauthier (aider)
c057dc9466 Feat: Add model metadata for openrouter/openrouter/quasar-alpha 2025-04-04 21:43:19 +13:00
Paul Gauthier (aider)
fff53a94d3 fix: Import offer_openrouter_oauth from aider/onboarding.py 2025-04-04 21:41:40 +13:00
Paul Gauthier (aider)
12beedd0a6 style: Run linter to fix line lengths and formatting issues 2025-04-04 21:40:47 +13:00
Paul Gauthier (aider)
80f60a7394 feat: Offer OpenRouter OAuth if model specified but API key is missing 2025-04-04 21:40:41 +13:00
Paul Gauthier
2359348505 copy 2025-04-04 21:39:47 +13:00
Paul Gauthier
63e3e06a8c copy 2025-04-04 18:53:12 +13:00
Paul Gauthier
dca92b580c add openrouter/openrouter/quasar-alpha 2025-04-04 18:52:59 +13:00
Paul Gauthier
24e2960092 add openrouter/openrouter/quasar-alpha 2025-04-04 18:52:16 +13:00
Paul Gauthier (aider)
be1a52c5c1 feat: Read highlight model from query string 2025-04-04 16:11:54 +13:00
Paul Gauthier
8a34a6c8f4 set version to 0.80.5.dev 2025-04-04 15:34:08 +13:00
Paul Gauthier
7924ea9bb9 version bump to 0.80.4 2025-04-04 15:34:04 +13:00
Paul Gauthier
a3a17ae792 copy 2025-04-04 15:31:04 +13:00
Paul Gauthier
f8801d811b feat: Remove max_tokens from deepseek model settings 2025-04-04 15:25:36 +13:00
Paul Gauthier
425284ac62 copy 2025-04-04 15:09:08 +13:00
Paul Gauthier
4872cdf905 copy 2025-04-04 15:08:21 +13:00
Paul Gauthier
88cd81c692 set version to 0.80.4.dev 2025-04-04 08:30:42 +13:00
Paul Gauthier
d45ecd0800 version bump to 0.80.3 2025-04-04 08:30:39 +13:00
Paul Gauthier
4bfcef60f4 copy 2025-04-04 07:58:59 +13:00
Paul Gauthier
e9b7e933f5 copy 2025-04-04 07:54:07 +13:00
Paul Gauthier
e5301cef49 copy 2025-04-04 07:52:16 +13:00
Paul Gauthier
01ca552174 copy 2025-04-04 07:49:36 +13:00
Paul Gauthier
4529d73bf3 feat: Add model metadata for openrouter/google/gemini-2.0-flash-exp:free 2025-04-03 08:43:19 +13:00
Paul Gauthier
0798906a51 Merge branch 'main' into gemini-weak-flash 2025-04-03 08:34:41 +13:00
Paul Gauthier
8547c24dac set version to 0.80.3.dev 2025-04-03 08:33:40 +13:00
Paul Gauthier
0e1e1aae2e version bump to 0.80.2 2025-04-03 08:33:36 +13:00
Paul Gauthier (aider)
9cc31e4087 feat: Configure weak models for Gemini 2.5 Pro 2025-04-03 08:12:27 +13:00
Paul Gauthier
e9c7555bb9 chore: Add TODO comment for Gemini 2.5 Pro models 2025-04-03 08:12:20 +13:00
Paul Gauthier
6f897fec59 copy 2025-04-03 08:10:13 +13:00
Paul Gauthier
8c3d77f4c7 bump deps to pickup https://github.com/BerriAI/litellm/pull/9667 2025-04-03 08:07:30 +13:00
Paul Gauthier
f9b60d83ac copy 2025-04-02 20:15:37 +13:00
Paul Gauthier (aider)
3992681b84 ci: Add Windows workflow to check PyPI version 2025-04-01 21:19:14 +13:00
Paul Gauthier
340bd78259 Revert "ci: Add Windows to check_pypi_version matrix and improve compatibility"
This reverts commit 12a46275a2.
2025-04-01 21:18:31 +13:00
Paul Gauthier (aider)
12a46275a2 ci: Add Windows to check_pypi_version matrix and improve compatibility 2025-04-01 21:17:28 +13:00
Paul Gauthier
b56234f1c9 copy 2025-04-01 21:15:25 +13:00
Paul Gauthier (aider)
60859ec2b9 ci: Fix latest tag detection to exclude dev tags 2025-04-01 21:14:24 +13:00
Paul Gauthier
0a840860f1 docs: Add comment explaining PyPI check workflow purpose 2025-04-01 21:14:17 +13:00
Paul Gauthier (aider)
cebae18dd6 ci: Correct version extraction in check_pypi_version workflow 2025-04-01 21:12:24 +13:00
Paul Gauthier (aider)
9c9c6b6591 ci: Improve robustness of aider version check in CI 2025-04-01 21:10:36 +13:00
Paul Gauthier (aider)
ca0ffc66d1 ci: Run check_pypi_version job across Python 3.9-3.12 2025-04-01 21:08:17 +13:00
Paul Gauthier (aider)
b0623f04fe ci: Add GitHub Action to verify PyPI version matches latest tag 2025-04-01 21:03:20 +13:00
Paul Gauthier
2dec862ea6 copy 2025-04-01 17:08:27 +13:00
Paul Gauthier
f18fe53a9a set version to 0.80.2.dev 2025-04-01 17:06:41 +13:00
Paul Gauthier
73348de2b4 version bump to 0.80.1 2025-04-01 17:06:37 +13:00
Paul Gauthier
f4a418bfcd copy 2025-04-01 17:03:58 +13:00
Paul Gauthier
50588800f5 copy 2025-04-01 16:15:19 +13:00
Paul Gauthier
2762215d66 copy 2025-04-01 16:14:02 +13:00
Paul Gauthier
4e53797aac Merge branch 'main' of github.com:Aider-AI/aider 2025-04-01 16:13:21 +13:00
Paul Gauthier
b24ac4b3a2 pin to avoid yanked versions #3699 2025-04-01 16:13:13 +13:00
paul-gauthier
88ab6afd3e Merge pull request #3698 from aj47/patch-1
Update benchmark README.md to specify how to config other settings
2025-04-01 15:27:38 +13:00
Paul Gauthier
5c5db0a961 noop 2025-04-01 15:27:05 +13:00
AJ (@techfren)
587186d96c Update benchmark README.md to specify how to config other settings 2025-03-31 17:05:53 -07:00
Paul Gauthier
d9ddf93f83 copy 2025-04-01 08:37:08 +13:00
Paul Gauthier
d3882d3513 Merge branch 'main' of github.com:Aider-AI/aider 2025-04-01 08:28:00 +13:00
paul-gauthier
a458215bbb Merge pull request #3692 from claui/requests 2025-04-01 06:53:26 +13:00
Claudia Pellegrino
7ae0fa3775 chore: remove redundant code
1. The module already imports `requests`, so by the time this check is
   called, the module is already loaded.

2. Even if the code path were taken, it would fail anyway, because the
   `aider[oauth]` extra was hallucinated and does not exist.

3. Downstream distributions usually have managed Python environments,
   where pip cannot be used at all.
   That means distros must patch out every such pip invocation
   (example: [1]; full disclosure: I maintain this but other distros
   will eventually bump into the same issues). Restricting at-runtime
   pip usage to the minimum necessary is friendlier to distro
   maintainers.

[1]: https://aur.archlinux.org/cgit/aur.git/tree/archlinux-use-system.patch?h=aider-chat&id=7f8156946857215104bce151454ad0101ade4a48
2025-03-31 19:13:41 +02:00
Paul Gauthier
f1695f8b15 copy 2025-03-31 19:56:59 +13:00
Paul Gauthier
4c08bbb9e5 copy 2025-03-31 19:34:36 +13:00
Paul Gauthier
9b55ff8c4c copy 2025-03-31 19:32:36 +13:00
Paul Gauthier
2096d2b786 copy 2025-03-31 19:27:29 +13:00
Paul Gauthier
70196cd6fd copy 2025-03-31 16:24:13 +13:00
Paul Gauthier
c2cba97722 copy 2025-03-31 14:32:36 +13:00
Paul Gauthier
7534ebd145 blame 2025-03-31 14:28:44 +13:00
Paul Gauthier
6b2331340b set version to 0.80.1.dev 2025-03-31 14:19:36 +13:00
Paul Gauthier
da7b5005fe version bump to 0.80.0 2025-03-31 14:19:32 +13:00
Paul Gauthier
9210e12316 copy 2025-03-31 14:13:54 +13:00
Paul Gauthier (aider)
2c47a79c38 ci: Skip languages.md in codespell check 2025-03-31 14:13:12 +13:00
Paul Gauthier
48cebef974 copy 2025-03-31 14:10:11 +13:00
Paul Gauthier (aider)
52952efd33 test: verify load_dotenv_files override behavior 2025-03-31 11:49:20 +13:00
Paul Gauthier
30dfd28ac4 copy 2025-03-31 11:46:37 +13:00
Paul Gauthier
b5a04f05f3 copy 2025-03-31 11:44:13 +13:00
Paul Gauthier (aider)
d5a34dcbc5 style: Fix trailing whitespace in homepage script 2025-03-31 11:42:47 +13:00
Paul Gauthier (aider)
fc6a05ced6 fix: Improve testimonial parsing for different dash formats 2025-03-31 11:42:40 +13:00
Paul Gauthier (aider)
2d3162a90b style: Remove trailing whitespace 2025-03-31 11:41:51 +13:00
Paul Gauthier (aider)
83c599e741 fix: Improve testimonial parsing from README 2025-03-31 11:41:44 +13:00
Paul Gauthier (aider)
c7f1671d5a feat: Generate testimonials JS in homepage script 2025-03-31 11:39:57 +13:00
Paul Gauthier
9f2d945691 kind words 2025-03-31 11:34:40 +13:00
Paul Gauthier
36ff099145 llama-index-core==0.12.26 2025-03-31 11:32:31 +13:00
Paul Gauthier
120e010e48 llama-index-core==0.12.24.post1 2025-03-31 11:25:07 +13:00
Paul Gauthier
2887816cf0 remove copilot 2025-03-31 11:22:14 +13:00
Paul Gauthier
9848479306 bump deps 2025-03-31 11:20:17 +13:00
Paul Gauthier
b662e6b9eb fix: Handle GitCommandNotFound error 2025-03-31 10:50:01 +13:00
Paul Gauthier
258f1f0848 copy 2025-03-31 10:42:52 +13:00
Paul Gauthier (aider)
a07f312089 style: Apply linter fixes 2025-03-31 10:33:00 +13:00
Paul Gauthier (aider)
605d8fe59a fix: Fix ColorParseError by ensuring hex colors have # prefix 2025-03-31 10:32:48 +13:00
Paul Gauthier (aider)
1c7db4da0d style: Apply linter fixes 2025-03-31 10:27:12 +13:00
Paul Gauthier (aider)
b0acc95b01 fix: Add missing ColorParseError import 2025-03-31 10:27:02 +13:00
Paul Gauthier (aider)
5bcad73515 refactor: Validate color settings once during initialization 2025-03-31 10:26:08 +13:00
Paul Gauthier (aider)
db05754d29 style: Apply linter formatting 2025-03-31 10:17:31 +13:00
Paul Gauthier (aider)
dfe3457906 test: Add test for cmd_test returning output on failure 2025-03-31 10:17:21 +13:00
Paul Gauthier (aider)
7dbb1a2aa8 fix: Return test errors from cmd_run to enable auto-fixing 2025-03-31 10:15:14 +13:00
Paul Gauthier (aider)
83dac4aae2 style: Improve formatting of OpenRouter key exchange error message 2025-03-31 09:17:32 +13:00
Paul Gauthier (aider)
75b79fa002 fix: Correct HTTPError status code access in onboarding 2025-03-31 09:17:26 +13:00
Paul Gauthier (aider)
27c1fd0262 fix: Handle FileNotFoundError in find_common_root 2025-03-31 09:15:26 +13:00
Paul Gauthier (aider)
8069e06f43 feat: Add openrouter deepseek-chat-v3-0324:free model 2025-03-31 09:12:39 +13:00
Paul Gauthier (aider)
8cd106fc8a fix: Prevent UnboundLocalError in get_tracked_files on IndexError 2025-03-31 09:10:29 +13:00
Paul Gauthier (aider)
a9c9877580 feat: Add free DeepSeek chat model configuration to model metadata 2025-03-31 09:08:51 +13:00
Paul Gauthier
19e1201c8a add google-cloud-bigquery as dev dep 2025-03-31 09:04:41 +13:00
Paul Gauthier (aider)
912f98e6eb fix: Remove unused import mock_open 2025-03-31 09:04:26 +13:00
Paul Gauthier (aider)
b6808e3700 test: Remove failing OpenRouter OAuth flow test 2025-03-31 08:53:21 +13:00
Paul Gauthier (aider)
a4f78b60e0 fix: Fix unused import and variable in onboarding tests 2025-03-31 08:51:19 +13:00
Paul Gauthier (aider)
6c9906c639 style: Fix whitespace and formatting in onboarding tests 2025-03-31 08:50:59 +13:00
Paul Gauthier (aider)
8a90af6779 fix: Remove redundant threading patch in onboarding test 2025-03-31 08:50:51 +13:00
Paul Gauthier
9831a13284 test: Simplify OpenRouter OAuth flow test 2025-03-31 08:50:45 +13:00
Paul Gauthier (aider)
d2386bc1f6 test: mock and assert offer_openrouter_oauth call in no-key test 2025-03-31 08:50:32 +13:00
Paul Gauthier
5b10af7b1a test: Disable streaming in main test call 2025-03-31 08:50:28 +13:00
Paul Gauthier (aider)
eacf3cc4ed test: Fix assertion failure and type error in onboarding tests 2025-03-31 08:44:32 +13:00
Paul Gauthier (aider)
87090139f6 test: Refactor onboarding test imports 2025-03-31 08:42:03 +13:00
Paul Gauthier (aider)
650c4cf948 style: Fix flake8 errors in onboarding tests 2025-03-31 08:41:35 +13:00
Paul Gauthier (aider)
24c074eeaa style: Apply linter fixes to onboarding tests 2025-03-31 08:41:11 +13:00
Paul Gauthier (aider)
b54629addb test: Add unit tests for onboarding functions 2025-03-31 08:41:05 +13:00
Paul Gauthier
cd67d11ecf test: Add onboarding tests 2025-03-31 08:40:59 +13:00
Paul Gauthier (aider)
16bb0c93e7 feat: Warn when using --stream and --cache-prompts together 2025-03-31 08:40:17 +13:00
Paul Gauthier
7c40c3a61c copy 2025-03-31 08:38:30 +13:00
Paul Gauthier
b8e8b7496d Merge branch 'main' of github.com:Aider-AI/aider 2025-03-31 08:36:57 +13:00
Paul Gauthier
d29d5e3a47 copy 2025-03-31 08:24:03 +13:00
paul-gauthier
db261d0fa4 Merge pull request #2980 from ivnvxd/fix-completion-menu-styling 2025-03-29 17:17:53 -10:00
Paul Gauthier
b7f6b847d6 Revert "bump deps"
This reverts commit 61147dfecf.
2025-03-30 11:05:38 +13:00
Paul Gauthier
5311a842a5 Revert "limit sentence-transformers<4 since 4.0.1 fails in GitHub Actions ubuntu and windows?"
This reverts commit e288f59da7.
2025-03-30 11:05:24 +13:00
Paul Gauthier
e288f59da7 limit sentence-transformers<4 since 4.0.1 fails in GitHub Actions ubuntu and windows? 2025-03-30 10:56:04 +13:00
Paul Gauthier
c62ceb5db1 test: Fix expected edit format in /model command tests 2025-03-28 20:27:12 -10:00
Paul Gauthier (aider)
35decf122d test: Add test for /model updating default edit format 2025-03-28 20:21:58 -10:00
Paul Gauthier (aider)
2adfe1507b test: Add tests for /model command edit_format behavior 2025-03-28 20:21:39 -10:00
Paul Gauthier (aider)
5516e6b279 feat: Update edit format on /model switch if using default 2025-03-28 20:20:46 -10:00
Paul Gauthier (aider)
8b811c610a refactor: Use get_raw_thinking_tokens in cmd_think_tokens 2025-03-28 20:12:04 -10:00
Paul Gauthier
23348f8e65 refactor: Remove redundant model arg from get_thinking/reasoning calls 2025-03-28 20:10:43 -10:00
Paul Gauthier (aider)
e1c3a2f8cf fix: Use self instead of model argument in get_reasoning_effort 2025-03-28 20:09:38 -10:00
Paul Gauthier (aider)
0b0493fa21 style: Remove unnecessary parentheses in conditions 2025-03-28 20:09:11 -10:00
Paul Gauthier (aider)
14d1742869 fix: Use self instead of model in get_raw_thinking_tokens 2025-03-28 20:09:05 -10:00
Paul Gauthier
96aa77288b refactor: Separate raw thinking token retrieval and fix self access 2025-03-28 20:09:01 -10:00
Paul Gauthier
a4c9c10029 style: Allow horizontal x-axis labels on leaderboard chart 2025-03-28 19:49:23 -10:00
Paul Gauthier (aider)
c9d561e7ad fix: Prevent leaderboard x-axis labels from disappearing 2025-03-28 19:43:26 -10:00
Paul Gauthier
87ba63c14c docs: Add chatgpt-4o-latest benchmark results 2025-03-28 19:36:06 -10:00
Paul Gauthier
0decbad7d0 Merge branch 'main' of github.com:Aider-AI/aider 2025-03-28 19:22:57 -10:00
Paul Gauthier
0e647dbc0e move 2025-03-28 19:21:44 -10:00
Paul Gauthier
2540d28b34 docs: Update Copilot documentation 2025-03-28 19:21:30 -10:00
Paul Gauthier (aider)
19a5e5bb00 docs: Add docs for Github Copilot models 2025-03-28 19:16:48 -10:00
Paul Gauthier
f22afc6458 docs: Add copilot.md 2025-03-28 19:16:44 -10:00
Paul Gauthier
ab00415ca1 Merge branch 'main' into feat/add_copilot 2025-03-28 19:13:54 -10:00
paul-gauthier
8df5406986 Merge pull request #3192 from miradnanali/fix-filename-quoting-for-lint
fix: Use shlex.quote() to enable linting filepaths containing shell metacharacters
2025-03-28 19:07:53 -10:00
Paul Gauthier
7f05159f0f Merge branch 'main' of github.com:Aider-AI/aider 2025-03-28 19:03:40 -10:00
Paul Gauthier
61147dfecf bump deps 2025-03-28 19:02:23 -10:00
paul-gauthier
06da133aac Merge pull request #3633 from susliko/scala-repomap
feat: add repomap support for Scala
2025-03-28 19:00:50 -10:00
Paul Gauthier
ff1d047048 docs: Add documentation for Ctrl-X Ctrl-E editor binding 2025-03-28 19:00:43 -10:00
paul-gauthier
4a8b17cb84 Merge pull request #3659 from iamFIREcracker/cx-ce-editor-key-binding
Invoke the editor by pressing `C-x C-e`
2025-03-28 18:58:13 -10:00
Paul Gauthier
fbafc09e6a copy 2025-03-28 18:54:20 -10:00
Paul Gauthier
c3c960383e feat: Offer OpenRouter OAuth if no model detected 2025-03-28 18:51:35 -10:00
Paul Gauthier
9e3adf0bf8 fix: Temporarily disable OpenRouter OAuth onboarding flow 2025-03-28 18:46:39 -10:00
Paul Gauthier
2bc0aa1777 docs: Fix docstring for check_openrouter_tier failure case 2025-03-28 18:45:31 -10:00
Paul Gauthier (aider)
3bc4064b61 fix: Default to free tier if OpenRouter tier check fails 2025-03-28 18:44:57 -10:00
Paul Gauthier (aider)
b4f9258f3c fix: Remove unused exception variable in webbrowser.open call 2025-03-28 18:29:26 -10:00
Paul Gauthier (aider)
ad844cce5c style: Fix linting issues in onboarding.py 2025-03-28 18:29:14 -10:00
Paul Gauthier (aider)
c73b064133 feat: Add OpenRouter tier-based model selection logic 2025-03-28 18:29:08 -10:00
Paul Gauthier
bd9b63a1aa refactor: Simplify OpenRouter OAuth flow messages and error handling 2025-03-28 18:29:05 -10:00
Paul Gauthier (aider)
2d87431aeb style: Apply linter formatting to onboarding.py 2025-03-28 18:03:10 -10:00
Paul Gauthier (aider)
3f3b1fb657 refactor: Update OpenRouter OAuth flow timeout to 5 minutes 2025-03-28 18:03:05 -10:00
Paul Gauthier
477f9eb4ec refactor: Update OpenRouter onboarding messages and flow 2025-03-28 18:03:04 -10:00
Paul Gauthier (aider)
91497dc2ee feat: Append OpenRouter API key to oauth-keys.env instead of overwriting 2025-03-28 17:57:26 -10:00
Paul Gauthier
928b78d9f6 feat: Simplify default model selection and improve OpenRouter OAuth key saving 2025-03-28 17:57:24 -10:00
Paul Gauthier (aider)
51825663b9 refactor: Extract model selection and OAuth logic into separate functions 2025-03-28 17:53:15 -10:00
Paul Gauthier
01fdbda728 refactor: Restructure model selection logic with new helper functions 2025-03-28 17:53:13 -10:00
Paul Gauthier
fa3c68fccd fix: Use print for auth URL and refine missing key message 2025-03-28 17:46:12 -10:00
Paul Gauthier (aider)
189977e4c7 fix: Update OpenRouter OAuth callback URL path to /callback/aider 2025-03-28 17:35:26 -10:00
Paul Gauthier (aider)
290fd99b6d feat: Load OAuth keys from ~/.aider/oauth-keys.env 2025-03-28 17:33:30 -10:00
Paul Gauthier (aider)
15cec5bd50 feat: Save OpenRouter API key to ~/.aider/oauth-keys.env 2025-03-28 17:32:39 -10:00
Paul Gauthier (aider)
f53db636e1 style: Format comments 2025-03-28 17:28:00 -10:00
Paul Gauthier (aider)
47d3802ffe feat: Handle user interruption during OpenRouter OAuth flow 2025-03-28 17:27:54 -10:00
Paul Gauthier (aider)
e98ffb5ae0 fix: Fix OAuth server premature shutdown on callback 2025-03-28 17:25:02 -10:00
Paul Gauthier (aider)
5d77eb1314 feat: Redirect callback URL to website if code param is missing 2025-03-28 17:23:21 -10:00
Paul Gauthier
f124cdbb6f refactor: Remove stream argument from Coder in onboarding 2025-03-28 17:21:04 -10:00
Paul Gauthier (aider)
1649d084d2 fix: Remove unused sys import 2025-03-28 17:16:28 -10:00
Paul Gauthier (aider)
36ca790c3d style: Sort imports alphabetically 2025-03-28 17:16:09 -10:00
Paul Gauthier (aider)
a91a8216b7 test: Add main function to test OpenRouter OAuth flow 2025-03-28 17:16:03 -10:00
Paul Gauthier (aider)
8cae7b20e7 fix: Remove unused variable found_key_env_var 2025-03-28 17:14:40 -10:00
Paul Gauthier (aider)
a537119f3d fix: Address flake8 linting errors in onboarding 2025-03-28 17:14:15 -10:00
Paul Gauthier (aider)
15fe0afe62 style: Run linter on onboarding module 2025-03-28 17:13:48 -10:00
Paul Gauthier (aider)
1b2a4db1ed feat: Add OpenRouter OAuth PKCE flow for authentication 2025-03-28 17:13:42 -10:00
Paul Gauthier (aider)
88a02723fa refactor: Extract default model selection logic to onboarding module 2025-03-28 16:54:10 -10:00
Paul Gauthier
7d013f35e2 rename 2025-03-28 16:51:58 -10:00
Paul Gauthier (aider)
e881d33bea docs: Update README cog import for homepage.py 2025-03-28 16:51:46 -10:00
Paul Gauthier (aider)
38da91becd refactor: Rename badges.py to homepage.py and update imports 2025-03-28 16:51:05 -10:00
Paul Gauthier
c99d96a700 copy 2025-03-28 16:46:08 -10:00
Paul Gauthier (aider)
fa89a6950b test: Update default Gemini model assertion 2025-03-28 16:43:39 -10:00
Paul Gauthier
cde08da282 refactor: Simplify model selection warning and analytics event logging 2025-03-28 16:42:12 -10:00
Paul Gauthier
8619bd4e84 refactor: Update auto_model_selection analytics event properties 2025-03-28 16:35:30 -10:00
Paul Gauthier (aider)
f49449b520 style: Remove trailing whitespace 2025-03-28 16:32:54 -10:00
Paul Gauthier (aider)
2fe79ac6a3 feat: Add analytics for auto-commits and auto-model selection 2025-03-28 16:32:47 -10:00
Paul Gauthier
d8830c43c5 fix: Clarify cost estimate warning for streaming/caching 2025-03-28 16:32:44 -10:00
Paul Gauthier (aider)
4ac945da70 feat: boost repomap ranking for files with mentioned path components 2025-03-28 16:23:35 -10:00
Paul Gauthier (aider)
ee0019e25f fix: Correct typo in streaming warning message 2025-03-28 16:21:05 -10:00
Paul Gauthier (aider)
f37b814570 feat: Improve streaming cost warning display 2025-03-28 16:20:23 -10:00
Paul Gauthier
e559bc8694 docs: Update model usage statistics in FAQ 2025-03-28 16:10:19 -10:00
Paul Gauthier (aider)
f7618440e7 chore: Remove unused VERTEX_AI_API_KEY entry 2025-03-28 16:10:08 -10:00
Paul Gauthier (aider)
7bc62cb674 feat: add VERTEXAI_PROJECT support for Gemini 2.5 Pro model 2025-03-28 16:09:59 -10:00
Paul Gauthier (aider)
db77e2e9b9 feat: prioritize gemini-2.5-pro when GEMINI or VERTEX keys present 2025-03-28 16:07:54 -10:00
Paul Gauthier (aider)
083b49f3c4 style: Improve testimonial card spacing and readability 2025-03-28 16:04:53 -10:00
Paul Gauthier (aider)
f3f0416d31 feat: maintain consistent height for testimonial cards 2025-03-28 16:02:54 -10:00
Paul Gauthier (aider)
775a9f86a1 style: Add CSS transitions for testimonial cards 2025-03-28 16:01:13 -10:00
Paul Gauthier (aider)
e2bfdc444a feat: replace flip animation with elegant fade transition for testimonials 2025-03-28 16:00:43 -10:00
Paul Gauthier
3c7783585e feat: Speed up testimonials rotation and add script tags 2025-03-28 15:57:53 -10:00
Paul Gauthier (aider)
761a297903 feat: include script tags in testimonials JS output 2025-03-28 15:53:53 -10:00
Paul Gauthier
6d30094a93 chore: Remove commented code from index.html 2025-03-28 15:53:47 -10:00
Paul Gauthier (aider)
d8e1816774 fix: Properly indent cog directive in index.html 2025-03-28 15:51:18 -10:00
Paul Gauthier
ae371cb362 feat: Add new testimonials to website 2025-03-28 15:51:11 -10:00
Paul Gauthier (aider)
73c46e8e24 fix: Remove unnecessary f-string in testimonials formatting 2025-03-28 15:49:14 -10:00
Paul Gauthier (aider)
ef4c40c692 style: Format code with linter 2025-03-28 15:48:48 -10:00
Paul Gauthier (aider)
04b3ada7f7 feat: dynamically load testimonials from README using cog 2025-03-28 15:48:39 -10:00
Paul Gauthier
424b43b3d3 copy 2025-03-28 15:45:04 -10:00
Paul Gauthier (aider)
9a9255d6f9 docs: add more user testimonials to README 2025-03-28 15:42:48 -10:00
Paul Gauthier
d9e52e41ff fix: Replace self.print_error with print for timeout message 2025-03-28 15:36:25 -10:00
Paul Gauthier (aider)
a038bc002a feat: Include URL in page timeout warning message 2025-03-28 15:35:01 -10:00
Paul Gauthier (aider)
fa256eb1a7 feat: Change timeout error to warning and continue scraping 2025-03-28 15:34:18 -10:00
Paul Gauthier (aider)
6689f001cf docs: Add positive user quotes to kind words section 2025-03-28 15:33:47 -10:00
Paul Gauthier
cc043bab9c Merge branch 'main' of github.com:Aider-AI/aider 2025-03-28 15:30:15 -10:00
Vasil Markoukin
5af73b1dcf feat: add repomap support for Scala
Resolves #3578
2025-03-28 10:07:57 +03:00
Paul Gauthier
85925a2dc6 copy 2025-03-27 18:40:09 -10:00
paul-gauthier
fb23b6c26f Merge pull request #3662 from schpet/markdown-headings-left 2025-03-27 11:58:31 -10:00
Peter Schilling (aider)
d5cec5f71e aider: chore: Remove unnecessary comment in mdstream.py 2025-03-27 14:08:04 -07:00
Peter Schilling (aider)
13b62e3d06 aider: fix: Use correct token type for markdown heading alignment 2025-03-27 13:59:58 -07:00
Peter Schilling (aider)
779f07f072 aider: fix: Align headings left while preserving h1/h2 styling 2025-03-27 13:58:05 -07:00
Peter Schilling (aider)
b923d63700 aider: style: Left-align markdown headings 2025-03-27 13:48:12 -07:00
Paul Gauthier
7e2dd9bc04 copy 2025-03-27 09:47:30 -10:00
Paul Gauthier
ef1f869b73 set version to 0.79.3.dev 2025-03-27 09:35:00 -10:00
Paul Gauthier
959d6334db version bump to 0.79.2 2025-03-27 09:34:57 -10:00
Paul Gauthier
d7b00b93c7 copy 2025-03-27 09:28:01 -10:00
Paul Gauthier
eec084c842 copy 2025-03-27 09:27:05 -10:00
Paul Gauthier
87b504a58f copy 2025-03-27 09:03:40 -10:00
Paul Gauthier (aider)
243d4d0727 feat: add openrouter/deepseek-chat-v3-0324 model config 2025-03-27 09:02:55 -10:00
Paul Gauthier (aider)
673acf4308 feat: enable retries for OpenRouter choices errors 2025-03-27 07:01:10 -10:00
Paul Gauthier (aider)
fd180ebff5 style: Format test_exceptions.py with linter 2025-03-27 06:58:46 -10:00
Paul Gauthier (aider)
61705ce7fc test: add coverage for OpenRouter API error detection 2025-03-27 06:58:38 -10:00
Paul Gauthier (aider)
6e1dd4474b feat: add OpenRouter API error detection 2025-03-27 06:56:28 -10:00
Matteo Landi (aider)
7924657584 feat: Improve C-x C-e editor keybinding to handle cursor and newline 2025-03-27 10:35:03 +01:00
Matteo Landi (aider)
4f5ed8ace0 feat: Add C-x C-e keybinding to edit input in external editor 2025-03-27 08:33:50 +01:00
Paul Gauthier (aider)
8737220fb6 feat: update Gemini 2.5 Pro max output tokens to 64k 2025-03-26 08:42:28 -10:00
Paul Gauthier
bcb01e8c1b Merge branch 'main' of github.com:Aider-AI/aider 2025-03-26 08:37:58 -10:00
Paul Gauthier
41f669bb89 feat: Add 'gemini' alias for gemini-2.5-pro model 2025-03-26 08:37:51 -10:00
Paul Gauthier
983bc199b3 cleanup 2025-03-26 08:37:40 -10:00
paul-gauthier
8f15269bd0 Merge pull request #3647 from iamFIREcracker/lisp-comments
Add support for Lisp-style comments in file watcher
2025-03-26 08:36:56 -10:00
Paul Gauthier (aider)
6ffe3e7067 style: Format code with linter 2025-03-26 07:11:22 -10:00
Paul Gauthier (aider)
51bf6035f7 feat: add footer safe zone for GitHub URL in confetti image 2025-03-26 07:11:15 -10:00
Paul Gauthier (aider)
249a6fc9b1 chore: remove yellow hexagon confettis below stars line 2025-03-26 07:10:36 -10:00
Paul Gauthier (aider)
c6d4337855 style: Fix whitespace in 30k-image.py 2025-03-26 07:09:28 -10:00
Paul Gauthier (aider)
9fa3636c57 feat: add safe zone for text in confetti generation 2025-03-26 07:09:20 -10:00
Paul Gauthier
a417e6e644 style: Fix trailing whitespace in SVG generation script 2025-03-26 07:07:16 -10:00
Paul Gauthier (aider)
999eb86d7a fix: Add missing math import in 30k-image.py 2025-03-26 07:01:51 -10:00
Paul Gauthier (aider)
7b97f93051 style: Reformat code with linter 2025-03-26 07:01:19 -10:00
Paul Gauthier (aider)
02bc926d75 feat: add script to generate 30k GitHub stars celebration SVG 2025-03-26 07:01:11 -10:00
Paul Gauthier
48ee3cdf98 feat: Add script to generate 30k images 2025-03-26 07:01:05 -10:00
Paul Gauthier (aider)
2556a912d3 style: Format SVG elements with consistent line breaks 2025-03-26 06:59:45 -10:00
Paul Gauthier (aider)
487674b1c5 feat: enhance celebration image with GitHub branding and animations 2025-03-26 06:59:37 -10:00
Paul Gauthier (aider)
347fbf6471 style: Format code with linter 2025-03-26 06:55:12 -10:00
Paul Gauthier (aider)
3eff70a3bc feat: enhance celebration image with decorations and glow effects 2025-03-26 06:55:04 -10:00
Paul Gauthier (aider)
ad7c708039 style: Format code with linter 2025-03-26 06:51:43 -10:00
Paul Gauthier (aider)
f993c1f22c feat: Improve celebration image with glow effect and tighter spacing 2025-03-26 06:51:36 -10:00
Paul Gauthier (aider)
75b714a1ad fix: Resolve flake8 errors in generate_celebration_image.py 2025-03-26 06:47:40 -10:00
Paul Gauthier (aider)
0636d40909 style: Fix linting issues in generate_celebration_image.py 2025-03-26 06:47:20 -10:00
Paul Gauthier (aider)
cbb3660a17 feat: Convert celebration image generator to SVG format 2025-03-26 06:47:13 -10:00
Paul Gauthier (aider)
42363beb72 style: Format code with linter 2025-03-26 06:45:10 -10:00
Paul Gauthier (aider)
efa36a7196 feat: add script to generate 30k stars celebration image 2025-03-26 06:45:03 -10:00
Matteo Landi (aider)
fab713a6a8 fix: Handle Lisp semicolon comments in watch.py 2025-03-26 13:01:53 +01:00
Matteo Landi (aider)
7d5f1143af test: Add Lisp-style comment tests to file watcher 2025-03-26 08:17:29 +01:00
Matteo Landi (aider)
f05f8df44c refactor: Add support for Lisp-style comments in file watcher 2025-03-26 08:13:09 +01:00
Paul Gauthier
c89a1a8021 set version to 0.79.2.dev 2025-03-25 15:06:16 -10:00
Paul Gauthier
db7c679e74 version bump to 0.79.1 2025-03-25 15:06:13 -10:00
Paul Gauthier (aider)
71cbbf545b style: Format test_ssl_verification.py with linter 2025-03-25 14:56:59 -10:00
Paul Gauthier (aider)
6809a7ec3e fix: mock fuzzy_match_models in SSL verification test 2025-03-25 14:56:51 -10:00
Paul Gauthier
70847a74c2 test: update model listing test to use metadata-only model 2025-03-25 14:51:24 -10:00
Paul Gauthier (aider)
6933bc8add style: Fix whitespace and formatting in test file 2025-03-25 14:46:55 -10:00
Paul Gauthier (aider)
a6cbaad5a2 test: fix test_list_models_with_direct_resource_patch to mock correct resource loading 2025-03-25 14:46:47 -10:00
Paul Gauthier (aider)
899972e22f fix: add --no-gitignore flag to failing list-models tests 2025-03-25 14:30:13 -10:00
Paul Gauthier
820b925b78 copy 2025-03-25 13:42:35 -10:00
Paul Gauthier (aider)
5457b43a89 docs: Add gemini-2.5-pro command to docs 2025-03-25 13:42:02 -10:00
Paul Gauthier (aider)
0adbc9678f fix: add mode attribute to test model metadata 2025-03-25 13:38:53 -10:00
Paul Gauthier
8d6a2ecf0e test: update model metadata test with new flags and provider format 2025-03-25 13:38:47 -10:00
Paul Gauthier (aider)
6acbd80cee style: Format test data with consistent indentation 2025-03-25 13:34:34 -10:00
Paul Gauthier (aider)
2331224157 fix: include local model metadata in fuzzy matching and update tests 2025-03-25 13:34:25 -10:00
Paul Gauthier (aider)
5d2aea434c style: Fix line length in test comment 2025-03-25 13:30:40 -10:00
Paul Gauthier (aider)
798f6983e4 style: Fix whitespace and formatting in test file 2025-03-25 13:30:19 -10:00
Paul Gauthier (aider)
a428fdc951 test: add tests for model listing with metadata sources 2025-03-25 13:30:10 -10:00
Paul Gauthier
ccacc09ff0 refactor: Reorder model listing and expand fuzzy matching 2025-03-25 13:28:53 -10:00
Paul Gauthier
40cc155aad copy 2025-03-25 11:27:25 -10:00
Paul Gauthier
645e0de971 blame 2025-03-25 11:26:54 -10:00
Paul Gauthier
325eb5968d set version to 0.79.1.dev 2025-03-25 11:15:03 -10:00
Paul Gauthier
65a7583731 version bump to 0.79.0 2025-03-25 11:14:59 -10:00
Paul Gauthier (aider)
6d8e4e8fb1 style: Fix string quote consistency in test_coder.py 2025-03-25 11:05:58 -10:00
Paul Gauthier (aider)
4716cce208 fix: pre-calculate Windows paths to avoid f-string backslash issues 2025-03-25 11:05:49 -10:00
Paul Gauthier
c67bbe6c00 copy 2025-03-25 11:04:25 -10:00
Paul Gauthier (aider)
1272e21603 style: Fix string quotes in test_coder.py 2025-03-25 11:01:54 -10:00
Paul Gauthier (aider)
7302280417 test: Add Windows path handling in file mention tests 2025-03-25 11:01:44 -10:00
Paul Gauthier (aider)
871c6d56dc refactor: Move windows_path variable outside test cases tuple 2025-03-25 11:01:21 -10:00
Paul Gauthier (aider)
eb0389938c fix: handle Windows path formatting in test cases 2025-03-25 10:59:45 -10:00
Paul Gauthier (aider)
e6c191bdc6 fix: Use raw string for backslash in f-string expression 2025-03-25 10:59:29 -10:00
Paul Gauthier
2727eb6dd7 copy 2025-03-25 10:58:00 -10:00
Paul Gauthier
821087bcce copy 2025-03-25 10:55:17 -10:00
Paul Gauthier
f1955577bc feat: Add Gemini Pro 2.5 test results to leaderboard 2025-03-25 10:43:05 -10:00
Paul Gauthier (aider)
966686cd5d feat: add gemini-2.5-pro model alias 2025-03-25 10:15:10 -10:00
Paul Gauthier
79d3d50de6 copy 2025-03-25 10:11:49 -10:00
Paul Gauthier
da59f0a0db add gemini 2.5 pro 2025-03-25 10:11:00 -10:00
Paul Gauthier
bdc00e5dd4 copy 2025-03-25 09:59:17 -10:00
Paul Gauthier
9854a4f92e feat: Add Gemini 2.5 Pro model settings 2025-03-25 09:27:36 -10:00
Paul Gauthier
33413ecfe9 copy 2025-03-25 07:01:10 -10:00
Paul Gauthier (aider)
c7e8d297a4 feat: Make SVG icons link to corresponding docs pages 2025-03-24 16:31:53 -10:00
Paul Gauthier (aider)
3619953f83 style: change icon colors from blue to green 2025-03-24 16:30:35 -10:00
Paul Gauthier (aider)
b20753c3ac style: update SVG icons to match site color scheme 2025-03-24 16:28:50 -10:00
Paul Gauthier
4fd6b7a608 initial 2025-03-24 16:26:02 -10:00
Paul Gauthier (aider)
1de8e477b9 docs: Update README to use local icon paths 2025-03-24 16:24:04 -10:00
Paul Gauthier (aider)
6c50645213 style: Reformat dl_icons.py with consistent spacing 2025-03-24 16:23:05 -10:00
Paul Gauthier (aider)
5aeea0c228 feat: add script to download SVG icons for local use 2025-03-24 16:22:57 -10:00
Paul Gauthier
86ceeb554d feat: Add script to download icons 2025-03-24 16:22:51 -10:00
Paul Gauthier (aider)
ca121e0e28 docs: update README icons to match index.html 2025-03-24 13:46:21 -10:00
Paul Gauthier (aider)
d1fef7fd17 docs: update icons in README to match index.html 2025-03-24 13:45:09 -10:00
Paul Gauthier (aider)
25d157afdc style: Move feature icons below headers in README 2025-03-24 13:42:34 -10:00
Paul Gauthier (aider)
97afe3cd0b style: Add valign=middle to README icon images 2025-03-24 13:41:42 -10:00
Paul Gauthier (aider)
2923304bdb style: improve README features section layout with larger icons 2025-03-24 13:40:07 -10:00
Paul Gauthier
10d741b6df copy 2025-03-24 13:34:35 -10:00
Paul Gauthier
12cd115ae4 Revert "docs: format features section with table layout for better readability"
This reverts commit d1def13cd1.
2025-03-24 13:33:34 -10:00
Paul Gauthier (aider)
d1def13cd1 docs: format features section with table layout for better readability 2025-03-24 13:32:53 -10:00
Paul Gauthier (aider)
127c305b1a style: increase icon sizes in README from 16px to 24px 2025-03-24 13:30:45 -10:00
Paul Gauthier (aider)
fd06db18a0 style: remove bullet points from README features section 2025-03-24 13:29:00 -10:00
Paul Gauthier (aider)
387b392c18 chore: Swap git and map icons between README and index 2025-03-24 13:27:17 -10:00
Paul Gauthier
964022f7b5 cleanupo 2025-03-24 13:25:51 -10:00
Paul Gauthier (aider)
9edc346c2c refactor: replace local icons with MDI CDN references 2025-03-24 13:25:05 -10:00
Paul Gauthier (aider)
2fe671744b style: Replace DNA icon with MDI brain icon 2025-03-24 13:22:34 -10:00
Paul Gauthier (aider)
fb8daa5607 feat: Replace inline SVGs with external icon files for GitHub compatibility 2025-03-24 13:21:07 -10:00
Paul Gauthier (aider)
65e0da72b8 style: Replace emojis with SVG icons in README 2025-03-24 13:16:27 -10:00
Paul Gauthier (aider)
3d5924e2f5 style: Increase icon size and enhance hover animation in feature cards 2025-03-24 13:12:10 -10:00
Paul Gauthier (aider)
5b2e2d630b refactor: Replace weather-cloudy icon with brain icon in feature card 2025-03-24 13:10:57 -10:00
Paul Gauthier (aider)
6a96cb6ba7 refactor: Replace SVG icon with MDI icon for images feature 2025-03-24 13:09:50 -10:00
Paul Gauthier (aider)
43ece9c644 refactor: Replace inline SVGs with Material Design Icons 2025-03-24 13:09:21 -10:00
Paul Gauthier (aider)
46cef723b7 style: Increase feature icon size and hover effect scale 2025-03-24 13:03:11 -10:00
Paul Gauthier (aider)
9b19dac569 style: Update feature icons to use secondary color for better distinction 2025-03-24 13:01:20 -10:00
Paul Gauthier (aider)
54eb642726 style: replace Git icon with standard Git branching icon 2025-03-24 12:59:10 -10:00
Paul Gauthier (aider)
5bb664657c fix: Replace broken cloud icon with proper Material Design icon 2025-03-24 12:56:57 -10:00
Paul Gauthier (aider)
dea4d16e87 style: replace emoji icons with material design SVGs and hover effects 2025-03-24 12:54:19 -10:00
Paul Gauthier
059cd23543 feat: add DeepSeek V3 (0324) to polyglot leaderboard 2025-03-24 12:44:25 -10:00
Paul Gauthier
502b8630a2 copy 2025-03-22 18:38:10 -07:00
Paul Gauthier (aider)
b2444b43a6 refactor: Pass placeholder to _generic_chat_command instead of special-casing context 2025-03-22 18:36:10 -07:00
Paul Gauthier (aider)
be87ff0193 feat: Set placeholder with args in /context command 2025-03-22 18:33:50 -07:00
Paul Gauthier (aider)
c7fe86021c style: Replace single quotes with double quotes in main.py 2025-03-22 18:32:32 -07:00
Paul Gauthier (aider)
99b0209c89 feat: Add placeholder parameter to SwitchCoder 2025-03-22 18:32:25 -07:00
Paul Gauthier (aider)
4d61b596ff style: Remove trailing whitespace in commands.py 2025-03-22 18:15:17 -07:00
Paul Gauthier (aider)
0549e7079d feat: Add /edit as an alias for /editor command 2025-03-22 18:15:11 -07:00
Paul Gauthier
b591b64d3f refactor: Update context handling and repo map logic 2025-03-22 16:20:23 -07:00
Paul Gauthier (aider)
a3377686fa style: Remove unnecessary blank line in repomap.py 2025-03-22 14:59:01 -07:00
Paul Gauthier (aider)
d23bba5d9f feat: Increase weight for snake_case and camelCase identifiers 2025-03-22 14:58:56 -07:00
Paul Gauthier
5e8fc3e4c8 refactor: Simplify and optimize weight calculation in RepoMap 2025-03-22 14:58:55 -07:00
Paul Gauthier (aider)
04e76ad6ff chore: Remove unused import from context_coder.py 2025-03-22 14:19:29 -07:00
Paul Gauthier (aider)
3a18a9296b style: Format code with consistent spacing in comments 2025-03-22 14:19:10 -07:00
Paul Gauthier (aider)
3e9a6ffbca chore: Comment out debug print statements in ContextCoder 2025-03-22 14:19:06 -07:00
Paul Gauthier
0b06e56182 refactor: Simplify file mention handling logic in ContextCoder 2025-03-22 14:19:05 -07:00
Paul Gauthier (aider)
fb5a32f429 style: Fix trailing whitespace and comma consistency 2025-03-22 14:16:55 -07:00
Paul Gauthier (aider)
75dfd4505b feat: Add /context command for contextually-aware edits 2025-03-22 14:16:49 -07:00
Paul Gauthier
5661d1428e refactor: Enhance file mention handling and context coder logic 2025-03-22 13:57:15 -07:00
Paul Gauthier (aider)
f543c1ee1c style: Break long line in test_coder.py to comply with flake8 E501 2025-03-22 13:37:11 -07:00
Paul Gauthier
74254cdbd5 feat: Add ContextCoder for identifying relevant files in requests 2025-03-22 13:36:58 -07:00
Paul Gauthier (aider)
a5c8c534c1 fix: Remove unnecessary f-string prefix in test case 2025-03-22 13:26:19 -07:00
Paul Gauthier (aider)
24159dda58 style: Format test_coder.py for readability 2025-03-22 13:26:03 -07:00
Paul Gauthier (aider)
ad0a2b3260 test: Add test cases for bold format file mentions 2025-03-22 13:25:58 -07:00
Paul Gauthier (aider)
7e51c68fde style: Format code according to linter rules 2025-03-22 13:23:52 -07:00
Paul Gauthier (aider)
3b376a15b7 test: Add comprehensive test for get_file_mentions with various formats 2025-03-22 13:23:46 -07:00
Paul Gauthier (aider)
8e5f311708 style: Remove trailing whitespace in base_prompts.py 2025-03-22 08:22:39 -07:00
Paul Gauthier (aider)
02c48fa8c3 style: Break long line in base_prompts.py to comply with flake8 E501 2025-03-22 08:22:20 -07:00
Paul Gauthier
51fa2eb103 feat: Add overeager model setting and prompt for precise request handling 2025-03-22 08:22:07 -07:00
Paul Gauthier (aider)
0fd08fe667 chore: Add overeager flag to all Claude 3.7 Sonnet model configurations 2025-03-22 08:20:53 -07:00
Paul Gauthier
0da65c6169 chore: Add overeager flag to anthropic/claude-3-7-sonnet-20250219 model settings 2025-03-22 08:20:51 -07:00
Paul Gauthier (aider)
d2c6db0680 style: Replace single quotes with double quotes in base_coder.py 2025-03-22 08:16:14 -07:00
Paul Gauthier (aider)
5b73938e29 refactor: improve model prompt selection logic in fmt_system_prompt 2025-03-22 08:16:07 -07:00
Paul Gauthier
2540933921 refactor: Simplify lazy_prompt assignment in fmt_system_prompt 2025-03-22 08:16:06 -07:00
Paul Gauthier
e75e2272f7 initial 2025-03-22 08:09:26 -07:00
Paul Gauthier
64b8fc80e8 refactor: Extract prompt prefix logic in InputOutput class 2025-03-21 20:40:29 -07:00
Paul Gauthier (aider)
033c149737 style: Break long comment line to comply with flake8 E501 2025-03-21 20:25:14 -07:00
Paul Gauthier
a6bce6d5f1 refactor: Change multiline input prompt from ". " to "> " 2025-03-21 20:25:04 -07:00
Paul Gauthier
94016c87fd refactor: Simplify asciinema command in tmux_record.sh 2025-03-21 20:19:08 -07:00
Paul Gauthier (aider)
4b6424f631 style: Format code with consistent spacing and indentation 2025-03-21 15:24:26 -07:00
Paul Gauthier (aider)
9bf70d8641 refactor: Enhance git blame detection with specific similarity thresholds 2025-03-21 15:24:22 -07:00
Paul Gauthier (aider)
0eb26fffe1 style: Improve typography with scale, spacing, and mobile optimizations 2025-03-21 13:56:07 -07:00
Paul Gauthier
279e7e1456 style: Adjust hero h1 font size to 2.5rem 2025-03-21 13:56:05 -07:00
Paul Gauthier (aider)
099fc7b31e style: Improve typography with better font stack, spacing, and hierarchy 2025-03-21 13:50:02 -07:00
Paul Gauthier (aider)
f1e070cc1e style: Format description text inline with title links 2025-03-21 13:30:39 -07:00
Paul Gauthier (aider)
36f2458f2e feat: Add page descriptions to table of contents with inline styling 2025-03-21 13:29:22 -07:00
Paul Gauthier
29db4231ee copy 2025-03-21 13:27:02 -07:00
Paul Gauthier (aider)
74926578a2 chore: Exclude homepage from main navigation 2025-03-21 13:21:32 -07:00
Paul Gauthier
5b8ae368bd docs: Remove redundant sections from index.md 2025-03-21 13:21:31 -07:00
Paul Gauthier (aider)
b3e368237e fix: Simplify table of contents Liquid syntax to avoid errors 2025-03-21 13:18:23 -07:00
Paul Gauthier (aider)
3ee5dc131d feat: Add hierarchical table of contents to documentation homepage 2025-03-21 13:17:34 -07:00
Paul Gauthier
2765d2fe66 docs: Add initial website documentation index 2025-03-21 13:10:59 -07:00
Paul Gauthier
f50fee407a copy 2025-03-21 12:13:32 -07:00
Paul Gauthier (aider)
f3295d7c1d style: Swap badge colors for Tokens/week and Singularity metrics 2025-03-21 12:12:54 -07:00
Paul Gauthier (aider)
dd02803f1f style: Swap colors of tokens/week and singularity badges 2025-03-21 12:12:29 -07:00
Paul Gauthier
d4e44d7555 copy 2025-03-21 12:09:59 -07:00
Paul Gauthier
f2b8d36d9e set version to 0.78.1.dev 2025-03-21 11:57:37 -07:00
Paul Gauthier
8d43d4ee21 version bump to 0.78.0 2025-03-21 11:57:34 -07:00
Paul Gauthier
b54af5dbe3 copy 2025-03-21 11:55:23 -07:00
Paul Gauthier (aider)
4980e901a0 feat: Add plain git log to update-history script context 2025-03-21 11:38:46 -07:00
Paul Gauthier
cd32311c1f copy 2025-03-21 11:37:49 -07:00
Paul Gauthier (aider)
b97997b009 fix: Remove unused imports in badges.py 2025-03-21 11:36:43 -07:00
Paul Gauthier (aider)
4aad9fbdd4 style: Format code with linter 2025-03-21 11:36:28 -07:00
Paul Gauthier (aider)
ac2439e25b feat: add 24-hour cache for BigQuery download stats 2025-03-21 11:36:24 -07:00
Paul Gauthier (aider)
ddc1556ae0 style: Reformat code to comply with linter rules 2025-03-21 11:25:13 -07:00
Paul Gauthier (aider)
0d75c4d0e3 test: add exponential backoff retry for help command test 2025-03-21 11:25:10 -07:00
Paul Gauthier
f3a042dcdf refactor: Simplify exception handling in platform info retrieval 2025-03-21 11:24:10 -07:00
Paul Gauthier (aider)
f9e0a99064 style: Remove trailing whitespace in base_coder.py 2025-03-21 11:23:57 -07:00
Paul Gauthier (aider)
d6906fb100 fix: Handle KeyError in platform info retrieval with clear message 2025-03-21 11:23:50 -07:00
Paul Gauthier (aider)
821662abcb style: Remove trailing whitespace in base_coder.py 2025-03-21 11:22:00 -07:00
Paul Gauthier (aider)
cf496abec0 fix: Handle platform info retrieval errors gracefully 2025-03-21 11:21:53 -07:00
Paul Gauthier
e245d39216 copy 2025-03-21 11:18:42 -07:00
paul-gauthier
44f87c2c17 Merge pull request #3553 from lentil32/main
fix: Redundant warning when `AWS_PROFILE` set for Bedrock
2025-03-21 11:16:27 -07:00
Paul Gauthier
a6fd0de762 copy 2025-03-21 11:16:10 -07:00
Carles Sala (aider)
072ecba4c5 feat: Add commands to switch main, editor, and weak models 2025-03-21 11:09:33 -07:00
Paul Gauthier (aider)
3ad5d75bee refactor: Remove unused variable in test_main.py 2025-03-21 11:05:35 -07:00
Paul Gauthier (aider)
8679c425e0 style: Remove trailing whitespace in test_main.py 2025-03-21 11:04:58 -07:00
Paul Gauthier (aider)
1ec257278e refactor: Move resolve_aiderignore_path to top level and add tests 2025-03-21 11:04:51 -07:00
paul-gauthier
ffe89362ab Merge pull request #3478 from mopemope/fix-ignore
refactor: enhance --aiderignore argument to resolve absolute and relative paths
2025-03-21 11:02:04 -07:00
paul-gauthier
a82c0f9e49 Merge pull request #3485 from codefromthecrypt/patch-1
ollama: suggest higher minimum context length
2025-03-21 09:36:06 -07:00
Paul Gauthier
413271e82a copy 2025-03-21 09:23:45 -07:00
Paul Gauthier (aider)
60b926b698 refactor: Remove redundant imports in completions methods 2025-03-21 09:21:59 -07:00
Paul Gauthier (aider)
98be67442e chore: Run linter and fix import order in commands.py 2025-03-21 09:21:01 -07:00
Paul Gauthier (aider)
8e9c75b6f8 chore: Add CommandCompletionException import to commands.py 2025-03-21 09:20:54 -07:00
Paul Gauthier (aider)
8c65604b29 style: Format docstring and multiline condition for better readability 2025-03-21 09:20:22 -07:00
Paul Gauthier (aider)
930923c211 style: Format code to comply with linter rules 2025-03-21 09:19:34 -07:00
Paul Gauthier (aider)
710d540dcd feat: Add CommandCompletionException class for autocompletion handling 2025-03-21 09:19:29 -07:00
Paul Gauthier (aider)
ddef8c2499 refactor: Add CommandCompletionException for autocompletion handling 2025-03-21 09:19:13 -07:00
Paul Gauthier
c6289c2bea refactor: Add comment for command completion handling in AutoCompleter 2025-03-21 09:19:12 -07:00
Paul Gauthier (aider)
b624bb6fb8 refactor: raise exceptions to use normal autocompleter 2025-03-21 09:18:22 -07:00
Paul Gauthier (aider)
4e03f4165d feat: Add autocompletion for /ask, /code and /architect commands 2025-03-21 09:16:26 -07:00
paul-gauthier
2f6ea2f499 Merge pull request #3579 from marcomayer/main
feat: vi-like behavior when pressing enter in multiline-mode
2025-03-21 09:06:52 -07:00
Paul Gauthier
8c47d1f9c0 copy 2025-03-21 09:03:48 -07:00
Paul Gauthier (aider)
e31be8d3c9 feat: Print source used in get_total_downloads function 2025-03-21 09:01:50 -07:00
Paul Gauthier
2069ad62d1 refactor: Remove badges markdown generation from main function 2025-03-21 09:01:48 -07:00
Paul Gauthier (aider)
2993e285c8 style: Format code in badges.py for better readability 2025-03-21 08:58:10 -07:00
Paul Gauthier (aider)
4ee9cee52a refactor: extract credentials_path from USE_BIGQUERY environment variable 2025-03-21 08:58:04 -07:00
Paul Gauthier (aider)
0e555699bd feat: exclude CI downloads from PyPI download count 2025-03-21 08:53:59 -07:00
Paul Gauthier (aider)
aad6c63206 style: Format code according to linter rules 2025-03-21 08:52:04 -07:00
Paul Gauthier (aider)
8c78e09f03 feat: Add BigQuery support for fetching PyPI download statistics 2025-03-21 08:52:00 -07:00
Paul Gauthier (aider)
25d1eac0f5 docs: Add Ctrl-Y keybinding to Emacs commands documentation 2025-03-21 08:48:28 -07:00
Paul Gauthier
26daf2cd31 copy 2025-03-21 07:38:48 -07:00
Paul Gauthier
280bd44ba3 copy 2025-03-21 07:33:00 -07:00
Paul Gauthier
c9d87fef71 copy 2025-03-21 07:31:00 -07:00
Paul Gauthier (aider)
649742f02a style: Format code according to linter rules 2025-03-21 07:27:57 -07:00
Paul Gauthier (aider)
245ee84c2d feat: Add OpenRouter support to set_thinking_tokens method 2025-03-21 07:27:52 -07:00
Paul Gauthier
76c09205d0 copy 2025-03-20 19:10:59 -07:00
Paul Gauthier
d365b5248c copy 2025-03-20 19:08:21 -07:00
Paul Gauthier
3dd91bc6f2 copy 2025-03-20 15:29:47 -07:00
Paul Gauthier (aider)
3dc5a48fcc fix: Handle newline in git commit message assertion 2025-03-20 15:23:41 -07:00
Paul Gauthier (aider)
bff077f855 style: Remove trailing whitespace in test_repo.py 2025-03-20 15:23:20 -07:00
Paul Gauthier (aider)
6022b09437 fix: Move pre-commit hook creation after initial commit in test 2025-03-20 15:23:15 -07:00
Paul Gauthier (aider)
62b52a78fe style: Remove trailing whitespace in test_repo.py 2025-03-20 15:22:07 -07:00
Paul Gauthier (aider)
e33dc9355d test: Add test for --git-commit-verify option 2025-03-20 15:22:03 -07:00
Paul Gauthier
834da07736 copy 2025-03-20 15:14:08 -07:00
Paul Gauthier (aider)
fe795cc2d5 chore: Change default git commit verify flag to False 2025-03-20 15:08:44 -07:00
Paul Gauthier (aider)
593de47438 docs: Add --no-git-commit-verify flag documentation 2025-03-20 15:07:51 -07:00
Paul Gauthier (aider)
ac231e43ad feat: Add --git-commit-verify flag to control git hook verification 2025-03-20 15:06:44 -07:00
Paul Gauthier
aca64071c8 copy 2025-03-20 14:31:03 -07:00
Paul Gauthier (aider)
5c205cd753 fix: use rounding instead of truncation for star counts 2025-03-20 14:29:57 -07:00
Paul Gauthier (aider)
57ce2c48b8 fix: round GitHub stars to whole numbers in HTML output 2025-03-20 14:28:58 -07:00
Paul Gauthier
0937b34983 chore: Update badges and stats in README and website 2025-03-20 14:25:24 -07:00
Paul Gauthier (aider)
291c4eb258 style: Remove trailing whitespace and standardize string quotes 2025-03-20 14:23:07 -07:00
Paul Gauthier (aider)
a8744708a0 feat: Add HTML-formatted badges generation function 2025-03-20 14:23:02 -07:00
Paul Gauthier (aider)
3010b94a64 refactor: move tooltip text to global constants 2025-03-20 14:21:35 -07:00
Paul Gauthier (aider)
9c4d173b1f style: Add whitespace around arithmetic operators in format_number 2025-03-20 14:20:45 -07:00
Paul Gauthier (aider)
cca155c5c6 refactor: Move tokens/week value to global constant TOKENS_PER_WEEK 2025-03-20 14:20:09 -07:00
Paul Gauthier (aider)
a93e7108e6 style: Format code with linter 2025-03-20 14:18:50 -07:00
Paul Gauthier (aider)
d26df6c178 feat: add get_badges_md() function to generate badges markdown 2025-03-20 14:18:41 -07:00
Paul Gauthier
e915964d81 style: Add noqa comment to badges.py for flake8 compliance 2025-03-20 14:18:36 -07:00
Paul Gauthier (aider)
1304ca2425 style: Remove trailing whitespace in badges.py 2025-03-20 14:15:14 -07:00
Paul Gauthier (aider)
894f6b6d1d feat: Add function to generate markdown badges with formatted stats 2025-03-20 14:15:08 -07:00
Paul Gauthier (aider)
6605a9b22a style: Remove trailing whitespace in badges.py 2025-03-20 14:12:34 -07:00
Paul Gauthier (aider)
b5d963d151 fix: properly identify latest release by parsing version numbers 2025-03-20 14:12:31 -07:00
Paul Gauthier (aider)
8f840ae0b1 refactor: Rename function and emphasize LATEST release in output 2025-03-20 14:11:08 -07:00
Paul Gauthier (aider)
7942ca9206 style: Format code and fix import order in badges.py 2025-03-20 14:10:43 -07:00
Paul Gauthier (aider)
a5614bfe40 feat: Add Aider contribution percentage to badges script 2025-03-20 14:10:39 -07:00
Paul Gauthier (aider)
eaac00ad3f style: Format code according to linter rules 2025-03-20 14:07:58 -07:00
Paul Gauthier (aider)
6687cc9465 feat: Add GitHub stars fetching to badges script 2025-03-20 14:07:52 -07:00
Paul Gauthier (aider)
5b9464ed31 style: Format code with linter in badges.py 2025-03-20 14:06:20 -07:00
Paul Gauthier (aider)
4c7d99b26c feat: Add .env support for PEPY_API_KEY in badges script 2025-03-20 14:06:16 -07:00
Paul Gauthier
5bf248164a chore: Make badges.py executable 2025-03-20 14:06:15 -07:00
Paul Gauthier (aider)
4eeae967db chore: Remove unused json import in badges.py 2025-03-20 14:05:38 -07:00
Paul Gauthier (aider)
0ac2a85a3e style: Reformat code and fix import order in badges.py 2025-03-20 14:05:26 -07:00
Paul Gauthier (aider)
71884e58d4 feat: Add script to fetch total downloads from pepy.tech API 2025-03-20 14:05:22 -07:00
Paul Gauthier
37b2f9617c feat: Add badges generation script 2025-03-20 14:05:21 -07:00
Paul Gauthier (aider)
01af14693c chore: Add Jekyll front matter to index.html for templating support 2025-03-20 13:50:37 -07:00
Paul Gauthier
90e2929fc5 copy 2025-03-20 13:47:13 -07:00
Paul Gauthier (aider)
8f260aa544 docs: Add tooltips to README badges 2025-03-20 13:44:34 -07:00
Paul Gauthier (aider)
ee72a09278 feat: Add tooltips to explain stats badges 2025-03-20 13:43:16 -07:00
Paul Gauthier
e6a422b6c2 copy 2025-03-20 11:45:50 -07:00
Paul Gauthier
d29aff919b copy 2025-03-20 11:20:01 -07:00
Paul Gauthier (aider)
5023bbe8c0 style: Fix lint issues by removing unused import and adding whitespace 2025-03-20 11:09:15 -07:00
Paul Gauthier
c08e3daf29 slim down logo svg 2025-03-20 11:08:31 -07:00
Paul Gauthier (aider)
9cf194b52b style: Format code with consistent spacing and line breaks 2025-03-20 11:07:55 -07:00
Paul Gauthier (aider)
1b0ba71ef0 refactor: Subset font to include only needed characters in SVG logo 2025-03-20 11:07:51 -07:00
Paul Gauthier
de5ab102b7 refactor: Update internal links to use relative paths 2025-03-20 11:04:16 -07:00
Paul Gauthier
4e2c7c3329 copy 2025-03-20 09:28:44 -07:00
Paul Gauthier (aider)
b62840c347 feat: Add SVG logo with progressive enhancement to Jekyll pages 2025-03-20 08:11:48 -07:00
Paul Gauthier
674379fe30 blame includes home page 2025-03-20 08:09:56 -07:00
Paul Gauthier
004ffb9f60 copy 2025-03-20 08:07:56 -07:00
Paul Gauthier (aider)
bed836b15a feat: Add progressive enhancement for SVG logo in header 2025-03-20 08:06:28 -07:00
Paul Gauthier
bbf219ecd2 refactor: Adjust Gaussian blur stdDeviation in SVG filter 2025-03-20 08:00:30 -07:00
Paul Gauthier (aider)
022bf4bdcc feat: Make SVG logo blur effect more transparent 2025-03-20 07:57:40 -07:00
Paul Gauthier
d8ed90a2c0 refactor: Adjust SVG glow filter parameters in logo_svg.py 2025-03-20 07:56:44 -07:00
Paul Gauthier (aider)
e5d9d91b01 style: Extend horizontal glow effect in logo SVG filter 2025-03-20 07:54:45 -07:00
Paul Gauthier (aider)
c8f6576cd7 feat: Add glow effect to SVG logo using Gaussian blur filter 2025-03-20 07:54:02 -07:00
Paul Gauthier
14f140fdc5 copy 2025-03-19 21:56:42 -07:00
Paul Gauthier (aider)
fdbe169423 refactor: Make SVG logo background transparent instead of white 2025-03-19 21:56:21 -07:00
Paul Gauthier (aider)
e4ec370e2a feat: Add bash syntax highlighting to code block using Prism.js 2025-03-19 21:54:34 -07:00
Paul Gauthier
dfbdb43c31 copy 2025-03-19 21:48:16 -07:00
Paul Gauthier (aider)
9b8606535d style: Vertically center text in SVG logo 2025-03-19 21:46:25 -07:00
Paul Gauthier (aider)
0b79fd0a8e style: Center text horizontally in SVG logo 2025-03-19 21:45:58 -07:00
Paul Gauthier
f032606f32 style: Change background color to black in SVG logo 2025-03-19 21:45:56 -07:00
Paul Gauthier
b652a8416d copy 2025-03-19 21:43:33 -07:00
Paul Gauthier
8f7b50f3df copy 2025-03-19 21:43:09 -07:00
Paul Gauthier
2adafad4e2 copy 2025-03-19 21:42:39 -07:00
Paul Gauthier (aider)
99a5862bc9 chore: Remove unused Path import from logo_svg.py 2025-03-19 21:40:48 -07:00
Paul Gauthier
6dda54f431 chore: Remove unused .logo-svg CSS class and add new logo SVG file 2025-03-19 21:40:37 -07:00
Paul Gauthier (aider)
8e187a913f docs: Add Aider logo to README.md 2025-03-19 21:38:48 -07:00
Paul Gauthier (aider)
8935c87d7a style: Format code with consistent quotes and line breaks 2025-03-19 21:36:20 -07:00
Paul Gauthier (aider)
c6e544750b feat: Add script to generate SVG logo with embedded font 2025-03-19 21:36:15 -07:00
Paul Gauthier
c14d406f59 feat: Add script for generating logo in SVG format 2025-03-19 21:36:14 -07:00
Paul Gauthier
4edfe39449 copy 2025-03-19 21:28:44 -07:00
Paul Gauthier (aider)
1239d77c88 docs: Add icons to feature list in README 2025-03-19 21:28:33 -07:00
Paul Gauthier
7d4b0b20e8 copy 2025-03-19 21:26:07 -07:00
Paul Gauthier
1f42cdd762 copy 2025-03-19 21:24:37 -07:00
Paul Gauthier (aider)
f182b81e0f docs: Add feature documentation links to README 2025-03-19 21:22:52 -07:00
Paul Gauthier
3f2256d4c4 rename 2025-03-19 21:21:29 -07:00
Paul Gauthier (aider)
e4b1b12b26 docs: Update README with polished content from index.html 2025-03-19 21:19:22 -07:00
Paul Gauthier
35477e0a5a docs: Add README.new.md 2025-03-19 21:19:21 -07:00
Paul Gauthier
f752c9c8a9 copy 2025-03-19 21:16:17 -07:00
Paul Gauthier (aider)
d5dd7b0a96 chore: Update badge text from "Codes Itself" to "Singularity" in README.md 2025-03-19 21:16:12 -07:00
Paul Gauthier
4e16eba6b0 docs: Update copy/paste feature description and button labels 2025-03-19 21:16:06 -07:00
Paul Gauthier (aider)
4f129e1c9d feat: Add feature cards for voice-to-code, linting/testing, and copy/paste 2025-03-19 21:06:04 -07:00
Paul Gauthier
ffbbb5539d docs: Update supported languages and API key placeholders in index.html 2025-03-19 21:06:03 -07:00
Paul Gauthier (aider)
30e5b48461 feat: Add CTA section to homepage with install and docs buttons 2025-03-19 20:45:37 -07:00
Paul Gauthier
0dc31011f5 chore: Update website text and remove redundant content 2025-03-19 20:45:35 -07:00
Paul Gauthier
479df00a3b chore: Update badge label from "Codes Itself" to "Inception" 2025-03-19 20:38:12 -07:00
Paul Gauthier (aider)
06f3e15ce9 style: Reduce vertical space between video and badges on mobile 2025-03-19 20:35:01 -07:00
Paul Gauthier
2f7fde163a docs: Update website copy for clarity and consistency 2025-03-19 20:33:06 -07:00
Paul Gauthier (aider)
71d26c2ec5 style: Reduce hero section padding on mobile devices 2025-03-19 20:32:18 -07:00
Paul Gauthier
acf8b40a28 copy 2025-03-19 18:07:56 -07:00
Paul Gauthier (aider)
318027d9e1 docs: Add icons to README badges 2025-03-19 17:49:30 -07:00
Paul Gauthier (aider)
3116e833a7 docs: Add "Codes Itself" badge to README 2025-03-19 17:46:39 -07:00
Paul Gauthier (aider)
1cb71b33fa feat: Rename "Self-Coded" badge to "Codes Itself" and link to HISTORY.html 2025-03-19 17:45:47 -07:00
Paul Gauthier (aider)
7e76b8d0c3 style: Replace self-coded icon with brain and increase stats container width 2025-03-19 17:44:51 -07:00
Paul Gauthier (aider)
e0e78cd879 feat: Add "Self-Coded: 72%" badge to stats section 2025-03-19 17:43:01 -07:00
Paul Gauthier
82e4dcf40f copy 2025-03-19 17:07:31 -07:00
Paul Gauthier
22b77ad14f copy 2025-03-19 17:04:30 -07:00
Paul Gauthier
9b23975f09 copy 2025-03-19 17:00:07 -07:00
Paul Gauthier (aider)
584c3a65f5 docs: Add FAQ link to More Info resources 2025-03-19 16:58:42 -07:00
Paul Gauthier
db4d6c4419 docs: Update feature titles and descriptions on website 2025-03-19 16:58:40 -07:00
Paul Gauthier
92cb1c60d1 copy 2025-03-19 16:05:34 -07:00
Paul Gauthier (aider)
ca72d0ca5b style: Standardize feature card title capitalization 2025-03-19 14:24:31 -07:00
Paul Gauthier (aider)
ba7f245d88 fix: Center hero content horizontally on narrow screens 2025-03-19 14:17:57 -07:00
Marco Mayer
ef67ba5cf4 feat: vi-like behavior when pressing enter in multiline-mode while in vi normal/navigation-mode 2025-03-19 22:11:26 +01:00
Paul Gauthier (aider)
1f630a03b9 style: Update feature cards with blue underline instead of shaded header 2025-03-19 14:09:21 -07:00
Paul Gauthier (aider)
5f71cdc497 style: Remove blue vertical line from hero content 2025-03-19 14:08:32 -07:00
Paul Gauthier (aider)
b85226b8a5 style: Adjust hero section alignment, spacing, and visual hierarchy 2025-03-19 14:07:43 -07:00
Paul Gauthier (aider)
af4acccf9f style: Update video container background to match gradient better 2025-03-19 14:03:24 -07:00
Paul Gauthier (aider)
3a3bc9898d fix: maintain video aspect ratio using padding-bottom technique 2025-03-19 13:59:06 -07:00
Paul Gauthier (aider)
5349c99c74 fix: Add aspect-ratio to video container and preload metadata 2025-03-19 13:55:50 -07:00
Paul Gauthier
68d175f1c5 style: Update section title capitalization in index.html 2025-03-19 13:55:48 -07:00
Paul Gauthier
352f1f31d2 copy 2025-03-19 13:49:20 -07:00
Paul Gauthier (aider)
c51ef714ad style: Remove whitespace around badge <img> tags in README.md 2025-03-19 13:49:12 -07:00
Paul Gauthier
5ae68a3c48 docs: Update README.md with clearer project description 2025-03-19 13:49:11 -07:00
Paul Gauthier
d2c7e51fac copy 2025-03-19 13:47:16 -07:00
Paul Gauthier (aider)
d9aa3fb973 style: Increase top margin of stats-container to 50px 2025-03-19 13:44:43 -07:00
Paul Gauthier
e1b79ddd69 style: Adjust hero h1 font size to 2.5rem 2025-03-19 13:43:30 -07:00
Paul Gauthier (aider)
3270a8737c refactor: Move stats-container below hero-grid in HTML layout 2025-03-19 13:42:58 -07:00
Paul Gauthier
cbe8d320fa style: Update hero heading to lowercase in website index.html 2025-03-19 13:42:57 -07:00
Paul Gauthier (aider)
78ce63e71e refactor: Move hero heading into 40% split container 2025-03-19 13:38:53 -07:00
Paul Gauthier (aider)
1bb396bea5 feat: implement two-column layout for More Information section 2025-03-19 13:37:13 -07:00
Paul Gauthier (aider)
16304beeab style: Keep buttons side-by-side on narrow screens with responsive CSS 2025-03-19 13:34:28 -07:00
Paul Gauthier
d2cfd541ed margin 2025-03-19 13:31:54 -07:00
Paul Gauthier
8b1aaf690c gradient 2025-03-19 13:31:00 -07:00
Paul Gauthier
f1ca8f594c style: Adjust gradient colors in testimonial-card 2025-03-19 13:26:59 -07:00
Paul Gauthier (aider)
78d2e0aa25 style: Reduce mobile nav bar height and adjust logo size 2025-03-19 13:08:07 -07:00
Paul Gauthier
4a3d239082 copy 2025-03-19 12:47:22 -07:00
Paul Gauthier
94eaee8d39 copy 2025-03-19 12:46:28 -07:00
Paul Gauthier (aider)
471f03ab4f style: Reduce feature card padding on mobile devices 2025-03-19 12:45:18 -07:00
Paul Gauthier
9df9af822c style: Adjust code block font size in home.css 2025-03-19 12:45:16 -07:00
Paul Gauthier (aider)
7b49623b31 style: Reduce font sizes for mobile responsiveness 2025-03-19 12:41:25 -07:00
Paul Gauthier
12bda2b8d0 copy 2025-03-19 12:37:59 -07:00
Paul Gauthier
2022f214aa Merge branch 'home' 2025-03-19 12:37:42 -07:00
Paul Gauthier (aider)
786738ba81 refactor: Move CSS styles to separate home.css file 2025-03-19 12:36:02 -07:00
Paul Gauthier
e4f1b59475 feat: Add home.css for website assets 2025-03-19 12:33:55 -07:00
Paul Gauthier
7cb302f571 move home to / 2025-03-19 12:32:54 -07:00
Paul Gauthier
8bae91cf6e initial 2025-03-19 12:30:30 -07:00
Paul Gauthier
44a145fc86 copy 2025-03-19 12:30:21 -07:00
Paul Gauthier
a1fa62adef copy 2025-03-19 12:28:51 -07:00
Paul Gauthier (aider)
fe247a8f6a style: Lighten sidebar gradient color in head_custom.html 2025-03-19 12:24:46 -07:00
Paul Gauthier (aider)
54e70eff13 style: Lighten sidebar gradient color in head_custom.html 2025-03-19 12:23:45 -07:00
Paul Gauthier (aider)
5453f4a85d style: Update sidebar gradient end color to #F5F6FA 2025-03-19 12:19:22 -07:00
Paul Gauthier (aider)
f2654390e7 style: Add gradient to sidebar matching hero section 2025-03-19 12:18:03 -07:00
Paul Gauthier
777903f7da copy 2025-03-19 12:14:29 -07:00
Paul Gauthier (aider)
2f7892561f style: update .site-title font to match "aider" logo styling 2025-03-19 12:13:36 -07:00
Paul Gauthier (aider)
6d79000d6c style: Add custom CSS for .site-title in head_custom.html 2025-03-19 12:11:20 -07:00
Paul Gauthier (aider)
284911cd6b style: Increase font size in Getting Started section for better readability 2025-03-19 12:04:46 -07:00
Paul Gauthier
70b6da108c docs: Update testimonials section title in home.html 2025-03-19 12:04:45 -07:00
Paul Gauthier (aider)
6de3b2b262 style: Adjust testimonial card gradient to use more blue with hint of green 2025-03-19 12:03:45 -07:00
Paul Gauthier (aider)
e7554c5413 refactor: Remove quotes from testimonial text in home.html 2025-03-19 11:59:34 -07:00
Paul Gauthier (aider)
2facd2ab16 style: Add fancy typographic quotes to testimonials using CSS 2025-03-19 11:59:19 -07:00
Paul Gauthier (aider)
20ba252c56 feat: Add gradient backgrounds to testimonial cards 2025-03-19 11:58:15 -07:00
Paul Gauthier (aider)
eba123e381 style: Update hero gradient to incorporate blue palette and green logo color 2025-03-19 11:45:59 -07:00
Paul Gauthier (aider)
3bb57af331 style: Darken main "aider" logo font color 2025-03-19 11:44:02 -07:00
Paul Gauthier
aeb991fdf3 chore: Update logo text to lowercase in home.html 2025-03-19 11:44:00 -07:00
Paul Gauthier
75a14380ef refactor: Update font path in home.html to use assets directory 2025-03-19 11:42:55 -07:00
Paul Gauthier (aider)
0aeecf4d9a style: Update "Aider" logo to use terminal font and green color 2025-03-19 11:39:18 -07:00
Paul Gauthier (aider)
447347c760 style: Enhance hero section background with richer gradient and effects 2025-03-19 11:36:43 -07:00
Paul Gauthier
79619de045 docs: Update language support description in home.html 2025-03-19 11:36:42 -07:00
Paul Gauthier (aider)
1af423e2df style: Adjust hero section layout and background for better visual emphasis 2025-03-19 11:27:41 -07:00
Paul Gauthier
92fcf9a159 badges in main readme 2025-03-19 11:23:33 -07:00
Paul Gauthier (aider)
d1b1cc5c14 docs: Add stats badges to README.md 2025-03-19 11:19:17 -07:00
Paul Gauthier (aider)
b9514ad82a style: Update language support icon to use styled "</>" 2025-03-19 11:15:35 -07:00
Paul Gauthier (aider)
7b3411b236 docs: Update feature card to highlight language support 2025-03-19 11:13:23 -07:00
Paul Gauthier (aider)
915e87e88e feat: Make feature cards fully clickable with external links 2025-03-19 11:12:08 -07:00
Paul Gauthier (aider)
face505f0d style: Enhance feature card visual hierarchy with borders and spacing 2025-03-19 11:10:27 -07:00
Paul Gauthier
dada307e79 refactor: Simplify feature titles in home.html 2025-03-19 11:10:26 -07:00
Paul Gauthier (aider)
5124c512c9 style: Replace header border with shaded background in feature cards 2025-03-19 11:08:36 -07:00
Paul Gauthier (aider)
89f579c1ba refactor: add card header with icon and title for better visual integration 2025-03-19 11:07:49 -07:00
Paul Gauthier (aider)
0035f28035 chore: Update Git integration icon from 🔄 to 🔀 2025-03-19 11:02:42 -07:00
Paul Gauthier
4d556d9235 chore: Update token statistics label and value in home.html 2025-03-19 11:02:41 -07:00
Paul Gauthier (aider)
dd5ef29355 refactor: Reorder feature cards with LLM, Map, Multifile in first row 2025-03-19 10:59:51 -07:00
Paul Gauthier
ca9922ef0a refactor: Simplify paragraph in home.html 2025-03-19 10:59:50 -07:00
Paul Gauthier (aider)
b674a0a5e8 feat: Replace Voice Coding card with LLM compatibility card using brain icon 2025-03-19 10:57:49 -07:00
Paul Gauthier (aider)
541d0e6f5c docs: Add installation and usage links to home page paragraph 2025-03-19 10:56:29 -07:00
Paul Gauthier (aider)
fc96e980fb docs: Add link to LLM connection documentation in home page 2025-03-19 10:55:42 -07:00
Paul Gauthier
1425e3e6c7 chore: Update documentation links to point to install.html 2025-03-19 10:54:52 -07:00
Paul Gauthier (aider)
b9d3c11032 chore: Update documentation links to point to /docs/usage.html 2025-03-19 10:52:21 -07:00
Paul Gauthier
81b65e0de3 refactor: Remove "Top Tier Performance" section from home.html 2025-03-19 10:52:20 -07:00
Paul Gauthier
0f80f6af27 copy 2025-03-19 10:48:40 -07:00
Paul Gauthier (aider)
5eedf98aae refactor: Restructure hero section layout with full-width title and badges 2025-03-19 10:33:34 -07:00
Paul Gauthier (aider)
8f45a2ef3d style: Update responsive layout for mobile devices in home.html 2025-03-19 10:31:36 -07:00
Paul Gauthier (aider)
9d51d4a572 refactor: Reorganize hero section into two-column layout 2025-03-19 10:31:22 -07:00
Paul Gauthier (aider)
9978c8ea48 refactor: Replace link with div for Token Processed badge 2025-03-19 10:29:00 -07:00
Paul Gauthier
e779358429 chore: Update token badge label and value in home.html 2025-03-19 10:28:59 -07:00
Paul Gauthier (aider)
8d663cc3d6 style: restyle stats section to use GitHub badges format 2025-03-19 10:23:55 -07:00
Paul Gauthier (aider)
a98ca30438 fix: prevent recently removed testimonials from immediate reuse 2025-03-19 10:16:44 -07:00
Paul Gauthier (aider)
589cb2ac79 feat: prevent consecutive flips of the same testimonial card 2025-03-19 10:14:59 -07:00
Paul Gauthier (aider)
d973be8fea feat: Add 3D card flip animation to testimonials 2025-03-19 10:14:11 -07:00
Paul Gauthier (aider)
41c3b59755 refactor: change testimonial rotation to random selection 2025-03-19 10:12:51 -07:00
Paul Gauthier (aider)
8bf168da47 feat: Update testimonials to rotate one at a time with fade animation 2025-03-19 10:11:30 -07:00
Paul Gauthier
0d85c06be2 refactor: Adjust testimonial rotation interval in home.html 2025-03-19 10:11:26 -07:00
Paul Gauthier (aider)
fadede7305 feat: Add dynamic rotating testimonials with user links 2025-03-19 10:09:21 -07:00
Paul Gauthier
a24d31fbba docs: Update feature title in home.html to "Map Of Your Code" 2025-03-19 10:09:08 -07:00
Paul Gauthier (aider)
c9d463443a style: Update IDE feature card icon to desktop emoji 2025-03-19 10:03:51 -07:00
Paul Gauthier (aider)
0e3d486658 docs: Update feature card to highlight IDE integration 2025-03-19 10:02:24 -07:00
Paul Gauthier (aider)
574ab6bdda feat: Add links to feature descriptions in home.html 2025-03-19 09:29:47 -07:00
Paul Gauthier
a172d15463 refactor: Update stats section in home.html with new icons and labels 2025-03-19 09:29:45 -07:00
Paul Gauthier (aider)
a1362b946a style: Enhance stats section with modern cards and hover effects 2025-03-19 09:04:05 -07:00
Paul Gauthier (aider)
6ecb4c5ece feat: Add stats section to home page 2025-03-19 09:02:36 -07:00
Paul Gauthier
63c1320f36 feat: Add initial home.html for Aider website 2025-03-19 09:02:34 -07:00
Paul Gauthier
bf484ce4c4 chore: Remove home.html file 2025-03-19 08:59:59 -07:00
Paul Gauthier
1700212f30 copy 2025-03-19 08:54:22 -07:00
Paul Gauthier
751ca3bf75 copy 2025-03-19 08:22:46 -07:00
Paul Gauthier (aider)
01be8bc64e style: Make macos-backdrop padding responsive using clamp() 2025-03-19 08:20:07 -07:00
Paul Gauthier
a9e8005b14 style: Adjust padding comment in macos-backdrop CSS class 2025-03-19 08:20:05 -07:00
Paul Gauthier (aider)
871cff6232 feat: Add stylish HTML landing page for Aider 2025-03-19 08:16:25 -07:00
Paul Gauthier
1de8f5ceda feat: Add home.html for website 2025-03-19 08:16:21 -07:00
Paul Gauthier
dd4d2420df copy 2025-03-18 19:07:03 -07:00
Paul Gauthier (aider)
e9b1a98314 fix: Adjust z-index and opacity for backdrop decorative lines 2025-03-18 19:00:24 -07:00
Paul Gauthier (aider)
f0f48e8e30 fix: Ensure decorative lines only appear in backdrop, not terminal area 2025-03-18 18:59:29 -07:00
Paul Gauthier (aider)
89b008e1eb style: Add decorative curved lines to macos-backdrop background 2025-03-18 18:58:05 -07:00
Paul Gauthier (aider)
fb3f8439e2 style: Increase top/bottom padding of .macos-backdrop by 50% 2025-03-18 18:57:30 -07:00
Paul Gauthier (aider)
f0e66d2bfb feat: Add macOS-like colorful backdrop to terminal display 2025-03-18 18:53:11 -07:00
Paul Gauthier
65ec254c1b copy 2025-03-18 18:42:23 -07:00
Paul Gauthier
47c0d95bd4 refactor: Add missing --read flag in update-history.py 2025-03-18 18:26:08 -07:00
Paul Gauthier
55d7bed563 copy 2025-03-18 18:25:57 -07:00
Paul Gauthier (aider)
9a4f3b8d8e style: Format code and add whitespace for readability 2025-03-18 18:23:45 -07:00
Paul Gauthier (aider)
d9c5ce15f3 refactor: Separate git log and diff in update-history script 2025-03-18 18:23:42 -07:00
Paul Gauthier (aider)
292908288b chore: Remove unused import of __version__ from aider 2025-03-18 18:18:51 -07:00
Paul Gauthier (aider)
7fec2661fc style: Standardize string quotes in update-history.py 2025-03-18 18:18:39 -07:00
Paul Gauthier (aider)
0cee8bc6ac refactor: Use latest version header in HISTORY.md for git log range 2025-03-18 18:18:34 -07:00
Paul Gauthier
37d867e47e better 2025-03-18 18:15:08 -07:00
Paul Gauthier
c1338fe92f copy 2025-03-18 18:09:25 -07:00
Paul Gauthier
1e90a679c0 copy 2025-03-18 18:06:41 -07:00
Paul Gauthier (aider)
ddb7b9cb8b docs: Expand explanation of accepts_settings behavior in reasoning docs 2025-03-18 17:45:19 -07:00
Paul Gauthier (aider)
31e1604d99 docs: Update reasoning settings documentation for accepts_settings and --no-check-model-accepts-settings 2025-03-18 17:45:06 -07:00
Paul Gauthier
e11c32bca5 refactor: Simplify model setting warning message in main.py 2025-03-18 17:43:57 -07:00
Paul Gauthier
16309dc077 test: Update test assertions and model in test_main.py 2025-03-18 17:40:26 -07:00
Paul Gauthier (aider)
8a1b496cd5 style: Format test_main.py with linter 2025-03-18 17:37:01 -07:00
Paul Gauthier (aider)
99cf99e014 test: update test for --check-model-accepts-settings flag 2025-03-18 17:36:55 -07:00
Paul Gauthier (aider)
f2e9b06dbd fix: Update tests and logic for model settings acceptance checks 2025-03-18 17:36:30 -07:00
Paul Gauthier (aider)
6cce7c34c2 style: Format test_main.py with linter 2025-03-18 17:33:58 -07:00
Paul Gauthier (aider)
dd2efac3ae test: verify Model.set_ methods are called appropriately in tests 2025-03-18 17:33:52 -07:00
Paul Gauthier (aider)
14c0e50721 style: Format warning message in main.py for readability 2025-03-18 17:22:31 -07:00
Paul Gauthier (aider)
68e218d002 refactor: ignore unsupported model parameters with warning instead of prompt 2025-03-18 17:22:25 -07:00
Paul Gauthier
0a026e71b7 copy 2025-03-18 14:43:36 -07:00
Paul Gauthier
5175a8c7ca copy 2025-03-18 14:42:12 -07:00
Paul Gauthier
661e0cfc71 copy 2025-03-18 14:30:22 -07:00
Paul Gauthier
9ff6f35330 copy 2025-03-18 14:13:08 -07:00
Paul Gauthier
ab5a066780 feat: Add controls to video player in recording.js 2025-03-18 14:05:06 -07:00
Paul Gauthier (aider)
c2d649e655 refactor: Use Jekyll templating for recordings list generation 2025-03-18 14:04:29 -07:00
Paul Gauthier (aider)
f82bb65810 docs: Add descriptions to recording pages using text from index 2025-03-18 14:03:03 -07:00
Paul Gauthier
e76c54b18e docs: Add empty description field to model-accepts-settings.md 2025-03-18 14:03:02 -07:00
Paul Gauthier
43658055d3 copy 2025-03-18 13:58:31 -07:00
Paul Gauthier (aider)
0b71fded7f docs: Add entry for model-accepts-settings recording to index 2025-03-18 13:56:43 -07:00
Paul Gauthier
03d1bada2a add model-accepts-settings recording 2025-03-18 13:53:16 -07:00
Paul Gauthier (aider)
ad76355299 feat: make toast notifications persist until audio/speech completes 2025-03-18 13:32:59 -07:00
Paul Gauthier (aider)
c98d409f0a fix: prevent duplicate speech synthesis fallback 2025-03-18 13:30:31 -07:00
Paul Gauthier
9084673fd7 copy 2025-03-18 12:39:01 -07:00
Paul Gauthier
8d7300a522 docs: Update reasoning model compatibility and settings documentation 2025-03-18 12:36:27 -07:00
Paul Gauthier (aider)
7c10600044 docs: Update reasoning model settings documentation with compatibility details 2025-03-18 12:32:22 -07:00
Paul Gauthier
277da37047 refactor: Simplify warning message in main.py 2025-03-18 12:30:47 -07:00
Paul Gauthier (aider)
f6d697ed2b refactor: rename warned to warn_setting for clarity 2025-03-18 12:28:41 -07:00
Paul Gauthier (aider)
f247927244 style: Format code to comply with linter rules 2025-03-18 12:27:54 -07:00
Paul Gauthier (aider)
7097e62582 refactor: Consolidate model setting checks into a loop 2025-03-18 12:27:48 -07:00
Paul Gauthier (aider)
e577bab263 refactor: Improve model settings warning logic and fix tmux recording script 2025-03-18 12:27:33 -07:00
Paul Gauthier (aider)
274c40793f refactor: Use warn_setting variable for model setting warnings 2025-03-18 12:27:28 -07:00
Paul Gauthier
afbe9266e7 refactor: Simplify warning messages and confirmation prompt 2025-03-18 12:27:27 -07:00
Paul Gauthier (aider)
195ed3e6b6 style: Remove trailing whitespace and format confirm_ask call 2025-03-18 12:24:13 -07:00
Paul Gauthier (aider)
ed8ace7884 feat: Add confirmation prompt for unsupported model parameters 2025-03-18 12:24:06 -07:00
Paul Gauthier (aider)
14761ebec2 fix: Update test_thinking_tokens_option to check correct thinking tokens location 2025-03-18 12:22:13 -07:00
Paul Gauthier (aider)
50d8a19397 style: Format test_main.py with consistent line breaks 2025-03-18 12:18:57 -07:00
Paul Gauthier (aider)
719324981d test: Add tests for accepts_settings configuration and thinking_tokens option 2025-03-18 12:18:52 -07:00
Paul Gauthier (aider)
182c06107f fix: move model setting warnings after settings are resolved 2025-03-18 12:13:55 -07:00
Paul Gauthier (aider)
d4d4852a0c feat: Add thinking_tokens and reasoning_effort settings to models 2025-03-18 12:08:52 -07:00
Paul Gauthier (aider)
f352fed313 style: Remove trailing whitespace in models.py 2025-03-18 12:05:23 -07:00
Paul Gauthier (aider)
5dfce2d199 feat: Add reasoning_effort and thinking_tokens settings to specific models 2025-03-18 12:05:17 -07:00
Paul Gauthier
6aafac544b refactor: Remove accepts_settings from model configurations 2025-03-18 12:05:11 -07:00
Paul Gauthier (aider)
2589c29b1c style: Format code to comply with linter rules 2025-03-18 12:01:55 -07:00
Paul Gauthier (aider)
076c38526a feat: Add --check-model-accepts-settings flag with default true 2025-03-18 12:01:45 -07:00
Paul Gauthier (aider)
9fd5cfa777 fix: warn when model settings are empty or missing specific keys 2025-03-18 12:00:36 -07:00
Paul Gauthier (aider)
c01db8783d style: Format warning messages to adhere to line length limit 2025-03-18 11:57:38 -07:00
Paul Gauthier (aider)
77101a96a1 feat: Add model setting validation for reasoning features 2025-03-18 11:57:31 -07:00
Paul Gauthier (aider)
46863b470c feat: Add terminal size output to tmux_record.sh 2025-03-18 11:53:28 -07:00
Paul Gauthier
736c1f7e1e chore: Make tmux_record.sh executable 2025-03-18 11:53:26 -07:00
Paul Gauthier (aider)
4cf9679334 feat: add check for exactly one active tmux window 2025-03-18 11:50:12 -07:00
Paul Gauthier
89c9290602 refactor: Simplify asciinema command in tmux_record.sh 2025-03-18 11:50:10 -07:00
Paul Gauthier (aider)
3ba75c5a62 feat: Add dynamic tmux window size detection to recording script 2025-03-18 11:49:25 -07:00
Paul Gauthier
4ceaed7183 feat: Add tmux recording script 2025-03-18 11:49:24 -07:00
Paul Gauthier
f310497d47 copy 2025-03-18 09:55:47 -07:00
Paul Gauthier
94bcaa71e6 copy 2025-03-17 21:24:34 -07:00
Paul Gauthier
67bdccbda6 refactor: Adjust padding in NoInsetCodeBlock syntax rendering 2025-03-17 21:17:02 -07:00
Paul Gauthier (aider)
f89dabbd0a refactor: Replace make_elements() with class var in NoInsetMarkdown 2025-03-17 21:15:30 -07:00
Paul Gauthier
76eee60ad5 refactor: Update NoInsetMarkdown to use NoInsetCodeBlock for fence elements 2025-03-17 21:15:28 -07:00
Paul Gauthier (aider)
ac4e4959eb style: Format code according to linter rules 2025-03-17 21:10:17 -07:00
Paul Gauthier (aider)
7316635aba feat: Remove padding from markdown code blocks using NoInsetMarkdown 2025-03-17 21:10:12 -07:00
Paul Gauthier
feb277049f copy 2025-03-17 19:43:50 -07:00
Paul Gauthier
35d5febd7d copy 2025-03-17 19:05:31 -07:00
lentil32 (aider)
679c634459 test: Add tests for AWS credential handling with AWS_PROFILE 2025-03-16 16:09:32 +09:00
lentil32 (aider)
cc33fc2822 feat: Handle AWS_PROFILE for Bedrock models in validate_environment 2025-03-16 16:00:15 +09:00
Adrian Cole
10d599f26a ollama: suggest higher minimum context length
This updates the doc with the new ENV variable ollama supports since [v0.5.13](https://github.com/ollama/ollama/releases/tag/v0.5.13)
2025-03-10 15:32:53 +08:00
Yutaka Matsubara
6b76ed8098 refactor: enhance --aiderignore argument to resolve absolute and relative paths 2025-03-10 08:41:49 +09:00
Son H. Nguyen
a1286d0d4d doc: add example command for github copilot models 2025-03-08 14:18:48 +07:00
Son H. Nguyen
eef3a3afeb feat: add copilot models to model list 2025-03-08 14:07:15 +07:00
Mir Adnan ALI
3e8f9aa31c fix: Use shlex.quote() to lint filepaths containing shell metacharacters 2025-02-08 17:31:01 -05:00
Andrey Ivanov
afebfe5f4f fix[io.py]: completion menu current item color styling 2025-01-23 23:09:17 +00:00
216 changed files with 12141 additions and 1847 deletions

View File

@@ -0,0 +1,86 @@
name: Check PyPI Version
# Check to be sure `pip install aider-chat` installs the most recently published version.
# If dependencies get yanked, it may render the latest version uninstallable.
# See https://github.com/Aider-AI/aider/issues/3699 for example.
on:
schedule:
# Run once a day at midnight UTC
- cron: '0 0 * * *'
workflow_dispatch: # Allows manual triggering
jobs:
check_version:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install aider-chat
run: pip install aider-chat
- name: Get installed aider version
id: installed_version
run: |
set -x # Enable debugging output
aider_version_output=$(aider --version)
if [ $? -ne 0 ]; then
echo "Error: 'aider --version' command failed."
exit 1
fi
echo "Raw aider --version output: $aider_version_output"
# Extract version number (format X.Y.Z)
version_num=$(echo "$aider_version_output" | grep -oP '\d+\.\d+\.\d+')
# Check if grep found anything
if [ -z "$version_num" ]; then
echo "Error: Could not extract version number using grep -oP '\d+\.\d+\.\d+' from output: $aider_version_output"
exit 1
fi
echo "Extracted version number: $version_num"
echo "version=$version_num" >> $GITHUB_OUTPUT
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for all tags
- name: Get latest tag
id: latest_tag
run: |
set -x # Enable debugging output
# Fetch all tags from remote just in case
git fetch --tags origin main
# Get the latest tag that strictly matches vX.Y.Z (no suffixes like .dev)
# List all tags, sort by version descending, filter for exact pattern, take the first one
latest_tag=$(git tag --sort=-v:refname | grep -P '^v\d+\.\d+\.\d+$' | head -n 1)
if [ -z "$latest_tag" ]; then
echo "Error: Could not find any tags matching the pattern '^v\d+\.\d+\.\d+$'"
exit 1
fi
echo "Latest non-dev tag: $latest_tag"
# Remove 'v' prefix for comparison
tag_num=${latest_tag#v}
echo "Extracted tag number: $tag_num"
echo "tag=$tag_num" >> $GITHUB_OUTPUT
- name: Compare versions
run: |
echo "Installed version: ${{ steps.installed_version.outputs.version }}"
echo "Latest tag version: ${{ steps.latest_tag.outputs.tag }}"
if [ "${{ steps.installed_version.outputs.version }}" != "${{ steps.latest_tag.outputs.tag }}" ]; then
echo "Error: Installed aider version (${{ steps.installed_version.outputs.version }}) does not match the latest tag (${{ steps.latest_tag.outputs.tag }})."
exit 1
fi
echo "Versions match."

View File

@@ -0,0 +1,90 @@
name: Windows Check PyPI Version
# Check to be sure `pip install aider-chat` installs the most recently published version on Windows.
# If dependencies get yanked, it may render the latest version uninstallable.
# See https://github.com/Aider-AI/aider/issues/3699 for example.
on:
schedule:
# Run once a day at 1 AM UTC (offset from Ubuntu check)
- cron: '0 1 * * *'
workflow_dispatch: # Allows manual triggering
jobs:
check_version:
runs-on: windows-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
defaults:
run:
shell: pwsh # Use PowerShell for all run steps
steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install aider-chat
run: pip install aider-chat
- name: Get installed aider version
id: installed_version
run: |
Write-Host "Running 'aider --version'..."
$aider_version_output = aider --version
if ($LASTEXITCODE -ne 0) {
Write-Error "Error: 'aider --version' command failed."
exit 1
}
Write-Host "Raw aider --version output: $aider_version_output"
# Extract version number (format X.Y.Z) using PowerShell regex
$match = [regex]::Match($aider_version_output, '\d+\.\d+\.\d+')
if (-not $match.Success) {
Write-Error "Error: Could not extract version number using regex '\d+\.\d+\.\d+' from output: $aider_version_output"
exit 1
}
$version_num = $match.Value
Write-Host "Extracted version number: $version_num"
echo "version=$version_num" >> $env:GITHUB_OUTPUT
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for all tags
- name: Get latest tag
id: latest_tag
run: |
Write-Host "Fetching tags..."
# Fetch all tags from remote just in case
git fetch --tags origin main
Write-Host "Getting latest non-dev tag..."
# Get the latest tag that strictly matches vX.Y.Z (no suffixes like .dev)
# List all tags, sort by version descending, filter for exact pattern, take the first one
$latest_tag = (git tag --sort=-v:refname | Select-String -Pattern '^v\d+\.\d+\.\d+$' | Select-Object -First 1).Line
if (-not $latest_tag) {
Write-Error "Error: Could not find any tags matching the pattern '^v\d+\.\d+\.\d+$'"
exit 1
}
Write-Host "Latest non-dev tag: $latest_tag"
# Remove 'v' prefix for comparison
$tag_num = $latest_tag.Substring(1)
Write-Host "Extracted tag number: $tag_num"
echo "tag=$tag_num" >> $env:GITHUB_OUTPUT
- name: Compare versions
run: |
Write-Host "Installed version: ${{ steps.installed_version.outputs.version }}"
Write-Host "Latest tag version: ${{ steps.latest_tag.outputs.tag }}"
if ("${{ steps.installed_version.outputs.version }}" -ne "${{ steps.latest_tag.outputs.tag }}") {
Write-Error "Error: Installed aider version (${{ steps.installed_version.outputs.version }}) does not match the latest tag (${{ steps.latest_tag.outputs.tag }})."
exit 1
}
Write-Host "Versions match."

View File

@@ -18,5 +18,6 @@ repos:
rev: v2.2.6
hooks:
- id: codespell
args: ["--skip", "aider/website/docs/languages.md"]
additional_dependencies:
- tomli

View File

@@ -1,10 +1,137 @@
# Release history
### main branch
### 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.
- Run with `aider --model quasar`
- Offer OpenRouter OAuth authentication if an OpenRouter model is specified but the API key is missing.
- Prevent retrying API calls when the provider reports insufficient credits.
- Improve URL detection to exclude trailing double quotes.
- Aider wrote 86% of the code in this release.
### Aider v0.80.4
- Bumped deps to pickup litellm change to properly display the root cause of OpenRouter "choices" errors.
### Aider v0.80.3
- Improve error message for OpenRouter API connection issues to mention potential rate limiting or upstream provider issues.
- Configure weak models (`gemini/gemini-2.0-flash` and `openrouter/google/gemini-2.0-flash-exp:free`) for Gemini 2.5 Pro models.
- Add model metadata for `openrouter/google/gemini-2.0-flash-exp:free`.
### Aider v0.80.2
- Bumped deps.
### Aider v0.80.1
- Updated deps for yanked fsspec and aiohttp packages #3699
- Removed redundant dependency check during OpenRouter OAuth flow, by Claudia Pellegrino.
### Aider v0.80.0
- OpenRouter OAuth integration:
- Offer to OAuth against OpenRouter if no model and keys are provided.
- Select OpenRouter default model based on free/paid tier status if `OPENROUTER_API_KEY` is set and no model is specified.
- Prioritize `gemini/gemini-2.5-pro-exp-03-25` if `GEMINI_API_KEY` is set, and `vertex_ai/gemini-2.5-pro-exp-03-25` if `VERTEXAI_PROJECT` is set, when no model is specified.
- Validate user-configured color settings on startup and warn/disable invalid ones.
- Warn at startup if `--stream` and `--cache-prompts` are used together, as cost estimates may be inaccurate.
- Boost repomap ranking for files whose path components match identifiers mentioned in the chat.
- Change web scraping timeout from an error to a warning, allowing scraping to continue with potentially incomplete content.
- Left-align markdown headings in the terminal output, by Peter Schilling.
- Update edit format to the new model's default when switching models with `/model`, if the user was using the old model's default format.
- Add `Ctrl-X Ctrl-E` keybinding to edit the current input buffer in an external editor, by Matteo Landi.
- Fix linting errors for filepaths containing shell metacharacters, by Mir Adnan ALI.
- Add the `openrouter/deepseek-chat-v3-0324:free` model.
- Add repomap support for the Scala language, by Vasil Markoukin.
- Fixed bug in `/run` that was preventing auto-testing.
- Fix bug preventing `UnboundLocalError` during git tree traversal.
- Handle `GitCommandNotFound` error if git is not installed or not in PATH.
- Handle `FileNotFoundError` if the current working directory is deleted while aider is running.
- Fix completion menu current item color styling, by Andrey Ivanov.
- Aider wrote 87% of the code in this release.
### Aider v0.79.2
- Added 'gemini' alias for gemini-2.5-pro model.
- Updated Gemini 2.5 Pro max output tokens to 64k.
- Added support for Lisp-style semicolon comments in file watcher, by Matteo Landi.
- Added OpenRouter API error detection and retries.
- Added openrouter/deepseek-chat-v3-0324 model.
- Aider wrote 93% of the code in this release.
### Aider v0.79.1
- Improved model listing to include all models in fuzzy matching, including those provided by aider (not litellm).
### Aider v0.79.0
- Added support for Gemini 2.5 Pro models.
- Added support for DeepSeek V3 0324 model.
- Added a new `/context` command that automatically identifies which files need to be edited for a given request.
- Added `/edit` as an alias for the `/editor` command.
- Added "overeager" mode for Claude 3.7 Sonnet models to try and keep it working within the requested scope.
- Aider wrote 65% of the code in this release.
### Aider v0.78.0
- Added support for thinking tokens for OpenRouter Sonnet 3.7.
- Added commands to switch between model types: `/editor-model` for Editor Model, and `/weak-model` for Weak Model, by csala.
- Added model setting validation to ignore `--reasoning-effort` and `--thinking-tokens` if the model doesn't support them.
- Added `--check-model-accepts-settings` flag (default: true) to force unsupported model settings.
- Annotated which models support reasoning_effort and thinking_tokens settings in the model settings data.
- Improved code block rendering in markdown output with better padding using NoInsetMarkdown.
- Added `--git-commit-verify` flag (default: False) to control whether git commit hooks are bypassed.
- Fixed autocompletion for `/ask`, `/code`, and `/architect` commands, by shladnik.
- Added vi-like behavior when pressing enter in multiline-mode while in vi normal/navigation-mode, by Marco Mayer.
- Added AWS_PROFILE support for Bedrock models, allowing use of AWS profiles instead of explicit credentials, by lentil32.
- Enhanced `--aiderignore` argument to resolve both absolute and relative paths, by mopemope.
- Improved platform information handling to gracefully handle retrieval errors.
- Aider wrote 92% of the code in this release.
### Aider v0.77.1
- Bumped dependencies to pickup litellm fix for Ollama.
- Added support for `openrouter/google/gemma-3-27b-it` model.
- Aider wrote 96% of the code in this release.
- Updated exclude patterns for help documentation.
### Aider v0.77.0

251
README.md
View File

@@ -1,144 +1,177 @@
<p align="center">
<a href="https://aider.chat/"><img src="https://aider.chat/assets/logo.svg" alt="Aider Logo" width="300"></a>
</p>
<!-- Edit README.md, not index.md -->
<h1 align="center">
AI Pair Programming in Your Terminal
</h1>
# Aider is AI pair programming in your terminal
Aider lets you pair program with LLMs,
to edit code in your local git repository.
Start a new project or work with an existing code base.
Aider works best with Claude 3.7 Sonnet, DeepSeek R1 & Chat V3, OpenAI o1, o3-mini & GPT-4o. Aider can [connect to almost any LLM, including local models](https://aider.chat/docs/llms.html).
<p align="center">
Aider lets you pair program with LLMs to start a new project or build on your existing codebase.
</p>
<!-- SCREENCAST START -->
<p align="center">
<img
src="https://aider.chat/assets/screencast.svg"
alt="aider screencast"
>
</p>
<!-- SCREENCAST END -->
<!-- VIDEO START
<p align="center">
<video style="max-width: 100%; height: auto;" autoplay loop muted playsinline>
<source src="/assets/shell-cmds-small.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</p>
VIDEO END -->
<p align="center">
<a href="https://discord.gg/Tv2uQnR88V">
<img src="https://img.shields.io/badge/Join-Discord-blue.svg"/>
</a>
<a href="https://aider.chat/docs/install.html">
<img src="https://img.shields.io/badge/Read-Docs-green.svg"/>
</a>
</p>
## Getting started
<!--[[[cog
# We can't "include" here.
# Because this page is rendered by GitHub as the repo README
cog.out(open("aider/website/_includes/get-started.md").read())
from scripts.homepage import get_badges_md
text = get_badges_md()
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-2.0M-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/#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-92%25-e74c3c?style=flat-square&labelColor=555555"/></a>
<!--[[[end]]]-->
</p>
If you already have python 3.8-3.13 installed, you can get started quickly like this:
## Features
### [Cloud and local LLMs](https://aider.chat/docs/llms.html)
<a href="https://aider.chat/docs/llms.html"><img src="https://aider.chat/assets/icons/brain.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Aider works best with Claude 3.7 Sonnet, DeepSeek R1 & Chat V3, OpenAI o1, o3-mini & GPT-4o, but can connect to almost any LLM, including local models.
<br>
### [Maps your codebase](https://aider.chat/docs/repomap.html)
<a href="https://aider.chat/docs/repomap.html"><img src="https://aider.chat/assets/icons/map-outline.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Aider makes a map of your entire codebase, which helps it work well in larger projects.
<br>
### [100+ code languages](https://aider.chat/docs/languages.html)
<a href="https://aider.chat/docs/languages.html"><img src="https://aider.chat/assets/icons/code-tags.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Aider works with most popular programming languages: python, javascript, rust, ruby, go, cpp, php, html, css, and dozens more.
<br>
### [Git integration](https://aider.chat/docs/git.html)
<a href="https://aider.chat/docs/git.html"><img src="https://aider.chat/assets/icons/source-branch.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Aider automatically commits changes with sensible commit messages. Use familiar git tools to easily diff, manage and undo AI changes.
<br>
### [Use in your IDE](https://aider.chat/docs/usage/watch.html)
<a href="https://aider.chat/docs/usage/watch.html"><img src="https://aider.chat/assets/icons/monitor.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Use aider from within your favorite IDE or editor. Ask for changes by adding comments to your code and aider will get to work.
<br>
### [Images & web pages](https://aider.chat/docs/usage/images-urls.html)
<a href="https://aider.chat/docs/usage/images-urls.html"><img src="https://aider.chat/assets/icons/image-multiple.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Add images and web pages to the chat to provide visual context, screenshots, reference docs, etc.
<br>
### [Voice-to-code](https://aider.chat/docs/usage/voice.html)
<a href="https://aider.chat/docs/usage/voice.html"><img src="https://aider.chat/assets/icons/microphone.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Speak with aider about your code! Request new features, test cases or bug fixes using your voice and let aider implement the changes.
<br>
### [Linting & testing](https://aider.chat/docs/usage/lint-test.html)
<a href="https://aider.chat/docs/usage/lint-test.html"><img src="https://aider.chat/assets/icons/check-all.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Automatically lint and test your code every time aider makes changes. Aider can fix problems detected by your linters and test suites.
<br>
### [Copy/paste to web chat](https://aider.chat/docs/usage/copypaste.html)
<a href="https://aider.chat/docs/usage/copypaste.html"><img src="https://aider.chat/assets/icons/content-copy.svg" width="32" height="32" align="left" valign="middle" style="margin-right:10px"></a>
Work with any LLM via its web chat interface. Aider streamlines copy/pasting code context and edits back and forth with a browser.
## Getting Started
```bash
python -m pip install aider-install
aider-install
# Change directory into your code base
# Change directory into your codebase
cd /to/your/project
# Work with DeepSeek via DeepSeek's API
aider --model deepseek --api-key deepseek=your-key-goes-here
# DeepSeek
aider --model deepseek --api-key deepseek=<key>
# Work with Claude 3.7 Sonnet via Anthropic's API
aider --model sonnet --api-key anthropic=your-key-goes-here
# Claude 3.7 Sonnet
aider --model sonnet --api-key anthropic=<key>
# Work with GPT-4o via OpenAI's API
aider --model gpt-4o --api-key openai=your-key-goes-here
# Work with Sonnet via OpenRouter's API
aider --model openrouter/anthropic/claude-3.7-sonnet --api-key openrouter=your-key-goes-here
# Work with DeepSeek via OpenRouter's API
aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here
# o3-mini
aider --model o3-mini --api-key openai=<key>
```
<!--[[[end]]]-->
See the
[installation instructions](https://aider.chat/docs/install.html)
and
[usage documentation](https://aider.chat/docs/usage.html)
for more details.
See the [installation instructions](https://aider.chat/docs/install.html) and [usage documentation](https://aider.chat/docs/usage.html) for more details.
## Features
## More Information
- Run aider with the files you want to edit: `aider <file1> <file2> ...`
- Ask for changes:
- Add new features or test cases.
- Describe a bug.
- Paste in an error message or GitHub issue URL.
- Refactor code.
- Update docs.
- Aider will edit your files to complete your request.
- Aider [automatically git commits](https://aider.chat/docs/git.html) changes with a sensible commit message.
- [Use aider inside your favorite editor or IDE](https://aider.chat/docs/usage/watch.html).
- Aider works with [most popular languages](https://aider.chat/docs/languages.html): python, javascript, typescript, php, html, css, and more...
- Aider can edit multiple files at once for complex requests.
- Aider uses a [map of your entire git repo](https://aider.chat/docs/repomap.html), which helps it work well in larger codebases.
- Edit files in your editor or IDE while chatting with aider,
and it will always use the latest version.
Pair program with AI.
- [Add images to the chat](https://aider.chat/docs/usage/images-urls.html) (GPT-4o, Claude 3.5 Sonnet, etc).
- [Add URLs to the chat](https://aider.chat/docs/usage/images-urls.html) and aider will read their content.
- [Code with your voice](https://aider.chat/docs/usage/voice.html).
- Aider works best with Claude 3.7 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
## Top tier performance
[Aider has one of the top scores on SWE Bench](https://aider.chat/2024/06/02/main-swe-bench.html).
SWE Bench is a challenging software engineering benchmark where aider
solved *real* GitHub issues from popular open source
projects like django, scikitlearn, matplotlib, etc.
## More info
- [Documentation](https://aider.chat/)
- [Installation](https://aider.chat/docs/install.html)
- [Usage](https://aider.chat/docs/usage.html)
- [Tutorial videos](https://aider.chat/docs/usage/tutorials.html)
### Documentation
- [Installation Guide](https://aider.chat/docs/install.html)
- [Usage Guide](https://aider.chat/docs/usage.html)
- [Tutorial Videos](https://aider.chat/docs/usage/tutorials.html)
- [Connecting to LLMs](https://aider.chat/docs/llms.html)
- [Configuration](https://aider.chat/docs/config.html)
- [Configuration Options](https://aider.chat/docs/config.html)
- [Troubleshooting](https://aider.chat/docs/troubleshooting.html)
- [FAQ](https://aider.chat/docs/faq.html)
### Community & Resources
- [LLM Leaderboards](https://aider.chat/docs/leaderboards/)
- [GitHub](https://github.com/Aider-AI/aider)
- [Discord](https://discord.gg/Tv2uQnR88V)
- [GitHub Repository](https://github.com/Aider-AI/aider)
- [Discord Community](https://discord.gg/Tv2uQnR88V)
- [Blog](https://aider.chat/blog/)
## Kind Words From Users
## Kind words from users
- *"My life has changed this week. 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)
- *"It's a cool workflow... Aider's ergonomics are perfect for me."* — [qup](https://news.ycombinator.com/item?id=38185326)
- *"It's really like having your senior developer live right in your Git repo - truly amazing!"* — [rappster](https://github.com/Aider-AI/aider/issues/124)
- *"What an amazing tool. It's incredible."* — [valyagolev](https://github.com/Aider-AI/aider/issues/6#issue-1722897858)
- *"Aider is such an astounding thing!"* — [cgrothaus](https://github.com/Aider-AI/aider/issues/82#issuecomment-1631876700)
- *"It was WAY faster than I would be getting off the ground and making the first few working versions."* — [Daniel Feldman](https://twitter.com/d_feldman/status/1662295077387923456)
- *"THANK YOU for Aider! It really feels like a glimpse into the future of coding."* — [derwiki](https://news.ycombinator.com/item?id=38205643)
- *"It's just amazing. It is freeing me to do things I felt were out my comfort zone before."* — [Dougie](https://discord.com/channels/1131200896827654144/1174002618058678323/1174084556257775656)
- *"This project is stellar."* — [funkytaco](https://github.com/Aider-AI/aider/issues/112#issuecomment-1637429008)
- *"Amazing project, definitely the best AI coding assistant I've used."* — [joshuavial](https://github.com/Aider-AI/aider/issues/84)
- *"I absolutely love using Aider ... It makes software development feel so much lighter as an experience."* — [principalideal0](https://discord.com/channels/1131200896827654144/1133421607499595858/1229689636012691468)
- *"I have been recovering from multiple shoulder surgeries ... and have used aider extensively. It has allowed me to continue productivity."* — [codeninja](https://www.reddit.com/r/OpenAI/s/nmNwkHy1zG)
- *"I am an aider addict. I'm getting so much more work done, but in less time."* — [dandandan](https://discord.com/channels/1131200896827654144/1131200896827654149/1135913253483069470)
- *"After wasting $100 on tokens trying to find something better, I'm back to Aider. It blows everything else out of the water hands down, there's no competition whatsoever."* — [SystemSculpt](https://discord.com/channels/1131200896827654144/1131200896827654149/1178736602797846548)
- *"Aider is amazing, coupled with Sonnet 3.5 it's quite mind blowing."* — [Josh Dingus](https://discord.com/channels/1131200896827654144/1133060684540813372/1262374225298198548)
- *"Hands down, this is the best AI coding assistant tool so far."* — [IndyDevDan](https://www.youtube.com/watch?v=MPYFPvxfGZs)
- *"[Aider] changed my daily coding workflows. It's mind-blowing how a single Python application can change your life."* — [maledorak](https://discord.com/channels/1131200896827654144/1131200896827654149/1258453375620747264)
- *"Best agent for actual dev work in existing codebases."* — [Nick Dobos](https://twitter.com/NickADobos/status/1690408967963652097?s=20)
- *"One of my favorite pieces of software. Blazing trails on new paradigms!"* — [Chris Wall](https://x.com/chris65536/status/1905053299251798432)
- *"Aider has been revolutionary for me and my work."* — [Starry Hope](https://x.com/starryhopeblog/status/1904985812137132056)
- *"Try aider! One of the best ways to vibe code."* — [Chris Wall](https://x.com/Chris65536/status/1905053418961391929)
- *"Aider is hands down the best. And it's free and opensource."* — [AriyaSavakaLurker](https://www.reddit.com/r/ChatGPTCoding/comments/1ik16y6/whats_your_take_on_aider/mbip39n/)
- *"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)
- *"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)
- *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)
- *It's a cool workflow... Aider's ergonomics are perfect for me.* -- [qup](https://news.ycombinator.com/item?id=38185326)
- *It's really like having your senior developer live right in your Git repo - truly amazing!* -- [rappster](https://github.com/Aider-AI/aider/issues/124)
- *What an amazing tool. It's incredible.* -- [valyagolev](https://github.com/Aider-AI/aider/issues/6#issue-1722897858)
- *Aider is such an astounding thing!* -- [cgrothaus](https://github.com/Aider-AI/aider/issues/82#issuecomment-1631876700)
- *It was WAY faster than I would be getting off the ground and making the first few working versions.* -- [Daniel Feldman](https://twitter.com/d_feldman/status/1662295077387923456)
- *THANK YOU for Aider! It really feels like a glimpse into the future of coding.* -- [derwiki](https://news.ycombinator.com/item?id=38205643)
- *It's just amazing. It is freeing me to do things I felt were out my comfort zone before.* -- [Dougie](https://discord.com/channels/1131200896827654144/1174002618058678323/1174084556257775656)
- *This project is stellar.* -- [funkytaco](https://github.com/Aider-AI/aider/issues/112#issuecomment-1637429008)
- *Amazing project, definitely the best AI coding assistant I've used.* -- [joshuavial](https://github.com/Aider-AI/aider/issues/84)
- *I absolutely love using Aider ... It makes software development feel so much lighter as an experience.* -- [principalideal0](https://discord.com/channels/1131200896827654144/1133421607499595858/1229689636012691468)
- *I have been recovering from multiple shoulder surgeries ... and have used aider extensively. It has allowed me to continue productivity.* -- [codeninja](https://www.reddit.com/r/OpenAI/s/nmNwkHy1zG)
- *I am an aider addict. I'm getting so much more work done, but in less time.* -- [dandandan](https://discord.com/channels/1131200896827654144/1131200896827654149/1135913253483069470)
- *After wasting $100 on tokens trying to find something better, I'm back to Aider. It blows everything else out of the water hands down, there's no competition whatsoever.* -- [SystemSculpt](https://discord.com/channels/1131200896827654144/1131200896827654149/1178736602797846548)
- *Aider is amazing, coupled with Sonnet 3.5 its quite mind blowing.* -- [Josh Dingus](https://discord.com/channels/1131200896827654144/1133060684540813372/1262374225298198548)
- *Hands down, this is the best AI coding assistant tool so far.* -- [IndyDevDan](https://www.youtube.com/watch?v=MPYFPvxfGZs)
- *[Aider] changed my daily coding workflows. It's mind-blowing how a single Python application can change your life.* -- [maledorak](https://discord.com/channels/1131200896827654144/1131200896827654149/1258453375620747264)
- *Best agent for actual dev work in existing codebases.* -- [Nick Dobos](https://twitter.com/NickADobos/status/1690408967963652097?s=20)

View File

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

View File

@@ -3,6 +3,7 @@
import argparse
import os
import sys
from pathlib import Path
import configargparse
@@ -17,6 +18,15 @@ from aider.deprecated import add_deprecated_model_args
from .dump import dump # noqa: F401
def resolve_aiderignore_path(path_str, git_root=None):
path = Path(path_str)
if path.is_absolute():
return str(path)
elif git_root:
return str(Path(git_root) / path)
return str(path)
def default_env_file(git_root):
return os.path.join(git_root, ".env") if git_root else ".env"
@@ -181,6 +191,14 @@ def get_parser(default_config_files, git_root):
default=True,
help="Only work with models that have meta-data available (default: True)",
)
group.add_argument(
"--check-model-accepts-settings",
action=argparse.BooleanOptionalAction,
default=True,
help=(
"Check if model accepts settings like reasoning_effort/thinking_tokens (default: True)"
),
)
group.add_argument(
"--max-chat-history-tokens",
type=int,
@@ -380,9 +398,11 @@ def get_parser(default_config_files, git_root):
default_aiderignore_file = (
os.path.join(git_root, ".aiderignore") if git_root else ".aiderignore"
)
group.add_argument(
"--aiderignore",
metavar="AIDERIGNORE",
type=lambda path_str: resolve_aiderignore_path(path_str, git_root),
default=default_aiderignore_file,
help="Specify the aider ignore file (default: .aiderignore in git root)",
)
@@ -428,6 +448,12 @@ def get_parser(default_config_files, git_root):
default=False,
help="Prefix all commit messages with 'aider: ' (default: False)",
)
group.add_argument(
"--git-commit-verify",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable git pre-commit hooks with --no-verify (default: False)",
)
group.add_argument(
"--commit",
action="store_true",

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

@@ -1,11 +1,14 @@
from .architect_coder import ArchitectCoder
from .ask_coder import AskCoder
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 .wholefile_coder import WholeFileCoder
@@ -18,9 +21,12 @@ __all__ = [
EditBlockCoder,
EditBlockFencedCoder,
WholeFileCoder,
PatchCoder,
UnifiedDiffCoder,
# SingleWholeFileFunctionCoder,
ArchitectCoder,
EditorEditBlockCoder,
EditorWholeFileCoder,
EditorDiffFencedCoder,
ContextCoder,
]

View File

@@ -209,12 +209,12 @@ class Coder:
output = f"{prefix}: {main_model.name} with {self.edit_format} edit format"
# Check for thinking token budget
thinking_tokens = main_model.get_thinking_tokens(main_model)
thinking_tokens = main_model.get_thinking_tokens()
if thinking_tokens:
output += f", {thinking_tokens} think tokens"
# Check for reasoning effort
reasoning_effort = main_model.get_reasoning_effort(main_model)
reasoning_effort = main_model.get_reasoning_effort()
if reasoning_effort:
output += f", reasoning {reasoning_effort}"
@@ -922,10 +922,11 @@ class Coder:
else:
self.io.tool_error(text)
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*)")
# Exclude double quotes from the matched URL characters
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
@@ -934,7 +935,8 @@ class Coder:
if not self.detect_urls:
return inp
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*[^\s,.])")
# Exclude double quotes from the matched URL characters
url_pattern = re.compile(r'(https?://[^\s/$.?#].[^\s"]*[^\s,.])')
urls = list(set(url_pattern.findall(inp))) # Use set to remove duplicates
group = ConfirmGroup(urls)
for url in urls:
@@ -1030,7 +1032,13 @@ class Coder:
return None
def get_platform_info(self):
platform_text = f"- Platform: {platform.platform()}\n"
platform_text = ""
try:
platform_text = f"- Platform: {platform.platform()}\n"
except KeyError:
# Skip platform info if it can't be retrieved
platform_text = "- Platform information unavailable\n"
shell_var = "COMSPEC" if os.name == "nt" else "SHELL"
shell_val = os.getenv(shell_var)
platform_text += f"- Shell: {shell_var}={shell_val}\n"
@@ -1071,17 +1079,25 @@ class Coder:
return platform_text
def fmt_system_prompt(self, prompt):
lazy_prompt = self.gpt_prompts.lazy_prompt if self.main_model.lazy else ""
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 = ""
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
@@ -1101,7 +1117,9 @@ class Coder:
lazy_prompt=lazy_prompt,
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,
)
@@ -1444,7 +1462,8 @@ class Coder:
return
try:
self.reply_completed()
if self.reply_completed():
return
except KeyboardInterrupt:
interrupted = True
@@ -1587,30 +1606,30 @@ class Coder:
)
]
def get_file_mentions(self, content):
def get_file_mentions(self, content, ignore_current=False):
words = set(word for word in content.split())
# drop sentence punctuation from the end
words = set(word.rstrip(",.!;:?") for word in words)
# strip away all kinds of quotes
quotes = "".join(['"', "'", "`"])
quotes = "\"'`*_"
words = set(word.strip(quotes) for word in words)
addable_rel_fnames = self.get_addable_relative_files()
if ignore_current:
addable_rel_fnames = self.get_all_relative_files()
existing_basenames = {}
else:
addable_rel_fnames = self.get_addable_relative_files()
# Get basenames of files already in chat or read-only
existing_basenames = {os.path.basename(f) for f in self.get_inchat_relative_files()} | {
os.path.basename(self.get_rel_fname(f)) for f in self.abs_read_only_fnames
}
# Get basenames of files already in chat or read-only
existing_basenames = {os.path.basename(f) for f in self.get_inchat_relative_files()} | {
os.path.basename(self.get_rel_fname(f)) for f in self.abs_read_only_fnames
}
mentioned_rel_fnames = set()
fname_to_rel_fnames = {}
for rel_fname in addable_rel_fnames:
# Skip files that share a basename with files already in chat
if os.path.basename(rel_fname) in existing_basenames:
continue
normalized_rel_fname = rel_fname.replace("\\", "/")
normalized_words = set(word.replace("\\", "/") for word in words)
if normalized_rel_fname in normalized_words:
@@ -1625,6 +1644,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])
@@ -1944,11 +1967,6 @@ class Coder:
f" ${format_cost(self.total_cost)} session."
)
if self.add_cache_headers and self.stream:
warning = " Use --no-stream for accurate caching costs."
self.usage_report = tokens_report + "\n" + cost_report + warning
return
if cache_hit_tokens and cache_write_tokens:
sep = "\n"
else:

View File

@@ -14,6 +14,9 @@ You NEVER leave comments describing code without implementing it!
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."""
example_messages = []
files_content_prefix = """I have *added these files to the chat* so you can go ahead and edit them.
@@ -50,3 +53,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

@@ -0,0 +1,53 @@
from .base_coder import Coder
from .context_prompts import ContextPrompts
class ContextCoder(Coder):
"""Identify which files need to be edited for a given request."""
edit_format = "context"
gpt_prompts = ContextPrompts()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.repo_map:
return
self.repo_map.refresh = "always"
self.repo_map.max_map_tokens *= self.repo_map.map_mul_no_files
self.repo_map.map_mul_no_files = 1.0
def reply_completed(self):
content = self.partial_response_content
if not content or not content.strip():
return True
# dump(repr(content))
current_rel_fnames = set(self.get_inchat_relative_files())
mentioned_rel_fnames = set(self.get_file_mentions(content, ignore_current=True))
# dump(current_rel_fnames)
# dump(mentioned_rel_fnames)
# dump(current_rel_fnames == mentioned_rel_fnames)
if mentioned_rel_fnames == current_rel_fnames:
return True
if self.num_reflections >= self.max_reflections - 1:
return True
self.abs_fnames = set()
for fname in mentioned_rel_fnames:
self.add_rel_fname(fname)
# dump(self.get_inchat_relative_files())
self.reflected_message = self.gpt_prompts.try_again
# mentioned_idents = self.get_ident_mentions(cur_msg_text)
# if mentioned_idents:
return True
def check_for_file_mentions(self, content):
pass

View File

@@ -0,0 +1,75 @@
# flake8: noqa: E501
from .base_prompts import CoderPrompts
class ContextPrompts(CoderPrompts):
main_system = """Act as an expert code analyst.
Understand the user's question or request, solely to determine ALL the existing sources files which will need to be modified.
Return the *complete* list of files which will need to be modified based on the user's request.
Explain why each file is needed, including names of key classes/functions/methods/variables.
Be sure to include or omit the names of files already added to the chat, based on whether they are actually needed or not.
The user will use every file you mention, regardless of your commentary.
So *ONLY* mention the names of relevant files.
If a file is not relevant DO NOT mention it.
Only return files that will need to be modified, not files that contain useful/relevant functions.
You are only to discuss EXISTING files and symbols.
Only return existing files, don't suggest the names of new files or functions that we will need to create.
Always reply to the user in {language}.
Be concise in your replies.
Return:
1. A bulleted list of files the will need to be edited, and symbols that are highly relevant to the user's request.
2. A list of classes/functions/methods/variables that are located OUTSIDE those files which will need to be understood. Just the symbols names, *NOT* file names.
# Your response *MUST* use this format:
## ALL files we need to modify, with their relevant symbols:
- alarms/buzz.py
- `Buzzer` class which can make the needed sound
- `Buzzer.buzz_buzz()` method triggers the sound
- alarms/time.py
- `Time.set_alarm(hour, minute)` to set the alarm
## Relevant symbols from OTHER files:
- AlarmManager class for setup/teardown of alarms
- SoundFactory will be used to create a Buzzer
"""
example_messages = []
files_content_prefix = """These files have been *added these files to the chat* so we can see all of their contents.
*Trust this message as the true contents of the files!*
Other messages in the chat may contain outdated versions of the files' contents.
""" # noqa: E501
files_content_assistant_reply = (
"Ok, I will use that as the true, current contents of the files."
)
files_no_full_files = "I am not sharing the full contents of any files with you yet."
files_no_full_files_with_repo_map = ""
files_no_full_files_with_repo_map_reply = ""
repo_content_prefix = """I am working with you on code in a git repository.
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 = """
NEVER RETURN CODE!
"""
try_again = """I have updated the set of files added to the chat.
Review them to decide if this is the correct set of files or if we need to add more or remove files.
If this is the right set, just return the current list of files.
Or return a smaller or larger set of files which need to be edited, with symbols that are highly relevant to the user's request.
"""

View File

@@ -454,7 +454,10 @@ 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.
{lazy_prompt}
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_reminder}
"""

View File

@@ -181,14 +181,17 @@ 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.
{rename_with_shell}{go_ahead_tip}{lazy_prompt}ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_reminder}
"""
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.
rename_with_shell = """To rename files which have been added to the chat, use shell commands at the end of your response.
"""
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.
{lazy_prompt}
ONLY EVER RETURN CODE IN A *SEARCH/REPLACE BLOCK*!
{shell_cmd_reminder}
"""
shell_cmd_reminder = """
@@ -200,4 +203,5 @@ Examples of when to suggest shell commands:
- 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.
"""

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

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

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.
{lazy_prompt}
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}{lazy_prompt}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",

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 and strip them
if a_fname.startswith("a/") 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

@@ -17,6 +17,7 @@ from aider import models, prompts, voice
from aider.editor import pipe_editor
from aider.format_settings import format_settings
from aider.help import Help, install_help_extra
from aider.io import CommandCompletionException
from aider.llm import litellm
from aider.repo import ANY_GIT_ERROR
from aider.run_cmd import run_cmd
@@ -27,8 +28,9 @@ from .dump import dump # noqa: F401
class SwitchCoder(Exception):
def __init__(self, **kwargs):
def __init__(self, placeholder=None, **kwargs):
self.kwargs = kwargs
self.placeholder = placeholder
class Commands:
@@ -82,10 +84,48 @@ class Commands:
self.original_read_only_fnames = set(original_read_only_fnames or [])
def cmd_model(self, args):
"Switch to a new LLM"
"Switch the Main Model to a new LLM"
model_name = args.strip()
model = models.Model(model_name, weak_model=self.coder.main_model.weak_model.name)
model = models.Model(
model_name,
editor_model=self.coder.main_model.editor_model.name,
weak_model=self.coder.main_model.weak_model.name,
)
models.sanity_check_models(self.io, model)
# Check if the current edit format is the default for the old model
old_model_edit_format = self.coder.main_model.edit_format
current_edit_format = self.coder.edit_format
new_edit_format = current_edit_format
if current_edit_format == old_model_edit_format:
# If the user was using the old model's default, switch to the new model's default
new_edit_format = model.edit_format
raise SwitchCoder(main_model=model, edit_format=new_edit_format)
def cmd_editor_model(self, args):
"Switch the Editor Model to a new LLM"
model_name = args.strip()
model = models.Model(
self.coder.main_model.name,
editor_model=model_name,
weak_model=self.coder.main_model.weak_model.name,
)
models.sanity_check_models(self.io, model)
raise SwitchCoder(main_model=model)
def cmd_weak_model(self, args):
"Switch the Weak Model to a new LLM"
model_name = args.strip()
model = models.Model(
self.coder.main_model.name,
editor_model=self.coder.main_model.editor_model.name,
weak_model=model_name,
)
models.sanity_check_models(self.io, model)
raise SwitchCoder(main_model=model)
@@ -118,6 +158,10 @@ class Commands:
" them."
),
),
(
"context",
"Automatically identify which files will need to be edited.",
),
]
)
@@ -970,9 +1014,15 @@ class Commands:
dict(role="assistant", content="Ok."),
]
if add and exit_status != 0:
if add_on_nonzero_exit and exit_status != 0:
# Return the formatted output message for test failures
return msg
elif add and exit_status != 0:
self.io.placeholder = "What's wrong? Fix"
# Return None if output wasn't added or command succeeded
return None
def cmd_exit(self, args):
"Exit the application"
self.coder.event("exit", reason="/exit")
@@ -1088,6 +1138,18 @@ class Commands:
show_announcements=False,
)
def completions_ask(self):
raise CommandCompletionException()
def completions_code(self):
raise CommandCompletionException()
def completions_architect(self):
raise CommandCompletionException()
def completions_context(self):
raise CommandCompletionException()
def cmd_ask(self, args):
"""Ask questions about the code base without editing any files. If no prompt provided, switches to ask mode.""" # noqa
return self._generic_chat_command(args, "ask")
@@ -1100,7 +1162,11 @@ class Commands:
"""Enter architect/editor mode using 2 different models. If no prompt provided, switches to architect/editor mode.""" # noqa
return self._generic_chat_command(args, "architect")
def _generic_chat_command(self, args, edit_format):
def cmd_context(self, args):
"""Enter context mode to see surrounding code context. If no prompt provided, switches to context mode.""" # noqa
return self._generic_chat_command(args, "context", placeholder=args.strip() or None)
def _generic_chat_command(self, args, edit_format, placeholder=None):
if not args.strip():
# Switch to the corresponding chat mode if no args provided
return self.cmd_chat_mode(edit_format)
@@ -1117,11 +1183,13 @@ class Commands:
user_msg = args
coder.run(user_msg)
# Use the provided placeholder if any
raise SwitchCoder(
edit_format=self.coder.edit_format,
summarize_from_coder=False,
from_coder=coder,
show_announcements=False,
placeholder=placeholder,
)
def get_help_md(self):
@@ -1434,17 +1502,21 @@ class Commands:
if user_input.strip():
self.io.set_placeholder(user_input.rstrip())
def cmd_edit(self, args=""):
"Alias for /editor: Open an editor to write a prompt"
return self.cmd_editor(args)
def cmd_think_tokens(self, args):
"Set the thinking token budget (supports formats like 8096, 8k, 10.5k, 0.5M)"
model = self.coder.main_model
if not args.strip():
# Display current value if no args are provided
formatted_budget = model.get_thinking_tokens(model)
formatted_budget = model.get_thinking_tokens()
if formatted_budget is None:
self.io.tool_output("Thinking tokens are not currently set.")
else:
budget = model.extra_params["thinking"].get("budget_tokens")
budget = model.get_raw_thinking_tokens()
self.io.tool_output(
f"Current thinking token budget: {budget:,} tokens ({formatted_budget})."
)
@@ -1453,8 +1525,8 @@ class Commands:
value = args.strip()
model.set_thinking_tokens(value)
formatted_budget = model.get_thinking_tokens(model)
budget = model.extra_params["thinking"].get("budget_tokens")
formatted_budget = model.get_thinking_tokens()
budget = model.get_raw_thinking_tokens()
self.io.tool_output(f"Set thinking token budget to {budget:,} tokens ({formatted_budget}).")
self.io.tool_output()
@@ -1469,7 +1541,7 @@ class Commands:
if not args.strip():
# Display current value if no args are provided
reasoning_value = model.get_reasoning_effort(model)
reasoning_value = model.get_reasoning_effort()
if reasoning_value is None:
self.io.tool_output("Reasoning effort is not currently set.")
else:
@@ -1478,7 +1550,7 @@ class Commands:
value = args.strip()
model.set_reasoning_effort(value)
reasoning_value = model.get_reasoning_effort(model)
reasoning_value = model.get_reasoning_effort()
self.io.tool_output(f"Set reasoning effort to {reasoning_value}")
self.io.tool_output()

View File

@@ -83,4 +83,25 @@ class LiteLLMExceptions:
)
if "boto3" in str(ex):
return ExInfo("APIConnectionError", False, "You need to: pip install boto3")
if "OpenrouterException" in str(ex) and "'choices'" in str(ex):
return ExInfo(
"APIConnectionError",
True,
(
"OpenRouter or the upstream API provider is down, overloaded or rate"
" limiting your requests."
),
)
# Check for specific non-retryable APIError cases like insufficient credits
if ex.__class__ is litellm.APIError:
err_str = str(ex).lower()
if "insufficient credits" in err_str and '"code":402' in err_str:
return ExInfo(
"APIError",
False,
"Insufficient credits with the API provider. Please add credits.",
)
# Fall through to default APIError handling if not the specific credits error
return self.exceptions.get(ex.__class__, ExInfo(None, None, None))

View File

@@ -18,6 +18,7 @@ from prompt_toolkit.enums import EditingMode
from prompt_toolkit.filters import Condition, is_searching
from prompt_toolkit.history import FileHistory
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.key_binding.vi_state import InputMode
from prompt_toolkit.keys import Keys
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.output.vt100 import is_dumb_terminal
@@ -25,6 +26,7 @@ from prompt_toolkit.shortcuts import CompleteStyle, PromptSession
from prompt_toolkit.styles import Style
from pygments.lexers import MarkdownLexer, guess_lexer_for_filename
from pygments.token import Token
from rich.color import ColorParseError
from rich.columns import Columns
from rich.console import Console
from rich.markdown import Markdown
@@ -34,6 +36,7 @@ from rich.text import Text
from aider.mdstream import MarkdownStream
from .dump import dump # noqa: F401
from .editor import pipe_editor
from .utils import is_image_file
# Constants
@@ -68,6 +71,13 @@ def restore_multiline(func):
return wrapper
class CommandCompletionException(Exception):
"""Raised when a command should use the normal autocompleter instead of
command-specific completion."""
pass
@dataclass
class ConfirmGroup:
preference: str = None
@@ -186,8 +196,12 @@ class AutoCompleter(Completer):
return
if text[0] == "/":
yield from self.get_command_completions(document, complete_event, text, words)
return
try:
yield from self.get_command_completions(document, complete_event, text, words)
return
except CommandCompletionException:
# Fall through to normal completion
pass
candidates = self.words
candidates.update(set(self.fname_to_rel_fnames))
@@ -348,6 +362,35 @@ class InputOutput:
self.file_watcher = file_watcher
self.root = root
# Validate color settings after console is initialized
self._validate_color_settings()
def _validate_color_settings(self):
"""Validate configured color strings and reset invalid ones."""
color_attributes = [
"user_input_color",
"tool_output_color",
"tool_error_color",
"tool_warning_color",
"assistant_output_color",
"completion_menu_color",
"completion_menu_bg_color",
"completion_menu_current_color",
"completion_menu_current_bg_color",
]
for attr_name in color_attributes:
color_value = getattr(self, attr_name, None)
if color_value:
try:
# Try creating a style to validate the color
RichStyle(color=color_value)
except ColorParseError as e:
self.console.print(
"[bold red]Warning:[/bold red] Invalid configuration for"
f" {attr_name}: '{color_value}'. {e}. Disabling this color."
)
setattr(self, attr_name, None) # Reset invalid color to None
def _get_style(self):
style_dict = {}
if not self.pretty:
@@ -373,9 +416,9 @@ class InputOutput:
# Conditionally add 'completion-menu.completion.current' style
completion_menu_current_style = []
if self.completion_menu_current_bg_color:
completion_menu_current_style.append(f"bg:{self.completion_menu_current_bg_color}")
completion_menu_current_style.append(self.completion_menu_current_bg_color)
if self.completion_menu_current_color:
completion_menu_current_style.append(self.completion_menu_current_color)
completion_menu_current_style.append(f"bg:{self.completion_menu_current_color}")
if completion_menu_current_style:
style_dict["completion-menu.completion.current"] = " ".join(
completion_menu_current_style
@@ -492,11 +535,16 @@ class InputOutput:
get_rel_fname(fname, root) for fname in (abs_read_only_fnames or [])
]
show = self.format_files_for_input(rel_fnames, rel_read_only_fnames)
prompt_prefix = ""
if edit_format:
show += edit_format
prompt_prefix += edit_format
if self.multiline_mode:
show += (" " if edit_format else "") + "multi"
show += "> "
prompt_prefix += (" " if edit_format else "") + "multi"
prompt_prefix += "> "
show += prompt_prefix
self.prompt_prefix = prompt_prefix
inp = ""
multiline_input = False
@@ -540,11 +588,30 @@ class InputOutput:
"Navigate forward through history"
event.current_buffer.history_forward()
@kb.add("c-x", "c-e")
def _(event):
"Edit current input in external editor (like Bash)"
buffer = event.current_buffer
current_text = buffer.text
# Open the editor with the current text
edited_text = pipe_editor(input_data=current_text)
# Replace the buffer with the edited text, strip any trailing newlines
buffer.text = edited_text.rstrip("\n")
# Move cursor to the end of the text
buffer.cursor_position = len(buffer.text)
@kb.add("enter", eager=True, filter=~is_searching)
def _(event):
"Handle Enter key press"
if self.multiline_mode:
# In multiline mode, Enter adds a newline
if self.multiline_mode and not (
self.editingmode == EditingMode.VI
and event.app.vi_state.input_mode == InputMode.NAVIGATION
):
# In multiline mode and if not in vi-mode or vi navigation/normal mode,
# Enter adds a newline
event.current_buffer.insert_text("\n")
else:
# In normal mode, Enter submits
@@ -562,7 +629,7 @@ class InputOutput:
while True:
if multiline_input:
show = ". "
show = self.prompt_prefix
try:
if self.prompt_session:
@@ -578,7 +645,7 @@ class InputOutput:
self.clipboard_watcher.start()
def get_continuation(width, line_number, is_soft_wrap):
return ". "
return self.prompt_prefix
line = self.prompt_session.prompt(
show,
@@ -896,6 +963,7 @@ class InputOutput:
if not isinstance(message, Text):
message = Text(message)
color = ensure_hash_prefix(color) if color else None
style = dict(style=color) if self.pretty and color else dict()
try:
self.console.print(message, **style)
@@ -926,7 +994,7 @@ class InputOutput:
style = dict()
if self.pretty:
if self.tool_output_color:
style["color"] = self.tool_output_color
style["color"] = ensure_hash_prefix(self.tool_output_color)
style["reverse"] = bold
style = RichStyle(**style)

View File

@@ -4,6 +4,7 @@ import subprocess
import sys
import traceback
import warnings
import shlex
from dataclasses import dataclass
from pathlib import Path
@@ -44,7 +45,7 @@ class Linter:
return fname
def run_cmd(self, cmd, rel_fname, code):
cmd += " " + rel_fname
cmd += " " + shlex.quote(rel_fname)
returncode = 0
stdout = ""

View File

@@ -30,6 +30,7 @@ from aider.history import ChatSummary
from aider.io import InputOutput
from aider.llm import litellm # noqa: F401; properly init litellm on launch
from aider.models import ModelSettings
from aider.onboarding import offer_openrouter_oauth, select_default_model
from aider.repo import ANY_GIT_ERROR, GitRepo
from aider.report import report_uncaught_exceptions
from aider.versioncheck import check_version, install_from_main_branch, install_upgrade
@@ -357,11 +358,21 @@ def register_models(git_root, model_settings_fname, io, verbose=False):
def load_dotenv_files(git_root, dotenv_fname, encoding="utf-8"):
# Standard .env file search path
dotenv_files = generate_search_path_list(
".env",
git_root,
dotenv_fname,
)
# Explicitly add the OAuth keys file to the beginning of the list
oauth_keys_file = Path.home() / ".aider" / "oauth-keys.env"
if oauth_keys_file.exists():
# Insert at the beginning so it's loaded first (and potentially overridden)
dotenv_files.insert(0, str(oauth_keys_file.resolve()))
# Remove duplicates if it somehow got included by generate_search_path_list
dotenv_files = list(dict.fromkeys(dotenv_files))
loaded = []
for fname in dotenv_files:
try:
@@ -714,11 +725,6 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.check_update:
check_version(io, verbose=args.verbose)
if args.list_models:
models.print_matching_models(io, args.list_models)
analytics.event("exit", reason="Listed models")
return 0
if args.git:
git_root = setup_git(git_root, io)
if args.gitignore:
@@ -738,6 +744,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
register_models(git_root, args.model_settings_file, io, verbose=args.verbose)
register_litellm_models(git_root, args.model_metadata_file, io, verbose=args.verbose)
if args.list_models:
models.print_matching_models(io, args.list_models)
analytics.event("exit", reason="Listed models")
return 0
# Process any command line aliases
if args.alias:
for alias_def in args.alias:
@@ -751,26 +762,49 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
alias, model = parts
models.MODEL_ALIASES[alias.strip()] = model.strip()
if not args.model:
# Select model based on available API keys
model_key_pairs = [
("ANTHROPIC_API_KEY", "sonnet"),
("DEEPSEEK_API_KEY", "deepseek"),
("OPENROUTER_API_KEY", "openrouter/anthropic/claude-3.7-sonnet"),
("OPENAI_API_KEY", "gpt-4o"),
("GEMINI_API_KEY", "flash"),
]
selected_model_name = select_default_model(args, io, analytics)
if not selected_model_name:
# Error message and analytics event are handled within select_default_model
# It might have already offered OAuth if no model/keys were found.
# If it failed here, we exit.
return 1
args.model = selected_model_name # Update args with the selected model
for env_key, model_name in model_key_pairs:
if os.environ.get(env_key):
args.model = model_name
io.tool_warning(
f"Found {env_key} so using {model_name} since no --model was specified."
# Check if an OpenRouter model was selected/specified but the key is missing
if args.model.startswith("openrouter/") and not os.environ.get("OPENROUTER_API_KEY"):
io.tool_warning(
f"The specified model '{args.model}' requires an OpenRouter API key, which was not"
" found."
)
# Attempt OAuth flow because the specific model needs it
if offer_openrouter_oauth(io, analytics):
# OAuth succeeded, the key should now be in os.environ.
# Check if the key is now present after the flow.
if os.environ.get("OPENROUTER_API_KEY"):
io.tool_output(
"OpenRouter successfully connected."
) # Inform user connection worked
else:
# This case should ideally not happen if offer_openrouter_oauth succeeded
# but check defensively.
io.tool_error(
"OpenRouter authentication seemed successful, but the key is still missing."
)
break
if not args.model:
io.tool_error("You need to specify a --model and an --api-key to use.")
io.offer_url(urls.models_and_keys, "Open documentation url for more info?")
analytics.event(
"exit",
reason="OpenRouter key missing after successful OAuth for specified model",
)
return 1
else:
# OAuth failed or was declined by the user
io.tool_error(
f"Unable to proceed without an OpenRouter API key for model '{args.model}'."
)
io.offer_url(urls.models_and_keys, "Open documentation URL for more info?")
analytics.event(
"exit",
reason="OpenRouter key missing for specified model and OAuth failed/declined",
)
return 1
main_model = models.Model(
@@ -787,16 +821,43 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
"Model setting 'remove_reasoning' is deprecated, please use 'reasoning_tag' instead."
)
# Set reasoning effort if specified
# Set reasoning effort and thinking tokens if specified
if args.reasoning_effort is not None:
main_model.set_reasoning_effort(args.reasoning_effort)
# Apply if check is disabled or model explicitly supports it
if not args.check_model_accepts_settings or (
main_model.accepts_settings and "reasoning_effort" in main_model.accepts_settings
):
main_model.set_reasoning_effort(args.reasoning_effort)
# Set thinking tokens if specified
if args.thinking_tokens is not None:
main_model.set_thinking_tokens(args.thinking_tokens)
# Apply if check is disabled or model explicitly supports it
if not args.check_model_accepts_settings or (
main_model.accepts_settings and "thinking_tokens" in main_model.accepts_settings
):
main_model.set_thinking_tokens(args.thinking_tokens)
# Show warnings about unsupported settings that are being ignored
if args.check_model_accepts_settings:
settings_to_check = [
{"arg": args.reasoning_effort, "name": "reasoning_effort"},
{"arg": args.thinking_tokens, "name": "thinking_tokens"},
]
for setting in settings_to_check:
if setting["arg"] is not None and (
not main_model.accepts_settings
or setting["name"] not in main_model.accepts_settings
):
io.tool_warning(
f"Warning: {main_model.name} does not support '{setting['name']}', ignoring."
)
io.tool_output(
f"Use --no-check-model-accepts-settings to force the '{setting['name']}'"
" setting."
)
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:
@@ -842,6 +903,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
attribute_commit_message_committer=args.attribute_commit_message_committer,
commit_prompt=args.commit_prompt,
subtree_only=args.subtree_only,
git_commit_verify=args.git_commit_verify,
)
except FileNotFoundError:
pass
@@ -890,6 +952,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
else:
map_tokens = args.map_tokens
# Track auto-commits configuration
analytics.event("auto_commits", enabled=bool(args.auto_commits))
try:
coder = Coder.create(
main_model=main_model,
@@ -1036,6 +1101,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io.tool_output(f"Cur working dir: {Path.cwd()}")
io.tool_output(f"Git working dir: {git_root}")
if args.stream and args.cache_prompts:
io.tool_warning("Cost estimates may be inaccurate when using streaming and caching.")
if args.load:
commands.cmd_load(args.load)
@@ -1081,6 +1149,10 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
except SwitchCoder as switch:
coder.ok_to_warm_cache = False
# Set the placeholder if provided
if hasattr(switch, "placeholder") and switch.placeholder is not None:
io.placeholder = switch.placeholder
kwargs = dict(io=io, from_coder=coder)
kwargs.update(switch.kwargs)
if "show_announcements" in kwargs:

View File

@@ -3,9 +3,12 @@
import io
import time
from rich import box
from rich.console import Console
from rich.live import Live
from rich.markdown import Markdown
from rich.markdown import CodeBlock, Heading, Markdown
from rich.panel import Panel
from rich.syntax import Syntax
from rich.text import Text
from aider.dump import dump # noqa: F401
@@ -46,6 +49,46 @@ The end.
""" # noqa: E501
class NoInsetCodeBlock(CodeBlock):
"""A code block with syntax highlighting and no padding."""
def __rich_console__(self, console, options):
code = str(self.text).rstrip()
syntax = Syntax(code, self.lexer_name, theme=self.theme, word_wrap=True, padding=(1, 0))
yield syntax
class LeftHeading(Heading):
"""A heading class that renders left-justified."""
def __rich_console__(self, console, options):
text = self.text
text.justify = "left" # Override justification
if self.tag == "h1":
# Draw a border around h1s, but keep text left-aligned
yield Panel(
text,
box=box.HEAVY,
style="markdown.h1.border",
)
else:
# Styled text for h2 and beyond
if self.tag == "h2":
yield Text("") # Keep the blank line before h2
yield text
class NoInsetMarkdown(Markdown):
"""Markdown with code blocks that have no padding and left-justified headings."""
elements = {
**Markdown.elements,
"fence": NoInsetCodeBlock,
"code_block": NoInsetCodeBlock,
"heading_open": LeftHeading,
}
class MarkdownStream:
"""Streaming markdown renderer that progressively displays content with a live updating window.
@@ -88,7 +131,7 @@ class MarkdownStream:
# Render the markdown to a string buffer
string_io = io.StringIO()
console = Console(file=string_io, force_terminal=True)
markdown = Markdown(text, **self.mdargs)
markdown = NoInsetMarkdown(text, **self.mdargs)
console.print(markdown)
output = string_io.getvalue()
@@ -186,6 +229,7 @@ if __name__ == "__main__":
_text = _text * 10
pm = MarkdownStream()
print("Using NoInsetMarkdown for code blocks with padding=0")
for i in range(6, len(_text), 5):
pm.update(_text[:i])
time.sleep(0.01)

View File

@@ -88,8 +88,14 @@ MODEL_ALIASES = {
"3": "gpt-3.5-turbo",
# Other models
"deepseek": "deepseek/deepseek-chat",
"r1": "deepseek/deepseek-reasoner",
"flash": "gemini/gemini-2.0-flash-exp",
"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-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.
@@ -103,6 +109,7 @@ class ModelSettings:
use_repo_map: bool = False
send_undo_reply: bool = False
lazy: bool = False
overeager: bool = False
reminder: str = "user"
examples_as_sys_msg: bool = False
extra_params: Optional[dict] = None
@@ -116,6 +123,7 @@ class ModelSettings:
reasoning_tag: Optional[str] = None
remove_reasoning: Optional[str] = None # Deprecated alias for reasoning_tag
system_prompt_prefix: Optional[str] = None
accepts_settings: Optional[list] = None
# Load model settings from package resource
@@ -295,6 +303,10 @@ class Model(ModelSettings):
exact_match = True
break # Continue to apply overrides
# Initialize accepts_settings if it's None
if self.accepts_settings is None:
self.accepts_settings = []
model = model.lower()
# If no exact match, try generic settings
@@ -302,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 = {}
@@ -322,6 +338,23 @@ 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:
@@ -343,6 +376,8 @@ class Model(ModelSettings):
self.use_temperature = False
self.streaming = False
self.system_prompt_prefix = "Formatting re-enabled. "
if "reasoning_effort" not in self.accepts_settings:
self.accepts_settings.append("reasoning_effort")
return # <--
if "deepseek" in model and "v3" in model:
@@ -358,7 +393,6 @@ class Model(ModelSettings):
self.examples_as_sys_msg = True
self.use_temperature = False
self.reasoning_tag = "think"
self.reasoning_tag = "think"
return # <--
if ("llama3" in model or "llama-3" in model) and "70b" in model:
@@ -384,6 +418,15 @@ class Model(ModelSettings):
self.reminder = "sys"
return # <--
if "3-7-sonnet" in model:
self.edit_format = "diff"
self.use_repo_map = True
self.examples_as_sys_msg = True
self.reminder = "user"
if "thinking_tokens" not in self.accepts_settings:
self.accepts_settings.append("thinking_tokens")
return # <--
if "3.5-sonnet" in model or "3-5-sonnet" in model:
self.edit_format = "diff"
self.use_repo_map = True
@@ -464,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
@@ -572,6 +617,21 @@ class Model(ModelSettings):
model = self.name
res = litellm.validate_environment(model)
# If missing AWS credential keys but AWS_PROFILE is set, consider AWS credentials valid
if res["missing_keys"] and any(
key in ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] for key in res["missing_keys"]
):
if model.startswith("bedrock/") or model.startswith("us.anthropic."):
if os.environ.get("AWS_PROFILE"):
res["missing_keys"] = [
k
for k in res["missing_keys"]
if k not in ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"]
]
if not res["missing_keys"]:
res["keys_in_environment"] = True
if res["keys_in_environment"]:
return res
if res["missing_keys"]:
@@ -646,16 +706,33 @@ class Model(ModelSettings):
self.use_temperature = False
if not self.extra_params:
self.extra_params = {}
self.extra_params["thinking"] = {"type": "enabled", "budget_tokens": num_tokens}
def get_thinking_tokens(self, model):
# OpenRouter models use 'reasoning' instead of 'thinking'
if self.name.startswith("openrouter/"):
self.extra_params["reasoning"] = {"max_tokens": num_tokens}
else:
self.extra_params["thinking"] = {"type": "enabled", "budget_tokens": num_tokens}
def get_raw_thinking_tokens(self):
"""Get formatted thinking token budget if available"""
if (
model.extra_params
and "thinking" in model.extra_params
and "budget_tokens" in model.extra_params["thinking"]
):
budget = model.extra_params["thinking"]["budget_tokens"]
budget = None
if self.extra_params:
# Check for OpenRouter reasoning format
if "reasoning" in self.extra_params and "max_tokens" in self.extra_params["reasoning"]:
budget = self.extra_params["reasoning"]["max_tokens"]
# Check for standard thinking format
elif (
"thinking" in self.extra_params and "budget_tokens" in self.extra_params["thinking"]
):
budget = self.extra_params["thinking"]["budget_tokens"]
return budget
def get_thinking_tokens(self):
budget = self.get_raw_thinking_tokens()
if budget is not None:
# Format as xx.yK for thousands, xx.yM for millions
if budget >= 1024 * 1024:
value = budget / (1024 * 1024)
@@ -671,14 +748,14 @@ class Model(ModelSettings):
return f"{value:.1f}k"
return None
def get_reasoning_effort(self, model):
def get_reasoning_effort(self):
"""Get reasoning effort value if available"""
if (
model.extra_params
and "extra_body" in model.extra_params
and "reasoning_effort" in model.extra_params["extra_body"]
self.extra_params
and "extra_body" in self.extra_params
and "reasoning_effort" in self.extra_params["extra_body"]
):
return model.extra_params["extra_body"]["reasoning_effort"]
return self.extra_params["extra_body"]["reasoning_effort"]
return None
def is_deepseek_r1(self):
@@ -699,7 +776,6 @@ class Model(ModelSettings):
kwargs = dict(
model=self.name,
messages=messages,
stream=stream,
)
@@ -730,6 +806,8 @@ class Model(ModelSettings):
kwargs["timeout"] = request_timeout
if self.verbose:
dump(kwargs)
kwargs["messages"] = messages
res = litellm.completion(**kwargs)
return hash_object, res
@@ -924,7 +1002,10 @@ def fuzzy_match_models(name):
name = name.lower()
chat_models = set()
for orig_model, attrs in litellm.model_cost.items():
model_metadata = list(litellm.model_cost.items())
model_metadata += list(model_info_manager.local_model_metadata.items())
for orig_model, attrs in model_metadata:
model = orig_model.lower()
if attrs.get("mode") != "chat":
continue

428
aider/onboarding.py Normal file
View File

@@ -0,0 +1,428 @@
import base64
import hashlib
import http.server
import os
import secrets
import socketserver
import threading
import time
import webbrowser
from urllib.parse import parse_qs, urlparse
import requests
from aider import urls
from aider.io import InputOutput
def check_openrouter_tier(api_key):
"""
Checks if the user is on a free tier for OpenRouter.
Args:
api_key: The OpenRouter API key to check.
Returns:
A boolean indicating if the user is on a free tier (True) or paid tier (False).
Returns True if the check fails.
"""
try:
response = requests.get(
"https://openrouter.ai/api/v1/auth/key",
headers={"Authorization": f"Bearer {api_key}"},
timeout=5, # Add a reasonable timeout
)
response.raise_for_status()
data = response.json()
# According to the documentation, 'is_free_tier' will be true if the user has never paid
return data.get("data", {}).get("is_free_tier", True) # Default to True if not found
except Exception:
# If there's any error, we'll default to assuming free tier
return True
def try_to_select_default_model():
"""
Attempts to select a default model based on available API keys.
Checks OpenRouter tier status to select appropriate model.
Returns:
The name of the selected model, or None if no suitable default is found.
"""
# Special handling for OpenRouter
openrouter_key = os.environ.get("OPENROUTER_API_KEY")
if openrouter_key:
# Check if the user is on a free tier
is_free_tier = check_openrouter_tier(openrouter_key)
if is_free_tier:
return "openrouter/google/gemini-2.5-pro-exp-03-25:free"
else:
return "openrouter/anthropic/claude-3.7-sonnet"
# Select model based on other available API keys
model_key_pairs = [
("ANTHROPIC_API_KEY", "sonnet"),
("DEEPSEEK_API_KEY", "deepseek"),
("OPENAI_API_KEY", "gpt-4o"),
("GEMINI_API_KEY", "gemini/gemini-2.5-pro-exp-03-25"),
("VERTEXAI_PROJECT", "vertex_ai/gemini-2.5-pro-exp-03-25"),
]
for env_key, model_name in model_key_pairs:
api_key_value = os.environ.get(env_key)
if api_key_value:
return model_name
return None
def offer_openrouter_oauth(io, analytics):
"""
Offers OpenRouter OAuth flow to the user if no API keys are found.
Args:
io: The InputOutput object for user interaction.
analytics: The Analytics object for tracking events.
Returns:
True if authentication was successful, False otherwise.
"""
# No API keys found - Offer OpenRouter OAuth
io.tool_output("OpenRouter provides free and paid access to many LLMs.")
# Use confirm_ask which handles non-interactive cases
if io.confirm_ask(
"Login to OpenRouter or create a free account?",
default="y",
):
analytics.event("oauth_flow_initiated", provider="openrouter")
openrouter_key = start_openrouter_oauth_flow(io, analytics)
if openrouter_key:
# Successfully got key via OAuth, use the default OpenRouter model
# Ensure OPENROUTER_API_KEY is now set in the environment for later use
os.environ["OPENROUTER_API_KEY"] = openrouter_key
# Track OAuth success leading to model selection
analytics.event("oauth_flow_success")
return True
# OAuth failed or was cancelled by user implicitly (e.g., closing browser)
# Error messages are handled within start_openrouter_oauth_flow
analytics.event("oauth_flow_failure")
io.tool_error("OpenRouter authentication did not complete successfully.")
# Fall through to the final error message
return False
def select_default_model(args, io, analytics):
"""
Selects a default model based on available API keys if no model is specified.
Offers OAuth flow for OpenRouter if no keys are found.
Args:
args: The command line arguments object.
io: The InputOutput object for user interaction.
analytics: The Analytics object for tracking events.
Returns:
The name of the selected model, or None if no suitable default is found.
"""
if args.model:
return args.model # Model already specified
model = try_to_select_default_model()
if model:
io.tool_warning(f"Using {model} model with API key from environment.")
analytics.event("auto_model_selection", model=model)
return model
no_model_msg = "No LLM model was specified and no API keys were provided."
io.tool_warning(no_model_msg)
# Try OAuth if no model was detected
offer_openrouter_oauth(io, analytics)
# Check again after potential OAuth success
model = try_to_select_default_model()
if model:
return model
io.offer_url(urls.models_and_keys, "Open documentation URL for more info?")
# Helper function to find an available port
def find_available_port(start_port=8484, end_port=8584):
for port in range(start_port, end_port + 1):
try:
# Check if the port is available by trying to bind to it
with socketserver.TCPServer(("localhost", port), None):
return port
except OSError:
# Port is likely already in use
continue
return None
# PKCE code generation
def generate_pkce_codes():
code_verifier = secrets.token_urlsafe(64)
hasher = hashlib.sha256()
hasher.update(code_verifier.encode("utf-8"))
code_challenge = base64.urlsafe_b64encode(hasher.digest()).rstrip(b"=").decode("utf-8")
return code_verifier, code_challenge
# Function to exchange the authorization code for an API key
def exchange_code_for_key(code, code_verifier, io):
try:
response = requests.post(
"https://openrouter.ai/api/v1/auth/keys",
headers={"Content-Type": "application/json"},
json={
"code": code,
"code_verifier": code_verifier,
"code_challenge_method": "S256",
},
timeout=30, # Add a timeout
)
response.raise_for_status() # Raise exception for bad status codes (4xx or 5xx)
data = response.json()
api_key = data.get("key")
if not api_key:
io.tool_error("Error: 'key' not found in OpenRouter response.")
io.tool_error(f"Response: {response.text}")
return None
return api_key
except requests.exceptions.Timeout:
io.tool_error("Error: Request to OpenRouter timed out during code exchange.")
return None
except requests.exceptions.HTTPError as e:
io.tool_error(
"Error exchanging code for OpenRouter key:"
f" {e.response.status_code} {e.response.reason}"
)
io.tool_error(f"Response: {e.response.text}")
return None
except requests.exceptions.RequestException as e:
io.tool_error(f"Error exchanging code for OpenRouter key: {e}")
return None
except Exception as e:
io.tool_error(f"Unexpected error during code exchange: {e}")
return None
# Function to start the OAuth flow
def start_openrouter_oauth_flow(io, analytics):
"""Initiates the OpenRouter OAuth PKCE flow using a local server."""
port = find_available_port()
if not port:
io.tool_error("Could not find an available port between 8484 and 8584.")
io.tool_error("Please ensure a port in this range is free, or configure manually.")
return None
callback_url = f"http://localhost:{port}/callback/aider"
auth_code = None
server_error = None
server_started = threading.Event()
shutdown_server = threading.Event()
class OAuthCallbackHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
nonlocal auth_code, server_error
parsed_path = urlparse(self.path)
if parsed_path.path == "/callback/aider":
query_params = parse_qs(parsed_path.query)
if "code" in query_params:
auth_code = query_params["code"][0]
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(
b"<html><body><h1>Success!</h1>"
b"<p>Aider has received the authentication code. "
b"You can close this browser tab.</p></body></html>"
)
# Signal the main thread to shut down the server
# Signal the main thread to shut down the server
shutdown_server.set()
else:
# Redirect to aider website if 'code' is missing (e.g., user visited manually)
self.send_response(302) # Found (temporary redirect)
self.send_header("Location", urls.website)
self.end_headers()
# No need to set server_error, just redirect.
# Do NOT shut down the server here; wait for timeout or success.
else:
# Redirect anything else (e.g., favicon.ico) to the main website as well
self.send_response(302)
self.send_header("Location", urls.website)
self.end_headers()
self.wfile.write(b"Not Found")
def log_message(self, format, *args):
# Suppress server logging to keep terminal clean
pass
def run_server():
nonlocal server_error
try:
with socketserver.TCPServer(("localhost", port), OAuthCallbackHandler) as httpd:
io.tool_output(f"Temporary server listening on {callback_url}", log_only=True)
server_started.set() # Signal that the server is ready
# Wait until shutdown is requested or timeout occurs (handled by main thread)
while not shutdown_server.is_set():
httpd.handle_request() # Handle one request at a time
# Add a small sleep to prevent busy-waiting if needed,
# though handle_request should block appropriately.
time.sleep(0.1)
io.tool_output("Shutting down temporary server.", log_only=True)
except Exception as e:
server_error = f"Failed to start or run temporary server: {e}"
server_started.set() # Signal even if failed, error will be checked
shutdown_server.set() # Ensure shutdown logic proceeds
server_thread = threading.Thread(target=run_server, daemon=True)
server_thread.start()
# Wait briefly for the server to start, or for an error
if not server_started.wait(timeout=5):
io.tool_error("Temporary authentication server failed to start in time.")
shutdown_server.set() # Ensure thread exits if it eventually starts
server_thread.join(timeout=1)
return None
# Check if server failed during startup
if server_error:
io.tool_error(server_error)
shutdown_server.set() # Ensure thread exits
server_thread.join(timeout=1)
return None
# Generate codes and URL
code_verifier, code_challenge = generate_pkce_codes()
auth_url_base = "https://openrouter.ai/auth"
auth_params = {
"callback_url": callback_url,
"code_challenge": code_challenge,
"code_challenge_method": "S256",
}
auth_url = f"{auth_url_base}?{'&'.join(f'{k}={v}' for k, v in auth_params.items())}"
io.tool_output("\nPlease open this URL in your browser to connect Aider with OpenRouter:")
io.tool_output()
print(auth_url)
MINUTES = 5
io.tool_output(f"\nWaiting up to {MINUTES} minutes for you to finish in the browser...")
io.tool_output("Use Control-C to interrupt.")
try:
webbrowser.open(auth_url)
except Exception:
pass
# Wait for the callback to set the auth_code or for timeout/error
interrupted = False
try:
shutdown_server.wait(timeout=MINUTES * 60) # Convert minutes to seconds
except KeyboardInterrupt:
io.tool_warning("\nOAuth flow interrupted.")
analytics.event("oauth_flow_failed", provider="openrouter", reason="user_interrupt")
interrupted = True
# Ensure the server thread is signaled to shut down
shutdown_server.set()
# Join the server thread to ensure it's cleaned up
server_thread.join(timeout=1)
if interrupted:
return None # Return None if interrupted by user
if server_error:
io.tool_error(f"Authentication failed: {server_error}")
analytics.event("oauth_flow_failed", provider="openrouter", reason=server_error)
return None
if not auth_code:
io.tool_error("Authentication with OpenRouter failed.")
analytics.event("oauth_flow_failed", provider="openrouter")
return None
io.tool_output("Completing authentication...")
analytics.event("oauth_flow_code_received", provider="openrouter")
# Exchange code for key
api_key = exchange_code_for_key(auth_code, code_verifier, io)
if api_key:
# Set env var for the current session immediately
os.environ["OPENROUTER_API_KEY"] = api_key
# Save the key to the oauth-keys.env file
try:
config_dir = os.path.expanduser("~/.aider")
os.makedirs(config_dir, exist_ok=True)
key_file = os.path.join(config_dir, "oauth-keys.env")
with open(key_file, "a", encoding="utf-8") as f:
f.write(f'OPENROUTER_API_KEY="{api_key}"\n')
io.tool_warning("Aider will load the OpenRouter key automatically in future sessions.")
io.tool_output()
analytics.event("oauth_flow_success", provider="openrouter")
return api_key
except Exception as e:
io.tool_error(f"Successfully obtained key, but failed to save it to file: {e}")
io.tool_warning("Set OPENROUTER_API_KEY environment variable for this session only.")
# Still return the key for the current session even if saving failed
analytics.event("oauth_flow_save_failed", provider="openrouter", reason=str(e))
return api_key
else:
io.tool_error("Authentication with OpenRouter failed.")
analytics.event("oauth_flow_failed", provider="openrouter", reason="code_exchange_failed")
return None
# Dummy Analytics class for testing
class DummyAnalytics:
def event(self, *args, **kwargs):
# print(f"Analytics Event: {args} {kwargs}") # Optional: print events
pass
def main():
"""Main function to test the OpenRouter OAuth flow."""
print("Starting OpenRouter OAuth flow test...")
# Use a real IO object for interaction
io = InputOutput(
pretty=True,
yes=False,
input_history_file=None,
chat_history_file=None,
tool_output_color="BLUE",
tool_error_color="RED",
)
# Use a dummy analytics object
analytics = DummyAnalytics()
# Ensure OPENROUTER_API_KEY is not set, to trigger the flow naturally
# (though start_openrouter_oauth_flow doesn't check this itself)
if "OPENROUTER_API_KEY" in os.environ:
print("Warning: OPENROUTER_API_KEY is already set in environment.")
# del os.environ["OPENROUTER_API_KEY"] # Optionally unset it for testing
api_key = start_openrouter_oauth_flow(io, analytics)
if api_key:
print("\nOAuth flow completed successfully!")
print(f"Obtained API Key (first 5 chars): {api_key[:5]}...")
# Be careful printing the key, even partially
else:
print("\nOAuth flow failed or was cancelled.")
print("\nOpenRouter OAuth flow test finished.")
if __name__ == "__main__":
main()

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

@@ -0,0 +1,65 @@
; Definitions
(package_clause
name: (package_identifier) @name.definition.module) @definition.module
(trait_definition
name: (identifier) @name.definition.interface) @definition.interface
(enum_definition
name: (identifier) @name.definition.enum) @definition.enum
(simple_enum_case
name: (identifier) @name.definition.class) @definition.class
(full_enum_case
name: (identifier) @name.definition.class) @definition.class
(class_definition
name: (identifier) @name.definition.class) @definition.class
(object_definition
name: (identifier) @name.definition.object) @definition.object
(function_definition
name: (identifier) @name.definition.function) @definition.function
(val_definition
pattern: (identifier) @name.definition.variable) @definition.variable
(given_definition
name: (identifier) @name.definition.variable) @definition.variable
(var_definition
pattern: (identifier) @name.definition.variable) @definition.variable
(val_declaration
name: (identifier) @name.definition.variable) @definition.variable
(var_declaration
name: (identifier) @name.definition.variable) @definition.variable
(type_definition
name: (type_identifier) @name.definition.type) @definition.type
(class_parameter
name: (identifier) @name.definition.property) @definition.property
; References
(call_expression
(identifier) @name.reference.call) @reference.call
(instance_expression
(type_identifier) @name.reference.interface) @reference.interface
(instance_expression
(generic_type
(type_identifier) @name.reference.interface)) @reference.interface
(extends_clause
(type_identifier) @name.reference.class) @reference.class
(extends_clause
(generic_type
(type_identifier) @name.reference.class)) @reference.class

View File

@@ -9,6 +9,7 @@ try:
git.exc.ODBError,
git.exc.GitError,
git.exc.InvalidGitRepositoryError,
git.exc.GitCommandNotFound,
]
except ImportError:
git = None
@@ -56,6 +57,7 @@ class GitRepo:
attribute_commit_message_committer=False,
commit_prompt=None,
subtree_only=False,
git_commit_verify=True,
):
self.io = io
self.models = models
@@ -69,6 +71,7 @@ class GitRepo:
self.attribute_commit_message_committer = attribute_commit_message_committer
self.commit_prompt = commit_prompt
self.subtree_only = subtree_only
self.git_commit_verify = git_commit_verify
self.ignore_file_cache = {}
if git_dname:
@@ -133,7 +136,9 @@ class GitRepo:
# if context:
# full_commit_message += "\n\n# Aider chat conversation:\n\n" + context
cmd = ["-m", full_commit_message, "--no-verify"]
cmd = ["-m", full_commit_message]
if not self.git_commit_verify:
cmd.append("--no-verify")
if fnames:
fnames = [str(self.abs_root_path(fn)) for fn in fnames]
for fname in fnames:
@@ -289,13 +294,19 @@ class GitRepo:
else:
try:
iterator = commit.tree.traverse()
blob = None # Initialize blob
while True:
try:
blob = next(iterator)
if blob.type == "blob": # blob is a file
files.add(blob.path)
except IndexError:
self.io.tool_warning(f"GitRepo: read error skipping {blob.path}")
# Handle potential index error during tree traversal
# without relying on potentially unassigned 'blob'
self.io.tool_warning(
"GitRepo: Index error encountered while reading git tree object."
" Skipping."
)
continue
except StopIteration:
break

View File

@@ -398,13 +398,30 @@ class RepoMap:
# dump(fname)
rel_fname = self.get_rel_fname(fname)
current_pers = 0.0 # Start with 0 personalization score
if fname in chat_fnames:
personalization[rel_fname] = personalize
current_pers += personalize
chat_rel_fnames.add(rel_fname)
if rel_fname in mentioned_fnames:
personalization[rel_fname] = personalize
# Use max to avoid double counting if in chat_fnames and mentioned_fnames
current_pers = max(current_pers, personalize)
# Check path components against mentioned_idents
path_obj = Path(rel_fname)
path_components = set(path_obj.parts)
basename_with_ext = path_obj.name
basename_without_ext, _ = os.path.splitext(basename_with_ext)
components_to_check = path_components.union({basename_with_ext, basename_without_ext})
matched_idents = components_to_check.intersection(mentioned_idents)
if matched_idents:
# Add personalization *once* if any path component matches a mentioned ident
current_pers += personalize
if current_pers > 0:
personalization[rel_fname] = current_pers # Assign the final calculated value
tags = list(self.get_tags(fname, rel_fname))
if tags is None:
@@ -445,12 +462,19 @@ class RepoMap:
progress()
definers = defines[ident]
mul = 1.0
is_snake = ("_" in ident) and any(c.isalpha() for c in ident)
is_camel = any(c.isupper() for c in ident) and any(c.islower() for c in ident)
if ident in mentioned_idents:
mul = 10
elif ident.startswith("_"):
mul = 0.1
else:
mul = 1
mul *= 10
if (is_snake or is_camel) and len(ident) >= 8:
mul *= 10
if ident.startswith("_"):
mul *= 0.1
if len(defines[ident]) > 5:
mul *= 0.1
for referencer, num_refs in Counter(references[ident]).items():
for definer in definers:
@@ -458,10 +482,14 @@ class RepoMap:
# if referencer == definer:
# continue
use_mul = mul
if referencer in chat_rel_fnames:
use_mul *= 50
# scale down so high freq (low value) mentions don't dominate
num_refs = math.sqrt(num_refs)
G.add_edge(referencer, definer, weight=mul * num_refs, ident=ident)
G.add_edge(referencer, definer, weight=use_mul * num_refs, ident=ident)
if not references:
pass

View File

@@ -63,6 +63,33 @@
//"supports_tool_choice": true,
"supports_prompt_caching": true
},
"openrouter/deepseek/deepseek-chat-v3-0324": {
"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-chat-v3-0324:free": {
"max_tokens": 131072,
"max_input_tokens": 131072,
"max_output_tokens": 131072,
"input_cost_per_token": 0,
"output_cost_per_token": 0,
"litellm_provider": "openrouter",
"supports_prompt_caching": true,
"mode": "chat",
"supports_tool_choice": true
},
"fireworks_ai/accounts/fireworks/models/deepseek-r1": {
"max_tokens": 160000,
"max_input_tokens": 128000,
@@ -81,6 +108,15 @@
"output_cost_per_token": 0.0000009,
"mode": "chat",
},
"fireworks_ai/accounts/fireworks/models/deepseek-v3-0324": {
"max_tokens": 160000,
"max_input_tokens": 100000,
"max_output_tokens": 8192,
"litellm_provider": "fireworks_ai",
"input_cost_per_token": 0.0000009,
"output_cost_per_token": 0.0000009,
"mode": "chat",
},
"o3-mini": {
"max_tokens": 100000,
"max_input_tokens": 200000,
@@ -129,6 +165,26 @@
"supports_system_messages": true,
"supports_response_schema": true
},
"openrouter/openrouter/quasar-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",
"supports_vision": true,
"supports_function_calling": true,
"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,
@@ -241,4 +297,312 @@
"supports_system_messages": true,
"supports_tool_choice": true
},
"gemini/gemini-2.5-pro-exp-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,
"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,
"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",
"litellm_provider": "gemini",
"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"
},
"gemini/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": "gemini",
"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"
},
"vertex_ai/gemini-2.5-pro-exp-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,
"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,
"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"
},
"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,
"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,
"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,
"output_cost_per_character": 0,
"output_cost_per_token_above_128k_tokens": 0,
"output_cost_per_character_above_128k_tokens": 0,
"litellm_provider": "openrouter",
"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/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"
},
"xai/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": "xai",
"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"
},
"xai/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": "xai",
"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"
},
"xai/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": "xai",
"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"
},
"xai/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": "xai",
"mode": "chat"
},
"openrouter/google/gemini-2.0-flash-exp:free": {
"max_tokens": 8192,
"max_input_tokens": 1048576,
"max_output_tokens": 8192,
"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,
"litellm_provider": "openrouter",
"mode": "chat",
"supports_system_messages": true,
"supports_function_calling": true,
"supports_vision": true,
"supports_response_schema": true,
"supports_audio_output": true,
"supports_tool_choice": true
},
}

View File

@@ -185,6 +185,7 @@
editor_edit_format: editor-diff
- name: anthropic/claude-3-7-sonnet-20250219
overeager: true
edit_format: diff
weak_model_name: anthropic/claude-3-5-haiku-20241022
use_repo_map: true
@@ -196,8 +197,10 @@
cache_control: true
editor_model_name: anthropic/claude-3-7-sonnet-20250219
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: anthropic/claude-3-7-sonnet-latest
overeager: true
edit_format: diff
weak_model_name: anthropic/claude-3-5-haiku-20241022
use_repo_map: true
@@ -209,6 +212,7 @@
cache_control: true
editor_model_name: anthropic/claude-3-7-sonnet-latest
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: claude-3-7-sonnet-20250219
edit_format: diff
@@ -222,8 +226,10 @@
cache_control: true
editor_model_name: claude-3-7-sonnet-20250219
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: claude-3-7-sonnet-latest
overeager: true
edit_format: diff
weak_model_name: claude-3-5-haiku-20241022
use_repo_map: true
@@ -235,8 +241,10 @@
cache_control: true
editor_model_name: claude-3-7-sonnet-latest
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0
overeager: true
edit_format: diff
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
use_repo_map: true
@@ -248,8 +256,10 @@
cache_control: true
editor_model_name: bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0
overeager: true
edit_format: diff
weak_model_name: bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0
use_repo_map: true
@@ -261,8 +271,10 @@
cache_control: true
editor_model_name: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: bedrock_converse/anthropic.claude-3-7-sonnet-20250219-v1:0
overeager: true
edit_format: diff
weak_model_name: bedrock_converse/anthropic.claude-3-5-haiku-20241022-v1:0
use_repo_map: true
@@ -274,8 +286,10 @@
cache_control: true
editor_model_name: bedrock_converse/anthropic.claude-3-7-sonnet-20250219-v1:0
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: bedrock_converse/us.anthropic.claude-3-7-sonnet-20250219-v1:0
overeager: true
edit_format: diff
weak_model_name: bedrock_converse/us.anthropic.claude-3-5-haiku-20241022-v1:0
use_repo_map: true
@@ -287,8 +301,10 @@
cache_control: true
editor_model_name: bedrock_converse/us.anthropic.claude-3-7-sonnet-20250219-v1:0
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: vertex_ai/claude-3-7-sonnet@20250219
overeager: true
edit_format: diff
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
use_repo_map: true
@@ -297,8 +313,10 @@
max_tokens: 64000
editor_model_name: vertex_ai/claude-3-7-sonnet@20250219
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: vertex_ai-anthropic_models/vertex_ai/claude-3-7-sonnet@20250219
overeager: true
edit_format: diff
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
use_repo_map: true
@@ -307,8 +325,10 @@
max_tokens: 64000
editor_model_name: vertex_ai-anthropic_models/vertex_ai/claude-3-7-sonnet@20250219
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: openrouter/anthropic/claude-3.7-sonnet
overeager: true
edit_format: diff
weak_model_name: openrouter/anthropic/claude-3-5-haiku
use_repo_map: true
@@ -320,8 +340,10 @@
cache_control: true
editor_model_name: openrouter/anthropic/claude-3.7-sonnet
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: openrouter/anthropic/claude-3.7-sonnet:beta
overeager: true
edit_format: diff
weak_model_name: openrouter/anthropic/claude-3-5-haiku
use_repo_map: true
@@ -333,6 +355,7 @@
cache_control: true
editor_model_name: openrouter/anthropic/claude-3.7-sonnet
editor_edit_format: editor-diff
accepts_settings: ["thinking_tokens"]
- name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0
edit_format: diff
@@ -560,6 +583,16 @@
extra_params:
max_tokens: 8192
caches_by_default: true
- name: openrouter/deepseek/deepseek-chat-v3-0324:free
edit_format: diff
weak_model_name: openrouter/deepseek/deepseek-chat-v3-0324:free
use_repo_map: true
examples_as_sys_msg: true
caches_by_default: true
use_temperature: false
editor_model_name: openrouter/deepseek/deepseek-chat-v3-0324:free
editor_edit_format: editor-diff
use_temperature: false
editor_model_name: openrouter/deepseek/deepseek-r1:free
editor_edit_format: editor-diff
@@ -635,6 +668,15 @@
reminder: sys
examples_as_sys_msg: true
- name: openrouter/deepseek/deepseek-chat-v3-0324
edit_format: diff
use_repo_map: true
reminder: sys
examples_as_sys_msg: true
extra_params:
max_tokens: 8192
caches_by_default: true
- name: openrouter/openai/gpt-4o
edit_format: diff
weak_model_name: openrouter/openai/gpt-4o-mini
@@ -694,6 +736,7 @@
streaming: false
editor_model_name: azure/gpt-4o
editor_edit_format: editor-diff
accepts_settings: ["reasoning_effort"]
- name: o1-preview
edit_format: architect
@@ -732,6 +775,7 @@
editor_model_name: openrouter/openai/gpt-4o
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: openai/o1
edit_format: diff
@@ -742,6 +786,7 @@
editor_model_name: openai/gpt-4o
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: o1
edit_format: diff
@@ -752,6 +797,7 @@
editor_model_name: gpt-4o
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: openrouter/qwen/qwen-2.5-coder-32b-instruct
edit_format: diff
@@ -771,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
@@ -792,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
@@ -800,7 +854,8 @@
editor_model_name: gpt-4o
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
@@ -809,6 +864,7 @@
editor_model_name: gpt-4o
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: openrouter/openai/o3-mini
edit_format: diff
@@ -818,6 +874,7 @@
editor_model_name: openrouter/openai/gpt-4o
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: openrouter/openai/o3-mini-high
edit_format: diff
@@ -827,6 +884,7 @@
editor_model_name: openrouter/openai/gpt-4o
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: azure/o3-mini
edit_format: diff
@@ -836,6 +894,7 @@
editor_model_name: azure/gpt-4o
editor_edit_format: editor-diff
system_prompt_prefix: "Formatting re-enabled. "
accepts_settings: ["reasoning_effort"]
- name: gpt-4.5-preview
edit_format: diff
@@ -846,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
@@ -891,10 +950,420 @@
- 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-preview-03-25
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
weak_model_name: gemini/gemini-2.0-flash
- name: openrouter/google/gemini-2.5-pro-exp-03-25:free
edit_format: diff-fenced
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
- name: vertex_ai/gemini-2.5-pro-preview-03-25
edit_format: diff-fenced
use_repo_map: true
# Need metadata for this one...
#weak_model_name: vertex_ai/gemini-2.0-flash
- 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

View File

@@ -159,7 +159,8 @@ class Scraper:
try:
response = page.goto(url, wait_until="networkidle", timeout=5000)
except PlaywrightTimeoutError:
self.print_error(f"Timeout while loading {url}")
print(f"Page didn't quiesce, scraping content anyway: {url}")
response = None
except PlaywrightError as e:
self.print_error(f"Error navigating to {url}: {str(e)}")
return None, None

View File

@@ -308,7 +308,11 @@ def find_common_root(abs_fnames):
except OSError:
pass
return safe_abs_path(os.getcwd())
try:
return safe_abs_path(os.getcwd())
except FileNotFoundError:
# Fallback if cwd is deleted
return "."
def format_tokens(count):

View File

@@ -64,7 +64,7 @@ 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
@@ -262,7 +262,7 @@ class FileWatcher:
line_nums.append(i)
comments.append(comment)
comment = comment.lower()
comment = comment.lstrip("/#-")
comment = comment.lstrip("/#-;") # Added semicolon for Lisp comments
comment = comment.strip()
if comment.startswith("ai!") or comment.endswith("ai!"):
has_action = "!"

View File

@@ -7,12 +7,13 @@ description: Release notes and stats on aider writing its own code.
# Release history
{% include blame.md %}
The above
[stats are based on the git commit history](/docs/faq.html#how-are-the-aider-wrote-xx-of-code-stats-computed)
Aider writes most of its own code, usually about 70-80% of the new code in each release.
These
[statistics are based on the git commit history](/docs/faq.html#how-are-the-aider-wrote-xx-of-code-stats-computed)
of the aider repo.
{% include blame.md %}
## Release notes
<!--[[[cog
@@ -23,11 +24,138 @@ cog.out(text)
]]]-->
### main branch
### 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.
- Run with `aider --model quasar`
- Offer OpenRouter OAuth authentication if an OpenRouter model is specified but the API key is missing.
- Prevent retrying API calls when the provider reports insufficient credits.
- Improve URL detection to exclude trailing double quotes.
- Aider wrote 86% of the code in this release.
### Aider v0.80.4
- Bumped deps to pickup litellm change to properly display the root cause of OpenRouter "choices" errors.
### Aider v0.80.3
- Improve error message for OpenRouter API connection issues to mention potential rate limiting or upstream provider issues.
- Configure weak models (`gemini/gemini-2.0-flash` and `openrouter/google/gemini-2.0-flash-exp:free`) for Gemini 2.5 Pro models.
- Add model metadata for `openrouter/google/gemini-2.0-flash-exp:free`.
### Aider v0.80.2
- Bumped deps.
### Aider v0.80.1
- Updated deps for yanked fsspec and aiohttp packages #3699
- Removed redundant dependency check during OpenRouter OAuth flow, by Claudia Pellegrino.
### Aider v0.80.0
- OpenRouter OAuth integration:
- Offer to OAuth against OpenRouter if no model and keys are provided.
- Select OpenRouter default model based on free/paid tier status if `OPENROUTER_API_KEY` is set and no model is specified.
- Prioritize `gemini/gemini-2.5-pro-exp-03-25` if `GEMINI_API_KEY` is set, and `vertex_ai/gemini-2.5-pro-exp-03-25` if `VERTEXAI_PROJECT` is set, when no model is specified.
- Validate user-configured color settings on startup and warn/disable invalid ones.
- Warn at startup if `--stream` and `--cache-prompts` are used together, as cost estimates may be inaccurate.
- Boost repomap ranking for files whose path components match identifiers mentioned in the chat.
- Change web scraping timeout from an error to a warning, allowing scraping to continue with potentially incomplete content.
- Left-align markdown headings in the terminal output, by Peter Schilling.
- Update edit format to the new model's default when switching models with `/model`, if the user was using the old model's default format.
- Add `Ctrl-X Ctrl-E` keybinding to edit the current input buffer in an external editor, by Matteo Landi.
- Fix linting errors for filepaths containing shell metacharacters, by Mir Adnan ALI.
- Add the `openrouter/deepseek-chat-v3-0324:free` model.
- Add repomap support for the Scala language, by Vasil Markoukin.
- Fixed bug in `/run` that was preventing auto-testing.
- Fix bug preventing `UnboundLocalError` during git tree traversal.
- Handle `GitCommandNotFound` error if git is not installed or not in PATH.
- Handle `FileNotFoundError` if the current working directory is deleted while aider is running.
- Fix completion menu current item color styling, by Andrey Ivanov.
- Aider wrote 87% of the code in this release.
### Aider v0.79.2
- Added 'gemini' alias for gemini-2.5-pro model.
- Updated Gemini 2.5 Pro max output tokens to 64k.
- Added support for Lisp-style semicolon comments in file watcher, by Matteo Landi.
- Added OpenRouter API error detection and retries.
- Added openrouter/deepseek-chat-v3-0324 model.
- Aider wrote 93% of the code in this release.
### Aider v0.79.1
- Improved model listing to include all models in fuzzy matching, including those provided by aider (not litellm).
### Aider v0.79.0
- Added support for Gemini 2.5 Pro models.
- Added support for DeepSeek V3 0324 model.
- Added a new `/context` command that automatically identifies which files need to be edited for a given request.
- Added `/edit` as an alias for the `/editor` command.
- Added "overeager" mode for Claude 3.7 Sonnet models to try and keep it working within the requested scope.
- Aider wrote 65% of the code in this release.
### Aider v0.78.0
- Added support for thinking tokens for OpenRouter Sonnet 3.7.
- Added commands to switch between model types: `/editor-model` for Editor Model, and `/weak-model` for Weak Model, by csala.
- Added model setting validation to ignore `--reasoning-effort` and `--thinking-tokens` if the model doesn't support them.
- Added `--check-model-accepts-settings` flag (default: true) to force unsupported model settings.
- Annotated which models support reasoning_effort and thinking_tokens settings in the model settings data.
- Improved code block rendering in markdown output with better padding using NoInsetMarkdown.
- Added `--git-commit-verify` flag (default: False) to control whether git commit hooks are bypassed.
- Fixed autocompletion for `/ask`, `/code`, and `/architect` commands, by shladnik.
- Added vi-like behavior when pressing enter in multiline-mode while in vi normal/navigation-mode, by Marco Mayer.
- Added AWS_PROFILE support for Bedrock models, allowing use of AWS profiles instead of explicit credentials, by lentil32.
- Enhanced `--aiderignore` argument to resolve both absolute and relative paths, by mopemope.
- Improved platform information handling to gracefully handle retrieval errors.
- Aider wrote 92% of the code in this release.
### Aider v0.77.1
- Bumped dependencies to pickup litellm fix for Ollama.
- Added support for `openrouter/google/gemma-3-27b-it` model.
- Aider wrote 96% of the code in this release.
- Updated exclude patterns for help documentation.
### Aider v0.77.0

View File

@@ -51,4 +51,19 @@ callouts:
note:
title: Note
color: yellow
# Custom CSS for our table of contents
kramdown:
syntax_highlighter_opts:
css_class: highlight
sass:
style: compressed
# Additional CSS
compress_html:
clippings: all
comments: all
endings: all
startings: []

View File

@@ -4175,3 +4175,328 @@
Yutaka Matsubara: 4
start_tag: v0.76.0
total_lines: 1945
- aider_percentage: 91.82
aider_total: 2682
end_date: '2025-03-21'
end_tag: v0.78.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/args.py:
Paul Gauthier (aider): 24
Yutaka Matsubara: 2
aider/coders/base_coder.py:
Paul Gauthier: 1
Paul Gauthier (aider): 6
aider/commands.py:
Carles Sala (aider): 30
Paul Gauthier (aider): 10
aider/help_pats.py:
Paul Gauthier: 6
aider/io.py:
Marco Mayer: 2
Paul Gauthier (aider): 17
aider/main.py:
Paul Gauthier: 5
Paul Gauthier (aider): 29
aider/mdstream.py:
Paul Gauthier: 1
Paul Gauthier (aider): 22
aider/models.py:
Paul Gauthier (aider): 41
lentil32 (aider): 15
aider/repo.py:
Paul Gauthier (aider): 5
aider/resources/model-settings.yml:
Paul Gauthier: 3
Paul Gauthier (aider): 22
aider/website/_includes/head_custom.html:
Paul Gauthier: 3
Paul Gauthier (aider): 53
aider/website/_includes/recording.js:
Paul Gauthier: 4
Paul Gauthier (aider): 424
aider/website/assets/asciinema/asciinema-player.min.js:
Paul Gauthier: 1
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
aider/website/index.html:
Paul Gauthier: 173
Paul Gauthier (aider): 371
scripts/badges.py:
Paul Gauthier: 1
Paul Gauthier (aider): 496
scripts/blame.py:
Paul Gauthier: 2
scripts/jekyll_run.sh:
Paul Gauthier: 1
Paul Gauthier (aider): 5
scripts/logo_svg.py:
Paul Gauthier: 5
Paul Gauthier (aider): 169
scripts/recording_audio.py:
Paul Gauthier (aider): 338
scripts/redact-cast.py:
Paul Gauthier: 22
Paul Gauthier (aider): 37
scripts/tmux_record.sh:
Paul Gauthier: 1
Paul Gauthier (aider): 17
scripts/update-docs.sh:
Paul Gauthier: 1
scripts/update-history.py:
Paul Gauthier: 1
Paul Gauthier (aider): 52
tests/basic/test_aws_credentials.py:
lentil32 (aider): 169
tests/basic/test_commands.py:
Carles Sala (aider): 40
tests/basic/test_main.py:
Paul Gauthier: 2
Paul Gauthier (aider): 193
tests/basic/test_repo.py:
Paul Gauthier (aider): 48
tests/help/test_help.py:
Paul Gauthier (aider): 49
grand_total:
Carles Sala (aider): 70
Marco Mayer: 2
Paul Gauthier: 235
Paul Gauthier (aider): 2428
Yutaka Matsubara: 2
lentil32 (aider): 184
start_tag: v0.77.0
total_lines: 2921
- aider_percentage: 65.38
aider_total: 221
end_date: '2025-03-25'
end_tag: v0.79.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/coders/__init__.py:
Paul Gauthier: 2
aider/coders/base_coder.py:
Paul Gauthier: 15
Paul Gauthier (aider): 5
aider/coders/context_coder.py:
Paul Gauthier: 45
Paul Gauthier (aider): 8
aider/commands.py:
Paul Gauthier: 1
Paul Gauthier (aider): 20
aider/io.py:
Paul Gauthier: 11
Paul Gauthier (aider): 2
aider/main.py:
Paul Gauthier (aider): 4
aider/models.py:
Paul Gauthier: 3
Paul Gauthier (aider): 1
aider/repomap.py:
Paul Gauthier: 17
aider/resources/model-settings.yml:
Paul Gauthier: 13
Paul Gauthier (aider): 10
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
aider/website/index.html:
Paul Gauthier: 3
Paul Gauthier (aider): 16
scripts/badges.py:
Paul Gauthier (aider): 2
scripts/blame.py:
Paul Gauthier (aider): 16
scripts/dl_icons.py:
Paul Gauthier (aider): 60
scripts/tmux_record.sh:
Paul Gauthier: 1
tests/basic/test_coder.py:
Paul Gauthier: 4
Paul Gauthier (aider): 77
grand_total:
Paul Gauthier: 117
Paul Gauthier (aider): 221
start_tag: v0.78.0
total_lines: 338
- aider_percentage: 86.86
aider_total: 1837
end_date: '2025-03-31'
end_tag: v0.80.0
file_counts:
aider/__init__.py:
Paul Gauthier: 1
aider/coders/base_coder.py:
Paul Gauthier: 2
aider/commands.py:
Paul Gauthier: 4
Paul Gauthier (aider): 20
aider/exceptions.py:
Paul Gauthier: 1
Paul Gauthier (aider): 3
aider/io.py:
Andrey Ivanov: 2
Matteo Landi (aider): 11
Paul Gauthier (aider): 38
aider/linter.py:
Mir Adnan ALI: 2
aider/main.py:
Paul Gauthier: 1
Paul Gauthier (aider): 21
aider/mdstream.py:
Peter Schilling (aider) (aider): 25
aider/models.py:
Paul Gauthier: 12
Paul Gauthier (aider): 9
aider/onboarding.py:
Paul Gauthier: 44
Paul Gauthier (aider): 389
aider/queries/tree-sitter-languages/scala-tags.scm:
Vasil Markoukin: 65
aider/repo.py:
Paul Gauthier: 1
Paul Gauthier (aider): 7
aider/repomap.py:
Paul Gauthier (aider): 19
aider/resources/model-settings.yml:
Paul Gauthier (aider): 13
aider/scrape.py:
Paul Gauthier: 1
Paul Gauthier (aider): 1
aider/utils.py:
Paul Gauthier (aider): 5
aider/watch.py:
Matteo Landi (aider): 2
aider/website/_includes/leaderboard.js:
Paul Gauthier: 1
Paul Gauthier (aider): 2
aider/website/docs/leaderboards/index.md:
Paul Gauthier: 1
aider/website/index.html:
Paul Gauthier: 51
Paul Gauthier (aider): 175
scripts/30k-image.py:
Paul Gauthier: 8
Paul Gauthier (aider): 227
scripts/homepage.py:
Paul Gauthier (aider): 122
tests/basic/test_commands.py:
Paul Gauthier: 2
Paul Gauthier (aider): 48
tests/basic/test_exceptions.py:
Paul Gauthier (aider): 17
tests/basic/test_io.py:
Paul Gauthier (aider): 28
tests/basic/test_main.py:
Paul Gauthier: 15
Paul Gauthier (aider): 199
tests/basic/test_onboarding.py:
Paul Gauthier (aider): 439
tests/basic/test_repomap.py:
Vasil Markoukin: 3
tests/basic/test_ssl_verification.py:
Paul Gauthier (aider): 8
tests/basic/test_watch.py:
Matteo Landi (aider): 9
tests/fixtures/languages/scala/test.scala:
Vasil Markoukin: 61
grand_total:
Andrey Ivanov: 2
Matteo Landi (aider): 22
Mir Adnan ALI: 2
Paul Gauthier: 145
Paul Gauthier (aider): 1790
Peter Schilling (aider) (aider): 25
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

@@ -1,6 +1,6 @@
- dirname: 2025-02-25-20-23-07--gemini-pro
test_cases: 225
model: gemini/gemini-2.0-pro-exp-02-05
model: Gemini 2.0 Pro exp-02-05
edit_format: whole
commit_hash: 2fccd47
pass_rate_1: 20.4
@@ -338,7 +338,7 @@
- dirname: 2024-12-25-13-31-51--deepseekv3preview-diff2
test_cases: 225
model: DeepSeek Chat V3
model: DeepSeek Chat V3 (prev)
edit_format: diff
commit_hash: 0a23c4a-dirty
pass_rate_1: 22.7
@@ -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
@@ -779,4 +779,422 @@
date: 2025-03-15
versions: 0.77.1.dev
seconds_per_case: 79.7
total_cost: 0.0000
- dirname: 2025-03-24-15-41-33--deepseek-v3-0324-polyglot-diff
test_cases: 225
model: DeepSeek V3 (0324)
edit_format: diff
commit_hash: 502b863
pass_rate_1: 28.0
pass_rate_2: 55.1
pass_num_1: 63
pass_num_2: 124
percent_cases_well_formed: 99.6
error_outputs: 32
num_malformed_responses: 1
num_with_malformed_responses: 1
user_asks: 96
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 2
test_timeouts: 4
total_tests: 225
command: aider --model deepseek/deepseek-chat
date: 2025-03-24
versions: 0.78.1.dev
seconds_per_case: 290.0
total_cost: 1.1164
- dirname: 2025-04-12-04-55-50--gemini-25-pro-diff-fenced
test_cases: 225
model: Gemini 2.5 Pro Preview 03-25
edit_format: diff-fenced
commit_hash: 0282574
pass_rate_1: 40.9
pass_rate_2: 72.9
pass_num_1: 92
pass_num_2: 164
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: 2
total_tests: 225
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
model: chatgpt-4o-latest (2025-03-29)
edit_format: diff
commit_hash: 0decbad
pass_rate_1: 16.4
pass_rate_2: 45.3
pass_num_1: 37
pass_num_2: 102
percent_cases_well_formed: 64.4
error_outputs: 85
num_malformed_responses: 85
num_with_malformed_responses: 80
user_asks: 174
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 4
total_tests: 225
command: aider --model chatgpt-4o-latest
date: 2025-03-29
versions: 0.79.3.dev
seconds_per_case: 10.3
total_cost: 19.7416
- dirname: 2025-04-04-02-57-25--qalpha-diff-exsys
test_cases: 225
model: Quasar Alpha
edit_format: diff
commit_hash: 8a34a6c-dirty
pass_rate_1: 21.8
pass_rate_2: 54.7
pass_num_1: 49
pass_num_2: 123
percent_cases_well_formed: 98.2
error_outputs: 4
num_malformed_responses: 4
num_with_malformed_responses: 4
user_asks: 187
lazy_comments: 0
syntax_errors: 0
indentation_errors: 0
exhausted_context_windows: 0
test_timeouts: 4
total_tests: 225
command: aider --model openrouter/openrouter/quasar-alpha
date: 2025-04-04
versions: 0.80.5.dev
seconds_per_case: 14.8
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

View File

@@ -5,21 +5,15 @@ If you already have python 3.8-3.13 installed, you can get started quickly like
python -m pip install aider-install
aider-install
# Change directory into your code base
# Change directory into your codebase
cd /to/your/project
# Work with DeepSeek via DeepSeek's API
aider --model deepseek --api-key deepseek=your-key-goes-here
# DeepSeek
aider --model deepseek --api-key deepseek=<key>
# Work with Claude 3.7 Sonnet via Anthropic's API
aider --model sonnet --api-key anthropic=your-key-goes-here
# Claude 3.7 Sonnet
aider --model sonnet --api-key anthropic=<key>
# Work with GPT-4o via OpenAI's API
aider --model gpt-4o --api-key openai=your-key-goes-here
# Work with Sonnet via OpenRouter's API
aider --model openrouter/anthropic/claude-3.7-sonnet --api-key openrouter=your-key-goes-here
# Work with DeepSeek via OpenRouter's API
aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here
# o3-mini
aider --model o3-mini --api-key openai=<key>
```

View File

@@ -5,10 +5,66 @@
<meta property="og:image" content="{{ site.url }}/assets/aider.jpg">
<meta property="twitter:image" content="{{ site.url }}/assets/aider-square.jpg">
{% endif %}
<!-- Custom site title styling -->
<style>
@font-face {
font-family: GlassTTYVT220;
src: local("Glass TTY VT220"), local("Glass TTY VT220 Medium"), url(/assets/Glass_TTY_VT220.ttf) format("truetype");
}
.site-title {
font-size: 1.8rem;
font-weight: 700;
font-family: 'GlassTTYVT220', monospace;
color: #14b014; /* terminal green color */
text-decoration: none;
letter-spacing: 0.5px;
}
/* For SVG logo inside site-title */
.site-title img {
height: 1.8rem;
vertical-align: middle;
}
/* Sidebar gradient styling to match hero section */
.side-bar {
background: linear-gradient(135deg, #ffffff 0%, rgba(20, 176, 20, 0.01) 25%, rgba(20, 176, 20, 0.04) 40%, rgba(220, 230, 255, 0.4) 60%, rgba(205, 218, 255, 0.4) 80%, #F5F6FA 100%);
}
</style>
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="{{ site.url }}/feed.xml">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700&display=swap" as="style" type="text/css" crossorigin>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Logo Progressive Enhancement for Jekyll pages -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const siteTitle = document.querySelector('.site-title');
if (siteTitle) {
const textContent = siteTitle.textContent; // Save the text for fallback
// Create new image element
const logoImg = new Image();
logoImg.src = '/assets/logo.svg';
logoImg.alt = 'Aider Logo';
logoImg.style.height = '1.8rem';
logoImg.style.verticalAlign = 'middle';
// Only replace if image loads successfully
logoImg.onload = function() {
siteTitle.textContent = ''; // Clear text
siteTitle.appendChild(logoImg);
};
// If image fails to load, do nothing (keep the text)
logoImg.onerror = function() {
console.log('SVG logo failed to load, keeping text fallback');
};
}
});
</script>
<meta name="theme-color" content="#157878">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="icon" type="image/png" sizes="32x32" href="{{ '/assets/icons/favicon-32x32.png' | relative_url }}">

View File

@@ -4,7 +4,11 @@ document.addEventListener('DOMContentLoaded', function () {
const redDiagonalPattern = pattern.draw('diagonal', 'rgba(255, 99, 132, 0.2)');
let displayedData = [];
const HIGHLIGHT_MODEL = '{{ highlight_model | default: "no no no" }}';
// Get highlight model from query string or Jekyll variable
const urlParams = new URLSearchParams(window.location.search);
const queryHighlight = urlParams.get('highlight');
const HIGHLIGHT_MODEL = queryHighlight || '{{ highlight_model | default: "no no no" }}';
var leaderboardData = {
labels: [],
datasets: [{
@@ -13,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
}, {
@@ -74,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') {
@@ -171,6 +177,9 @@ document.addEventListener('DOMContentLoaded', function () {
},
x: {
ticks: {
autoSkip: false, // Prevent labels from being automatically skipped
maxRotation: 90, // Allow labels to rotate up to 90 degrees
minRotation: 0,
callback: function(value, index) {
const label = this.getLabelForValue(value);
if (label.length <= "claude-3-5-sonnet".length) {

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.

View File

@@ -73,19 +73,64 @@
/* Page container styling */
.page-container {
max-width: 900px;
max-width: 950px;
margin-left: auto;
margin-right: auto;
position: relative;
}
.terminal-container {
border-radius: 6px;
overflow: hidden;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
margin-top: 20px;
margin-bottom: 20px;
/* macOS backdrop styling */
.macos-backdrop {
background: linear-gradient(135deg, #ff9966, #ff5e62, #6666ff, #0066ff);
border-radius: 12px;
padding: clamp(5px, 5vw, 50px) clamp(5px, 2.5vw, 50px);
margin: 20px 0;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
position: relative;
overflow: hidden;
}
/* Add subtle wave animation to backdrop */
.macos-backdrop::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(circle at center, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 70%);
opacity: 0.7;
pointer-events: none;
}
/* Add decorative curved lines to the backdrop */
.macos-backdrop::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(circle at 20% 30%, transparent 0%, transparent 60%, rgba(255,255,255,0.2) 61%, transparent 62%),
radial-gradient(circle at 80% 70%, transparent 0%, transparent 40%, rgba(255,255,255,0.2) 41%, transparent 42%),
radial-gradient(circle at 40% 90%, transparent 0%, transparent 70%, rgba(255,255,255,0.2) 71%, transparent 72%),
radial-gradient(circle at 60% 10%, transparent 0%, transparent 50%, rgba(255,255,255,0.2) 51%, transparent 52%);
background-size: 100% 100%;
opacity: 1;
pointer-events: none;
z-index: 0;
}
.terminal-container {
border-radius: 8px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
margin-top: 0;
margin-bottom: 0;
position: relative;
background-color: white; /* Add background color to terminal container */
z-index: 2; /* Ensure terminal appears above the backdrop effects */
}
/* Timestamp link styling */

View File

@@ -121,7 +121,8 @@ document.addEventListener('DOMContentLoaded', function() {
idleTimeLimit: 1,
theme: "aider",
poster: "npt:0:01",
markers: markers
markers: markers,
controls: true
}
);
@@ -145,6 +146,9 @@ document.addEventListener('DOMContentLoaded', function() {
}
}, 100);
// Track active toast elements
let activeToast = null;
// Function to display toast notification
function showToast(text) {
// Get the appropriate container based on fullscreen state
@@ -176,6 +180,11 @@ document.addEventListener('DOMContentLoaded', function() {
container = fsContainer;
}
// Remove any existing toast
if (activeToast) {
hideToast(activeToast);
}
// Create toast element
const toast = document.createElement('div');
toast.className = 'toast-notification';
@@ -184,27 +193,55 @@ document.addEventListener('DOMContentLoaded', function() {
// Add to container
container.appendChild(toast);
// Store reference to active toast
activeToast = {
element: toast,
container: container
};
// Trigger animation
setTimeout(() => {
toast.style.opacity = '1';
}, 10);
// Remove after 3 seconds
setTimeout(() => {
toast.style.opacity = '0';
setTimeout(() => {
if (container && container.contains(toast)) {
container.removeChild(toast);
}
}, 300); // Wait for fade out animation
}, 3000);
return activeToast;
}
// Function to hide a toast
function hideToast(toastInfo) {
if (!toastInfo || !toastInfo.element) return;
toastInfo.element.style.opacity = '0';
setTimeout(() => {
if (toastInfo.container && toastInfo.container.contains(toastInfo.element)) {
toastInfo.container.removeChild(toastInfo.element);
}
// If this was the active toast, clear the reference
if (activeToast === toastInfo) {
activeToast = null;
}
}, 300); // Wait for fade out animation
}
// Track if TTS is currently in progress to prevent duplicates
let ttsInProgress = false;
let currentToast = null;
// Improved browser TTS function
function useBrowserTTS(text) {
// Don't start new speech if already in progress
if (ttsInProgress) {
console.log('Speech synthesis already in progress, skipping');
return false;
}
if ('speechSynthesis' in window) {
console.log('Using browser TTS fallback');
// Set flag to prevent duplicate speech
ttsInProgress = true;
// Cancel any ongoing speech
window.speechSynthesis.cancel();
@@ -219,8 +256,26 @@ document.addEventListener('DOMContentLoaded', function() {
}
utterance.onstart = () => console.log('Speech started');
utterance.onend = () => console.log('Speech ended');
utterance.onerror = (e) => console.warn('Speech error:', e);
utterance.onend = () => {
console.log('Speech ended');
ttsInProgress = false; // Reset flag when speech completes
// Hide toast when speech ends
if (currentToast) {
hideToast(currentToast);
currentToast = null;
}
};
utterance.onerror = (e) => {
console.warn('Speech error:', e);
ttsInProgress = false; // Reset flag on error
// Also hide toast on error
if (currentToast) {
hideToast(currentToast);
currentToast = null;
}
};
window.speechSynthesis.speak(utterance);
return true;
@@ -231,6 +286,9 @@ document.addEventListener('DOMContentLoaded', function() {
// Function to play pre-generated TTS audio files
function speakText(text, timeInSeconds) {
// Show the toast and keep reference
currentToast = showToast(text);
// Format time for filename (MM-SS)
const minutes = Math.floor(timeInSeconds / 60);
const seconds = timeInSeconds % 60;
@@ -250,6 +308,9 @@ document.addEventListener('DOMContentLoaded', function() {
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
console.log(`Device is iOS: ${isIOS}`);
// Flag to track if we've already fallen back to TTS
let fallenBackToTTS = false;
try {
// Create or reuse audio element
if (!globalAudio) {
@@ -258,9 +319,25 @@ document.addEventListener('DOMContentLoaded', function() {
}
// Set up event handlers
globalAudio.onended = () => {
console.log('Audio playback ended');
// Hide toast when audio ends
if (currentToast) {
hideToast(currentToast);
currentToast = null;
}
};
globalAudio.onerror = (e) => {
console.warn(`Audio error: ${e.type}`, e);
useBrowserTTS(text);
if (!fallenBackToTTS) {
fallenBackToTTS = true;
useBrowserTTS(text);
} else if (currentToast) {
// If we've already tried TTS and that failed too, hide the toast
hideToast(currentToast);
currentToast = null;
}
};
// For iOS, preload might help with subsequent plays
@@ -283,7 +360,10 @@ document.addEventListener('DOMContentLoaded', function() {
console.log("iOS playback failed, trying SpeechSynthesis");
}
useBrowserTTS(text);
if (!fallenBackToTTS) {
fallenBackToTTS = true;
useBrowserTTS(text);
}
});
}
} catch (e) {
@@ -335,9 +415,8 @@ document.addEventListener('DOMContentLoaded', function() {
const { index, time, label } = event;
console.log(`marker! ${index} - ${time} - ${label}`);
// Speak the marker label and show toast
// Speak the marker label (toast is now shown within speakText)
speakText(label, time);
showToast(label);
// Highlight the corresponding timestamp in the transcript
highlightTimestamp(time);

View File

@@ -12,16 +12,18 @@
<div class="page-container">
<div class="toast-container" id="toast-container"></div>
<div class="terminal-container">
<div class="terminal-header">
<div class="terminal-buttons">
<div class="terminal-button terminal-close"></div>
<div class="terminal-button terminal-minimize"></div>
<div class="terminal-button terminal-expand"></div>
<div class="macos-backdrop">
<div class="terminal-container">
<div class="terminal-header">
<div class="terminal-buttons">
<div class="terminal-button terminal-close"></div>
<div class="terminal-button terminal-minimize"></div>
<div class="terminal-button terminal-expand"></div>
</div>
<div class="terminal-title">aider</div>
</div>
<div class="terminal-title">aider</div>
<div id="demo"></div>
</div>
<div id="demo"></div>
</div>
</div>

Binary file not shown.

View File

@@ -0,0 +1,46 @@
{
"00-01": "Users sometimes run aider with \"reasoning\" settings that aren't supported by the model they're using. This can cause LLM API calls to completely fail, with non-specific error messages from the API provider. We're going to warn users up front to prevent this.",
"01-30": "Looks like it's including some extra changes we don't want.",
"01-45": "Let's have a look at the models code and clean up some stray lines.",
"02-00": "It also made the warning logic too conservative. We want to warn unless the setting is explicitly known to be supported.",
"03-00": "Ok, good. Now lets add a setting to silence these warnings for power users who are doing something intentional.",
"03-45": "Now we need to update the database of model settings to annotate which models support which reasoning settings. We'll start with the code that handles \"fallback\" settings for known models on unknown providers.",
"04-45": "Oh, we forgot to give aider the actual file with that code! Aider asks to see it.",
"05-00": "Ok, we've confused aider by asking it to change code it couldn't see.",
"05-10": "Let's clear the chat and refine the prompt and try again.",
"06-00": "Ok, looks good. Let's move on and update the full model settings database YAML file. Each main model like \"o1\" appears here from many providers, like OpenAI, OpenRouter, etc. We want to update them all.",
"09-20": "Looks good. Let's review the YAML file and eyeball all the relevant models.",
"10-20": "Now let's do some manual testing.",
"10-55": "Let's see if aider can spot the problem?",
"11-28": "That doesn't sound like a promising solution. Let's add more of the relevant code, clear history and try again.",
"12-00": "Ok, let's try aider's proposed solution.",
"12-48": "Time for some manual print debugging.",
"13-00": "It seems like the \"accept_settings\" value is not being set?",
"14-30": "Aha! I have a local model settings file for Sonnet which overrides aider's built in settings. And we did not update it. Let's add \"accepts_settings\" there.",
"14-45": "That was the problem, it wasn't a bug.",
"14-59": "Ok, let's add test coverage for all this stuff.",
"15-09": "And while aider writes tests, let's use \"git diff\" to review all the changes we've made.",
"15-34": "Aider is done writing tests, let's try them.",
"15-44": "One passed, one failed. Let's eyeball the passing test first.",
"16-04": "And let's see if aider can fix the failing test.",
"16-14": "Aider needs to see another file, which makes sense.",
"16-29": "It's found the problem, but is trying to \"fix\" the code. We want it to fix the test.",
"16-47": "Ok, tests are passing.",
"16-55": "We should stop and ask the user \"are you sure?\", not just flash a warning if they're about to break their API calls.",
"17-59": "Ok, that confirmation dialog looks good.",
"18-35": "This code is a little bit repetitive. Let's do a bit of refactoring.",
"20-25": "Are tests still passing after the refactor?",
"20-55": "Tests passed, good. Let's tweak the warning text.",
"21-10": "And now let's have aider update the docs to explain these changes.",
"22-32": "Let's proofread and edit the updated docs.",
"24-25": "And a \"git diff\" of all the docs changes to do a final check.",
"24-56": "Let's have aider update the project's HISTORY file.",
"26-20": "All done!",
"00-25": "Ok, let's ask aider to add a new model setting where we can note which reasoning settings it supports. And then print a warning if the user tries to apply an unsupported setting.",
"07-43": "Let's interrupt and refine the prompt to be more clear about which models to update.",
"10-41": "Ok, it should not be warning us about using \"thinking tokens\" with Sonnet 3.7.",
"12-32": "And see if it worked... Nope! Still getting the unneeded warning. Undo that change!",
"19-44": "Sonnet is messing up the code editing instructions, so aider is retrying.",
"19-54": "Let's clear the chat history and try again.",
"25-35": "We can refine the HISTORY entries a bit."
}

Some files were not shown because too many files have changed in this diff Show More