mirror of
https://github.com/Aider-AI/aider
synced 2026-05-05 06:32:04 +02:00
Compare commits
922 Commits
v0.73.1.de
...
v0.77.2.de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97a3bfca4e | ||
|
|
cf58133e06 | ||
|
|
0d1811a4ae | ||
|
|
2a8bb715f0 | ||
|
|
cf93869d3f | ||
|
|
77976a5253 | ||
|
|
5af46aaa2e | ||
|
|
4f4b10fd86 | ||
|
|
26789115b6 | ||
|
|
87a28dcb9f | ||
|
|
1ad99f39e2 | ||
|
|
dfbeec199e | ||
|
|
41a99ec29d | ||
|
|
7cee3aa1f1 | ||
|
|
b86d8099f1 | ||
|
|
9c4a0043dd | ||
|
|
5cde755976 | ||
|
|
51aab7b656 | ||
|
|
791dc213fa | ||
|
|
8404165db3 | ||
|
|
aee52c01a3 | ||
|
|
58e16b0c48 | ||
|
|
3225ac88c0 | ||
|
|
38b8b85ec2 | ||
|
|
278f748c1c | ||
|
|
874df40303 | ||
|
|
0465d8ce80 | ||
|
|
e9b3f5fd43 | ||
|
|
c49bc2418b | ||
|
|
fd21f5195d | ||
|
|
a1aa63fa06 | ||
|
|
b0a619c714 | ||
|
|
ec648f2c6f | ||
|
|
7ac7c72e03 | ||
|
|
f1d00dbd7f | ||
|
|
f644aba7a8 | ||
|
|
ed75287c8c | ||
|
|
a035c73c41 | ||
|
|
781a619262 | ||
|
|
e08b63cc9f | ||
|
|
97ed57a252 | ||
|
|
71f1779c8c | ||
|
|
116f44cade | ||
|
|
2ebdd689ab | ||
|
|
beecc1a718 | ||
|
|
557ba2adc1 | ||
|
|
89780c1283 | ||
|
|
411e7f86c1 | ||
|
|
610fce67e1 | ||
|
|
d9350cd3ed | ||
|
|
54d6643a1f | ||
|
|
f664420628 | ||
|
|
d4d4c6de68 | ||
|
|
b4313599f8 | ||
|
|
6866f8f0a9 | ||
|
|
3cb478214b | ||
|
|
8d7b4d6446 | ||
|
|
cc6b0bcd72 | ||
|
|
831564cf48 | ||
|
|
4e59b62026 | ||
|
|
f345b9b0ff | ||
|
|
d4fb88a8c4 | ||
|
|
2cb1b6be46 | ||
|
|
feda315c2b | ||
|
|
41219a7d85 | ||
|
|
813a201b6a | ||
|
|
1bc40d48fe | ||
|
|
ddb4e51938 | ||
|
|
9ee67c343d | ||
|
|
bb816eae83 | ||
|
|
92bd446d09 | ||
|
|
a7526fa9c4 | ||
|
|
9b6ff487da | ||
|
|
9d61490743 | ||
|
|
9cce6e41fa | ||
|
|
a56dbdf502 | ||
|
|
7d5f27fa34 | ||
|
|
a61ba0db22 | ||
|
|
7f02a889e2 | ||
|
|
88d388a574 | ||
|
|
4d5a659e1e | ||
|
|
ecfcf1071d | ||
|
|
ec385d45e9 | ||
|
|
985107bb4b | ||
|
|
eb340c74ac | ||
|
|
9a16b33f00 | ||
|
|
0acebc5916 | ||
|
|
8442d9fe5f | ||
|
|
5318dd1a80 | ||
|
|
d916180ec8 | ||
|
|
6e5aa08ee0 | ||
|
|
83e115cde5 | ||
|
|
a3a92cd5dd | ||
|
|
16fc10fb0f | ||
|
|
6bba8b57d4 | ||
|
|
f45c75a137 | ||
|
|
3348df0652 | ||
|
|
3b6a01b63d | ||
|
|
a3554a95c5 | ||
|
|
6fa9af20c0 | ||
|
|
e23437dfa4 | ||
|
|
dcf9eaad77 | ||
|
|
768df05692 | ||
|
|
e0d5d35e32 | ||
|
|
a718a05414 | ||
|
|
953391d9d0 | ||
|
|
4ca229fd42 | ||
|
|
693a43efc8 | ||
|
|
f3d4c931f5 | ||
|
|
ece21315b1 | ||
|
|
318cc57ffe | ||
|
|
ba17924174 | ||
|
|
6bc9daa6ee | ||
|
|
2d8bc95bae | ||
|
|
520eb4a932 | ||
|
|
03733516cc | ||
|
|
e561130336 | ||
|
|
169fa2e7b7 | ||
|
|
6d6db996fb | ||
|
|
f8642bfd94 | ||
|
|
dfdd6bf533 | ||
|
|
91cef71048 | ||
|
|
3daf632384 | ||
|
|
dba5fb9dfa | ||
|
|
70d10a0bb2 | ||
|
|
97291b806a | ||
|
|
c583f008e9 | ||
|
|
b182eba56f | ||
|
|
de5da0e7ce | ||
|
|
f2a893c0d4 | ||
|
|
371a03c794 | ||
|
|
88e3d48be5 | ||
|
|
e8a8681a75 | ||
|
|
b541eec3b8 | ||
|
|
ce3f732645 | ||
|
|
1b3cae1ed5 | ||
|
|
024b9130a0 | ||
|
|
61a8b6020f | ||
|
|
d25877aace | ||
|
|
c3c2d4dc22 | ||
|
|
7454154599 | ||
|
|
04ecea614b | ||
|
|
084a14b640 | ||
|
|
a477759a49 | ||
|
|
d4df207612 | ||
|
|
57d492d4b8 | ||
|
|
fb7413436c | ||
|
|
2cc8105e68 | ||
|
|
a83d5ff123 | ||
|
|
a709d650df | ||
|
|
570e8eae31 | ||
|
|
22f1703bee | ||
|
|
14037eaeb8 | ||
|
|
189d64dc3d | ||
|
|
315f8093c6 | ||
|
|
a776d70e0d | ||
|
|
1ab6c70ac7 | ||
|
|
73eb8701dd | ||
|
|
a503f291e7 | ||
|
|
b54d800024 | ||
|
|
d74068464d | ||
|
|
86a5e8dbe1 | ||
|
|
24d2b683c8 | ||
|
|
9451f0abe4 | ||
|
|
544d58ddbd | ||
|
|
7c1d2d75e0 | ||
|
|
0b949f47d9 | ||
|
|
393b45dd21 | ||
|
|
6bb43555dc | ||
|
|
ba03b07602 | ||
|
|
0ac4c0b97d | ||
|
|
41e93a4d94 | ||
|
|
a0b5b19d38 | ||
|
|
65fad5ae30 | ||
|
|
a689f2116c | ||
|
|
68b5c90d95 | ||
|
|
44eb9af7bc | ||
|
|
9e824e6070 | ||
|
|
ba6bb527a7 | ||
|
|
3525eeae54 | ||
|
|
e535e01e83 | ||
|
|
3b1c81e50e | ||
|
|
89406e5b7d | ||
|
|
d5cc855c0f | ||
|
|
2ed61eaf92 | ||
|
|
865f71e2cc | ||
|
|
08a75808df | ||
|
|
c9dd37db8e | ||
|
|
7e86c8a90c | ||
|
|
b87a5496e9 | ||
|
|
9a88363437 | ||
|
|
c0b9665cfc | ||
|
|
70284ce1c2 | ||
|
|
48621dadaa | ||
|
|
e69bad57e4 | ||
|
|
f55099e969 | ||
|
|
76994facec | ||
|
|
2d843f6e79 | ||
|
|
e15518dd29 | ||
|
|
011e0fd109 | ||
|
|
5f125c1812 | ||
|
|
a6ebed8d16 | ||
|
|
849e02cbfb | ||
|
|
1ab5238405 | ||
|
|
ae6192111d | ||
|
|
59af4114dd | ||
|
|
4491b88763 | ||
|
|
92377fc390 | ||
|
|
79b8e50412 | ||
|
|
b5cd39cc50 | ||
|
|
63c2a98f3c | ||
|
|
c168f78a13 | ||
|
|
42d45b4037 | ||
|
|
c41df63629 | ||
|
|
330bb81206 | ||
|
|
d84c755ee8 | ||
|
|
a24ff28031 | ||
|
|
3a837c472e | ||
|
|
f4880e2ef3 | ||
|
|
a2e4022e31 | ||
|
|
5668b41daa | ||
|
|
c052270048 | ||
|
|
70547171ca | ||
|
|
881868bf17 | ||
|
|
e90eb39a9b | ||
|
|
9513d307a1 | ||
|
|
533e5ec03f | ||
|
|
55f63395c7 | ||
|
|
4253d98a73 | ||
|
|
0c4af58866 | ||
|
|
a5919bd27d | ||
|
|
5e40974fdd | ||
|
|
a27f4d0e04 | ||
|
|
1bb3041298 | ||
|
|
dc6040adda | ||
|
|
864725ff3d | ||
|
|
0fcbea03e5 | ||
|
|
2ce63e6ad3 | ||
|
|
d45af94cee | ||
|
|
1f874b654d | ||
|
|
a7a21757bc | ||
|
|
1bed4e8972 | ||
|
|
efcda12dda | ||
|
|
d7b4079ab5 | ||
|
|
2eb1513612 | ||
|
|
87bcbe0420 | ||
|
|
26b0c6e6da | ||
|
|
8cfbc9b827 | ||
|
|
46eee9e642 | ||
|
|
7d902d2f3e | ||
|
|
3d05007024 | ||
|
|
a2bf2e2910 | ||
|
|
9cf4286cee | ||
|
|
c9ddca3a16 | ||
|
|
06370cb096 | ||
|
|
342586519d | ||
|
|
89174bb524 | ||
|
|
1fa3bc4018 | ||
|
|
d68e2b33fb | ||
|
|
1313cd8216 | ||
|
|
7afc8c760c | ||
|
|
79f714ab16 | ||
|
|
e21bab2d17 | ||
|
|
4288cf2a39 | ||
|
|
9d570a9cb1 | ||
|
|
333ddfb37a | ||
|
|
10a5250527 | ||
|
|
fd57eccdca | ||
|
|
1432be9be6 | ||
|
|
1773bbf759 | ||
|
|
5c94624186 | ||
|
|
dc06c2fab3 | ||
|
|
f37799b39c | ||
|
|
cc84f590fe | ||
|
|
afcf3e77b5 | ||
|
|
0406dda2a6 | ||
|
|
935227f7e7 | ||
|
|
67ebb2566d | ||
|
|
1c736161c5 | ||
|
|
a348c2d013 | ||
|
|
444a95bc6c | ||
|
|
c38cdef220 | ||
|
|
5608db0892 | ||
|
|
98b3722a02 | ||
|
|
2d623ff196 | ||
|
|
703e124277 | ||
|
|
68c27f885f | ||
|
|
58cd190ca9 | ||
|
|
2c5c2b2f67 | ||
|
|
e10fe50c6f | ||
|
|
b8ad0b15e8 | ||
|
|
1b81fb0fdf | ||
|
|
703cb8849d | ||
|
|
55f856b23c | ||
|
|
93c284a67d | ||
|
|
38fd715247 | ||
|
|
987d024847 | ||
|
|
a3c0d628a1 | ||
|
|
3cb6ec9ddb | ||
|
|
c21619608e | ||
|
|
76a8789bc1 | ||
|
|
bbf538e06c | ||
|
|
d94ab3395b | ||
|
|
6d8457a61f | ||
|
|
303f8e1bc9 | ||
|
|
e638116a2f | ||
|
|
5bac9133e6 | ||
|
|
6fde4041ba | ||
|
|
d0c8b38ffc | ||
|
|
be7888ab18 | ||
|
|
11b71fa28c | ||
|
|
c838f9bfd5 | ||
|
|
8d073ce221 | ||
|
|
0be5d39453 | ||
|
|
74ecdf2d3f | ||
|
|
20eacfab0f | ||
|
|
0396e15a3b | ||
|
|
3432a936ea | ||
|
|
87cd2b5dfe | ||
|
|
313b91edbe | ||
|
|
a1f104cb4d | ||
|
|
eadb8d5d0a | ||
|
|
41ae947885 | ||
|
|
84f610c0e9 | ||
|
|
0df959cf68 | ||
|
|
a15d10ea1e | ||
|
|
a37d6e86df | ||
|
|
a405063385 | ||
|
|
f5a5b85e9d | ||
|
|
ba7d941e5b | ||
|
|
804a2d1af9 | ||
|
|
c1bc6e161e | ||
|
|
af1b728b90 | ||
|
|
14e37a82ab | ||
|
|
f8a7854efa | ||
|
|
072ce87051 | ||
|
|
cac9b4460e | ||
|
|
67bf90a149 | ||
|
|
af8558b19e | ||
|
|
1903542f11 | ||
|
|
3ed16fb796 | ||
|
|
6f99392eda | ||
|
|
680dbfbf77 | ||
|
|
51a72b497b | ||
|
|
d6e57dd194 | ||
|
|
e92ab55da6 | ||
|
|
c78b3e0204 | ||
|
|
ac1c05389a | ||
|
|
95583fe2cd | ||
|
|
ddedda9233 | ||
|
|
d30b9d1513 | ||
|
|
4c35f88ea0 | ||
|
|
e6623ae0a8 | ||
|
|
4755578822 | ||
|
|
319d543ac2 | ||
|
|
9e668cda7f | ||
|
|
5447483da2 | ||
|
|
8e22a8d107 | ||
|
|
18d27ab4e4 | ||
|
|
fe60832492 | ||
|
|
6bf683409f | ||
|
|
634bfb1eae | ||
|
|
c9d597d2b1 | ||
|
|
92c616f717 | ||
|
|
b1e8d29ae0 | ||
|
|
e0cef55fcd | ||
|
|
9aacf5c7db | ||
|
|
4858749a20 | ||
|
|
b53c0b982a | ||
|
|
2aac9ff9c5 | ||
|
|
bdaa70ada5 | ||
|
|
ca6abdfc61 | ||
|
|
e18593fe88 | ||
|
|
08401aff26 | ||
|
|
cddc67ad69 | ||
|
|
586af2a435 | ||
|
|
97091fab60 | ||
|
|
5f2cf75be8 | ||
|
|
37c7b81c95 | ||
|
|
779a266713 | ||
|
|
ebaedc6f05 | ||
|
|
08a392787a | ||
|
|
883bf74bad | ||
|
|
80de3335b7 | ||
|
|
794072bdf8 | ||
|
|
e28fdb9cb1 | ||
|
|
7873d1c6b3 | ||
|
|
f8c069132e | ||
|
|
c53833072f | ||
|
|
16d7cf7a52 | ||
|
|
3b9c2b9729 | ||
|
|
b230fea66f | ||
|
|
f9b6501af1 | ||
|
|
0cd8e3701d | ||
|
|
8545672839 | ||
|
|
4a6c4b95f1 | ||
|
|
c893bc21ab | ||
|
|
c8c5cbf8cc | ||
|
|
54ef8a1e19 | ||
|
|
82df218bcb | ||
|
|
f613ad6c05 | ||
|
|
4e732d0379 | ||
|
|
ad8b5c9d29 | ||
|
|
1ab4bf14dc | ||
|
|
068a0b4576 | ||
|
|
5f694f228f | ||
|
|
2ffe49130d | ||
|
|
f7d18ef976 | ||
|
|
8233eb6007 | ||
|
|
de4693cdf3 | ||
|
|
8fb235c3f5 | ||
|
|
6feb00dcd9 | ||
|
|
4fc1847a70 | ||
|
|
e7f16f07f7 | ||
|
|
d9551b3106 | ||
|
|
854428795b | ||
|
|
5c3b4bd987 | ||
|
|
9d686d3e52 | ||
|
|
b62e00b935 | ||
|
|
634745c818 | ||
|
|
490c6d9a28 | ||
|
|
e6dd9978cb | ||
|
|
240a5613a5 | ||
|
|
fb96cbcaaf | ||
|
|
b58f879db7 | ||
|
|
1585c6095e | ||
|
|
30a630412d | ||
|
|
e5ca79cd51 | ||
|
|
148353aca4 | ||
|
|
7a098ce740 | ||
|
|
f3b9831a0c | ||
|
|
01454674c8 | ||
|
|
5093b18ecc | ||
|
|
c16cfd0668 | ||
|
|
1674cd5db9 | ||
|
|
f111ab48fb | ||
|
|
65309854ac | ||
|
|
cf0aff8c40 | ||
|
|
16b768485a | ||
|
|
c2e7b533d3 | ||
|
|
539859f1ab | ||
|
|
d1d40a9a76 | ||
|
|
52162a5604 | ||
|
|
84e84207a5 | ||
|
|
a4e1745eca | ||
|
|
5931979b74 | ||
|
|
a412a65315 | ||
|
|
25da0674bb | ||
|
|
c823bf4fbb | ||
|
|
cfd0e67a6b | ||
|
|
94f3af57f1 | ||
|
|
0050a3fe6c | ||
|
|
0e65ddee37 | ||
|
|
101f7de889 | ||
|
|
a21c1ff92d | ||
|
|
f9bb2e498e | ||
|
|
f6bb803be5 | ||
|
|
204a88c171 | ||
|
|
012afc0708 | ||
|
|
cf089abb64 | ||
|
|
40e463cdc1 | ||
|
|
6a1284a5ca | ||
|
|
60522ee474 | ||
|
|
0045641db7 | ||
|
|
97b5b1b669 | ||
|
|
448de8519a | ||
|
|
95e1fe0446 | ||
|
|
47254be254 | ||
|
|
3da15bfd19 | ||
|
|
c79db2581b | ||
|
|
93b86a8800 | ||
|
|
56ba7ef411 | ||
|
|
e2117fd8a9 | ||
|
|
e817c76e38 | ||
|
|
65e059a7d2 | ||
|
|
f661025acc | ||
|
|
2fe1b1e16e | ||
|
|
665ffe3984 | ||
|
|
c3401047e0 | ||
|
|
996177ceaf | ||
|
|
09e998523f | ||
|
|
38e8d27416 | ||
|
|
813de04596 | ||
|
|
3c0eae4180 | ||
|
|
99424a9f53 | ||
|
|
51d118fdb5 | ||
|
|
a26509a1fd | ||
|
|
0db70379e8 | ||
|
|
c612b5d17b | ||
|
|
1b469cce49 | ||
|
|
c62cbd2d77 | ||
|
|
da1bc19052 | ||
|
|
8e2246ec5c | ||
|
|
5cf6945bcb | ||
|
|
7132ae47d7 | ||
|
|
96bde4ad03 | ||
|
|
85b9bdd8f4 | ||
|
|
e5a85108d7 | ||
|
|
aaa3a8ebda | ||
|
|
9ceb766a67 | ||
|
|
f894240fbb | ||
|
|
4bac8e2ebe | ||
|
|
d3ad1fd384 | ||
|
|
ed0e4189e4 | ||
|
|
5f147242be | ||
|
|
c7b4c22b94 | ||
|
|
667bacf81e | ||
|
|
e896b0ea96 | ||
|
|
3b0a5a8b41 | ||
|
|
81d39e9bde | ||
|
|
59eabf03a6 | ||
|
|
4fc4987c43 | ||
|
|
dbf5bb149a | ||
|
|
38acbf6970 | ||
|
|
ad4bd91751 | ||
|
|
1a6f290979 | ||
|
|
c6e02a620a | ||
|
|
90efaa41c2 | ||
|
|
51a73ad8b5 | ||
|
|
93f2387d1b | ||
|
|
207a631a65 | ||
|
|
74e60e98b7 | ||
|
|
6ca6bf7457 | ||
|
|
ea49cdeb17 | ||
|
|
bcc8b1917a | ||
|
|
67b12d4416 | ||
|
|
dc02daecee | ||
|
|
6212b38ea6 | ||
|
|
ce7e5726e7 | ||
|
|
1156b3f22e | ||
|
|
66097f3507 | ||
|
|
146f02d314 | ||
|
|
77e5882ce7 | ||
|
|
d44850a4f3 | ||
|
|
e6e692dc43 | ||
|
|
dc65770ae3 | ||
|
|
8c15802277 | ||
|
|
3d666d9929 | ||
|
|
c0c960ec2e | ||
|
|
2bb4db127c | ||
|
|
dd1a5d4f58 | ||
|
|
961fdf7029 | ||
|
|
ff3d2b006f | ||
|
|
d7efbad3df | ||
|
|
d70995bb1a | ||
|
|
1b58e95dce | ||
|
|
780f70d5c6 | ||
|
|
a01e1f96fa | ||
|
|
3adb443ca5 | ||
|
|
dc9ff3a004 | ||
|
|
f879f4f432 | ||
|
|
183f831a7e | ||
|
|
3c361be621 | ||
|
|
5764d44faf | ||
|
|
ce86677faa | ||
|
|
17d93b39d5 | ||
|
|
1357b85a3d | ||
|
|
c67cb5c604 | ||
|
|
6ffb0df6cb | ||
|
|
032b40c78d | ||
|
|
742aea115b | ||
|
|
0f16cd46f9 | ||
|
|
eea64cf272 | ||
|
|
3d5c5f8054 | ||
|
|
748099a324 | ||
|
|
9c1d050d8b | ||
|
|
4ef834e295 | ||
|
|
50bead172b | ||
|
|
ee4508af03 | ||
|
|
6638959d66 | ||
|
|
f266a9d25d | ||
|
|
6cb8e1a518 | ||
|
|
85375359ed | ||
|
|
17c9ba2c68 | ||
|
|
34334ad8b8 | ||
|
|
4527714094 | ||
|
|
b43d74dbb7 | ||
|
|
0c4140ff02 | ||
|
|
b074c02fa2 | ||
|
|
7636c97f9f | ||
|
|
4211ab28b0 | ||
|
|
cecfbc7e20 | ||
|
|
31a6aff932 | ||
|
|
c4a67c4356 | ||
|
|
9f5765134b | ||
|
|
0c5b51d2ac | ||
|
|
31c4198cee | ||
|
|
a94c4b4ce4 | ||
|
|
088dd99ec1 | ||
|
|
4f9b907b4d | ||
|
|
e7dc3e6062 | ||
|
|
53055e78eb | ||
|
|
9a9c34aa18 | ||
|
|
2f1384840c | ||
|
|
b462e55799 | ||
|
|
263ec60ba6 | ||
|
|
8d44a57200 | ||
|
|
976722c129 | ||
|
|
4a9447d344 | ||
|
|
ac2ed9aa87 | ||
|
|
51cf241dae | ||
|
|
f239b8e26d | ||
|
|
ab9f4161ea | ||
|
|
1d10e649b7 | ||
|
|
a95b40aac6 | ||
|
|
1b5777821f | ||
|
|
587d469193 | ||
|
|
6c3e30f3ea | ||
|
|
91dbcae9e2 | ||
|
|
fb5db4f6b7 | ||
|
|
a1e029a825 | ||
|
|
54dbf9b6f2 | ||
|
|
b6344951fe | ||
|
|
ea972118b5 | ||
|
|
2fccd4799d | ||
|
|
a3937e4d0d | ||
|
|
acb022d5d5 | ||
|
|
b6e46d6101 | ||
|
|
347f75f804 | ||
|
|
4005ced505 | ||
|
|
c748c35b37 | ||
|
|
a73836ca43 | ||
|
|
b357fab326 | ||
|
|
16a3000451 | ||
|
|
c4fac2d179 | ||
|
|
60d11a6eba | ||
|
|
93edbda984 | ||
|
|
75bd94d757 | ||
|
|
a5cf0b6ef5 | ||
|
|
506280d645 | ||
|
|
2f79b4fde7 | ||
|
|
846f98628d | ||
|
|
eed9be5a9e | ||
|
|
27c77afafc | ||
|
|
c156b2f817 | ||
|
|
96fcc5df6b | ||
|
|
3c775fd5de | ||
|
|
75e9ee6528 | ||
|
|
ea0ee96398 | ||
|
|
3fd4a2841a | ||
|
|
6ecf44c87a | ||
|
|
031e8cea6e | ||
|
|
757fbb0124 | ||
|
|
d65e3f73df | ||
|
|
5b13105d58 | ||
|
|
c8745afb37 | ||
|
|
85189c0bde | ||
|
|
a8635bade2 | ||
|
|
4560572ff2 | ||
|
|
c7fa57fd14 | ||
|
|
54965fdf2e | ||
|
|
30361aa685 | ||
|
|
8be93b72c4 | ||
|
|
c7e9d645e5 | ||
|
|
fe6a3c89f3 | ||
|
|
686a32cbc0 | ||
|
|
55d7397ff5 | ||
|
|
3714d554df | ||
|
|
0415de853b | ||
|
|
0ba1e8f904 | ||
|
|
58bfcb0953 | ||
|
|
fa281d89d2 | ||
|
|
908b10dae0 | ||
|
|
ea03f9def0 | ||
|
|
3510799fca | ||
|
|
1f4a63d6db | ||
|
|
dd94a444d2 | ||
|
|
50fafc9ff6 | ||
|
|
47fc6a689d | ||
|
|
86175a1827 | ||
|
|
6d6e25df4e | ||
|
|
5402ed112c | ||
|
|
235b83d02e | ||
|
|
6ffbec969a | ||
|
|
185ea71646 | ||
|
|
69fcc3acd7 | ||
|
|
da94cf4aab | ||
|
|
8799cf95b4 | ||
|
|
108ce18d51 | ||
|
|
f67ea5d010 | ||
|
|
dd857aeccf | ||
|
|
44b1acd385 | ||
|
|
b2f6018e05 | ||
|
|
bca6507f11 | ||
|
|
30332c2ba5 | ||
|
|
17919d7503 | ||
|
|
42237ced80 | ||
|
|
737021ccdf | ||
|
|
22ed9d8d7c | ||
|
|
49dcd11813 | ||
|
|
7c30086d78 | ||
|
|
e2dbfdc537 | ||
|
|
674eb109c2 | ||
|
|
927b5bc8cc | ||
|
|
f7dd0fc582 | ||
|
|
35f30bde04 | ||
|
|
a682b50fd4 | ||
|
|
3b5024749f | ||
|
|
2a56d892d7 | ||
|
|
e3d5eaf388 | ||
|
|
5d1f50117b | ||
|
|
f6a2ec15d7 | ||
|
|
64a8d56725 | ||
|
|
71caea32e7 | ||
|
|
17993ef9ff | ||
|
|
b0aa4ef4c8 | ||
|
|
5c4aaa27d9 | ||
|
|
53586d95d0 | ||
|
|
3877ab1f00 | ||
|
|
2425322e8d | ||
|
|
3f80a113d1 | ||
|
|
9ad20849d3 | ||
|
|
c8c58280d8 | ||
|
|
d40505cd16 | ||
|
|
25c5f84090 | ||
|
|
a58293f04b | ||
|
|
1408fb41b8 | ||
|
|
cb7cb8e527 | ||
|
|
d750dbc703 | ||
|
|
91b417138a | ||
|
|
db5eabd927 | ||
|
|
cbcc0fde04 | ||
|
|
cca3b98a09 | ||
|
|
e63b8ff35d | ||
|
|
b6a37bf0e2 | ||
|
|
249ca4fd75 | ||
|
|
d382869b98 | ||
|
|
41a3c27aba | ||
|
|
af48c46c30 | ||
|
|
52bc51a197 | ||
|
|
57ca9cc840 | ||
|
|
56d6a47ad3 | ||
|
|
b806360a49 | ||
|
|
739a88ed00 | ||
|
|
38d4341e59 | ||
|
|
6118d91922 | ||
|
|
71ac7efafe | ||
|
|
cf0710225c | ||
|
|
21e96df85a | ||
|
|
79f32c2ebd | ||
|
|
492a1f69b3 | ||
|
|
32b962e186 | ||
|
|
37beb8e6b2 | ||
|
|
1ee9f3815d | ||
|
|
65a5e8721c | ||
|
|
036c7a2117 | ||
|
|
229e8e1ad1 | ||
|
|
390bb1bdc5 | ||
|
|
83b401b241 | ||
|
|
cfb2c1f62a | ||
|
|
4ad7df746e | ||
|
|
a218b1d3d0 | ||
|
|
6f61aff735 | ||
|
|
4893f78286 | ||
|
|
97296f3169 | ||
|
|
ebcf4364f5 | ||
|
|
6d0078d39b | ||
|
|
9b80b693c1 | ||
|
|
2e1e26fdb9 | ||
|
|
ddeb43783c | ||
|
|
b61e527baa | ||
|
|
53ce96b48f | ||
|
|
36ea166c20 | ||
|
|
f9fd4c71f1 | ||
|
|
44171417e3 | ||
|
|
b554a46a4c | ||
|
|
19a2c37678 | ||
|
|
23d74040ed | ||
|
|
685e63b9da | ||
|
|
39855f4d2b | ||
|
|
ae6fc41ca9 | ||
|
|
1bb41bec2a | ||
|
|
041d679a54 | ||
|
|
46058c275c | ||
|
|
b9e15a1340 | ||
|
|
f9eb4ffee2 | ||
|
|
419952f33b | ||
|
|
af8bdcd9e0 | ||
|
|
54122af9d7 | ||
|
|
5e4852bd32 | ||
|
|
3714f9fdbd | ||
|
|
a9dd6e0f3d | ||
|
|
3c9f4ee555 | ||
|
|
7ff0b4c6b9 | ||
|
|
648662469b | ||
|
|
c37ddd7872 | ||
|
|
17f35cde19 | ||
|
|
b5d17b99df | ||
|
|
5c9746e209 | ||
|
|
51938affc2 | ||
|
|
856006a68d | ||
|
|
a2622263ce | ||
|
|
7db1613b1a | ||
|
|
3add686e9b | ||
|
|
a9f0983f0f | ||
|
|
3b16d6c291 | ||
|
|
85399bd6e2 | ||
|
|
aef2b95d41 | ||
|
|
11a233da84 | ||
|
|
016aa87e34 | ||
|
|
9094af565f | ||
|
|
d7de908c66 | ||
|
|
a3985ac94c | ||
|
|
b48f26020a | ||
|
|
630d3679b5 | ||
|
|
78c89eb29b | ||
|
|
7fe4996bbe | ||
|
|
370deda5a7 | ||
|
|
d0d8ff8313 | ||
|
|
550b9ebf4d | ||
|
|
2265456bda | ||
|
|
b0f1cde33f | ||
|
|
cdd150be42 | ||
|
|
0d24d75d8f | ||
|
|
5c866c67b5 | ||
|
|
b49fea87ab | ||
|
|
1c262d22ce | ||
|
|
0dde77009e | ||
|
|
3e71c35fdd | ||
|
|
10f1fc5e92 | ||
|
|
8fbad757bf | ||
|
|
5755aa3eb8 | ||
|
|
f76d14f613 | ||
|
|
0c3470bab2 | ||
|
|
315ad06ecc | ||
|
|
c1627612cf | ||
|
|
b5cfceeed6 | ||
|
|
7fe7dd743c | ||
|
|
3e36f27987 | ||
|
|
b9f4f3f71c | ||
|
|
ff1230c3ae | ||
|
|
e71ec574e1 | ||
|
|
c2e716ec4a | ||
|
|
5ad8bb1830 | ||
|
|
751e78baa9 | ||
|
|
be620bd437 | ||
|
|
44365651a6 | ||
|
|
7b557c0586 | ||
|
|
495a27c0a7 | ||
|
|
e07fddb20b | ||
|
|
56eb1d106f | ||
|
|
c8b6d61ae2 | ||
|
|
47e91e943c | ||
|
|
4f8c52f09e | ||
|
|
f20b32b01b | ||
|
|
37cbb5ed01 | ||
|
|
289e13cb46 | ||
|
|
fb03c4c311 | ||
|
|
a65aecaf74 | ||
|
|
da9ba0a26a | ||
|
|
8440e881c0 | ||
|
|
85fa8a4761 | ||
|
|
5c8c78ca69 | ||
|
|
e9097c3b29 | ||
|
|
d53ee24741 | ||
|
|
6517cb15ef | ||
|
|
7b78f92feb | ||
|
|
0af6dc3838 | ||
|
|
e313a2ea45 | ||
|
|
f21ef30482 | ||
|
|
606fce65ab | ||
|
|
b4084484ff | ||
|
|
80062908d9 | ||
|
|
af8f7e95b0 | ||
|
|
9553478384 | ||
|
|
535b3ce286 | ||
|
|
cfe9c86edd | ||
|
|
ee66044425 | ||
|
|
30d56e1af0 | ||
|
|
354630770b | ||
|
|
74da63e3ca | ||
|
|
faa438bc51 | ||
|
|
6de6fb1932 | ||
|
|
6a8acefa30 | ||
|
|
ddec8325e7 | ||
|
|
b1852526f5 | ||
|
|
20aaf58ee9 | ||
|
|
b3db597c4b | ||
|
|
d302f228f9 | ||
|
|
74d5e2b0c1 | ||
|
|
dd42d24d8a | ||
|
|
5692fb32cd | ||
|
|
dbf80d564b | ||
|
|
72b82a8d19 | ||
|
|
c3beaedaa6 | ||
|
|
db694b20df | ||
|
|
34227ce738 | ||
|
|
24b1360eb8 | ||
|
|
60aff26d94 | ||
|
|
144bdf7dc7 | ||
|
|
8db4bb298e | ||
|
|
028477f34d | ||
|
|
6725c9e3cd | ||
|
|
a14dee5b8d | ||
|
|
2f8a1fc58f | ||
|
|
f250c4310e | ||
|
|
ad46e8a5e0 | ||
|
|
1e7031e5f4 | ||
|
|
8c736e979d | ||
|
|
335742a023 | ||
|
|
384ff3484c | ||
|
|
e17c29c258 | ||
|
|
e7d979ca74 | ||
|
|
bc2f38c790 | ||
|
|
88ee089d86 | ||
|
|
d9adaa5020 | ||
|
|
4a963adbcb | ||
|
|
56ac57b4cf | ||
|
|
cdbe2393c4 | ||
|
|
2f4490d059 | ||
|
|
447660504c | ||
|
|
5e44d18d54 | ||
|
|
7a9edae227 | ||
|
|
81b7bd35f4 | ||
|
|
4b946a23ca | ||
|
|
5ab92b1833 | ||
|
|
1a6a16e061 | ||
|
|
061b602334 | ||
|
|
f7deb02560 | ||
|
|
9dfe85eca3 | ||
|
|
ee837889db | ||
|
|
a5f4cba72f |
120
HISTORY.md
120
HISTORY.md
@@ -1,5 +1,123 @@
|
|||||||
# Release history
|
# Release history
|
||||||
|
|
||||||
|
### main branch
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
### Aider v0.77.0
|
||||||
|
|
||||||
|
- Big upgrade in [programming languages supported](https://aider.chat/docs/languages.html) by adopting [tree-sitter-language-pack](https://github.com/Goldziher/tree-sitter-language-pack/).
|
||||||
|
- 130 new languages with linter support.
|
||||||
|
- 20 new languages with repo-map support.
|
||||||
|
- Added `/think-tokens` command to set thinking token budget with support for human-readable formats (8k, 10.5k, 0.5M).
|
||||||
|
- Added `/reasoning-effort` command to control model reasoning level.
|
||||||
|
- The `/think-tokens` and `/reasoning-effort` commands display current settings when called without arguments.
|
||||||
|
- Display of thinking token budget and reasoning effort in model information.
|
||||||
|
- Changed `--thinking-tokens` argument to accept string values with human-readable formats.
|
||||||
|
- Added `--auto-accept-architect` flag (default: true) to automatically accept changes from architect coder format without confirmation.
|
||||||
|
- Added support for `cohere_chat/command-a-03-2025` and `gemini/gemma-3-27b-it`
|
||||||
|
- The bare `/drop` command now preserves original read-only files provided via args.read.
|
||||||
|
- Fixed a bug where default model would be set by deprecated `--shortcut` switches even when already specified in the command line.
|
||||||
|
- Improved AutoCompleter to require 3 characters for autocompletion to reduce noise.
|
||||||
|
- Aider wrote 72% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.76.2
|
||||||
|
|
||||||
|
- Fixed handling of JSONDecodeError when loading model cache file.
|
||||||
|
- Fixed handling of GitCommandError when retrieving git user configuration.
|
||||||
|
- Aider wrote 75% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.76.1
|
||||||
|
|
||||||
|
- Added ignore_permission_denied option to file watcher to prevent errors when accessing restricted files, by Yutaka Matsubara.
|
||||||
|
- Aider wrote 0% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.76.0
|
||||||
|
|
||||||
|
- Improved support for thinking/reasoningmodels:
|
||||||
|
- Added `--thinking-tokens` CLI option to control token budget for models that support thinking.
|
||||||
|
- Display thinking/reasoning content from LLMs which return it.
|
||||||
|
- Enhanced handling of reasoning tags to better clean up model responses.
|
||||||
|
- Added deprecation warning for `remove_reasoning` setting, now replaced by `reasoning_tag`.
|
||||||
|
- Aider will notify you when it's completed the last request and needs your input:
|
||||||
|
- Added [notifications when LLM responses are ready](https://aider.chat/docs/usage/notifications.html) with `--notifications` flag.
|
||||||
|
- Specify desktop notification command with `--notifications-command`.
|
||||||
|
- Added support for QWQ 32B.
|
||||||
|
- Switch to `tree-sitter-language-pack` for tree sitter support.
|
||||||
|
- Improved error handling for EOF (Ctrl+D) in user input prompts.
|
||||||
|
- Added helper function to ensure hex color values have a # prefix.
|
||||||
|
- Fixed handling of Git errors when reading staged files.
|
||||||
|
- Improved SSL verification control for model information requests.
|
||||||
|
- Improved empty LLM response handling with clearer warning messages.
|
||||||
|
- Fixed Git identity retrieval to respect global configuration, by Akira Komamura.
|
||||||
|
- Offer to install dependencies for Bedrock and Vertex AI models.
|
||||||
|
- Deprecated model shortcut args (like --4o, --opus) in favor of the --model flag.
|
||||||
|
- Aider wrote 85% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.75.3
|
||||||
|
|
||||||
|
- Support for V3 free on OpenRouter: `--model openrouter/deepseek/deepseek-chat:free`.
|
||||||
|
|
||||||
|
### Aider v0.75.2
|
||||||
|
|
||||||
|
- Added support for Claude 3.7 Sonnet models on OpenRouter, Bedrock and Vertex AI.
|
||||||
|
- Updated default model to Claude 3.7 Sonnet on OpenRouter.
|
||||||
|
- Added support for GPT-4.5-preview model.
|
||||||
|
- Added support for Claude 3.7 Sonnet:beta on OpenRouter.
|
||||||
|
- Fixed weak_model_name patterns to match main model name patterns for some models.
|
||||||
|
|
||||||
|
### Aider v0.75.1
|
||||||
|
|
||||||
|
- Added support for `openrouter/anthropic/claude-3.7-sonnet`
|
||||||
|
|
||||||
|
### Aider v0.75.0
|
||||||
|
|
||||||
|
- Basic support for Claude 3.7 Sonnet
|
||||||
|
- Use `--model sonnet` to use the new 3.7
|
||||||
|
- Thinking support coming soon.
|
||||||
|
- Bugfix to `/editor` command.
|
||||||
|
- Aider wrote 46% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.74.3
|
||||||
|
|
||||||
|
- Downgrade streamlit dependency to avoid threading bug.
|
||||||
|
- Added support for tree-sitter language pack.
|
||||||
|
- Added openrouter/o3-mini-high model configuration.
|
||||||
|
- Added build.gradle.kts to special files for Kotlin project support, by Lucas Shadler.
|
||||||
|
|
||||||
|
### Aider v0.74.2
|
||||||
|
|
||||||
|
- Prevent more than one cache warming thread from becoming active.
|
||||||
|
- Fixed continuation prompt ". " for multiline input.
|
||||||
|
- Added HCL (Terraform) syntax support, by Warren Krewenki.
|
||||||
|
|
||||||
|
### Aider v0.74.1
|
||||||
|
|
||||||
|
- Have o1 & o3-mini generate markdown by sending the magic "Formatting re-enabled." string.
|
||||||
|
- Bugfix for multi-line inputs, which should not include the ". " continuation prompt.
|
||||||
|
|
||||||
|
### Aider v0.74.0
|
||||||
|
|
||||||
|
- Dynamically changes the Ollama context window to hold the current chat.
|
||||||
|
- Better support for o3-mini, DeepSeek V3 & R1, o1-mini, o1 especially via third-party API providers.
|
||||||
|
- Remove `<think>` tags from R1 responses for commit messages (and other weak model uses).
|
||||||
|
- Can now specify `use_temperature: <float>` in model settings, not just true/false.
|
||||||
|
- The full docker container now includes `boto3` for Bedrock.
|
||||||
|
- Docker containers now set `HOME=/app` which is the normal project mount-point, to persist `~/.aider`.
|
||||||
|
- Bugfix to prevent creating incorrect filenames like `python`, `php`, etc.
|
||||||
|
- Bugfix for `--timeout`
|
||||||
|
- Bugfix so that `/model` now correctly reports that the weak model is not changed.
|
||||||
|
- Bugfix so that multi-line mode persists through ^C at confirmation prompts.
|
||||||
|
- Watch files now fully ignores top-level directories named in ignore files, to reduce the chance of hitting OS watch limits. Helpful to ignore giant subtrees like `node_modules`.
|
||||||
|
- Fast startup with more providers and when model metadata provided in local files.
|
||||||
|
- Improved .gitignore handling:
|
||||||
|
- Honor ignores already in effect regardless of how they've been configured.
|
||||||
|
- Check for .env only when the file exists.
|
||||||
|
- Yes/No prompts now accept All/Skip as alias for Y/N even when not processing a group of confirmations.
|
||||||
|
- Aider wrote 77% of the code in this release.
|
||||||
|
|
||||||
### Aider v0.73.0
|
### Aider v0.73.0
|
||||||
|
|
||||||
- Full support for o3-mini: `aider --model o3-mini`
|
- Full support for o3-mini: `aider --model o3-mini`
|
||||||
@@ -8,7 +126,7 @@
|
|||||||
- Added support for removing model-specific reasoning tags from responses with `remove_reasoning: tagname` model setting.
|
- Added support for removing model-specific reasoning tags from responses with `remove_reasoning: tagname` model setting.
|
||||||
- Auto-create parent directories when creating new files, by xqyz.
|
- Auto-create parent directories when creating new files, by xqyz.
|
||||||
- Support for R1 free on OpenRouter: `--model openrouter/deepseek/deepseek-r1:free`
|
- Support for R1 free on OpenRouter: `--model openrouter/deepseek/deepseek-r1:free`
|
||||||
- Aider wrote 70% of the code in this release.
|
- Aider wrote 69% of the code in this release.
|
||||||
|
|
||||||
### Aider v0.72.3
|
### Aider v0.72.3
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
Aider lets you pair program with LLMs,
|
Aider lets you pair program with LLMs,
|
||||||
to edit code in your local git repository.
|
to edit code in your local git repository.
|
||||||
Start a new project or work with an existing code base.
|
Start a new project or work with an existing code base.
|
||||||
Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
|
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).
|
||||||
|
|
||||||
|
|
||||||
<!-- SCREENCAST START -->
|
<!-- SCREENCAST START -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -55,14 +54,14 @@ cd /to/your/project
|
|||||||
# Work with DeepSeek via DeepSeek's API
|
# Work with DeepSeek via DeepSeek's API
|
||||||
aider --model deepseek --api-key deepseek=your-key-goes-here
|
aider --model deepseek --api-key deepseek=your-key-goes-here
|
||||||
|
|
||||||
# Work with Claude 3.5 Sonnet via Anthropic's API
|
# Work with Claude 3.7 Sonnet via Anthropic's API
|
||||||
aider --model sonnet --api-key anthropic=your-key-goes-here
|
aider --model sonnet --api-key anthropic=your-key-goes-here
|
||||||
|
|
||||||
# Work with GPT-4o via OpenAI's API
|
# Work with GPT-4o via OpenAI's API
|
||||||
aider --model gpt-4o --api-key openai=your-key-goes-here
|
aider --model gpt-4o --api-key openai=your-key-goes-here
|
||||||
|
|
||||||
# Work with Sonnet via OpenRouter's API
|
# Work with Sonnet via OpenRouter's API
|
||||||
aider --model openrouter/anthropic/claude-3.5-sonnet --api-key openrouter=your-key-goes-here
|
aider --model openrouter/anthropic/claude-3.7-sonnet --api-key openrouter=your-key-goes-here
|
||||||
|
|
||||||
# Work with DeepSeek via OpenRouter's API
|
# Work with DeepSeek via OpenRouter's API
|
||||||
aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here
|
aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here
|
||||||
@@ -96,7 +95,7 @@ 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 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.
|
- [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).
|
- [Code with your voice](https://aider.chat/docs/usage/voice.html).
|
||||||
- Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.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
|
## Top tier performance
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from packaging import version
|
from packaging import version
|
||||||
|
|
||||||
__version__ = "0.73.1.dev"
|
__version__ = "0.77.2.dev"
|
||||||
safe_version = __version__
|
safe_version = __version__
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
129
aider/args.py
129
aider/args.py
@@ -12,6 +12,7 @@ from aider.args_formatter import (
|
|||||||
MarkdownHelpFormatter,
|
MarkdownHelpFormatter,
|
||||||
YamlHelpFormatter,
|
YamlHelpFormatter,
|
||||||
)
|
)
|
||||||
|
from aider.deprecated import add_deprecated_model_args
|
||||||
|
|
||||||
from .dump import dump # noqa: F401
|
from .dump import dump # noqa: F401
|
||||||
|
|
||||||
@@ -38,98 +39,6 @@ def get_parser(default_config_files, git_root):
|
|||||||
default=None,
|
default=None,
|
||||||
help="Specify the model to use for the main chat",
|
help="Specify the model to use for the main chat",
|
||||||
)
|
)
|
||||||
opus_model = "claude-3-opus-20240229"
|
|
||||||
group.add_argument(
|
|
||||||
"--opus",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=opus_model,
|
|
||||||
help=f"Use {opus_model} model for the main chat",
|
|
||||||
)
|
|
||||||
sonnet_model = "claude-3-5-sonnet-20241022"
|
|
||||||
group.add_argument(
|
|
||||||
"--sonnet",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=sonnet_model,
|
|
||||||
help=f"Use {sonnet_model} model for the main chat",
|
|
||||||
)
|
|
||||||
haiku_model = "claude-3-5-haiku-20241022"
|
|
||||||
group.add_argument(
|
|
||||||
"--haiku",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=haiku_model,
|
|
||||||
help=f"Use {haiku_model} model for the main chat",
|
|
||||||
)
|
|
||||||
gpt_4_model = "gpt-4-0613"
|
|
||||||
group.add_argument(
|
|
||||||
"--4",
|
|
||||||
"-4",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=gpt_4_model,
|
|
||||||
help=f"Use {gpt_4_model} model for the main chat",
|
|
||||||
)
|
|
||||||
gpt_4o_model = "gpt-4o"
|
|
||||||
group.add_argument(
|
|
||||||
"--4o",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=gpt_4o_model,
|
|
||||||
help=f"Use {gpt_4o_model} model for the main chat",
|
|
||||||
)
|
|
||||||
gpt_4o_mini_model = "gpt-4o-mini"
|
|
||||||
group.add_argument(
|
|
||||||
"--mini",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=gpt_4o_mini_model,
|
|
||||||
help=f"Use {gpt_4o_mini_model} model for the main chat",
|
|
||||||
)
|
|
||||||
gpt_4_turbo_model = "gpt-4-1106-preview"
|
|
||||||
group.add_argument(
|
|
||||||
"--4-turbo",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=gpt_4_turbo_model,
|
|
||||||
help=f"Use {gpt_4_turbo_model} model for the main chat",
|
|
||||||
)
|
|
||||||
gpt_3_model_name = "gpt-3.5-turbo"
|
|
||||||
group.add_argument(
|
|
||||||
"--35turbo",
|
|
||||||
"--35-turbo",
|
|
||||||
"--3",
|
|
||||||
"-3",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=gpt_3_model_name,
|
|
||||||
help=f"Use {gpt_3_model_name} model for the main chat",
|
|
||||||
)
|
|
||||||
deepseek_model = "deepseek/deepseek-chat"
|
|
||||||
group.add_argument(
|
|
||||||
"--deepseek",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=deepseek_model,
|
|
||||||
help=f"Use {deepseek_model} model for the main chat",
|
|
||||||
)
|
|
||||||
o1_mini_model = "o1-mini"
|
|
||||||
group.add_argument(
|
|
||||||
"--o1-mini",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=o1_mini_model,
|
|
||||||
help=f"Use {o1_mini_model} model for the main chat",
|
|
||||||
)
|
|
||||||
o1_preview_model = "o1-preview"
|
|
||||||
group.add_argument(
|
|
||||||
"--o1-preview",
|
|
||||||
action="store_const",
|
|
||||||
dest="model",
|
|
||||||
const=o1_preview_model,
|
|
||||||
help=f"Use {o1_preview_model} model for the main chat",
|
|
||||||
)
|
|
||||||
|
|
||||||
##########
|
##########
|
||||||
group = parser.add_argument_group("API Keys and settings")
|
group = parser.add_argument_group("API Keys and settings")
|
||||||
@@ -208,6 +117,11 @@ def get_parser(default_config_files, git_root):
|
|||||||
type=str,
|
type=str,
|
||||||
help="Set the reasoning_effort API parameter (default: not set)",
|
help="Set the reasoning_effort API parameter (default: not set)",
|
||||||
)
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--thinking-tokens",
|
||||||
|
type=str,
|
||||||
|
help="Set the thinking token budget for models that support it (default: not set)",
|
||||||
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"--verify-ssl",
|
"--verify-ssl",
|
||||||
action=argparse.BooleanOptionalAction,
|
action=argparse.BooleanOptionalAction,
|
||||||
@@ -216,7 +130,7 @@ def get_parser(default_config_files, git_root):
|
|||||||
)
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"--timeout",
|
"--timeout",
|
||||||
type=int,
|
type=float,
|
||||||
default=None,
|
default=None,
|
||||||
help="Timeout in seconds for API calls (default: None)",
|
help="Timeout in seconds for API calls (default: None)",
|
||||||
)
|
)
|
||||||
@@ -234,6 +148,12 @@ def get_parser(default_config_files, git_root):
|
|||||||
const="architect",
|
const="architect",
|
||||||
help="Use architect edit format for the main chat",
|
help="Use architect edit format for the main chat",
|
||||||
)
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--auto-accept-architect",
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
default=True,
|
||||||
|
help="Enable/disable automatic acceptance of architect changes (default: True)",
|
||||||
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"--weak-model",
|
"--weak-model",
|
||||||
metavar="WEAK_MODEL",
|
metavar="WEAK_MODEL",
|
||||||
@@ -813,6 +733,24 @@ def get_parser(default_config_files, git_root):
|
|||||||
default=False,
|
default=False,
|
||||||
help="Enable/disable multi-line input mode with Meta-Enter to submit (default: False)",
|
help="Enable/disable multi-line input mode with Meta-Enter to submit (default: False)",
|
||||||
)
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--notifications",
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
default=False,
|
||||||
|
help=(
|
||||||
|
"Enable/disable terminal bell notifications when LLM responses are ready (default:"
|
||||||
|
" False)"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
group.add_argument(
|
||||||
|
"--notifications-command",
|
||||||
|
metavar="COMMAND",
|
||||||
|
default=None,
|
||||||
|
help=(
|
||||||
|
"Specify a command to run for notifications instead of the terminal bell. If not"
|
||||||
|
" specified, a default command for your OS may be used."
|
||||||
|
),
|
||||||
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"--detect-urls",
|
"--detect-urls",
|
||||||
action=argparse.BooleanOptionalAction,
|
action=argparse.BooleanOptionalAction,
|
||||||
@@ -824,6 +762,11 @@ def get_parser(default_config_files, git_root):
|
|||||||
help="Specify which editor to use for the /editor command",
|
help="Specify which editor to use for the /editor command",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
##########
|
||||||
|
group = parser.add_argument_group("Deprecated model settings")
|
||||||
|
# Add deprecated model shortcut arguments
|
||||||
|
add_deprecated_model_args(parser, group)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -148,11 +148,14 @@ class YamlHelpFormatter(argparse.HelpFormatter):
|
|||||||
parts.append(f"#{switch}: xxx")
|
parts.append(f"#{switch}: xxx")
|
||||||
parts.append("## Specify multiple values like this:")
|
parts.append("## Specify multiple values like this:")
|
||||||
parts.append(f"#{switch}:")
|
parts.append(f"#{switch}:")
|
||||||
parts.append(f"# - xxx")
|
parts.append("# - xxx")
|
||||||
parts.append(f"# - yyy")
|
parts.append("# - yyy")
|
||||||
parts.append(f"# - zzz")
|
parts.append("# - zzz")
|
||||||
else:
|
else:
|
||||||
parts.append(f"#{switch}: xxx\n")
|
if switch.endswith("color"):
|
||||||
|
parts.append(f'#{switch}: "xxx"\n')
|
||||||
|
else:
|
||||||
|
parts.append(f"#{switch}: xxx\n")
|
||||||
|
|
||||||
###
|
###
|
||||||
# parts.append(str(action))
|
# parts.append(str(action))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from .base_coder import Coder
|
|||||||
class ArchitectCoder(AskCoder):
|
class ArchitectCoder(AskCoder):
|
||||||
edit_format = "architect"
|
edit_format = "architect"
|
||||||
gpt_prompts = ArchitectPrompts()
|
gpt_prompts = ArchitectPrompts()
|
||||||
|
auto_accept_architect = False
|
||||||
|
|
||||||
def reply_completed(self):
|
def reply_completed(self):
|
||||||
content = self.partial_response_content
|
content = self.partial_response_content
|
||||||
@@ -13,7 +14,7 @@ class ArchitectCoder(AskCoder):
|
|||||||
if not content or not content.strip():
|
if not content or not content.strip():
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.io.confirm_ask("Edit the files?"):
|
if not self.auto_accept_architect and not self.io.confirm_ask("Edit the files?"):
|
||||||
return
|
return
|
||||||
|
|
||||||
kwargs = dict()
|
kwargs = dict()
|
||||||
|
|||||||
@@ -27,10 +27,16 @@ from aider.history import ChatSummary
|
|||||||
from aider.io import ConfirmGroup, InputOutput
|
from aider.io import ConfirmGroup, InputOutput
|
||||||
from aider.linter import Linter
|
from aider.linter import Linter
|
||||||
from aider.llm import litellm
|
from aider.llm import litellm
|
||||||
|
from aider.models import RETRY_TIMEOUT
|
||||||
|
from aider.reasoning_tags import (
|
||||||
|
REASONING_TAG,
|
||||||
|
format_reasoning_content,
|
||||||
|
remove_reasoning_content,
|
||||||
|
replace_reasoning_tags,
|
||||||
|
)
|
||||||
from aider.repo import ANY_GIT_ERROR, GitRepo
|
from aider.repo import ANY_GIT_ERROR, GitRepo
|
||||||
from aider.repomap import RepoMap
|
from aider.repomap import RepoMap
|
||||||
from aider.run_cmd import run_cmd
|
from aider.run_cmd import run_cmd
|
||||||
from aider.sendchat import RETRY_TIMEOUT, send_completion
|
|
||||||
from aider.utils import format_content, format_messages, format_tokens, is_image_file
|
from aider.utils import format_content, format_messages, format_tokens, is_image_file
|
||||||
|
|
||||||
from ..dump import dump # noqa: F401
|
from ..dump import dump # noqa: F401
|
||||||
@@ -60,7 +66,7 @@ def wrap_fence(name):
|
|||||||
|
|
||||||
all_fences = [
|
all_fences = [
|
||||||
("`" * 3, "`" * 3),
|
("`" * 3, "`" * 3),
|
||||||
("`" * 4, "`" * 4),
|
("`" * 4, "`" * 4), # LLMs ignore and revert to triple-backtick, causing #2879
|
||||||
wrap_fence("source"),
|
wrap_fence("source"),
|
||||||
wrap_fence("code"),
|
wrap_fence("code"),
|
||||||
wrap_fence("pre"),
|
wrap_fence("pre"),
|
||||||
@@ -85,7 +91,7 @@ class Coder:
|
|||||||
max_reflections = 3
|
max_reflections = 3
|
||||||
edit_format = None
|
edit_format = None
|
||||||
yield_stream = False
|
yield_stream = False
|
||||||
temperature = 0
|
temperature = None
|
||||||
auto_lint = True
|
auto_lint = True
|
||||||
auto_test = False
|
auto_test = False
|
||||||
test_cmd = None
|
test_cmd = None
|
||||||
@@ -144,7 +150,13 @@ class Coder:
|
|||||||
# the system prompt.
|
# the system prompt.
|
||||||
done_messages = from_coder.done_messages
|
done_messages = from_coder.done_messages
|
||||||
if edit_format != from_coder.edit_format and done_messages and summarize_from_coder:
|
if edit_format != from_coder.edit_format and done_messages and summarize_from_coder:
|
||||||
done_messages = from_coder.summarizer.summarize_all(done_messages)
|
try:
|
||||||
|
done_messages = from_coder.summarizer.summarize_all(done_messages)
|
||||||
|
except ValueError:
|
||||||
|
# If summarization fails, keep the original messages and warn the user
|
||||||
|
io.tool_warning(
|
||||||
|
"Chat history summarization failed, continuing with full history"
|
||||||
|
)
|
||||||
|
|
||||||
# Bring along context from the old Coder
|
# Bring along context from the old Coder
|
||||||
update = dict(
|
update = dict(
|
||||||
@@ -162,6 +174,7 @@ class Coder:
|
|||||||
use_kwargs.update(kwargs) # override passed kwargs
|
use_kwargs.update(kwargs) # override passed kwargs
|
||||||
|
|
||||||
kwargs = use_kwargs
|
kwargs = use_kwargs
|
||||||
|
from_coder.ok_to_warm_cache = False
|
||||||
|
|
||||||
for coder in coders.__all__:
|
for coder in coders.__all__:
|
||||||
if hasattr(coder, "edit_format") and coder.edit_format == edit_format:
|
if hasattr(coder, "edit_format") and coder.edit_format == edit_format:
|
||||||
@@ -194,10 +207,22 @@ class Coder:
|
|||||||
prefix = "Model"
|
prefix = "Model"
|
||||||
|
|
||||||
output = f"{prefix}: {main_model.name} with {self.edit_format} edit format"
|
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)
|
||||||
|
if thinking_tokens:
|
||||||
|
output += f", {thinking_tokens} think tokens"
|
||||||
|
|
||||||
|
# Check for reasoning effort
|
||||||
|
reasoning_effort = main_model.get_reasoning_effort(main_model)
|
||||||
|
if reasoning_effort:
|
||||||
|
output += f", reasoning {reasoning_effort}"
|
||||||
|
|
||||||
if self.add_cache_headers or main_model.caches_by_default:
|
if self.add_cache_headers or main_model.caches_by_default:
|
||||||
output += ", prompt cache"
|
output += ", prompt cache"
|
||||||
if main_model.info.get("supports_assistant_prefill"):
|
if main_model.info.get("supports_assistant_prefill"):
|
||||||
output += ", infinite output"
|
output += ", infinite output"
|
||||||
|
|
||||||
lines.append(output)
|
lines.append(output)
|
||||||
|
|
||||||
if self.edit_format == "architect":
|
if self.edit_format == "architect":
|
||||||
@@ -258,6 +283,8 @@ class Coder:
|
|||||||
|
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
ok_to_warm_cache = False
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
main_model,
|
main_model,
|
||||||
@@ -295,6 +322,7 @@ class Coder:
|
|||||||
ignore_mentions=None,
|
ignore_mentions=None,
|
||||||
file_watcher=None,
|
file_watcher=None,
|
||||||
auto_copy_context=False,
|
auto_copy_context=False,
|
||||||
|
auto_accept_architect=True,
|
||||||
):
|
):
|
||||||
# Fill in a dummy Analytics if needed, but it is never .enable()'d
|
# Fill in a dummy Analytics if needed, but it is never .enable()'d
|
||||||
self.analytics = analytics if analytics is not None else Analytics()
|
self.analytics = analytics if analytics is not None else Analytics()
|
||||||
@@ -307,6 +335,7 @@ class Coder:
|
|||||||
self.abs_root_path_cache = {}
|
self.abs_root_path_cache = {}
|
||||||
|
|
||||||
self.auto_copy_context = auto_copy_context
|
self.auto_copy_context = auto_copy_context
|
||||||
|
self.auto_accept_architect = auto_accept_architect
|
||||||
|
|
||||||
self.ignore_mentions = ignore_mentions
|
self.ignore_mentions = ignore_mentions
|
||||||
if not self.ignore_mentions:
|
if not self.ignore_mentions:
|
||||||
@@ -366,6 +395,10 @@ class Coder:
|
|||||||
self.pretty = self.io.pretty
|
self.pretty = self.io.pretty
|
||||||
|
|
||||||
self.main_model = main_model
|
self.main_model = main_model
|
||||||
|
# Set the reasoning tag name based on model settings or default
|
||||||
|
self.reasoning_tag_name = (
|
||||||
|
self.main_model.reasoning_tag if self.main_model.reasoning_tag else REASONING_TAG
|
||||||
|
)
|
||||||
|
|
||||||
self.stream = stream and main_model.streaming
|
self.stream = stream and main_model.streaming
|
||||||
|
|
||||||
@@ -1055,14 +1088,26 @@ class Coder:
|
|||||||
else:
|
else:
|
||||||
language = "the same language they are using"
|
language = "the same language they are using"
|
||||||
|
|
||||||
|
if self.fence[0] == "`" * 4:
|
||||||
|
quad_backtick_reminder = (
|
||||||
|
"\nIMPORTANT: Use *quadruple* backticks ```` as fences, not triple backticks!\n"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
quad_backtick_reminder = ""
|
||||||
|
|
||||||
prompt = prompt.format(
|
prompt = prompt.format(
|
||||||
fence=self.fence,
|
fence=self.fence,
|
||||||
|
quad_backtick_reminder=quad_backtick_reminder,
|
||||||
lazy_prompt=lazy_prompt,
|
lazy_prompt=lazy_prompt,
|
||||||
platform=platform_text,
|
platform=platform_text,
|
||||||
shell_cmd_prompt=shell_cmd_prompt,
|
shell_cmd_prompt=shell_cmd_prompt,
|
||||||
shell_cmd_reminder=shell_cmd_reminder,
|
shell_cmd_reminder=shell_cmd_reminder,
|
||||||
language=language,
|
language=language,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self.main_model.system_prompt_prefix:
|
||||||
|
prompt = self.main_model.system_prompt_prefix + prompt
|
||||||
|
|
||||||
return prompt
|
return prompt
|
||||||
|
|
||||||
def format_chat_chunks(self):
|
def format_chat_chunks(self):
|
||||||
@@ -1182,8 +1227,11 @@ class Coder:
|
|||||||
return
|
return
|
||||||
if not self.num_cache_warming_pings:
|
if not self.num_cache_warming_pings:
|
||||||
return
|
return
|
||||||
|
if not self.ok_to_warm_cache:
|
||||||
|
return
|
||||||
|
|
||||||
delay = 5 * 60 - 5
|
delay = 5 * 60 - 5
|
||||||
|
delay = float(os.environ.get("AIDER_CACHE_KEEPALIVE_DELAY", delay))
|
||||||
self.next_cache_warm = time.time() + delay
|
self.next_cache_warm = time.time() + delay
|
||||||
self.warming_pings_left = self.num_cache_warming_pings
|
self.warming_pings_left = self.num_cache_warming_pings
|
||||||
self.cache_warming_chunks = chunks
|
self.cache_warming_chunks = chunks
|
||||||
@@ -1192,7 +1240,7 @@ class Coder:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def warm_cache_worker():
|
def warm_cache_worker():
|
||||||
while True:
|
while self.ok_to_warm_cache:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
if self.warming_pings_left <= 0:
|
if self.warming_pings_left <= 0:
|
||||||
continue
|
continue
|
||||||
@@ -1235,8 +1283,6 @@ class Coder:
|
|||||||
input_tokens = self.main_model.token_count(messages)
|
input_tokens = self.main_model.token_count(messages)
|
||||||
max_input_tokens = self.main_model.info.get("max_input_tokens") or 0
|
max_input_tokens = self.main_model.info.get("max_input_tokens") or 0
|
||||||
|
|
||||||
proceed = None
|
|
||||||
|
|
||||||
if max_input_tokens and input_tokens >= max_input_tokens:
|
if max_input_tokens and input_tokens >= max_input_tokens:
|
||||||
self.io.tool_error(
|
self.io.tool_error(
|
||||||
f"Your estimated chat context of {input_tokens:,} tokens exceeds the"
|
f"Your estimated chat context of {input_tokens:,} tokens exceeds the"
|
||||||
@@ -1246,31 +1292,21 @@ class Coder:
|
|||||||
self.io.tool_output("- Use /drop to remove unneeded files from the chat")
|
self.io.tool_output("- Use /drop to remove unneeded files from the chat")
|
||||||
self.io.tool_output("- Use /clear to clear the chat history")
|
self.io.tool_output("- Use /clear to clear the chat history")
|
||||||
self.io.tool_output("- Break your code into smaller files")
|
self.io.tool_output("- Break your code into smaller files")
|
||||||
proceed = "Y"
|
|
||||||
self.io.tool_output(
|
self.io.tool_output(
|
||||||
"It's probably safe to try and send the request, most providers won't charge if"
|
"It's probably safe to try and send the request, most providers won't charge if"
|
||||||
" the context limit is exceeded."
|
" the context limit is exceeded."
|
||||||
)
|
)
|
||||||
|
|
||||||
# Special warning for Ollama models about context window size
|
if not self.io.confirm_ask("Try to proceed anyway?"):
|
||||||
if self.main_model.name.startswith(("ollama/", "ollama_chat/")):
|
return False
|
||||||
extra_params = getattr(self.main_model, "extra_params", None) or {}
|
|
||||||
num_ctx = extra_params.get("num_ctx", 2048)
|
|
||||||
if input_tokens > num_ctx:
|
|
||||||
proceed = "N"
|
|
||||||
self.io.tool_warning(f"""
|
|
||||||
Your Ollama model is configured with num_ctx={num_ctx} tokens of context window.
|
|
||||||
You are attempting to send {input_tokens} tokens.
|
|
||||||
See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|
||||||
""".strip()) # noqa
|
|
||||||
|
|
||||||
if proceed and not self.io.confirm_ask("Try to proceed anyway?", default=proceed):
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def send_message(self, inp):
|
def send_message(self, inp):
|
||||||
self.event("message_send_starting")
|
self.event("message_send_starting")
|
||||||
|
|
||||||
|
# Notify IO that LLM processing is starting
|
||||||
|
self.io.llm_started()
|
||||||
|
|
||||||
self.cur_messages += [
|
self.cur_messages += [
|
||||||
dict(role="user", content=inp),
|
dict(role="user", content=inp),
|
||||||
]
|
]
|
||||||
@@ -1339,7 +1375,7 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
exhausted = True
|
exhausted = True
|
||||||
break
|
break
|
||||||
|
|
||||||
self.multi_response_content = self.get_multi_response_content()
|
self.multi_response_content = self.get_multi_response_content_in_progress()
|
||||||
|
|
||||||
if messages[-1]["role"] == "assistant":
|
if messages[-1]["role"] == "assistant":
|
||||||
messages[-1]["content"] = self.multi_response_content
|
messages[-1]["content"] = self.multi_response_content
|
||||||
@@ -1359,9 +1395,15 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
self.live_incremental_response(True)
|
self.live_incremental_response(True)
|
||||||
self.mdstream = None
|
self.mdstream = None
|
||||||
|
|
||||||
self.partial_response_content = self.get_multi_response_content(True)
|
self.partial_response_content = self.get_multi_response_content_in_progress(True)
|
||||||
|
self.remove_reasoning_content()
|
||||||
self.multi_response_content = ""
|
self.multi_response_content = ""
|
||||||
|
|
||||||
|
###
|
||||||
|
# print()
|
||||||
|
# print("=" * 20)
|
||||||
|
# dump(self.partial_response_content)
|
||||||
|
|
||||||
self.io.tool_output()
|
self.io.tool_output()
|
||||||
|
|
||||||
self.show_usage_report()
|
self.show_usage_report()
|
||||||
@@ -1529,6 +1571,10 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""Cleanup when the Coder object is destroyed."""
|
||||||
|
self.ok_to_warm_cache = False
|
||||||
|
|
||||||
def add_assistant_reply_to_cur_messages(self):
|
def add_assistant_reply_to_cur_messages(self):
|
||||||
if self.partial_response_content:
|
if self.partial_response_content:
|
||||||
self.cur_messages += [dict(role="assistant", content=self.partial_response_content)]
|
self.cur_messages += [dict(role="assistant", content=self.partial_response_content)]
|
||||||
@@ -1595,7 +1641,9 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
added_fnames = []
|
added_fnames = []
|
||||||
group = ConfirmGroup(new_mentions)
|
group = ConfirmGroup(new_mentions)
|
||||||
for rel_fname in sorted(new_mentions):
|
for rel_fname in sorted(new_mentions):
|
||||||
if self.io.confirm_ask(f"Add {rel_fname} to the chat?", group=group, allow_never=True):
|
if self.io.confirm_ask(
|
||||||
|
"Add file to the chat?", subject=rel_fname, group=group, allow_never=True
|
||||||
|
):
|
||||||
self.add_rel_fname(rel_fname)
|
self.add_rel_fname(rel_fname)
|
||||||
added_fnames.append(rel_fname)
|
added_fnames.append(rel_fname)
|
||||||
else:
|
else:
|
||||||
@@ -1605,6 +1653,9 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
return prompts.added_files.format(fnames=", ".join(added_fnames))
|
return prompts.added_files.format(fnames=", ".join(added_fnames))
|
||||||
|
|
||||||
def send(self, messages, model=None, functions=None):
|
def send(self, messages, model=None, functions=None):
|
||||||
|
self.got_reasoning_content = False
|
||||||
|
self.ended_reasoning_content = False
|
||||||
|
|
||||||
if not model:
|
if not model:
|
||||||
model = self.main_model
|
model = self.main_model
|
||||||
|
|
||||||
@@ -1613,20 +1664,13 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
|
|
||||||
self.io.log_llm_history("TO LLM", format_messages(messages))
|
self.io.log_llm_history("TO LLM", format_messages(messages))
|
||||||
|
|
||||||
if self.main_model.use_temperature:
|
|
||||||
temp = self.temperature
|
|
||||||
else:
|
|
||||||
temp = None
|
|
||||||
|
|
||||||
completion = None
|
completion = None
|
||||||
try:
|
try:
|
||||||
hash_object, completion = send_completion(
|
hash_object, completion = model.send_completion(
|
||||||
model.name,
|
|
||||||
messages,
|
messages,
|
||||||
functions,
|
functions,
|
||||||
self.stream,
|
self.stream,
|
||||||
temp,
|
self.temperature,
|
||||||
extra_params=model.extra_params,
|
|
||||||
)
|
)
|
||||||
self.chat_completion_call_hashes.append(hash_object.hexdigest())
|
self.chat_completion_call_hashes.append(hash_object.hexdigest())
|
||||||
|
|
||||||
@@ -1679,6 +1723,14 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
except AttributeError as func_err:
|
except AttributeError as func_err:
|
||||||
show_func_err = func_err
|
show_func_err = func_err
|
||||||
|
|
||||||
|
try:
|
||||||
|
reasoning_content = completion.choices[0].message.reasoning_content
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
reasoning_content = completion.choices[0].message.reasoning
|
||||||
|
except AttributeError:
|
||||||
|
reasoning_content = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.partial_response_content = completion.choices[0].message.content or ""
|
self.partial_response_content = completion.choices[0].message.content or ""
|
||||||
except AttributeError as content_err:
|
except AttributeError as content_err:
|
||||||
@@ -1697,6 +1749,15 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
raise Exception("No data found in LLM response!")
|
raise Exception("No data found in LLM response!")
|
||||||
|
|
||||||
show_resp = self.render_incremental_response(True)
|
show_resp = self.render_incremental_response(True)
|
||||||
|
|
||||||
|
if reasoning_content:
|
||||||
|
formatted_reasoning = format_reasoning_content(
|
||||||
|
reasoning_content, self.reasoning_tag_name
|
||||||
|
)
|
||||||
|
show_resp = formatted_reasoning + show_resp
|
||||||
|
|
||||||
|
show_resp = replace_reasoning_tags(show_resp, self.reasoning_tag_name)
|
||||||
|
|
||||||
self.io.assistant_output(show_resp, pretty=self.show_pretty())
|
self.io.assistant_output(show_resp, pretty=self.show_pretty())
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -1706,6 +1767,8 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
raise FinishReasonLength()
|
raise FinishReasonLength()
|
||||||
|
|
||||||
def show_send_output_stream(self, completion):
|
def show_send_output_stream(self, completion):
|
||||||
|
received_content = False
|
||||||
|
|
||||||
for chunk in completion:
|
for chunk in completion:
|
||||||
if len(chunk.choices) == 0:
|
if len(chunk.choices) == 0:
|
||||||
continue
|
continue
|
||||||
@@ -1724,19 +1787,46 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
self.partial_response_function_call[k] += v
|
self.partial_response_function_call[k] += v
|
||||||
else:
|
else:
|
||||||
self.partial_response_function_call[k] = v
|
self.partial_response_function_call[k] = v
|
||||||
|
received_content = True
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
text = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
text = chunk.choices[0].delta.content
|
reasoning_content = chunk.choices[0].delta.reasoning_content
|
||||||
if text:
|
|
||||||
self.partial_response_content += text
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
text = None
|
try:
|
||||||
|
reasoning_content = chunk.choices[0].delta.reasoning
|
||||||
|
except AttributeError:
|
||||||
|
reasoning_content = None
|
||||||
|
|
||||||
|
if reasoning_content:
|
||||||
|
if not self.got_reasoning_content:
|
||||||
|
text += f"<{REASONING_TAG}>\n\n"
|
||||||
|
text += reasoning_content
|
||||||
|
self.got_reasoning_content = True
|
||||||
|
received_content = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
content = chunk.choices[0].delta.content
|
||||||
|
if content:
|
||||||
|
if self.got_reasoning_content and not self.ended_reasoning_content:
|
||||||
|
text += f"\n\n</{self.reasoning_tag_name}>\n\n"
|
||||||
|
self.ended_reasoning_content = True
|
||||||
|
|
||||||
|
text += content
|
||||||
|
received_content = True
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.partial_response_content += text
|
||||||
|
|
||||||
if self.show_pretty():
|
if self.show_pretty():
|
||||||
self.live_incremental_response(False)
|
self.live_incremental_response(False)
|
||||||
elif text:
|
elif text:
|
||||||
|
# Apply reasoning tag formatting
|
||||||
|
text = replace_reasoning_tags(text, self.reasoning_tag_name)
|
||||||
try:
|
try:
|
||||||
sys.stdout.write(text)
|
sys.stdout.write(text)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
@@ -1748,12 +1838,25 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
yield text
|
yield text
|
||||||
|
|
||||||
|
if not received_content:
|
||||||
|
self.io.tool_warning("Empty response received from LLM. Check your provider account?")
|
||||||
|
|
||||||
def live_incremental_response(self, final):
|
def live_incremental_response(self, final):
|
||||||
show_resp = self.render_incremental_response(final)
|
show_resp = self.render_incremental_response(final)
|
||||||
|
# Apply any reasoning tag formatting
|
||||||
|
show_resp = replace_reasoning_tags(show_resp, self.reasoning_tag_name)
|
||||||
self.mdstream.update(show_resp, final=final)
|
self.mdstream.update(show_resp, final=final)
|
||||||
|
|
||||||
def render_incremental_response(self, final):
|
def render_incremental_response(self, final):
|
||||||
return self.get_multi_response_content()
|
return self.get_multi_response_content_in_progress()
|
||||||
|
|
||||||
|
def remove_reasoning_content(self):
|
||||||
|
"""Remove reasoning content from the model's response."""
|
||||||
|
|
||||||
|
self.partial_response_content = remove_reasoning_content(
|
||||||
|
self.partial_response_content,
|
||||||
|
self.reasoning_tag_name,
|
||||||
|
)
|
||||||
|
|
||||||
def calculate_and_show_tokens_and_cost(self, messages, completion=None):
|
def calculate_and_show_tokens_and_cost(self, messages, completion=None):
|
||||||
prompt_tokens = 0
|
prompt_tokens = 0
|
||||||
@@ -1876,22 +1979,14 @@ See https://aider.chat/docs/llms/ollama.html#setting-the-context-window-size
|
|||||||
self.message_tokens_sent = 0
|
self.message_tokens_sent = 0
|
||||||
self.message_tokens_received = 0
|
self.message_tokens_received = 0
|
||||||
|
|
||||||
def get_multi_response_content(self, final=False):
|
def get_multi_response_content_in_progress(self, final=False):
|
||||||
cur = self.multi_response_content or ""
|
cur = self.multi_response_content or ""
|
||||||
new = self.partial_response_content or ""
|
new = self.partial_response_content or ""
|
||||||
|
|
||||||
if new.rstrip() != new and not final:
|
if new.rstrip() != new and not final:
|
||||||
new = new.rstrip()
|
new = new.rstrip()
|
||||||
|
|
||||||
res = cur + new
|
return cur + new
|
||||||
|
|
||||||
if self.main_model.remove_reasoning:
|
|
||||||
pattern = (
|
|
||||||
f"<{self.main_model.remove_reasoning}>.*?</{self.main_model.remove_reasoning}>"
|
|
||||||
)
|
|
||||||
res = re.sub(pattern, "", res, flags=re.DOTALL).strip()
|
|
||||||
|
|
||||||
return res
|
|
||||||
|
|
||||||
def get_rel_fname(self, fname):
|
def get_rel_fname(self, fname):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -401,6 +401,9 @@ missing_filename_err = (
|
|||||||
" {fence[0]}"
|
" {fence[0]}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Always be willing to treat triple-backticks as a fence when searching for filenames
|
||||||
|
triple_backticks = "`" * 3
|
||||||
|
|
||||||
|
|
||||||
def strip_filename(filename, fence):
|
def strip_filename(filename, fence):
|
||||||
filename = filename.strip()
|
filename = filename.strip()
|
||||||
@@ -409,7 +412,7 @@ def strip_filename(filename, fence):
|
|||||||
return
|
return
|
||||||
|
|
||||||
start_fence = fence[0]
|
start_fence = fence[0]
|
||||||
if filename.startswith(start_fence):
|
if filename.startswith(start_fence) or filename.startswith(triple_backticks):
|
||||||
return
|
return
|
||||||
|
|
||||||
filename = filename.rstrip(":")
|
filename = filename.rstrip(":")
|
||||||
@@ -546,7 +549,7 @@ def find_filename(lines, fence, valid_fnames):
|
|||||||
filenames.append(filename)
|
filenames.append(filename)
|
||||||
|
|
||||||
# Only continue as long as we keep seeing fences
|
# Only continue as long as we keep seeing fences
|
||||||
if not line.startswith(fence[0]):
|
if not line.startswith(fence[0]) and not line.startswith(triple_backticks):
|
||||||
break
|
break
|
||||||
|
|
||||||
if not filenames:
|
if not filenames:
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ Every *SEARCH/REPLACE block* must use this format:
|
|||||||
8. The closing fence: {fence[1]}
|
8. The closing fence: {fence[1]}
|
||||||
|
|
||||||
Use the *FULL* file path, as shown to you by the user.
|
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.
|
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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ class WholeFileCoder(Coder):
|
|||||||
try:
|
try:
|
||||||
return self.get_edits(mode="diff")
|
return self.get_edits(mode="diff")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return self.get_multi_response_content()
|
return self.get_multi_response_content_in_progress()
|
||||||
|
|
||||||
def get_edits(self, mode="update"):
|
def get_edits(self, mode="update"):
|
||||||
content = self.get_multi_response_content()
|
content = self.get_multi_response_content_in_progress()
|
||||||
|
|
||||||
chat_files = self.get_inchat_relative_files()
|
chat_files = self.get_inchat_relative_files()
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class Commands:
|
|||||||
parser=None,
|
parser=None,
|
||||||
verbose=False,
|
verbose=False,
|
||||||
editor=None,
|
editor=None,
|
||||||
|
original_read_only_fnames=None,
|
||||||
):
|
):
|
||||||
self.io = io
|
self.io = io
|
||||||
self.coder = coder
|
self.coder = coder
|
||||||
@@ -77,11 +78,14 @@ class Commands:
|
|||||||
self.help = None
|
self.help = None
|
||||||
self.editor = editor
|
self.editor = editor
|
||||||
|
|
||||||
|
# Store the original read-only filenames provided via args.read
|
||||||
|
self.original_read_only_fnames = set(original_read_only_fnames or [])
|
||||||
|
|
||||||
def cmd_model(self, args):
|
def cmd_model(self, args):
|
||||||
"Switch to a new LLM"
|
"Switch to a new LLM"
|
||||||
|
|
||||||
model_name = args.strip()
|
model_name = args.strip()
|
||||||
model = models.Model(model_name)
|
model = models.Model(model_name, weak_model=self.coder.main_model.weak_model.name)
|
||||||
models.sanity_check_models(self.io, model)
|
models.sanity_check_models(self.io, model)
|
||||||
raise SwitchCoder(main_model=model)
|
raise SwitchCoder(main_model=model)
|
||||||
|
|
||||||
@@ -355,7 +359,21 @@ class Commands:
|
|||||||
|
|
||||||
def _drop_all_files(self):
|
def _drop_all_files(self):
|
||||||
self.coder.abs_fnames = set()
|
self.coder.abs_fnames = set()
|
||||||
self.coder.abs_read_only_fnames = set()
|
|
||||||
|
# When dropping all files, keep those that were originally provided via args.read
|
||||||
|
if self.original_read_only_fnames:
|
||||||
|
# Keep only the original read-only files
|
||||||
|
to_keep = set()
|
||||||
|
for abs_fname in self.coder.abs_read_only_fnames:
|
||||||
|
rel_fname = self.coder.get_rel_fname(abs_fname)
|
||||||
|
if (
|
||||||
|
abs_fname in self.original_read_only_fnames
|
||||||
|
or rel_fname in self.original_read_only_fnames
|
||||||
|
):
|
||||||
|
to_keep.add(abs_fname)
|
||||||
|
self.coder.abs_read_only_fnames = to_keep
|
||||||
|
else:
|
||||||
|
self.coder.abs_read_only_fnames = set()
|
||||||
|
|
||||||
def _clear_chat_history(self):
|
def _clear_chat_history(self):
|
||||||
self.coder.done_messages = []
|
self.coder.done_messages = []
|
||||||
@@ -404,6 +422,7 @@ class Commands:
|
|||||||
|
|
||||||
fence = "`" * 3
|
fence = "`" * 3
|
||||||
|
|
||||||
|
file_res = []
|
||||||
# files
|
# files
|
||||||
for fname in self.coder.abs_fnames:
|
for fname in self.coder.abs_fnames:
|
||||||
relative_fname = self.coder.get_rel_fname(fname)
|
relative_fname = self.coder.get_rel_fname(fname)
|
||||||
@@ -414,7 +433,7 @@ class Commands:
|
|||||||
# approximate
|
# approximate
|
||||||
content = f"{relative_fname}\n{fence}\n" + content + "{fence}\n"
|
content = f"{relative_fname}\n{fence}\n" + content + "{fence}\n"
|
||||||
tokens = self.coder.main_model.token_count(content)
|
tokens = self.coder.main_model.token_count(content)
|
||||||
res.append((tokens, f"{relative_fname}", "/drop to remove"))
|
file_res.append((tokens, f"{relative_fname}", "/drop to remove"))
|
||||||
|
|
||||||
# read-only files
|
# read-only files
|
||||||
for fname in self.coder.abs_read_only_fnames:
|
for fname in self.coder.abs_read_only_fnames:
|
||||||
@@ -424,7 +443,10 @@ class Commands:
|
|||||||
# approximate
|
# approximate
|
||||||
content = f"{relative_fname}\n{fence}\n" + content + "{fence}\n"
|
content = f"{relative_fname}\n{fence}\n" + content + "{fence}\n"
|
||||||
tokens = self.coder.main_model.token_count(content)
|
tokens = self.coder.main_model.token_count(content)
|
||||||
res.append((tokens, f"{relative_fname} (read-only)", "/drop to remove"))
|
file_res.append((tokens, f"{relative_fname} (read-only)", "/drop to remove"))
|
||||||
|
|
||||||
|
file_res.sort()
|
||||||
|
res.extend(file_res)
|
||||||
|
|
||||||
self.io.tool_output(
|
self.io.tool_output(
|
||||||
f"Approximate context window usage for {self.coder.main_model.name}, in tokens:"
|
f"Approximate context window usage for {self.coder.main_model.name}, in tokens:"
|
||||||
@@ -818,7 +840,12 @@ class Commands:
|
|||||||
"Remove files from the chat session to free up context space"
|
"Remove files from the chat session to free up context space"
|
||||||
|
|
||||||
if not args.strip():
|
if not args.strip():
|
||||||
self.io.tool_output("Dropping all files from the chat session.")
|
if self.original_read_only_fnames:
|
||||||
|
self.io.tool_output(
|
||||||
|
"Dropping all files from the chat session except originally read-only files."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.io.tool_output("Dropping all files from the chat session.")
|
||||||
self._drop_all_files()
|
self._drop_all_files()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1407,6 +1434,58 @@ class Commands:
|
|||||||
if user_input.strip():
|
if user_input.strip():
|
||||||
self.io.set_placeholder(user_input.rstrip())
|
self.io.set_placeholder(user_input.rstrip())
|
||||||
|
|
||||||
|
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)
|
||||||
|
if formatted_budget is None:
|
||||||
|
self.io.tool_output("Thinking tokens are not currently set.")
|
||||||
|
else:
|
||||||
|
budget = model.extra_params["thinking"].get("budget_tokens")
|
||||||
|
self.io.tool_output(
|
||||||
|
f"Current thinking token budget: {budget:,} tokens ({formatted_budget})."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
value = args.strip()
|
||||||
|
model.set_thinking_tokens(value)
|
||||||
|
|
||||||
|
formatted_budget = model.get_thinking_tokens(model)
|
||||||
|
budget = model.extra_params["thinking"].get("budget_tokens")
|
||||||
|
|
||||||
|
self.io.tool_output(f"Set thinking token budget to {budget:,} tokens ({formatted_budget}).")
|
||||||
|
self.io.tool_output()
|
||||||
|
|
||||||
|
# Output announcements
|
||||||
|
announcements = "\n".join(self.coder.get_announcements())
|
||||||
|
self.io.tool_output(announcements)
|
||||||
|
|
||||||
|
def cmd_reasoning_effort(self, args):
|
||||||
|
"Set the reasoning effort level (values: number or low/medium/high depending on model)"
|
||||||
|
model = self.coder.main_model
|
||||||
|
|
||||||
|
if not args.strip():
|
||||||
|
# Display current value if no args are provided
|
||||||
|
reasoning_value = model.get_reasoning_effort(model)
|
||||||
|
if reasoning_value is None:
|
||||||
|
self.io.tool_output("Reasoning effort is not currently set.")
|
||||||
|
else:
|
||||||
|
self.io.tool_output(f"Current reasoning effort: {reasoning_value}")
|
||||||
|
return
|
||||||
|
|
||||||
|
value = args.strip()
|
||||||
|
model.set_reasoning_effort(value)
|
||||||
|
reasoning_value = model.get_reasoning_effort(model)
|
||||||
|
self.io.tool_output(f"Set reasoning effort to {reasoning_value}")
|
||||||
|
self.io.tool_output()
|
||||||
|
|
||||||
|
# Output announcements
|
||||||
|
announcements = "\n".join(self.coder.get_announcements())
|
||||||
|
self.io.tool_output(announcements)
|
||||||
|
|
||||||
def cmd_copy_context(self, args=None):
|
def cmd_copy_context(self, args=None):
|
||||||
"""Copy the current chat context as markdown, suitable to paste into a web UI"""
|
"""Copy the current chat context as markdown, suitable to paste into a web UI"""
|
||||||
|
|
||||||
|
|||||||
126
aider/deprecated.py
Normal file
126
aider/deprecated.py
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
def add_deprecated_model_args(parser, group):
|
||||||
|
"""Add deprecated model shortcut arguments to the argparse parser."""
|
||||||
|
opus_model = "claude-3-opus-20240229"
|
||||||
|
group.add_argument(
|
||||||
|
"--opus",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {opus_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
sonnet_model = "anthropic/claude-3-7-sonnet-20250219"
|
||||||
|
group.add_argument(
|
||||||
|
"--sonnet",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {sonnet_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
haiku_model = "claude-3-5-haiku-20241022"
|
||||||
|
group.add_argument(
|
||||||
|
"--haiku",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {haiku_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
gpt_4_model = "gpt-4-0613"
|
||||||
|
group.add_argument(
|
||||||
|
"--4",
|
||||||
|
"-4",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {gpt_4_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
gpt_4o_model = "gpt-4o"
|
||||||
|
group.add_argument(
|
||||||
|
"--4o",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {gpt_4o_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
gpt_4o_mini_model = "gpt-4o-mini"
|
||||||
|
group.add_argument(
|
||||||
|
"--mini",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {gpt_4o_mini_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
gpt_4_turbo_model = "gpt-4-1106-preview"
|
||||||
|
group.add_argument(
|
||||||
|
"--4-turbo",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {gpt_4_turbo_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
gpt_3_model_name = "gpt-3.5-turbo"
|
||||||
|
group.add_argument(
|
||||||
|
"--35turbo",
|
||||||
|
"--35-turbo",
|
||||||
|
"--3",
|
||||||
|
"-3",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {gpt_3_model_name} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
deepseek_model = "deepseek/deepseek-chat"
|
||||||
|
group.add_argument(
|
||||||
|
"--deepseek",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {deepseek_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
o1_mini_model = "o1-mini"
|
||||||
|
group.add_argument(
|
||||||
|
"--o1-mini",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {o1_mini_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
o1_preview_model = "o1-preview"
|
||||||
|
group.add_argument(
|
||||||
|
"--o1-preview",
|
||||||
|
action="store_true",
|
||||||
|
help=f"Use {o1_preview_model} model for the main chat (deprecated, use --model)",
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_deprecated_model_args(args, io):
|
||||||
|
"""Handle deprecated model shortcut arguments and provide appropriate warnings."""
|
||||||
|
# Define model mapping
|
||||||
|
model_map = {
|
||||||
|
"opus": "claude-3-opus-20240229",
|
||||||
|
"sonnet": "anthropic/claude-3-7-sonnet-20250219",
|
||||||
|
"haiku": "claude-3-5-haiku-20241022",
|
||||||
|
"4": "gpt-4-0613",
|
||||||
|
"4o": "gpt-4o",
|
||||||
|
"mini": "gpt-4o-mini",
|
||||||
|
"4_turbo": "gpt-4-1106-preview",
|
||||||
|
"35turbo": "gpt-3.5-turbo",
|
||||||
|
"deepseek": "deepseek/deepseek-chat",
|
||||||
|
"o1_mini": "o1-mini",
|
||||||
|
"o1_preview": "o1-preview",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if any deprecated args are used
|
||||||
|
for arg_name, model_name in model_map.items():
|
||||||
|
arg_name_clean = arg_name.replace("-", "_")
|
||||||
|
if hasattr(args, arg_name_clean) and getattr(args, arg_name_clean):
|
||||||
|
# Find preferred name to display in warning
|
||||||
|
from aider.models import MODEL_ALIASES
|
||||||
|
|
||||||
|
display_name = model_name
|
||||||
|
# Check if there's a shorter alias for this model
|
||||||
|
for alias, full_name in MODEL_ALIASES.items():
|
||||||
|
if full_name == model_name:
|
||||||
|
display_name = alias
|
||||||
|
break
|
||||||
|
|
||||||
|
# Show the warning
|
||||||
|
io.tool_warning(
|
||||||
|
f"The --{arg_name.replace('_', '-')} flag is deprecated and will be removed in a"
|
||||||
|
f" future version. Please use --model {display_name} instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set the model
|
||||||
|
if not args.model:
|
||||||
|
args.model = model_name
|
||||||
|
break
|
||||||
@@ -10,12 +10,13 @@ This module provides functionality to:
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import shlex
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
|
from aider.dump import dump # noqa
|
||||||
|
|
||||||
DEFAULT_EDITOR_NIX = "vi"
|
DEFAULT_EDITOR_NIX = "vi"
|
||||||
DEFAULT_EDITOR_OS_X = "vim"
|
DEFAULT_EDITOR_OS_X = "vim"
|
||||||
DEFAULT_EDITOR_WINDOWS = "notepad"
|
DEFAULT_EDITOR_WINDOWS = "notepad"
|
||||||
@@ -87,13 +88,13 @@ def get_environment_editor(default=None):
|
|||||||
|
|
||||||
def discover_editor(editor_override=None):
|
def discover_editor(editor_override=None):
|
||||||
"""
|
"""
|
||||||
Discovers and returns the appropriate editor command as a list of arguments.
|
Discovers and returns the appropriate editor command.
|
||||||
|
|
||||||
Handles cases where the editor command includes arguments, including quoted arguments
|
Handles cases where the editor command includes arguments, including quoted arguments
|
||||||
with spaces (e.g. 'vim -c "set noswapfile"').
|
with spaces (e.g. 'vim -c "set noswapfile"').
|
||||||
|
|
||||||
:return: A list of command parts ready for subprocess execution
|
:return: The editor command as a string
|
||||||
:rtype: list[str]
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
@@ -102,14 +103,13 @@ def discover_editor(editor_override=None):
|
|||||||
default_editor = DEFAULT_EDITOR_OS_X
|
default_editor = DEFAULT_EDITOR_OS_X
|
||||||
else:
|
else:
|
||||||
default_editor = DEFAULT_EDITOR_NIX
|
default_editor = DEFAULT_EDITOR_NIX
|
||||||
|
|
||||||
if editor_override:
|
if editor_override:
|
||||||
editor = editor_override
|
editor = editor_override
|
||||||
else:
|
else:
|
||||||
editor = get_environment_editor(default_editor)
|
editor = get_environment_editor(default_editor)
|
||||||
try:
|
|
||||||
return shlex.split(editor)
|
return editor
|
||||||
except ValueError as e:
|
|
||||||
raise RuntimeError(f"Invalid editor command format '{editor}': {e}")
|
|
||||||
|
|
||||||
|
|
||||||
def pipe_editor(input_data="", suffix=None, editor=None):
|
def pipe_editor(input_data="", suffix=None, editor=None):
|
||||||
@@ -128,9 +128,10 @@ def pipe_editor(input_data="", suffix=None, editor=None):
|
|||||||
:rtype: str
|
:rtype: str
|
||||||
"""
|
"""
|
||||||
filepath = write_temp_file(input_data, suffix)
|
filepath = write_temp_file(input_data, suffix)
|
||||||
command_parts = discover_editor(editor)
|
command_str = discover_editor(editor)
|
||||||
command_parts.append(filepath)
|
command_str += " " + filepath
|
||||||
subprocess.call(command_parts)
|
|
||||||
|
subprocess.call(command_str, shell=True)
|
||||||
with open(filepath, "r") as f:
|
with open(filepath, "r") as f:
|
||||||
output_data = f.read()
|
output_data = f.read()
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from aider.dump import dump # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ExInfo:
|
class ExInfo:
|
||||||
@@ -50,6 +52,7 @@ EXCEPTIONS = [
|
|||||||
|
|
||||||
class LiteLLMExceptions:
|
class LiteLLMExceptions:
|
||||||
exceptions = dict()
|
exceptions = dict()
|
||||||
|
exception_info = {exi.name: exi for exi in EXCEPTIONS}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._load()
|
self._load()
|
||||||
@@ -58,20 +61,13 @@ class LiteLLMExceptions:
|
|||||||
import litellm
|
import litellm
|
||||||
|
|
||||||
for var in dir(litellm):
|
for var in dir(litellm):
|
||||||
if not var.endswith("Error"):
|
if var.endswith("Error"):
|
||||||
continue
|
if var not in self.exception_info:
|
||||||
|
raise ValueError(f"{var} is in litellm but not in aider's exceptions list")
|
||||||
ex_info = None
|
|
||||||
for exi in EXCEPTIONS:
|
|
||||||
if var == exi.name:
|
|
||||||
ex_info = exi
|
|
||||||
break
|
|
||||||
|
|
||||||
if strict and not ex_info:
|
|
||||||
raise ValueError(f"{var} is in litellm but not in aider's exceptions list")
|
|
||||||
|
|
||||||
|
for var in self.exception_info:
|
||||||
ex = getattr(litellm, var)
|
ex = getattr(litellm, var)
|
||||||
self.exceptions[ex] = ex_info
|
self.exceptions[ex] = self.exception_info[var]
|
||||||
|
|
||||||
def exceptions_tuple(self):
|
def exceptions_tuple(self):
|
||||||
return tuple(self.exceptions)
|
return tuple(self.exceptions)
|
||||||
|
|||||||
@@ -10,4 +10,10 @@ exclude_website_pats = [
|
|||||||
"docs/unified-diffs.md",
|
"docs/unified-diffs.md",
|
||||||
"docs/leaderboards/index.md",
|
"docs/leaderboards/index.md",
|
||||||
"assets/**",
|
"assets/**",
|
||||||
|
".jekyll-metadata",
|
||||||
|
"Gemfile.lock",
|
||||||
|
"Gemfile",
|
||||||
|
"_config.yml",
|
||||||
|
"**/OLD/**",
|
||||||
|
"OLD/**",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import argparse
|
|||||||
|
|
||||||
from aider import models, prompts
|
from aider import models, prompts
|
||||||
from aider.dump import dump # noqa: F401
|
from aider.dump import dump # noqa: F401
|
||||||
from aider.sendchat import simple_send_with_retries
|
|
||||||
|
|
||||||
|
|
||||||
class ChatSummary:
|
class ChatSummary:
|
||||||
@@ -114,7 +113,7 @@ class ChatSummary:
|
|||||||
|
|
||||||
for model in self.models:
|
for model in self.models:
|
||||||
try:
|
try:
|
||||||
summary = simple_send_with_retries(model, summarize_messages)
|
summary = model.simple_send_with_retries(summarize_messages)
|
||||||
if summary is not None:
|
if summary is not None:
|
||||||
summary = prompts.summary_prefix + summary
|
summary = prompts.summary_prefix + summary
|
||||||
return [dict(role="user", content=summary)]
|
return [dict(role="user", content=summary)]
|
||||||
|
|||||||
209
aider/io.py
209
aider/io.py
@@ -1,6 +1,9 @@
|
|||||||
import base64
|
import base64
|
||||||
|
import functools
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
|
import subprocess
|
||||||
import time
|
import time
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
@@ -33,6 +36,37 @@ from aider.mdstream import MarkdownStream
|
|||||||
from .dump import dump # noqa: F401
|
from .dump import dump # noqa: F401
|
||||||
from .utils import is_image_file
|
from .utils import is_image_file
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
NOTIFICATION_MESSAGE = "Aider is waiting for your input"
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_hash_prefix(color):
|
||||||
|
"""Ensure hex color values have a # prefix."""
|
||||||
|
if not color:
|
||||||
|
return color
|
||||||
|
if isinstance(color, str) and color.strip() and not color.startswith("#"):
|
||||||
|
# Check if it's a valid hex color (3 or 6 hex digits)
|
||||||
|
if all(c in "0123456789ABCDEFabcdef" for c in color) and len(color) in (3, 6):
|
||||||
|
return f"#{color}"
|
||||||
|
return color
|
||||||
|
|
||||||
|
|
||||||
|
def restore_multiline(func):
|
||||||
|
"""Decorator to restore multiline mode after function execution"""
|
||||||
|
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
orig_multiline = self.multiline_mode
|
||||||
|
self.multiline_mode = False
|
||||||
|
try:
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
self.multiline_mode = orig_multiline
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ConfirmGroup:
|
class ConfirmGroup:
|
||||||
@@ -160,6 +194,11 @@ class AutoCompleter(Completer):
|
|||||||
candidates = [word if type(word) is tuple else (word, word) for word in candidates]
|
candidates = [word if type(word) is tuple else (word, word) for word in candidates]
|
||||||
|
|
||||||
last_word = words[-1]
|
last_word = words[-1]
|
||||||
|
|
||||||
|
# Only provide completions if the user has typed at least 3 characters
|
||||||
|
if len(last_word) < 3:
|
||||||
|
return
|
||||||
|
|
||||||
completions = []
|
completions = []
|
||||||
for word_match, word_insert in candidates:
|
for word_match, word_insert in candidates:
|
||||||
if word_match.lower().startswith(last_word.lower()):
|
if word_match.lower().startswith(last_word.lower()):
|
||||||
@@ -178,6 +217,8 @@ class InputOutput:
|
|||||||
num_error_outputs = 0
|
num_error_outputs = 0
|
||||||
num_user_asks = 0
|
num_user_asks = 0
|
||||||
clipboard_watcher = None
|
clipboard_watcher = None
|
||||||
|
bell_on_next_input = False
|
||||||
|
notifications_command = None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -206,25 +247,40 @@ class InputOutput:
|
|||||||
file_watcher=None,
|
file_watcher=None,
|
||||||
multiline_mode=False,
|
multiline_mode=False,
|
||||||
root=".",
|
root=".",
|
||||||
|
notifications=False,
|
||||||
|
notifications_command=None,
|
||||||
):
|
):
|
||||||
self.placeholder = None
|
self.placeholder = None
|
||||||
self.interrupted = False
|
self.interrupted = False
|
||||||
self.never_prompts = set()
|
self.never_prompts = set()
|
||||||
self.editingmode = editingmode
|
self.editingmode = editingmode
|
||||||
self.multiline_mode = multiline_mode
|
self.multiline_mode = multiline_mode
|
||||||
|
self.bell_on_next_input = False
|
||||||
|
self.notifications = notifications
|
||||||
|
if notifications and notifications_command is None:
|
||||||
|
self.notifications_command = self.get_default_notification_command()
|
||||||
|
else:
|
||||||
|
self.notifications_command = notifications_command
|
||||||
|
|
||||||
no_color = os.environ.get("NO_COLOR")
|
no_color = os.environ.get("NO_COLOR")
|
||||||
if no_color is not None and no_color != "":
|
if no_color is not None and no_color != "":
|
||||||
pretty = False
|
pretty = False
|
||||||
|
|
||||||
self.user_input_color = user_input_color if pretty else None
|
self.user_input_color = ensure_hash_prefix(user_input_color) if pretty else None
|
||||||
self.tool_output_color = tool_output_color if pretty else None
|
self.tool_output_color = ensure_hash_prefix(tool_output_color) if pretty else None
|
||||||
self.tool_error_color = tool_error_color if pretty else None
|
self.tool_error_color = ensure_hash_prefix(tool_error_color) if pretty else None
|
||||||
self.tool_warning_color = tool_warning_color if pretty else None
|
self.tool_warning_color = ensure_hash_prefix(tool_warning_color) if pretty else None
|
||||||
self.assistant_output_color = assistant_output_color
|
self.assistant_output_color = ensure_hash_prefix(assistant_output_color)
|
||||||
self.completion_menu_color = completion_menu_color if pretty else None
|
self.completion_menu_color = ensure_hash_prefix(completion_menu_color) if pretty else None
|
||||||
self.completion_menu_bg_color = completion_menu_bg_color if pretty else None
|
self.completion_menu_bg_color = (
|
||||||
self.completion_menu_current_color = completion_menu_current_color if pretty else None
|
ensure_hash_prefix(completion_menu_bg_color) if pretty else None
|
||||||
self.completion_menu_current_bg_color = completion_menu_current_bg_color if pretty else None
|
)
|
||||||
|
self.completion_menu_current_color = (
|
||||||
|
ensure_hash_prefix(completion_menu_current_color) if pretty else None
|
||||||
|
)
|
||||||
|
self.completion_menu_current_bg_color = (
|
||||||
|
ensure_hash_prefix(completion_menu_current_bg_color) if pretty else None
|
||||||
|
)
|
||||||
|
|
||||||
self.code_theme = code_theme
|
self.code_theme = code_theme
|
||||||
|
|
||||||
@@ -426,6 +482,9 @@ class InputOutput:
|
|||||||
):
|
):
|
||||||
self.rule()
|
self.rule()
|
||||||
|
|
||||||
|
# Ring the bell if needed
|
||||||
|
self.ring_bell()
|
||||||
|
|
||||||
rel_fnames = list(rel_fnames)
|
rel_fnames = list(rel_fnames)
|
||||||
show = ""
|
show = ""
|
||||||
if rel_fnames:
|
if rel_fnames:
|
||||||
@@ -518,6 +577,9 @@ class InputOutput:
|
|||||||
if self.clipboard_watcher:
|
if self.clipboard_watcher:
|
||||||
self.clipboard_watcher.start()
|
self.clipboard_watcher.start()
|
||||||
|
|
||||||
|
def get_continuation(width, line_number, is_soft_wrap):
|
||||||
|
return ". "
|
||||||
|
|
||||||
line = self.prompt_session.prompt(
|
line = self.prompt_session.prompt(
|
||||||
show,
|
show,
|
||||||
default=default,
|
default=default,
|
||||||
@@ -527,6 +589,7 @@ class InputOutput:
|
|||||||
style=style,
|
style=style,
|
||||||
key_bindings=kb,
|
key_bindings=kb,
|
||||||
complete_while_typing=True,
|
complete_while_typing=True,
|
||||||
|
prompt_continuation=get_continuation,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
line = input(show)
|
line = input(show)
|
||||||
@@ -662,6 +725,7 @@ class InputOutput:
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@restore_multiline
|
||||||
def confirm_ask(
|
def confirm_ask(
|
||||||
self,
|
self,
|
||||||
question,
|
question,
|
||||||
@@ -671,11 +735,11 @@ class InputOutput:
|
|||||||
group=None,
|
group=None,
|
||||||
allow_never=False,
|
allow_never=False,
|
||||||
):
|
):
|
||||||
# Temporarily disable multiline mode for yes/no prompts
|
|
||||||
orig_multiline = self.multiline_mode
|
|
||||||
self.multiline_mode = False
|
|
||||||
self.num_user_asks += 1
|
self.num_user_asks += 1
|
||||||
|
|
||||||
|
# Ring the bell if needed
|
||||||
|
self.ring_bell()
|
||||||
|
|
||||||
question_id = (question, subject)
|
question_id = (question, subject)
|
||||||
|
|
||||||
if question_id in self.never_prompts:
|
if question_id in self.never_prompts:
|
||||||
@@ -686,14 +750,12 @@ class InputOutput:
|
|||||||
if group:
|
if group:
|
||||||
allow_never = True
|
allow_never = True
|
||||||
|
|
||||||
valid_responses = ["yes", "no"]
|
valid_responses = ["yes", "no", "skip", "all"]
|
||||||
options = " (Y)es/(N)o"
|
options = " (Y)es/(N)o"
|
||||||
if group:
|
if group:
|
||||||
if not explicit_yes_required:
|
if not explicit_yes_required:
|
||||||
options += "/(A)ll"
|
options += "/(A)ll"
|
||||||
valid_responses.append("all")
|
|
||||||
options += "/(S)kip all"
|
options += "/(S)kip all"
|
||||||
valid_responses.append("skip")
|
|
||||||
if allow_never:
|
if allow_never:
|
||||||
options += "/(D)on't ask again"
|
options += "/(D)on't ask again"
|
||||||
valid_responses.append("don't")
|
valid_responses.append("don't")
|
||||||
@@ -732,14 +794,19 @@ class InputOutput:
|
|||||||
self.user_input(f"{question}{res}", log_only=False)
|
self.user_input(f"{question}{res}", log_only=False)
|
||||||
else:
|
else:
|
||||||
while True:
|
while True:
|
||||||
if self.prompt_session:
|
try:
|
||||||
res = self.prompt_session.prompt(
|
if self.prompt_session:
|
||||||
question,
|
res = self.prompt_session.prompt(
|
||||||
style=style,
|
question,
|
||||||
complete_while_typing=False,
|
style=style,
|
||||||
)
|
complete_while_typing=False,
|
||||||
else:
|
)
|
||||||
res = input(question)
|
else:
|
||||||
|
res = input(question)
|
||||||
|
except EOFError:
|
||||||
|
# Treat EOF (Ctrl+D) as if the user pressed Enter
|
||||||
|
res = default
|
||||||
|
break
|
||||||
|
|
||||||
if not res:
|
if not res:
|
||||||
res = default
|
res = default
|
||||||
@@ -777,17 +844,15 @@ class InputOutput:
|
|||||||
hist = f"{question.strip()} {res}"
|
hist = f"{question.strip()} {res}"
|
||||||
self.append_chat_history(hist, linebreak=True, blockquote=True)
|
self.append_chat_history(hist, linebreak=True, blockquote=True)
|
||||||
|
|
||||||
# Restore original multiline mode
|
|
||||||
self.multiline_mode = orig_multiline
|
|
||||||
|
|
||||||
return is_yes
|
return is_yes
|
||||||
|
|
||||||
|
@restore_multiline
|
||||||
def prompt_ask(self, question, default="", subject=None):
|
def prompt_ask(self, question, default="", subject=None):
|
||||||
# Temporarily disable multiline mode for prompts
|
|
||||||
orig_multiline = self.multiline_mode
|
|
||||||
self.multiline_mode = False
|
|
||||||
self.num_user_asks += 1
|
self.num_user_asks += 1
|
||||||
|
|
||||||
|
# Ring the bell if needed
|
||||||
|
self.ring_bell()
|
||||||
|
|
||||||
if subject:
|
if subject:
|
||||||
self.tool_output()
|
self.tool_output()
|
||||||
self.tool_output(subject, bold=True)
|
self.tool_output(subject, bold=True)
|
||||||
@@ -799,24 +864,25 @@ class InputOutput:
|
|||||||
elif self.yes is False:
|
elif self.yes is False:
|
||||||
res = "no"
|
res = "no"
|
||||||
else:
|
else:
|
||||||
if self.prompt_session:
|
try:
|
||||||
res = self.prompt_session.prompt(
|
if self.prompt_session:
|
||||||
question + " ",
|
res = self.prompt_session.prompt(
|
||||||
default=default,
|
question + " ",
|
||||||
style=style,
|
default=default,
|
||||||
complete_while_typing=True,
|
style=style,
|
||||||
)
|
complete_while_typing=True,
|
||||||
else:
|
)
|
||||||
res = input(question + " ")
|
else:
|
||||||
|
res = input(question + " ")
|
||||||
|
except EOFError:
|
||||||
|
# Treat EOF (Ctrl+D) as if the user pressed Enter
|
||||||
|
res = default
|
||||||
|
|
||||||
hist = f"{question.strip()} {res.strip()}"
|
hist = f"{question.strip()} {res.strip()}"
|
||||||
self.append_chat_history(hist, linebreak=True, blockquote=True)
|
self.append_chat_history(hist, linebreak=True, blockquote=True)
|
||||||
if self.yes in (True, False):
|
if self.yes in (True, False):
|
||||||
self.tool_output(hist)
|
self.tool_output(hist)
|
||||||
|
|
||||||
# Restore original multiline mode
|
|
||||||
self.multiline_mode = orig_multiline
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _tool_message(self, message="", strip=True, color=None):
|
def _tool_message(self, message="", strip=True, color=None):
|
||||||
@@ -872,6 +938,10 @@ class InputOutput:
|
|||||||
return mdStream
|
return mdStream
|
||||||
|
|
||||||
def assistant_output(self, message, pretty=None):
|
def assistant_output(self, message, pretty=None):
|
||||||
|
if not message:
|
||||||
|
self.tool_warning("Empty response received from LLM. Check your provider account?")
|
||||||
|
return
|
||||||
|
|
||||||
show_resp = message
|
show_resp = message
|
||||||
|
|
||||||
# Coder will force pretty off if fence is not triple-backticks
|
# Coder will force pretty off if fence is not triple-backticks
|
||||||
@@ -883,7 +953,7 @@ class InputOutput:
|
|||||||
message, style=self.assistant_output_color, code_theme=self.code_theme
|
message, style=self.assistant_output_color, code_theme=self.code_theme
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
show_resp = Text(message or "<no response>")
|
show_resp = Text(message or "(empty response)")
|
||||||
|
|
||||||
self.console.print(show_resp)
|
self.console.print(show_resp)
|
||||||
|
|
||||||
@@ -894,6 +964,61 @@ class InputOutput:
|
|||||||
def print(self, message=""):
|
def print(self, message=""):
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
|
def llm_started(self):
|
||||||
|
"""Mark that the LLM has started processing, so we should ring the bell on next input"""
|
||||||
|
self.bell_on_next_input = True
|
||||||
|
|
||||||
|
def get_default_notification_command(self):
|
||||||
|
"""Return a default notification command based on the operating system."""
|
||||||
|
import platform
|
||||||
|
|
||||||
|
system = platform.system()
|
||||||
|
|
||||||
|
if system == "Darwin": # macOS
|
||||||
|
# Check for terminal-notifier first
|
||||||
|
if shutil.which("terminal-notifier"):
|
||||||
|
return f"terminal-notifier -title 'Aider' -message '{NOTIFICATION_MESSAGE}'"
|
||||||
|
# Fall back to osascript
|
||||||
|
return (
|
||||||
|
f'osascript -e \'display notification "{NOTIFICATION_MESSAGE}" with title "Aider"\''
|
||||||
|
)
|
||||||
|
elif system == "Linux":
|
||||||
|
# Check for common Linux notification tools
|
||||||
|
for cmd in ["notify-send", "zenity"]:
|
||||||
|
if shutil.which(cmd):
|
||||||
|
if cmd == "notify-send":
|
||||||
|
return f"notify-send 'Aider' '{NOTIFICATION_MESSAGE}'"
|
||||||
|
elif cmd == "zenity":
|
||||||
|
return f"zenity --notification --text='{NOTIFICATION_MESSAGE}'"
|
||||||
|
return None # No known notification tool found
|
||||||
|
elif system == "Windows":
|
||||||
|
# PowerShell notification
|
||||||
|
return (
|
||||||
|
"powershell -command"
|
||||||
|
" \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms');"
|
||||||
|
f" [System.Windows.Forms.MessageBox]::Show('{NOTIFICATION_MESSAGE}',"
|
||||||
|
" 'Aider')\""
|
||||||
|
)
|
||||||
|
|
||||||
|
return None # Unknown system
|
||||||
|
|
||||||
|
def ring_bell(self):
|
||||||
|
"""Ring the terminal bell if needed and clear the flag"""
|
||||||
|
if self.bell_on_next_input and self.notifications:
|
||||||
|
if self.notifications_command:
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
self.notifications_command, shell=True, capture_output=True
|
||||||
|
)
|
||||||
|
if result.returncode != 0 and result.stderr:
|
||||||
|
error_msg = result.stderr.decode("utf-8", errors="replace")
|
||||||
|
self.tool_warning(f"Failed to run notifications command: {error_msg}")
|
||||||
|
except Exception as e:
|
||||||
|
self.tool_warning(f"Failed to run notifications command: {e}")
|
||||||
|
else:
|
||||||
|
print("\a", end="", flush=True) # Ring the bell
|
||||||
|
self.bell_on_next_input = False # Clear the flag
|
||||||
|
|
||||||
def toggle_multiline_mode(self):
|
def toggle_multiline_mode(self):
|
||||||
"""Toggle between normal and multiline input modes"""
|
"""Toggle between normal and multiline input modes"""
|
||||||
self.multiline_mode = not self.multiline_mode
|
self.multiline_mode = not self.multiline_mode
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from dataclasses import dataclass
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from grep_ast import TreeContext, filename_to_lang
|
from grep_ast import TreeContext, filename_to_lang
|
||||||
from tree_sitter_languages import get_parser # noqa: E402
|
from grep_ast.tsl import get_parser # noqa: E402
|
||||||
|
|
||||||
from aider.dump import dump # noqa: F401
|
from aider.dump import dump # noqa: F401
|
||||||
from aider.run_cmd import run_cmd_subprocess # noqa: F401
|
from aider.run_cmd import run_cmd_subprocess # noqa: F401
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import importlib
|
|||||||
import os
|
import os
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from aider.dump import dump # noqa: F401
|
||||||
|
|
||||||
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic")
|
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic")
|
||||||
|
|
||||||
AIDER_SITE_URL = "https://aider.chat"
|
AIDER_SITE_URL = "https://aider.chat"
|
||||||
|
|||||||
118
aider/main.py
118
aider/main.py
@@ -1,4 +1,3 @@
|
|||||||
import configparser
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@@ -25,6 +24,7 @@ from aider.coders import Coder
|
|||||||
from aider.coders.base_coder import UnknownEditFormat
|
from aider.coders.base_coder import UnknownEditFormat
|
||||||
from aider.commands import Commands, SwitchCoder
|
from aider.commands import Commands, SwitchCoder
|
||||||
from aider.copypaste import ClipboardWatcher
|
from aider.copypaste import ClipboardWatcher
|
||||||
|
from aider.deprecated import handle_deprecated_model_args
|
||||||
from aider.format_settings import format_settings, scrub_sensitive_info
|
from aider.format_settings import format_settings, scrub_sensitive_info
|
||||||
from aider.history import ChatSummary
|
from aider.history import ChatSummary
|
||||||
from aider.io import InputOutput
|
from aider.io import InputOutput
|
||||||
@@ -126,17 +126,15 @@ def setup_git(git_root, io):
|
|||||||
if not repo:
|
if not repo:
|
||||||
return
|
return
|
||||||
|
|
||||||
user_name = None
|
try:
|
||||||
user_email = None
|
user_name = repo.git.config("--get", "user.name") or None
|
||||||
with repo.config_reader() as config:
|
except git.exc.GitCommandError:
|
||||||
try:
|
user_name = None
|
||||||
user_name = config.get_value("user", "name", None)
|
|
||||||
except (configparser.NoSectionError, configparser.NoOptionError):
|
try:
|
||||||
pass
|
user_email = repo.git.config("--get", "user.email") or None
|
||||||
try:
|
except git.exc.GitCommandError:
|
||||||
user_email = config.get_value("user", "email", None)
|
user_email = None
|
||||||
except (configparser.NoSectionError, configparser.NoOptionError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if user_name and user_email:
|
if user_name and user_email:
|
||||||
return repo.working_tree_dir
|
return repo.working_tree_dir
|
||||||
@@ -158,40 +156,39 @@ def check_gitignore(git_root, io, ask=True):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
repo = git.Repo(git_root)
|
repo = git.Repo(git_root)
|
||||||
if repo.ignored(".aider") and repo.ignored(".env"):
|
patterns_to_add = []
|
||||||
|
|
||||||
|
if not repo.ignored(".aider"):
|
||||||
|
patterns_to_add.append(".aider*")
|
||||||
|
|
||||||
|
env_path = Path(git_root) / ".env"
|
||||||
|
if env_path.exists() and not repo.ignored(".env"):
|
||||||
|
patterns_to_add.append(".env")
|
||||||
|
|
||||||
|
if not patterns_to_add:
|
||||||
return
|
return
|
||||||
except ANY_GIT_ERROR:
|
|
||||||
pass
|
|
||||||
|
|
||||||
patterns = [".aider*", ".env"]
|
gitignore_file = Path(git_root) / ".gitignore"
|
||||||
patterns_to_add = []
|
if gitignore_file.exists():
|
||||||
|
try:
|
||||||
gitignore_file = Path(git_root) / ".gitignore"
|
content = io.read_text(gitignore_file)
|
||||||
if gitignore_file.exists():
|
if content is None:
|
||||||
try:
|
return
|
||||||
content = io.read_text(gitignore_file)
|
if not content.endswith("\n"):
|
||||||
if content is None:
|
content += "\n"
|
||||||
|
except OSError as e:
|
||||||
|
io.tool_error(f"Error when trying to read {gitignore_file}: {e}")
|
||||||
return
|
return
|
||||||
existing_lines = content.splitlines()
|
else:
|
||||||
for pat in patterns:
|
content = ""
|
||||||
if pat not in existing_lines:
|
except ANY_GIT_ERROR:
|
||||||
if "*" in pat or (Path(git_root) / pat).exists():
|
return
|
||||||
patterns_to_add.append(pat)
|
|
||||||
except OSError as e:
|
if ask:
|
||||||
io.tool_error(f"Error when trying to read {gitignore_file}: {e}")
|
io.tool_output("You can skip this check with --no-gitignore")
|
||||||
|
if not io.confirm_ask(f"Add {', '.join(patterns_to_add)} to .gitignore (recommended)?"):
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
content = ""
|
|
||||||
patterns_to_add = patterns
|
|
||||||
|
|
||||||
if not patterns_to_add:
|
|
||||||
return
|
|
||||||
|
|
||||||
if ask and not io.confirm_ask(f"Add {', '.join(patterns_to_add)} to .gitignore (recommended)?"):
|
|
||||||
return
|
|
||||||
|
|
||||||
if content and not content.endswith("\n"):
|
|
||||||
content += "\n"
|
|
||||||
content += "\n".join(patterns_to_add) + "\n"
|
content += "\n".join(patterns_to_add) + "\n"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -508,10 +505,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
litellm._load_litellm()
|
litellm._load_litellm()
|
||||||
litellm._lazy_module.client_session = httpx.Client(verify=False)
|
litellm._lazy_module.client_session = httpx.Client(verify=False)
|
||||||
litellm._lazy_module.aclient_session = httpx.AsyncClient(verify=False)
|
litellm._lazy_module.aclient_session = httpx.AsyncClient(verify=False)
|
||||||
|
# Set verify_ssl on the model_info_manager
|
||||||
|
models.model_info_manager.set_verify_ssl(False)
|
||||||
|
|
||||||
if args.timeout:
|
if args.timeout:
|
||||||
litellm._load_litellm()
|
models.request_timeout = args.timeout
|
||||||
litellm._lazy_module.request_timeout = args.timeout
|
|
||||||
|
|
||||||
if args.dark_mode:
|
if args.dark_mode:
|
||||||
args.user_input_color = "#32FF32"
|
args.user_input_color = "#32FF32"
|
||||||
@@ -557,6 +555,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
editingmode=editing_mode,
|
editingmode=editing_mode,
|
||||||
fancy_input=args.fancy_input,
|
fancy_input=args.fancy_input,
|
||||||
multiline_mode=args.multiline,
|
multiline_mode=args.multiline,
|
||||||
|
notifications=args.notifications,
|
||||||
|
notifications_command=args.notifications_command,
|
||||||
)
|
)
|
||||||
|
|
||||||
io = get_io(args.pretty)
|
io = get_io(args.pretty)
|
||||||
@@ -596,6 +596,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
|
|
||||||
if args.openai_api_key:
|
if args.openai_api_key:
|
||||||
os.environ["OPENAI_API_KEY"] = args.openai_api_key
|
os.environ["OPENAI_API_KEY"] = args.openai_api_key
|
||||||
|
|
||||||
|
# Handle deprecated model shortcut args
|
||||||
|
handle_deprecated_model_args(args, io)
|
||||||
if args.openai_api_base:
|
if args.openai_api_base:
|
||||||
os.environ["OPENAI_API_BASE"] = args.openai_api_base
|
os.environ["OPENAI_API_BASE"] = args.openai_api_base
|
||||||
if args.openai_api_version:
|
if args.openai_api_version:
|
||||||
@@ -753,7 +756,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
model_key_pairs = [
|
model_key_pairs = [
|
||||||
("ANTHROPIC_API_KEY", "sonnet"),
|
("ANTHROPIC_API_KEY", "sonnet"),
|
||||||
("DEEPSEEK_API_KEY", "deepseek"),
|
("DEEPSEEK_API_KEY", "deepseek"),
|
||||||
("OPENROUTER_API_KEY", "openrouter/anthropic/claude-3.5-sonnet"),
|
("OPENROUTER_API_KEY", "openrouter/anthropic/claude-3.7-sonnet"),
|
||||||
("OPENAI_API_KEY", "gpt-4o"),
|
("OPENAI_API_KEY", "gpt-4o"),
|
||||||
("GEMINI_API_KEY", "flash"),
|
("GEMINI_API_KEY", "flash"),
|
||||||
]
|
]
|
||||||
@@ -775,15 +778,22 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
weak_model=args.weak_model,
|
weak_model=args.weak_model,
|
||||||
editor_model=args.editor_model,
|
editor_model=args.editor_model,
|
||||||
editor_edit_format=args.editor_edit_format,
|
editor_edit_format=args.editor_edit_format,
|
||||||
|
verbose=args.verbose,
|
||||||
)
|
)
|
||||||
|
|
||||||
# add --reasoning-effort cli param
|
# Check if deprecated remove_reasoning is set
|
||||||
|
if main_model.remove_reasoning is not None:
|
||||||
|
io.tool_warning(
|
||||||
|
"Model setting 'remove_reasoning' is deprecated, please use 'reasoning_tag' instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set reasoning effort if specified
|
||||||
if args.reasoning_effort is not None:
|
if args.reasoning_effort is not None:
|
||||||
if not getattr(main_model, "extra_params", None):
|
main_model.set_reasoning_effort(args.reasoning_effort)
|
||||||
main_model.extra_params = {}
|
|
||||||
if "extra_body" not in main_model.extra_params:
|
# Set thinking tokens if specified
|
||||||
main_model.extra_params["extra_body"] = {}
|
if args.thinking_tokens is not None:
|
||||||
main_model.extra_params["extra_body"]["reasoning_effort"] = args.reasoning_effort
|
main_model.set_thinking_tokens(args.thinking_tokens)
|
||||||
|
|
||||||
if args.copy_paste and args.edit_format is None:
|
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"):
|
||||||
@@ -857,6 +867,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
parser=parser,
|
parser=parser,
|
||||||
verbose=args.verbose,
|
verbose=args.verbose,
|
||||||
editor=args.editor,
|
editor=args.editor,
|
||||||
|
original_read_only_fnames=read_only_fnames,
|
||||||
)
|
)
|
||||||
|
|
||||||
summarizer = ChatSummary(
|
summarizer = ChatSummary(
|
||||||
@@ -911,6 +922,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
chat_language=args.chat_language,
|
chat_language=args.chat_language,
|
||||||
detect_urls=args.detect_urls,
|
detect_urls=args.detect_urls,
|
||||||
auto_copy_context=args.copy_paste,
|
auto_copy_context=args.copy_paste,
|
||||||
|
auto_accept_architect=args.auto_accept_architect,
|
||||||
)
|
)
|
||||||
except UnknownEditFormat as err:
|
except UnknownEditFormat as err:
|
||||||
io.tool_error(str(err))
|
io.tool_error(str(err))
|
||||||
@@ -992,6 +1004,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
analytics.event("exit", reason="Failed to read apply content")
|
analytics.event("exit", reason="Failed to read apply content")
|
||||||
return
|
return
|
||||||
coder.partial_response_content = content
|
coder.partial_response_content = content
|
||||||
|
# For testing #2879
|
||||||
|
# from aider.coders.base_coder import all_fences
|
||||||
|
# coder.fence = all_fences[1]
|
||||||
coder.apply_updates()
|
coder.apply_updates()
|
||||||
analytics.event("exit", reason="Applied updates")
|
analytics.event("exit", reason="Applied updates")
|
||||||
return
|
return
|
||||||
@@ -1059,10 +1074,13 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
coder.ok_to_warm_cache = bool(args.cache_keepalive_pings)
|
||||||
coder.run()
|
coder.run()
|
||||||
analytics.event("exit", reason="Completed main CLI coder.run")
|
analytics.event("exit", reason="Completed main CLI coder.run")
|
||||||
return
|
return
|
||||||
except SwitchCoder as switch:
|
except SwitchCoder as switch:
|
||||||
|
coder.ok_to_warm_cache = False
|
||||||
|
|
||||||
kwargs = dict(io=io, from_coder=coder)
|
kwargs = dict(io=io, from_coder=coder)
|
||||||
kwargs.update(switch.kwargs)
|
kwargs.update(switch.kwargs)
|
||||||
if "show_announcements" in kwargs:
|
if "show_announcements" in kwargs:
|
||||||
|
|||||||
352
aider/models.py
352
aider/models.py
@@ -1,4 +1,5 @@
|
|||||||
import difflib
|
import difflib
|
||||||
|
import hashlib
|
||||||
import importlib.resources
|
import importlib.resources
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
@@ -8,7 +9,7 @@ import sys
|
|||||||
import time
|
import time
|
||||||
from dataclasses import dataclass, fields
|
from dataclasses import dataclass, fields
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional, Union
|
||||||
|
|
||||||
import json5
|
import json5
|
||||||
import yaml
|
import yaml
|
||||||
@@ -16,11 +17,21 @@ from PIL import Image
|
|||||||
|
|
||||||
from aider.dump import dump # noqa: F401
|
from aider.dump import dump # noqa: F401
|
||||||
from aider.llm import litellm
|
from aider.llm import litellm
|
||||||
|
from aider.sendchat import ensure_alternating_roles, sanity_check_messages
|
||||||
|
from aider.utils import check_pip_install_extra
|
||||||
|
|
||||||
|
RETRY_TIMEOUT = 60
|
||||||
|
|
||||||
|
request_timeout = 600
|
||||||
|
|
||||||
DEFAULT_MODEL_NAME = "gpt-4o"
|
DEFAULT_MODEL_NAME = "gpt-4o"
|
||||||
ANTHROPIC_BETA_HEADER = "prompt-caching-2024-07-31,pdfs-2024-09-25"
|
ANTHROPIC_BETA_HEADER = "prompt-caching-2024-07-31,pdfs-2024-09-25"
|
||||||
|
|
||||||
OPENAI_MODELS = """
|
OPENAI_MODELS = """
|
||||||
|
o1
|
||||||
|
o1-preview
|
||||||
|
o1-mini
|
||||||
|
o3-mini
|
||||||
gpt-4
|
gpt-4
|
||||||
gpt-4o
|
gpt-4o
|
||||||
gpt-4o-2024-05-13
|
gpt-4o-2024-05-13
|
||||||
@@ -65,7 +76,7 @@ ANTHROPIC_MODELS = [ln.strip() for ln in ANTHROPIC_MODELS.splitlines() if ln.str
|
|||||||
# Mapping of model aliases to their canonical names
|
# Mapping of model aliases to their canonical names
|
||||||
MODEL_ALIASES = {
|
MODEL_ALIASES = {
|
||||||
# Claude models
|
# Claude models
|
||||||
"sonnet": "claude-3-5-sonnet-20241022",
|
"sonnet": "anthropic/claude-3-7-sonnet-20250219",
|
||||||
"haiku": "claude-3-5-haiku-20241022",
|
"haiku": "claude-3-5-haiku-20241022",
|
||||||
"opus": "claude-3-opus-20240229",
|
"opus": "claude-3-opus-20240229",
|
||||||
# GPT models
|
# GPT models
|
||||||
@@ -80,6 +91,7 @@ MODEL_ALIASES = {
|
|||||||
"r1": "deepseek/deepseek-reasoner",
|
"r1": "deepseek/deepseek-reasoner",
|
||||||
"flash": "gemini/gemini-2.0-flash-exp",
|
"flash": "gemini/gemini-2.0-flash-exp",
|
||||||
}
|
}
|
||||||
|
# Model metadata loaded from resources and user's files.
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -97,11 +109,13 @@ class ModelSettings:
|
|||||||
cache_control: bool = False
|
cache_control: bool = False
|
||||||
caches_by_default: bool = False
|
caches_by_default: bool = False
|
||||||
use_system_prompt: bool = True
|
use_system_prompt: bool = True
|
||||||
use_temperature: bool = True
|
use_temperature: Union[bool, float] = True
|
||||||
streaming: bool = True
|
streaming: bool = True
|
||||||
editor_model_name: Optional[str] = None
|
editor_model_name: Optional[str] = None
|
||||||
editor_edit_format: Optional[str] = None
|
editor_edit_format: Optional[str] = None
|
||||||
remove_reasoning: Optional[str] = None
|
reasoning_tag: Optional[str] = None
|
||||||
|
remove_reasoning: Optional[str] = None # Deprecated alias for reasoning_tag
|
||||||
|
system_prompt_prefix: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
# Load model settings from package resource
|
# Load model settings from package resource
|
||||||
@@ -123,23 +137,38 @@ class ModelInfoManager:
|
|||||||
self.cache_dir = Path.home() / ".aider" / "caches"
|
self.cache_dir = Path.home() / ".aider" / "caches"
|
||||||
self.cache_file = self.cache_dir / "model_prices_and_context_window.json"
|
self.cache_file = self.cache_dir / "model_prices_and_context_window.json"
|
||||||
self.content = None
|
self.content = None
|
||||||
self._load_cache()
|
self.local_model_metadata = {}
|
||||||
|
self.verify_ssl = True
|
||||||
|
self._cache_loaded = False
|
||||||
|
|
||||||
|
def set_verify_ssl(self, verify_ssl):
|
||||||
|
self.verify_ssl = verify_ssl
|
||||||
|
|
||||||
def _load_cache(self):
|
def _load_cache(self):
|
||||||
|
if self._cache_loaded:
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
||||||
if self.cache_file.exists():
|
if self.cache_file.exists():
|
||||||
cache_age = time.time() - self.cache_file.stat().st_mtime
|
cache_age = time.time() - self.cache_file.stat().st_mtime
|
||||||
if cache_age < self.CACHE_TTL:
|
if cache_age < self.CACHE_TTL:
|
||||||
self.content = json.loads(self.cache_file.read_text())
|
try:
|
||||||
|
self.content = json.loads(self.cache_file.read_text())
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
# If the cache file is corrupted, treat it as missing
|
||||||
|
self.content = None
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
self._cache_loaded = True
|
||||||
|
|
||||||
def _update_cache(self):
|
def _update_cache(self):
|
||||||
try:
|
try:
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
response = requests.get(self.MODEL_INFO_URL, timeout=5)
|
# Respect the --no-verify-ssl switch
|
||||||
|
response = requests.get(self.MODEL_INFO_URL, timeout=5, verify=self.verify_ssl)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
self.content = response.json()
|
self.content = response.json()
|
||||||
try:
|
try:
|
||||||
@@ -155,6 +184,13 @@ class ModelInfoManager:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def get_model_from_cached_json_db(self, model):
|
def get_model_from_cached_json_db(self, model):
|
||||||
|
data = self.local_model_metadata.get(model)
|
||||||
|
if data:
|
||||||
|
return data
|
||||||
|
|
||||||
|
# Ensure cache is loaded before checking content
|
||||||
|
self._load_cache()
|
||||||
|
|
||||||
if not self.content:
|
if not self.content:
|
||||||
self._update_cache()
|
self._update_cache()
|
||||||
|
|
||||||
@@ -194,11 +230,14 @@ model_info_manager = ModelInfoManager()
|
|||||||
|
|
||||||
|
|
||||||
class Model(ModelSettings):
|
class Model(ModelSettings):
|
||||||
def __init__(self, model, weak_model=None, editor_model=None, editor_edit_format=None):
|
def __init__(
|
||||||
|
self, model, weak_model=None, editor_model=None, editor_edit_format=None, verbose=False
|
||||||
|
):
|
||||||
# Map any alias to its canonical name
|
# Map any alias to its canonical name
|
||||||
model = MODEL_ALIASES.get(model, model)
|
model = MODEL_ALIASES.get(model, model)
|
||||||
|
|
||||||
self.name = model
|
self.name = model
|
||||||
|
self.verbose = verbose
|
||||||
|
|
||||||
self.max_chat_history_tokens = 1024
|
self.max_chat_history_tokens = 1024
|
||||||
self.weak_model = None
|
self.weak_model = None
|
||||||
@@ -241,6 +280,11 @@ class Model(ModelSettings):
|
|||||||
val = getattr(source, field.name)
|
val = getattr(source, field.name)
|
||||||
setattr(self, field.name, val)
|
setattr(self, field.name, val)
|
||||||
|
|
||||||
|
# Handle backward compatibility: if remove_reasoning is set but reasoning_tag isn't,
|
||||||
|
# use remove_reasoning's value for reasoning_tag
|
||||||
|
if self.reasoning_tag is None and self.remove_reasoning is not None:
|
||||||
|
self.reasoning_tag = self.remove_reasoning
|
||||||
|
|
||||||
def configure_model_settings(self, model):
|
def configure_model_settings(self, model):
|
||||||
# Look for exact model match
|
# Look for exact model match
|
||||||
exact_match = False
|
exact_match = False
|
||||||
@@ -273,6 +317,50 @@ class Model(ModelSettings):
|
|||||||
self.extra_params[key] = value
|
self.extra_params[key] = value
|
||||||
|
|
||||||
def apply_generic_model_settings(self, model):
|
def apply_generic_model_settings(self, model):
|
||||||
|
if "/o3-mini" in model:
|
||||||
|
self.edit_format = "diff"
|
||||||
|
self.use_repo_map = True
|
||||||
|
self.use_temperature = False
|
||||||
|
self.system_prompt_prefix = "Formatting re-enabled. "
|
||||||
|
return # <--
|
||||||
|
|
||||||
|
if "/o1-mini" in model:
|
||||||
|
self.use_repo_map = True
|
||||||
|
self.use_temperature = False
|
||||||
|
self.use_system_prompt = False
|
||||||
|
return # <--
|
||||||
|
|
||||||
|
if "/o1-preview" in model:
|
||||||
|
self.edit_format = "diff"
|
||||||
|
self.use_repo_map = True
|
||||||
|
self.use_temperature = False
|
||||||
|
self.use_system_prompt = False
|
||||||
|
return # <--
|
||||||
|
|
||||||
|
if "/o1" in model:
|
||||||
|
self.edit_format = "diff"
|
||||||
|
self.use_repo_map = True
|
||||||
|
self.use_temperature = False
|
||||||
|
self.streaming = False
|
||||||
|
self.system_prompt_prefix = "Formatting re-enabled. "
|
||||||
|
return # <--
|
||||||
|
|
||||||
|
if "deepseek" in model and "v3" in model:
|
||||||
|
self.edit_format = "diff"
|
||||||
|
self.use_repo_map = True
|
||||||
|
self.reminder = "sys"
|
||||||
|
self.examples_as_sys_msg = True
|
||||||
|
return # <--
|
||||||
|
|
||||||
|
if "deepseek" in model and ("r1" in model or "reasoning" in model):
|
||||||
|
self.edit_format = "diff"
|
||||||
|
self.use_repo_map = True
|
||||||
|
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:
|
if ("llama3" in model or "llama-3" in model) and "70b" in model:
|
||||||
self.edit_format = "diff"
|
self.edit_format = "diff"
|
||||||
self.use_repo_map = True
|
self.use_repo_map = True
|
||||||
@@ -317,8 +405,16 @@ class Model(ModelSettings):
|
|||||||
self.edit_format = "diff"
|
self.edit_format = "diff"
|
||||||
self.editor_edit_format = "editor-diff"
|
self.editor_edit_format = "editor-diff"
|
||||||
self.use_repo_map = True
|
self.use_repo_map = True
|
||||||
if model.startswith("ollama/") or model.startswith("ollama_chat/"):
|
return # <--
|
||||||
self.extra_params = dict(num_ctx=8 * 1024)
|
|
||||||
|
if "qwq" in model and "32b" in model and "preview" not in model:
|
||||||
|
self.edit_format = "diff"
|
||||||
|
self.editor_edit_format = "editor-diff"
|
||||||
|
self.use_repo_map = True
|
||||||
|
self.reasoning_tag = "think"
|
||||||
|
self.examples_as_sys_msg = True
|
||||||
|
self.use_temperature = 0.6
|
||||||
|
self.extra_params = dict(top_p=0.95)
|
||||||
return # <--
|
return # <--
|
||||||
|
|
||||||
# use the defaults
|
# use the defaults
|
||||||
@@ -440,14 +536,31 @@ class Model(ModelSettings):
|
|||||||
"""Fast path for common models. Avoids forcing litellm import."""
|
"""Fast path for common models. Avoids forcing litellm import."""
|
||||||
|
|
||||||
model = self.name
|
model = self.name
|
||||||
if model in OPENAI_MODELS or model.startswith("openai/"):
|
|
||||||
|
pieces = model.split("/")
|
||||||
|
if len(pieces) > 1:
|
||||||
|
provider = pieces[0]
|
||||||
|
else:
|
||||||
|
provider = None
|
||||||
|
|
||||||
|
keymap = dict(
|
||||||
|
openrouter="OPENROUTER_API_KEY",
|
||||||
|
openai="OPENAI_API_KEY",
|
||||||
|
deepseek="DEEPSEEK_API_KEY",
|
||||||
|
gemini="GEMINI_API_KEY",
|
||||||
|
anthropic="ANTHROPIC_API_KEY",
|
||||||
|
groq="GROQ_API_KEY",
|
||||||
|
fireworks_ai="FIREWORKS_API_KEY",
|
||||||
|
)
|
||||||
|
var = None
|
||||||
|
if model in OPENAI_MODELS:
|
||||||
var = "OPENAI_API_KEY"
|
var = "OPENAI_API_KEY"
|
||||||
elif model in ANTHROPIC_MODELS or model.startswith("anthropic/"):
|
elif model in ANTHROPIC_MODELS:
|
||||||
var = "ANTHROPIC_API_KEY"
|
var = "ANTHROPIC_API_KEY"
|
||||||
else:
|
else:
|
||||||
return
|
var = keymap.get(provider)
|
||||||
|
|
||||||
if os.environ.get(var):
|
if var and os.environ.get(var):
|
||||||
return dict(keys_in_environment=[var], missing_keys=[])
|
return dict(keys_in_environment=[var], missing_keys=[])
|
||||||
|
|
||||||
def validate_environment(self):
|
def validate_environment(self):
|
||||||
@@ -483,6 +596,185 @@ class Model(ModelSettings):
|
|||||||
map_tokens = max(map_tokens, 1024)
|
map_tokens = max(map_tokens, 1024)
|
||||||
return map_tokens
|
return map_tokens
|
||||||
|
|
||||||
|
def set_reasoning_effort(self, effort):
|
||||||
|
"""Set the reasoning effort parameter for models that support it"""
|
||||||
|
if effort is not None:
|
||||||
|
if not self.extra_params:
|
||||||
|
self.extra_params = {}
|
||||||
|
if "extra_body" not in self.extra_params:
|
||||||
|
self.extra_params["extra_body"] = {}
|
||||||
|
self.extra_params["extra_body"]["reasoning_effort"] = effort
|
||||||
|
|
||||||
|
def parse_token_value(self, value):
|
||||||
|
"""
|
||||||
|
Parse a token value string into an integer.
|
||||||
|
Accepts formats: 8096, "8k", "10.5k", "0.5M", "10K", etc.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: String or int token value
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Integer token value
|
||||||
|
"""
|
||||||
|
if isinstance(value, int):
|
||||||
|
return value
|
||||||
|
|
||||||
|
if not isinstance(value, str):
|
||||||
|
return int(value) # Try to convert to int
|
||||||
|
|
||||||
|
value = value.strip().upper()
|
||||||
|
|
||||||
|
if value.endswith("K"):
|
||||||
|
multiplier = 1024
|
||||||
|
value = value[:-1]
|
||||||
|
elif value.endswith("M"):
|
||||||
|
multiplier = 1024 * 1024
|
||||||
|
value = value[:-1]
|
||||||
|
else:
|
||||||
|
multiplier = 1
|
||||||
|
|
||||||
|
# Convert to float first to handle decimal values like "10.5k"
|
||||||
|
return int(float(value) * multiplier)
|
||||||
|
|
||||||
|
def set_thinking_tokens(self, value):
|
||||||
|
"""
|
||||||
|
Set the thinking token budget for models that support it.
|
||||||
|
Accepts formats: 8096, "8k", "10.5k", "0.5M", "10K", etc.
|
||||||
|
"""
|
||||||
|
if value is not None:
|
||||||
|
num_tokens = self.parse_token_value(value)
|
||||||
|
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):
|
||||||
|
"""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"]
|
||||||
|
# Format as xx.yK for thousands, xx.yM for millions
|
||||||
|
if budget >= 1024 * 1024:
|
||||||
|
value = budget / (1024 * 1024)
|
||||||
|
if value == int(value):
|
||||||
|
return f"{int(value)}M"
|
||||||
|
else:
|
||||||
|
return f"{value:.1f}M"
|
||||||
|
else:
|
||||||
|
value = budget / 1024
|
||||||
|
if value == int(value):
|
||||||
|
return f"{int(value)}k"
|
||||||
|
else:
|
||||||
|
return f"{value:.1f}k"
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_reasoning_effort(self, model):
|
||||||
|
"""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"]
|
||||||
|
):
|
||||||
|
return model.extra_params["extra_body"]["reasoning_effort"]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def is_deepseek_r1(self):
|
||||||
|
name = self.name.lower()
|
||||||
|
if "deepseek" not in name:
|
||||||
|
return
|
||||||
|
return "r1" in name or "reasoner" in name
|
||||||
|
|
||||||
|
def is_ollama(self):
|
||||||
|
return self.name.startswith("ollama/") or self.name.startswith("ollama_chat/")
|
||||||
|
|
||||||
|
def send_completion(self, messages, functions, stream, temperature=None):
|
||||||
|
if os.environ.get("AIDER_SANITY_CHECK_TURNS"):
|
||||||
|
sanity_check_messages(messages)
|
||||||
|
|
||||||
|
if self.is_deepseek_r1():
|
||||||
|
messages = ensure_alternating_roles(messages)
|
||||||
|
|
||||||
|
kwargs = dict(
|
||||||
|
model=self.name,
|
||||||
|
messages=messages,
|
||||||
|
stream=stream,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.use_temperature is not False:
|
||||||
|
if temperature is None:
|
||||||
|
if isinstance(self.use_temperature, bool):
|
||||||
|
temperature = 0
|
||||||
|
else:
|
||||||
|
temperature = float(self.use_temperature)
|
||||||
|
|
||||||
|
kwargs["temperature"] = temperature
|
||||||
|
|
||||||
|
if functions is not None:
|
||||||
|
function = functions[0]
|
||||||
|
kwargs["tools"] = [dict(type="function", function=function)]
|
||||||
|
kwargs["tool_choice"] = {"type": "function", "function": {"name": function["name"]}}
|
||||||
|
if self.extra_params:
|
||||||
|
kwargs.update(self.extra_params)
|
||||||
|
if self.is_ollama() and "num_ctx" not in kwargs:
|
||||||
|
num_ctx = int(self.token_count(messages) * 1.25) + 8192
|
||||||
|
kwargs["num_ctx"] = num_ctx
|
||||||
|
key = json.dumps(kwargs, sort_keys=True).encode()
|
||||||
|
|
||||||
|
# dump(kwargs)
|
||||||
|
|
||||||
|
hash_object = hashlib.sha1(key)
|
||||||
|
if "timeout" not in kwargs:
|
||||||
|
kwargs["timeout"] = request_timeout
|
||||||
|
if self.verbose:
|
||||||
|
dump(kwargs)
|
||||||
|
res = litellm.completion(**kwargs)
|
||||||
|
return hash_object, res
|
||||||
|
|
||||||
|
def simple_send_with_retries(self, messages):
|
||||||
|
from aider.exceptions import LiteLLMExceptions
|
||||||
|
|
||||||
|
litellm_ex = LiteLLMExceptions()
|
||||||
|
if "deepseek-reasoner" in self.name:
|
||||||
|
messages = ensure_alternating_roles(messages)
|
||||||
|
retry_delay = 0.125
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
kwargs = {
|
||||||
|
"messages": messages,
|
||||||
|
"functions": None,
|
||||||
|
"stream": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
_hash, response = self.send_completion(**kwargs)
|
||||||
|
if not response or not hasattr(response, "choices") or not response.choices:
|
||||||
|
return None
|
||||||
|
res = response.choices[0].message.content
|
||||||
|
from aider.reasoning_tags import remove_reasoning_content
|
||||||
|
|
||||||
|
return remove_reasoning_content(res, self.reasoning_tag)
|
||||||
|
|
||||||
|
except litellm_ex.exceptions_tuple() as err:
|
||||||
|
ex_info = litellm_ex.get_ex_info(err)
|
||||||
|
print(str(err))
|
||||||
|
if ex_info.description:
|
||||||
|
print(ex_info.description)
|
||||||
|
should_retry = ex_info.retry
|
||||||
|
if should_retry:
|
||||||
|
retry_delay *= 2
|
||||||
|
if retry_delay > RETRY_TIMEOUT:
|
||||||
|
should_retry = False
|
||||||
|
if not should_retry:
|
||||||
|
return None
|
||||||
|
print(f"Retrying in {retry_delay:.1f} seconds...")
|
||||||
|
time.sleep(retry_delay)
|
||||||
|
continue
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def register_models(model_settings_fnames):
|
def register_models(model_settings_fnames):
|
||||||
files_loaded = []
|
files_loaded = []
|
||||||
@@ -527,9 +819,8 @@ def register_litellm_models(model_fnames):
|
|||||||
if not model_def:
|
if not model_def:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# only load litellm if we have actual data
|
# Defer registration with litellm to faster path.
|
||||||
litellm._load_litellm()
|
model_info_manager.local_model_metadata.update(model_def)
|
||||||
litellm.register_model(model_def)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f"Error loading model definition from {model_fname}: {e}")
|
raise Exception(f"Error loading model definition from {model_fname}: {e}")
|
||||||
|
|
||||||
@@ -587,6 +878,9 @@ def sanity_check_model(io, model):
|
|||||||
show = True
|
show = True
|
||||||
io.tool_warning(f"Warning for {model}: Unknown which environment variables are required.")
|
io.tool_warning(f"Warning for {model}: Unknown which environment variables are required.")
|
||||||
|
|
||||||
|
# Check for model-specific dependencies
|
||||||
|
check_for_dependencies(io, model.name)
|
||||||
|
|
||||||
if not model.info:
|
if not model.info:
|
||||||
show = True
|
show = True
|
||||||
io.tool_warning(
|
io.tool_warning(
|
||||||
@@ -602,6 +896,30 @@ def sanity_check_model(io, model):
|
|||||||
return show
|
return show
|
||||||
|
|
||||||
|
|
||||||
|
def check_for_dependencies(io, model_name):
|
||||||
|
"""
|
||||||
|
Check for model-specific dependencies and install them if needed.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
io: The IO object for user interaction
|
||||||
|
model_name: The name of the model to check dependencies for
|
||||||
|
"""
|
||||||
|
# Check if this is a Bedrock model and ensure boto3 is installed
|
||||||
|
if model_name.startswith("bedrock/"):
|
||||||
|
check_pip_install_extra(
|
||||||
|
io, "boto3", "AWS Bedrock models require the boto3 package.", ["boto3"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if this is a Vertex AI model and ensure google-cloud-aiplatform is installed
|
||||||
|
elif model_name.startswith("vertex_ai/"):
|
||||||
|
check_pip_install_extra(
|
||||||
|
io,
|
||||||
|
"google.cloud.aiplatform",
|
||||||
|
"Google Vertex AI models require the google-cloud-aiplatform package.",
|
||||||
|
["google-cloud-aiplatform"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def fuzzy_match_models(name):
|
def fuzzy_match_models(name):
|
||||||
name = name.lower()
|
name = name.lower()
|
||||||
|
|
||||||
|
|||||||
7
aider/queries/tree-sitter-language-pack/README.md
Normal file
7
aider/queries/tree-sitter-language-pack/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
These scm files are all adapted from the github repositories listed here:
|
||||||
|
|
||||||
|
https://github.com/Goldziher/tree-sitter-language-pack/blob/main/sources/language_definitions.json
|
||||||
|
|
||||||
|
See this URL for information on the licenses of each repo:
|
||||||
|
|
||||||
|
https://github.com/Goldziher/tree-sitter-language-pack/
|
||||||
5
aider/queries/tree-sitter-language-pack/arduino-tags.scm
Normal file
5
aider/queries/tree-sitter-language-pack/arduino-tags.scm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
(function_declarator
|
||||||
|
declarator: (identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (identifier) @name.reference.call) @reference.call
|
||||||
16
aider/queries/tree-sitter-language-pack/chatito-tags.scm
Normal file
16
aider/queries/tree-sitter-language-pack/chatito-tags.scm
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
; Definitions
|
||||||
|
(intent_def
|
||||||
|
(intent) @name.definition.intent) @definition.intent
|
||||||
|
|
||||||
|
(slot_def
|
||||||
|
(slot) @name.definition.slot) @definition.slot
|
||||||
|
|
||||||
|
(alias_def
|
||||||
|
(alias) @name.definition.alias) @definition.alias
|
||||||
|
|
||||||
|
; References
|
||||||
|
(slot_ref
|
||||||
|
(slot) @name.reference.slot) @reference.slot
|
||||||
|
|
||||||
|
(alias_ref
|
||||||
|
(alias) @name.reference.alias) @reference.alias
|
||||||
122
aider/queries/tree-sitter-language-pack/commonlisp-tags.scm
Normal file
122
aider/queries/tree-sitter-language-pack/commonlisp-tags.scm
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;; Function Definitions ;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(defun_header
|
||||||
|
function_name: (sym_lit) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;; Function Calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;;
|
||||||
|
;;; Basically, we consider every list literal with symbol as the
|
||||||
|
;;; first element to be a call to a function named by that element.
|
||||||
|
;;; But we must exclude some cases. Note, tree-sitter @ignore
|
||||||
|
;;; cases only work if they are declared before the cases
|
||||||
|
;;; we want to include.
|
||||||
|
|
||||||
|
;; Exclude lambda lists for function definitions
|
||||||
|
;; For example:
|
||||||
|
;;
|
||||||
|
;; (defun my-func (arg1 arg2) ...)
|
||||||
|
;;
|
||||||
|
;; do not treat (arg1 arg2) as a call of function arg1
|
||||||
|
;;
|
||||||
|
(defun_header
|
||||||
|
lambda_list: (list_lit . [(sym_lit) (package_lit)] @ignore))
|
||||||
|
|
||||||
|
;; Similar to the above, but for
|
||||||
|
;;
|
||||||
|
;; (defmethod m ((type1 param1) (type2 param2)) ...)
|
||||||
|
;;
|
||||||
|
;; where list literals having symbol as their first element
|
||||||
|
;; are nested inside the lambda list.
|
||||||
|
(defun_header
|
||||||
|
lambda_list: (list_lit (list_lit . [(sym_lit) (package_lit)] @ignore)))
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; (let ((var ...) (var2 ...)) ...)
|
||||||
|
;;
|
||||||
|
;; - exclude var, var2
|
||||||
|
;; - the same for let*, flet, labels, macrolet, symbol-macrolet
|
||||||
|
(list_lit . [(sym_lit) (package_lit)] @name.reference.call
|
||||||
|
. (list_lit (list_lit . [(sym_lit) (package_lit)] @ignore))
|
||||||
|
(#match? @name.reference.call
|
||||||
|
"(?i)^(cl:)?(let|let\\*|flet|labels|macrolet|symbol-macrolet)$")
|
||||||
|
)
|
||||||
|
|
||||||
|
;; TODO:
|
||||||
|
;; - exclude also:
|
||||||
|
;; - (defclass name (parent parent2)
|
||||||
|
;; ((slot1 ...)
|
||||||
|
;; (slot2 ...))
|
||||||
|
;; exclude the parent, slot1, slot2
|
||||||
|
;; - (flet ((func-1 (param1 param2))) ...)
|
||||||
|
;; - we already exclude func-1, but param1 is still recognized
|
||||||
|
;; as a function call - exclude it too
|
||||||
|
;; - the same for labels
|
||||||
|
;; - the same macrolet
|
||||||
|
;; - what else?
|
||||||
|
;; (that's a non-goal to completely support all macros
|
||||||
|
;; and special operators, but every one we support
|
||||||
|
;; makes the solution a little bit better)
|
||||||
|
;; - (flet ((func-1 (param1 param2))) ...)
|
||||||
|
;; - instead of simply excluding it, as we do today,
|
||||||
|
;; tag func-1 as @local.definition.function (I suppose)
|
||||||
|
;; - the same for labels, macrolet
|
||||||
|
;; - @local.scope for let, let*, flet, labels, macrolet
|
||||||
|
;; - I guess the whole span of the scope text,
|
||||||
|
;; till the closing paren, should be tagged as @local.scope;
|
||||||
|
;; Hopefully, combined with @local.definition.function
|
||||||
|
;; within the scope, the usual @reference.call within
|
||||||
|
;; that scope will refer to the local definition,
|
||||||
|
;; and there will be no need to use @local.reference.call
|
||||||
|
;; (which is more difficult to implement).
|
||||||
|
;; - When implementing, remember the scope rules differences
|
||||||
|
;; of let vs let*, flet vs labels.
|
||||||
|
|
||||||
|
|
||||||
|
;; Include all other cases - list literal with symbol as the
|
||||||
|
;; first element
|
||||||
|
(list_lit . [(sym_lit) (package_lit)] @name.reference.call) @reference.call
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;; classes
|
||||||
|
|
||||||
|
(list_lit . [(sym_lit) (package_lit)] @ignore
|
||||||
|
. [(sym_lit) (package_lit)] @name.definition.class
|
||||||
|
(#match? @ignore "(?i)^(cl:)?defclass$")
|
||||||
|
) @definition.class
|
||||||
|
|
||||||
|
(list_lit . [(sym_lit) (package_lit)] @ignore
|
||||||
|
. (quoting_lit [(sym_lit) (package_lit)] @name.reference.class)
|
||||||
|
(#match? @ignore "(?i)^(cl:)?make-instance$")
|
||||||
|
) @reference.class
|
||||||
|
|
||||||
|
;;; TODO:
|
||||||
|
;; - @reference.class for base classes
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;; TODO:
|
||||||
|
;; - Symbols referenced in defpackage
|
||||||
|
;;
|
||||||
|
;; (defpackage ...
|
||||||
|
;; (:export (symbol-a :symbol-b #:symbol-c "SYMBOL-D")))
|
||||||
|
;;
|
||||||
|
;; The goal is to allow quick navigation from the API
|
||||||
|
;; overview in the form of defpackage, to the definition
|
||||||
|
;; where user can read parameters, docstring, etc.
|
||||||
|
;; - The @name must not include the colon, or sharpsign colon, quotes,
|
||||||
|
;; just symbol-a, symbol-b, symbol-c, sybmol-d
|
||||||
|
;; - Downcase the names specified as string literals?
|
||||||
|
;; ("SYMBOL-D" -> symbol-d)
|
||||||
|
;; - We don't know if the exported symbol is a function, variable,
|
||||||
|
;; class or something else. The official doc
|
||||||
|
;; (https://tree-sitter.github.io/tree-sitter/code-navigation-systems)
|
||||||
|
;; does not even suggest a tag for variable reference.
|
||||||
|
;; (Although in practice, the `tree-sitter tags` command
|
||||||
|
;; allows any @reference.* and @definition.* tags)
|
||||||
|
;; Probably it's better to just use @reference.call for all
|
||||||
|
;; the symbols in the :export clause.
|
||||||
|
;;
|
||||||
|
;; - The same for the export function call:
|
||||||
|
;;
|
||||||
|
;; (export '(symbol-a :symbol-b #:symbol-c "SYMBOL-D"))
|
||||||
15
aider/queries/tree-sitter-language-pack/cpp-tags.scm
Normal file
15
aider/queries/tree-sitter-language-pack/cpp-tags.scm
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
(struct_specifier name: (type_identifier) @name.definition.class body:(_)) @definition.class
|
||||||
|
|
||||||
|
(declaration type: (union_specifier name: (type_identifier) @name.definition.class)) @definition.class
|
||||||
|
|
||||||
|
(function_declarator declarator: (identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
(function_declarator declarator: (field_identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
(function_declarator declarator: (qualified_identifier scope: (namespace_identifier) @local.scope name: (identifier) @name.definition.method)) @definition.method
|
||||||
|
|
||||||
|
(type_definition declarator: (type_identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(enum_specifier name: (type_identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(class_specifier name: (type_identifier) @name.definition.class) @definition.class
|
||||||
26
aider/queries/tree-sitter-language-pack/csharp-tags.scm
Normal file
26
aider/queries/tree-sitter-language-pack/csharp-tags.scm
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
; Based on https://github.com/tree-sitter/tree-sitter-c-sharp/blob/master/queries/tags.scm
|
||||||
|
; MIT License.
|
||||||
|
|
||||||
|
(class_declaration name: (identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(class_declaration (base_list (_) @name.reference.class)) @reference.class
|
||||||
|
|
||||||
|
(interface_declaration name: (identifier) @name.definition.interface) @definition.interface
|
||||||
|
|
||||||
|
(interface_declaration (base_list (_) @name.reference.interface)) @reference.interface
|
||||||
|
|
||||||
|
(method_declaration name: (identifier) @name.definition.method) @definition.method
|
||||||
|
|
||||||
|
(object_creation_expression type: (identifier) @name.reference.class) @reference.class
|
||||||
|
|
||||||
|
(type_parameter_constraints_clause (identifier) @name.reference.class) @reference.class
|
||||||
|
|
||||||
|
(type_parameter_constraint (type type: (identifier) @name.reference.class)) @reference.class
|
||||||
|
|
||||||
|
(variable_declaration type: (identifier) @name.reference.class) @reference.class
|
||||||
|
|
||||||
|
(invocation_expression function: (member_access_expression name: (identifier) @name.reference.send)) @reference.send
|
||||||
|
|
||||||
|
(namespace_declaration name: (identifier) @name.definition.module) @definition.module
|
||||||
|
|
||||||
|
(namespace_declaration name: (identifier) @name.definition.module) @module
|
||||||
26
aider/queries/tree-sitter-language-pack/d-tags.scm
Normal file
26
aider/queries/tree-sitter-language-pack/d-tags.scm
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
(module_def (module_declaration (module_fqn) @name.definition.module)) @definition.module
|
||||||
|
|
||||||
|
(struct_declaration (struct) . (identifier) @name.definition.class) @definition.class
|
||||||
|
(interface_declaration (interface) . (identifier) @name.definition.interface) @definition.interface
|
||||||
|
(enum_declaration (enum) . (identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(class_declaration (class) . (identifier) @name.definition.class) @definition.class
|
||||||
|
(constructor (this) @name.definition.method) @definition.method
|
||||||
|
(destructor (this) @name.definition.method) @definition.method
|
||||||
|
(postblit (this) @name.definition.method) @definition.method
|
||||||
|
|
||||||
|
(manifest_declarator . (identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(function_declaration (identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
(union_declaration (union) . (identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(anonymous_enum_declaration (enum_member . (identifier) @name.definition.constant)) @definition.constant
|
||||||
|
|
||||||
|
(enum_declaration (enum_member . (identifier) @name.definition.constant)) @definition.constant
|
||||||
|
|
||||||
|
(call_expression (identifier) @name.reference.call) @reference.call
|
||||||
|
(call_expression (type (template_instance (identifier) @name.reference.call))) @reference.call
|
||||||
|
(parameter (type (identifier) @name.reference.class) @reference.class (identifier))
|
||||||
|
|
||||||
|
(variable_declaration (type (identifier) @name.reference.class) @reference.class (declarator))
|
||||||
92
aider/queries/tree-sitter-language-pack/dart-tags.scm
Normal file
92
aider/queries/tree-sitter-language-pack/dart-tags.scm
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
(class_definition
|
||||||
|
name: (identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
(function_signature)) @definition.method
|
||||||
|
|
||||||
|
(type_alias
|
||||||
|
(type_identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
(getter_signature
|
||||||
|
name: (identifier) @name.definition.method)) @definition.method
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
(setter_signature
|
||||||
|
name: (identifier) @name.definition.method)) @definition.method
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
(function_signature
|
||||||
|
name: (identifier) @name.definition.method)) @definition.method
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
(factory_constructor_signature
|
||||||
|
(identifier) @name.definition.method)) @definition.method
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
(constructor_signature
|
||||||
|
name: (identifier) @name.definition.method)) @definition.method
|
||||||
|
|
||||||
|
(method_signature
|
||||||
|
(operator_signature)) @definition.method
|
||||||
|
|
||||||
|
(method_signature) @definition.method
|
||||||
|
|
||||||
|
(mixin_declaration
|
||||||
|
(mixin)
|
||||||
|
(identifier) @name.definition.mixin) @definition.mixin
|
||||||
|
|
||||||
|
(extension_declaration
|
||||||
|
name: (identifier) @name.definition.extension) @definition.extension
|
||||||
|
|
||||||
|
|
||||||
|
(new_expression
|
||||||
|
(type_identifier) @name.reference.class) @reference.class
|
||||||
|
|
||||||
|
(enum_declaration
|
||||||
|
name: (identifier) @name.definition.enum) @definition.enum
|
||||||
|
|
||||||
|
(function_signature
|
||||||
|
name: (identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
(initialized_variable_definition
|
||||||
|
name: (identifier)
|
||||||
|
value: (identifier) @name.reference.class
|
||||||
|
value: (selector
|
||||||
|
"!"?
|
||||||
|
(argument_part
|
||||||
|
(arguments
|
||||||
|
(argument)*))?)?) @reference.class
|
||||||
|
|
||||||
|
(assignment_expression
|
||||||
|
left: (assignable_expression
|
||||||
|
(identifier)
|
||||||
|
(unconditional_assignable_selector
|
||||||
|
"."
|
||||||
|
(identifier) @name.reference.send))) @reference.call
|
||||||
|
|
||||||
|
(assignment_expression
|
||||||
|
left: (assignable_expression
|
||||||
|
(identifier)
|
||||||
|
(conditional_assignable_selector
|
||||||
|
"?."
|
||||||
|
(identifier) @name.reference.send))) @reference.call
|
||||||
|
|
||||||
|
((identifier) @name.reference.send
|
||||||
|
(selector
|
||||||
|
"!"?
|
||||||
|
(conditional_assignable_selector
|
||||||
|
"?." (identifier) @name.reference.send)?
|
||||||
|
(unconditional_assignable_selector
|
||||||
|
"."? (identifier) @name.reference.send)?
|
||||||
|
(argument_part
|
||||||
|
(arguments
|
||||||
|
(argument)*))?)*
|
||||||
|
(cascade_section
|
||||||
|
(cascade_selector
|
||||||
|
(identifier)) @name.reference.send
|
||||||
|
(argument_part
|
||||||
|
(arguments
|
||||||
|
(argument)*))?)?) @reference.call
|
||||||
|
|
||||||
5
aider/queries/tree-sitter-language-pack/elisp-tags.scm
Normal file
5
aider/queries/tree-sitter-language-pack/elisp-tags.scm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
;; defun/defsubst
|
||||||
|
(function_definition name: (symbol) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
;; Treat macros as function definitions for the sake of TAGS.
|
||||||
|
(macro_definition name: (symbol) @name.definition.function) @definition.function
|
||||||
54
aider/queries/tree-sitter-language-pack/elixir-tags.scm
Normal file
54
aider/queries/tree-sitter-language-pack/elixir-tags.scm
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
; Definitions
|
||||||
|
|
||||||
|
; * modules and protocols
|
||||||
|
(call
|
||||||
|
target: (identifier) @ignore
|
||||||
|
(arguments (alias) @name.definition.module)
|
||||||
|
(#any-of? @ignore "defmodule" "defprotocol")) @definition.module
|
||||||
|
|
||||||
|
; * functions/macros
|
||||||
|
(call
|
||||||
|
target: (identifier) @ignore
|
||||||
|
(arguments
|
||||||
|
[
|
||||||
|
; zero-arity functions with no parentheses
|
||||||
|
(identifier) @name.definition.function
|
||||||
|
; regular function clause
|
||||||
|
(call target: (identifier) @name.definition.function)
|
||||||
|
; function clause with a guard clause
|
||||||
|
(binary_operator
|
||||||
|
left: (call target: (identifier) @name.definition.function)
|
||||||
|
operator: "when")
|
||||||
|
])
|
||||||
|
(#any-of? @ignore "def" "defp" "defdelegate" "defguard" "defguardp" "defmacro" "defmacrop" "defn" "defnp")) @definition.function
|
||||||
|
|
||||||
|
; References
|
||||||
|
|
||||||
|
; ignore calls to kernel/special-forms keywords
|
||||||
|
(call
|
||||||
|
target: (identifier) @ignore
|
||||||
|
(#any-of? @ignore "def" "defp" "defdelegate" "defguard" "defguardp" "defmacro" "defmacrop" "defn" "defnp" "defmodule" "defprotocol" "defimpl" "defstruct" "defexception" "defoverridable" "alias" "case" "cond" "else" "for" "if" "import" "quote" "raise" "receive" "require" "reraise" "super" "throw" "try" "unless" "unquote" "unquote_splicing" "use" "with"))
|
||||||
|
|
||||||
|
; ignore module attributes
|
||||||
|
(unary_operator
|
||||||
|
operator: "@"
|
||||||
|
operand: (call
|
||||||
|
target: (identifier) @ignore))
|
||||||
|
|
||||||
|
; * function call
|
||||||
|
(call
|
||||||
|
target: [
|
||||||
|
; local
|
||||||
|
(identifier) @name.reference.call
|
||||||
|
; remote
|
||||||
|
(dot
|
||||||
|
right: (identifier) @name.reference.call)
|
||||||
|
]) @reference.call
|
||||||
|
|
||||||
|
; * pipe into function call
|
||||||
|
(binary_operator
|
||||||
|
operator: "|>"
|
||||||
|
right: (identifier) @name.reference.call) @reference.call
|
||||||
|
|
||||||
|
; * modules
|
||||||
|
(alias) @name.reference.module @reference.module
|
||||||
19
aider/queries/tree-sitter-language-pack/elm-tags.scm
Normal file
19
aider/queries/tree-sitter-language-pack/elm-tags.scm
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
(value_declaration (function_declaration_left (lower_case_identifier) @name.definition.function)) @definition.function
|
||||||
|
|
||||||
|
(function_call_expr (value_expr (value_qid) @name.reference.function)) @reference.function
|
||||||
|
(exposed_value (lower_case_identifier) @name.reference.function) @reference.function
|
||||||
|
(type_annotation ((lower_case_identifier) @name.reference.function) (colon)) @reference.function
|
||||||
|
|
||||||
|
(type_declaration ((upper_case_identifier) @name.definition.type) ) @definition.type
|
||||||
|
|
||||||
|
(type_ref (upper_case_qid (upper_case_identifier) @name.reference.type)) @reference.type
|
||||||
|
(exposed_type (upper_case_identifier) @name.reference.type) @reference.type
|
||||||
|
|
||||||
|
(type_declaration (union_variant (upper_case_identifier) @name.definition.union)) @definition.union
|
||||||
|
|
||||||
|
(value_expr (upper_case_qid (upper_case_identifier) @name.reference.union)) @reference.union
|
||||||
|
|
||||||
|
|
||||||
|
(module_declaration
|
||||||
|
(upper_case_qid (upper_case_identifier)) @name.definition.module
|
||||||
|
) @definition.module
|
||||||
41
aider/queries/tree-sitter-language-pack/gleam-tags.scm
Normal file
41
aider/queries/tree-sitter-language-pack/gleam-tags.scm
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
; Modules
|
||||||
|
(module) @name.reference.module @reference.module
|
||||||
|
(import alias: (identifier) @name.reference.module) @reference.module
|
||||||
|
(remote_type_identifier
|
||||||
|
module: (identifier) @name.reference.module) @reference.module
|
||||||
|
((field_access
|
||||||
|
record: (identifier) @name.reference.module)
|
||||||
|
(#is-not? local)) @reference.module
|
||||||
|
|
||||||
|
; Functions
|
||||||
|
(function
|
||||||
|
name: (identifier) @name.definition.function) @definition.function
|
||||||
|
(external_function
|
||||||
|
name: (identifier) @name.definition.function) @definition.function
|
||||||
|
(unqualified_import (identifier) @name.reference.function) @reference.function
|
||||||
|
((function_call
|
||||||
|
function: (identifier) @name.reference.function) @reference.function
|
||||||
|
(#is-not? local))
|
||||||
|
((field_access
|
||||||
|
record: (identifier) @ignore
|
||||||
|
field: (label) @name.reference.function)
|
||||||
|
(#is-not? local)) @reference.function
|
||||||
|
((binary_expression
|
||||||
|
operator: "|>"
|
||||||
|
right: (identifier) @name.reference.function)
|
||||||
|
(#is-not? local)) @reference.function
|
||||||
|
|
||||||
|
; Types
|
||||||
|
(type_definition
|
||||||
|
(type_name
|
||||||
|
name: (type_identifier) @name.definition.type)) @definition.type
|
||||||
|
(type_definition
|
||||||
|
(data_constructors
|
||||||
|
(data_constructor
|
||||||
|
name: (constructor_name) @name.definition.constructor))) @definition.constructor
|
||||||
|
(external_type
|
||||||
|
(type_name
|
||||||
|
name: (type_identifier) @name.definition.type)) @definition.type
|
||||||
|
|
||||||
|
(type_identifier) @name.reference.type @reference.type
|
||||||
|
(constructor_name) @name.reference.constructor @reference.constructor
|
||||||
42
aider/queries/tree-sitter-language-pack/go-tags.scm
Normal file
42
aider/queries/tree-sitter-language-pack/go-tags.scm
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
(function_declaration
|
||||||
|
name: (identifier) @name.definition.function) @definition.function
|
||||||
|
(#strip! @doc "^//\\s*")
|
||||||
|
(#set-adjacent! @doc @definition.function)
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
(method_declaration
|
||||||
|
name: (field_identifier) @name.definition.method) @definition.method
|
||||||
|
(#strip! @doc "^//\\s*")
|
||||||
|
(#set-adjacent! @doc @definition.method)
|
||||||
|
)
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: [
|
||||||
|
(identifier) @name.reference.call
|
||||||
|
(parenthesized_expression (identifier) @name.reference.call)
|
||||||
|
(selector_expression field: (field_identifier) @name.reference.call)
|
||||||
|
(parenthesized_expression (selector_expression field: (field_identifier) @name.reference.call))
|
||||||
|
]) @reference.call
|
||||||
|
|
||||||
|
(type_spec
|
||||||
|
name: (type_identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(type_identifier) @name.reference.type @reference.type
|
||||||
|
|
||||||
|
(package_clause "package" (package_identifier) @name.definition.module)
|
||||||
|
|
||||||
|
(type_declaration (type_spec name: (type_identifier) @name.definition.interface type: (interface_type)))
|
||||||
|
|
||||||
|
(type_declaration (type_spec name: (type_identifier) @name.definition.class type: (struct_type)))
|
||||||
|
|
||||||
|
(import_declaration (import_spec) @name.reference.module)
|
||||||
|
|
||||||
|
(var_declaration (var_spec name: (identifier) @name.definition.variable))
|
||||||
|
|
||||||
|
(const_declaration (const_spec name: (identifier) @name.definition.constant))
|
||||||
20
aider/queries/tree-sitter-language-pack/java-tags.scm
Normal file
20
aider/queries/tree-sitter-language-pack/java-tags.scm
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
(class_declaration
|
||||||
|
name: (identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(method_declaration
|
||||||
|
name: (identifier) @name.definition.method) @definition.method
|
||||||
|
|
||||||
|
(method_invocation
|
||||||
|
name: (identifier) @name.reference.method
|
||||||
|
arguments: (argument_list) @reference.call)
|
||||||
|
|
||||||
|
(interface_declaration
|
||||||
|
name: (identifier) @name.definition.interface) @definition.interface
|
||||||
|
|
||||||
|
(type_list
|
||||||
|
(type_identifier) @name.reference.interface) @reference.implementation
|
||||||
|
|
||||||
|
(object_creation_expression
|
||||||
|
type: (type_identifier) @name.reference.class) @reference.class
|
||||||
|
|
||||||
|
(superclass (type_identifier) @name.reference.class) @reference.class
|
||||||
88
aider/queries/tree-sitter-language-pack/javascript-tags.scm
Normal file
88
aider/queries/tree-sitter-language-pack/javascript-tags.scm
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
(method_definition
|
||||||
|
name: (property_identifier) @name.definition.method) @definition.method
|
||||||
|
(#not-eq? @name.definition.method "constructor")
|
||||||
|
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
||||||
|
(#select-adjacent! @doc @definition.method)
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
[
|
||||||
|
(class
|
||||||
|
name: (_) @name.definition.class)
|
||||||
|
(class_declaration
|
||||||
|
name: (_) @name.definition.class)
|
||||||
|
] @definition.class
|
||||||
|
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
||||||
|
(#select-adjacent! @doc @definition.class)
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
[
|
||||||
|
(function_expression
|
||||||
|
name: (identifier) @name.definition.function)
|
||||||
|
(function_declaration
|
||||||
|
name: (identifier) @name.definition.function)
|
||||||
|
(generator_function
|
||||||
|
name: (identifier) @name.definition.function)
|
||||||
|
(generator_function_declaration
|
||||||
|
name: (identifier) @name.definition.function)
|
||||||
|
] @definition.function
|
||||||
|
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
||||||
|
(#select-adjacent! @doc @definition.function)
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
(lexical_declaration
|
||||||
|
(variable_declarator
|
||||||
|
name: (identifier) @name.definition.function
|
||||||
|
value: [(arrow_function) (function_expression)]) @definition.function)
|
||||||
|
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
||||||
|
(#select-adjacent! @doc @definition.function)
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
(variable_declaration
|
||||||
|
(variable_declarator
|
||||||
|
name: (identifier) @name.definition.function
|
||||||
|
value: [(arrow_function) (function_expression)]) @definition.function)
|
||||||
|
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
||||||
|
(#select-adjacent! @doc @definition.function)
|
||||||
|
)
|
||||||
|
|
||||||
|
(assignment_expression
|
||||||
|
left: [
|
||||||
|
(identifier) @name.definition.function
|
||||||
|
(member_expression
|
||||||
|
property: (property_identifier) @name.definition.function)
|
||||||
|
]
|
||||||
|
right: [(arrow_function) (function_expression)]
|
||||||
|
) @definition.function
|
||||||
|
|
||||||
|
(pair
|
||||||
|
key: (property_identifier) @name.definition.function
|
||||||
|
value: [(arrow_function) (function_expression)]) @definition.function
|
||||||
|
|
||||||
|
(
|
||||||
|
(call_expression
|
||||||
|
function: (identifier) @name.reference.call) @reference.call
|
||||||
|
(#not-match? @name.reference.call "^(require)$")
|
||||||
|
)
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (member_expression
|
||||||
|
property: (property_identifier) @name.reference.call)
|
||||||
|
arguments: (_) @reference.call)
|
||||||
|
|
||||||
|
(new_expression
|
||||||
|
constructor: (_) @name.reference.class) @reference.class
|
||||||
34
aider/queries/tree-sitter-language-pack/lua-tags.scm
Normal file
34
aider/queries/tree-sitter-language-pack/lua-tags.scm
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
(function_declaration
|
||||||
|
name: [
|
||||||
|
(identifier) @name.definition.function
|
||||||
|
(dot_index_expression
|
||||||
|
field: (identifier) @name.definition.function)
|
||||||
|
]) @definition.function
|
||||||
|
|
||||||
|
(function_declaration
|
||||||
|
name: (method_index_expression
|
||||||
|
method: (identifier) @name.definition.method)) @definition.method
|
||||||
|
|
||||||
|
(assignment_statement
|
||||||
|
(variable_list .
|
||||||
|
name: [
|
||||||
|
(identifier) @name.definition.function
|
||||||
|
(dot_index_expression
|
||||||
|
field: (identifier) @name.definition.function)
|
||||||
|
])
|
||||||
|
(expression_list .
|
||||||
|
value: (function_definition))) @definition.function
|
||||||
|
|
||||||
|
(table_constructor
|
||||||
|
(field
|
||||||
|
name: (identifier) @name.definition.function
|
||||||
|
value: (function_definition))) @definition.function
|
||||||
|
|
||||||
|
(function_call
|
||||||
|
name: [
|
||||||
|
(identifier) @name.reference.call
|
||||||
|
(dot_index_expression
|
||||||
|
field: (identifier) @name.reference.call)
|
||||||
|
(method_index_expression
|
||||||
|
method: (identifier) @name.reference.method)
|
||||||
|
]) @reference.call
|
||||||
39
aider/queries/tree-sitter-language-pack/pony-tags.scm
Normal file
39
aider/queries/tree-sitter-language-pack/pony-tags.scm
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
;Class definitions @definition.class
|
||||||
|
;Function definitions @definition.function
|
||||||
|
;Interface definitions @definition.interface
|
||||||
|
;Method definitions @definition.method
|
||||||
|
;Module definitions @definition.module
|
||||||
|
;Function/method calls @reference.call
|
||||||
|
;Class reference @reference.class
|
||||||
|
;Interface implementation @reference.implementation
|
||||||
|
(
|
||||||
|
(identifier) @reference.class
|
||||||
|
(#match? @reference.class "^_*[A-Z][a-zA-Z0-9_]*$")
|
||||||
|
)
|
||||||
|
|
||||||
|
(class_definition (identifier) @name.definition.class) @definition.class
|
||||||
|
(actor_definition (identifier) @name.definition.class) @definition.class
|
||||||
|
(primitive_definition (identifier) @name.definition.class) @definition.class
|
||||||
|
(struct_definition (identifier) @name.definition.class) @definition.class
|
||||||
|
(type_alias (identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(trait_definition (identifier) @name.definition.interface) @definition.interface
|
||||||
|
(interface_definition (identifier) @name.definition.interface) @definition.interface
|
||||||
|
|
||||||
|
(constructor (identifier) @name.definition.method) @definition.method
|
||||||
|
(method (identifier) @name.definition.method) @definition.method
|
||||||
|
(behavior (identifier) @name.definition.method) @definition.method
|
||||||
|
|
||||||
|
(class_definition (type) @name.reference.implementation) @reference.implementation
|
||||||
|
(actor_definition (type) @name.reference.implementation) @reference.implementation
|
||||||
|
(primitive_definition (type) @name.reference.implementation) @reference.implementation
|
||||||
|
(struct_definition (type) @name.reference.implementation) @reference.implementation
|
||||||
|
(type_alias (type) @name.reference.implementation) @reference.implementation
|
||||||
|
|
||||||
|
; calls - not catching all possible call cases of callees for capturing the method name
|
||||||
|
(call_expression callee: [(identifier) (ffi_identifier)] @name.reference.call) @reference.call
|
||||||
|
(call_expression callee: (generic_expression [(identifier) (ffi_identifier)] @name.reference.call)) @reference.call
|
||||||
|
(call_expression callee: (member_expression (identifier) @name.reference.call .)) @reference.call
|
||||||
|
(call_expression callee: (member_expression (generic_expression [(identifier) (ffi_identifier)] @name.reference.call) .)) @reference.call
|
||||||
|
; TODO: add more possible callee expressions
|
||||||
|
(call_expression) @reference.call
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
(property
|
||||||
|
(key) @name.definition.property) @definition.property
|
||||||
|
|
||||||
|
(substitution
|
||||||
|
(key) @name.reference.property) @reference.property
|
||||||
14
aider/queries/tree-sitter-language-pack/python-tags.scm
Normal file
14
aider/queries/tree-sitter-language-pack/python-tags.scm
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
(module (expression_statement (assignment left: (identifier) @name.definition.constant) @definition.constant))
|
||||||
|
|
||||||
|
(class_definition
|
||||||
|
name: (identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(function_definition
|
||||||
|
name: (identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
(call
|
||||||
|
function: [
|
||||||
|
(identifier) @name.reference.call
|
||||||
|
(attribute
|
||||||
|
attribute: (identifier) @name.reference.call)
|
||||||
|
]) @reference.call
|
||||||
21
aider/queries/tree-sitter-language-pack/r-tags.scm
Normal file
21
aider/queries/tree-sitter-language-pack/r-tags.scm
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
(binary_operator
|
||||||
|
lhs: (identifier) @name.definition.function
|
||||||
|
operator: "<-"
|
||||||
|
rhs: (function_definition)
|
||||||
|
) @definition.function
|
||||||
|
|
||||||
|
(binary_operator
|
||||||
|
lhs: (identifier) @name.definition.function
|
||||||
|
operator: "="
|
||||||
|
rhs: (function_definition)
|
||||||
|
) @definition.function
|
||||||
|
|
||||||
|
(call
|
||||||
|
function: (identifier) @name.reference.call
|
||||||
|
) @reference.call
|
||||||
|
|
||||||
|
(call
|
||||||
|
function: (namespace_operator
|
||||||
|
rhs: (identifier) @name.reference.call
|
||||||
|
)
|
||||||
|
) @reference.call
|
||||||
12
aider/queries/tree-sitter-language-pack/racket-tags.scm
Normal file
12
aider/queries/tree-sitter-language-pack/racket-tags.scm
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
(list
|
||||||
|
.
|
||||||
|
(symbol) @reference._define
|
||||||
|
(#match? @reference._define "^(define|define/contract)$")
|
||||||
|
.
|
||||||
|
(list
|
||||||
|
.
|
||||||
|
(symbol) @name.definition.function) @definition.function)
|
||||||
|
|
||||||
|
(list
|
||||||
|
.
|
||||||
|
(symbol) @name.reference.call)
|
||||||
60
aider/queries/tree-sitter-language-pack/rust-tags.scm
Normal file
60
aider/queries/tree-sitter-language-pack/rust-tags.scm
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
; ADT definitions
|
||||||
|
|
||||||
|
(struct_item
|
||||||
|
name: (type_identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(enum_item
|
||||||
|
name: (type_identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(union_item
|
||||||
|
name: (type_identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
; type aliases
|
||||||
|
|
||||||
|
(type_item
|
||||||
|
name: (type_identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
; method definitions
|
||||||
|
|
||||||
|
(declaration_list
|
||||||
|
(function_item
|
||||||
|
name: (identifier) @name.definition.method) @definition.method)
|
||||||
|
|
||||||
|
; function definitions
|
||||||
|
|
||||||
|
(function_item
|
||||||
|
name: (identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
; trait definitions
|
||||||
|
(trait_item
|
||||||
|
name: (type_identifier) @name.definition.interface) @definition.interface
|
||||||
|
|
||||||
|
; module definitions
|
||||||
|
(mod_item
|
||||||
|
name: (identifier) @name.definition.module) @definition.module
|
||||||
|
|
||||||
|
; macro definitions
|
||||||
|
|
||||||
|
(macro_definition
|
||||||
|
name: (identifier) @name.definition.macro) @definition.macro
|
||||||
|
|
||||||
|
; references
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (identifier) @name.reference.call) @reference.call
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (field_expression
|
||||||
|
field: (field_identifier) @name.reference.call)) @reference.call
|
||||||
|
|
||||||
|
(macro_invocation
|
||||||
|
macro: (identifier) @name.reference.call) @reference.call
|
||||||
|
|
||||||
|
; implementations
|
||||||
|
|
||||||
|
(impl_item
|
||||||
|
trait: (type_identifier) @name.reference.implementation) @reference.implementation
|
||||||
|
|
||||||
|
(impl_item
|
||||||
|
type: (type_identifier) @name.reference.implementation
|
||||||
|
!trait) @reference.implementation
|
||||||
43
aider/queries/tree-sitter-language-pack/solidity-tags.scm
Normal file
43
aider/queries/tree-sitter-language-pack/solidity-tags.scm
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
;; Method and Function declarations
|
||||||
|
(contract_declaration (_
|
||||||
|
(function_definition
|
||||||
|
name: (identifier) @name.definition.function) @definition.method))
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_definition
|
||||||
|
name: (identifier) @name.definition.function) @definition.function)
|
||||||
|
|
||||||
|
;; Contract, struct, enum and interface declarations
|
||||||
|
(contract_declaration
|
||||||
|
name: (identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(interface_declaration
|
||||||
|
name: (identifier) @name.definition.interface) @definition.interface
|
||||||
|
|
||||||
|
(library_declaration
|
||||||
|
name: (identifier) @name.definition.class) @definition.interface
|
||||||
|
|
||||||
|
(struct_declaration name: (identifier) @name.definition.class) @definition.class
|
||||||
|
(enum_declaration name: (identifier) @name.definition.class) @definition.class
|
||||||
|
(event_definition name: (identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
;; Function calls
|
||||||
|
(call_expression (expression (identifier)) @name.reference.call ) @reference.call
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
(expression (member_expression
|
||||||
|
property: (_) @name.reference.method ))) @reference.call
|
||||||
|
|
||||||
|
;; Log emit
|
||||||
|
(emit_statement name: (_) @name.reference.class) @reference.class
|
||||||
|
|
||||||
|
|
||||||
|
;; Inheritance
|
||||||
|
|
||||||
|
(inheritance_specifier
|
||||||
|
ancestor: (user_defined_type (_) @name.reference.class . )) @reference.class
|
||||||
|
|
||||||
|
|
||||||
|
;; Imports ( note that unknown is not standardised )
|
||||||
|
(import_directive
|
||||||
|
import_name: (_) @name.reference.module ) @reference.unknown
|
||||||
51
aider/queries/tree-sitter-language-pack/swift-tags.scm
Normal file
51
aider/queries/tree-sitter-language-pack/swift-tags.scm
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
(class_declaration
|
||||||
|
name: (type_identifier) @name.definition.class) @definition.class
|
||||||
|
|
||||||
|
(protocol_declaration
|
||||||
|
name: (type_identifier) @name.definition.interface) @definition.interface
|
||||||
|
|
||||||
|
(class_declaration
|
||||||
|
(class_body
|
||||||
|
[
|
||||||
|
(function_declaration
|
||||||
|
name: (simple_identifier) @name.definition.method
|
||||||
|
)
|
||||||
|
(subscript_declaration
|
||||||
|
(parameter (simple_identifier) @name.definition.method)
|
||||||
|
)
|
||||||
|
(init_declaration "init" @name.definition.method)
|
||||||
|
(deinit_declaration "deinit" @name.definition.method)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
) @definition.method
|
||||||
|
|
||||||
|
(protocol_declaration
|
||||||
|
(protocol_body
|
||||||
|
[
|
||||||
|
(protocol_function_declaration
|
||||||
|
name: (simple_identifier) @name.definition.method
|
||||||
|
)
|
||||||
|
(subscript_declaration
|
||||||
|
(parameter (simple_identifier) @name.definition.method)
|
||||||
|
)
|
||||||
|
(init_declaration "init" @name.definition.method)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
) @definition.method
|
||||||
|
|
||||||
|
(class_declaration
|
||||||
|
(class_body
|
||||||
|
[
|
||||||
|
(property_declaration
|
||||||
|
(pattern (simple_identifier) @name.definition.property)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
) @definition.property
|
||||||
|
|
||||||
|
(property_declaration
|
||||||
|
(pattern (simple_identifier) @name.definition.property)
|
||||||
|
) @definition.property
|
||||||
|
|
||||||
|
(function_declaration
|
||||||
|
name: (simple_identifier) @name.definition.function) @definition.function
|
||||||
20
aider/queries/tree-sitter-language-pack/udev-tags.scm
Normal file
20
aider/queries/tree-sitter-language-pack/udev-tags.scm
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
(assignment
|
||||||
|
key: "LABEL"
|
||||||
|
(value
|
||||||
|
(content) @name.definition.label)) @definition.label
|
||||||
|
|
||||||
|
(assignment
|
||||||
|
key: "GOTO"
|
||||||
|
(value
|
||||||
|
(content) @name.reference.label)) @reference.label
|
||||||
|
|
||||||
|
(assignment
|
||||||
|
key: "ENV"
|
||||||
|
(env_var) @name.definition.variable) @definition.variable
|
||||||
|
|
||||||
|
(match
|
||||||
|
key: "ENV"
|
||||||
|
(env_var) @name.reference.variable) @reference.variable
|
||||||
|
|
||||||
|
(var_sub
|
||||||
|
(env_var) @name.reference.variable) @reference.variable
|
||||||
9
aider/queries/tree-sitter-languages/c-tags.scm
Normal file
9
aider/queries/tree-sitter-languages/c-tags.scm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
(struct_specifier name: (type_identifier) @name.definition.class body:(_)) @definition.class
|
||||||
|
|
||||||
|
(declaration type: (union_specifier name: (type_identifier) @name.definition.class)) @definition.class
|
||||||
|
|
||||||
|
(function_declarator declarator: (identifier) @name.definition.function) @definition.function
|
||||||
|
|
||||||
|
(type_definition declarator: (type_identifier) @name.definition.type) @definition.type
|
||||||
|
|
||||||
|
(enum_specifier name: (type_identifier) @name.definition.type) @definition.type
|
||||||
77
aider/queries/tree-sitter-languages/hcl-tags.scm
Normal file
77
aider/queries/tree-sitter-languages/hcl-tags.scm
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
;; Based on https://github.com/tree-sitter-grammars/tree-sitter-hcl/blob/main/make_grammar.js
|
||||||
|
;; Which has Apache 2.0 License
|
||||||
|
;; tags.scm for Terraform (tree-sitter-hcl)
|
||||||
|
|
||||||
|
; === Definitions: Terraform Blocks ===
|
||||||
|
(block
|
||||||
|
(identifier) @block_type
|
||||||
|
(string_lit (template_literal) @resource_type)
|
||||||
|
(string_lit (template_literal) @name.definition.resource)
|
||||||
|
(body) @definition.resource
|
||||||
|
) (#eq? @block_type "resource")
|
||||||
|
|
||||||
|
(block
|
||||||
|
(identifier) @block_type
|
||||||
|
(string_lit (template_literal) @name.definition.module)
|
||||||
|
(body) @definition.module
|
||||||
|
) (#eq? @block_type "module")
|
||||||
|
|
||||||
|
(block
|
||||||
|
(identifier) @block_type
|
||||||
|
(string_lit (template_literal) @name.definition.variable)
|
||||||
|
(body) @definition.variable
|
||||||
|
) (#eq? @block_type "variable")
|
||||||
|
|
||||||
|
(block
|
||||||
|
(identifier) @block_type
|
||||||
|
(string_lit (template_literal) @name.definition.output)
|
||||||
|
(body) @definition.output
|
||||||
|
) (#eq? @block_type "output")
|
||||||
|
|
||||||
|
(block
|
||||||
|
(identifier) @block_type
|
||||||
|
(string_lit (template_literal) @name.definition.provider)
|
||||||
|
(body) @definition.provider
|
||||||
|
) (#eq? @block_type "provider")
|
||||||
|
|
||||||
|
(block
|
||||||
|
(identifier) @block_type
|
||||||
|
(body
|
||||||
|
(attribute
|
||||||
|
(identifier) @name.definition.local
|
||||||
|
(expression) @definition.local
|
||||||
|
)+
|
||||||
|
)
|
||||||
|
) (#eq? @block_type "locals")
|
||||||
|
|
||||||
|
; === References: Variables, Locals, Modules, Data, Resources ===
|
||||||
|
((variable_expr) @ref_type
|
||||||
|
(get_attr (identifier) @name.reference.variable)
|
||||||
|
) @reference.variable
|
||||||
|
(#eq? @ref_type "var")
|
||||||
|
|
||||||
|
((variable_expr) @ref_type
|
||||||
|
(get_attr (identifier) @name.reference.local)
|
||||||
|
) @reference.local
|
||||||
|
(#eq? @ref_type "local")
|
||||||
|
|
||||||
|
((variable_expr) @ref_type
|
||||||
|
(get_attr (identifier) @name.reference.module)
|
||||||
|
) @reference.module
|
||||||
|
(#eq? @ref_type "module")
|
||||||
|
|
||||||
|
((variable_expr) @ref_type
|
||||||
|
(get_attr (identifier) @data_source_type)
|
||||||
|
(get_attr (identifier) @name.reference.data)
|
||||||
|
) @reference.data
|
||||||
|
(#eq? @ref_type "data")
|
||||||
|
|
||||||
|
((variable_expr) @resource_type
|
||||||
|
(get_attr (identifier) @name.reference.resource)
|
||||||
|
) @reference.resource
|
||||||
|
(#not-eq? @resource_type "var")
|
||||||
|
(#not-eq? @resource_type "local")
|
||||||
|
(#not-eq? @resource_type "module")
|
||||||
|
(#not-eq? @resource_type "data")
|
||||||
|
(#not-eq? @resource_type "provider")
|
||||||
|
(#not-eq? @resource_type "output")
|
||||||
64
aider/queries/tree-sitter-languages/ruby-tags.scm
Normal file
64
aider/queries/tree-sitter-languages/ruby-tags.scm
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
; Method definitions
|
||||||
|
|
||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
[
|
||||||
|
(method
|
||||||
|
name: (_) @name.definition.method) @definition.method
|
||||||
|
(singleton_method
|
||||||
|
name: (_) @name.definition.method) @definition.method
|
||||||
|
]
|
||||||
|
(#strip! @doc "^#\\s*")
|
||||||
|
(#select-adjacent! @doc @definition.method)
|
||||||
|
)
|
||||||
|
|
||||||
|
(alias
|
||||||
|
name: (_) @name.definition.method) @definition.method
|
||||||
|
|
||||||
|
(setter
|
||||||
|
(identifier) @ignore)
|
||||||
|
|
||||||
|
; Class definitions
|
||||||
|
|
||||||
|
(
|
||||||
|
(comment)* @doc
|
||||||
|
.
|
||||||
|
[
|
||||||
|
(class
|
||||||
|
name: [
|
||||||
|
(constant) @name.definition.class
|
||||||
|
(scope_resolution
|
||||||
|
name: (_) @name.definition.class)
|
||||||
|
]) @definition.class
|
||||||
|
(singleton_class
|
||||||
|
value: [
|
||||||
|
(constant) @name.definition.class
|
||||||
|
(scope_resolution
|
||||||
|
name: (_) @name.definition.class)
|
||||||
|
]) @definition.class
|
||||||
|
]
|
||||||
|
(#strip! @doc "^#\\s*")
|
||||||
|
(#select-adjacent! @doc @definition.class)
|
||||||
|
)
|
||||||
|
|
||||||
|
; Module definitions
|
||||||
|
|
||||||
|
(
|
||||||
|
(module
|
||||||
|
name: [
|
||||||
|
(constant) @name.definition.module
|
||||||
|
(scope_resolution
|
||||||
|
name: (_) @name.definition.module)
|
||||||
|
]) @definition.module
|
||||||
|
)
|
||||||
|
|
||||||
|
; Calls
|
||||||
|
|
||||||
|
(call method: (identifier) @name.reference.call) @reference.call
|
||||||
|
|
||||||
|
(
|
||||||
|
[(identifier) (constant)] @name.reference.call @reference.call
|
||||||
|
(#is-not? local)
|
||||||
|
(#not-match? @name.reference.call "^(lambda|load|require|require_relative|__FILE__|__LINE__)$")
|
||||||
|
)
|
||||||
82
aider/reasoning_tags.py
Normal file
82
aider/reasoning_tags.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from aider.dump import dump # noqa
|
||||||
|
|
||||||
|
# Standard tag identifier
|
||||||
|
REASONING_TAG = "thinking-content-" + "7bbeb8e1441453ad999a0bbba8a46d4b"
|
||||||
|
# Output formatting
|
||||||
|
REASONING_START = "--------------\n► **THINKING**"
|
||||||
|
REASONING_END = "------------\n► **ANSWER**"
|
||||||
|
|
||||||
|
|
||||||
|
def remove_reasoning_content(res, reasoning_tag):
|
||||||
|
"""
|
||||||
|
Remove reasoning content from text based on tags.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
res (str): The text to process
|
||||||
|
reasoning_tag (str): The tag name to remove
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Text with reasoning content removed
|
||||||
|
"""
|
||||||
|
if not reasoning_tag:
|
||||||
|
return res
|
||||||
|
|
||||||
|
# Try to match the complete tag pattern first
|
||||||
|
pattern = f"<{reasoning_tag}>.*?</{reasoning_tag}>"
|
||||||
|
res = re.sub(pattern, "", res, flags=re.DOTALL).strip()
|
||||||
|
|
||||||
|
# If closing tag exists but opening tag might be missing, remove everything before closing
|
||||||
|
# tag
|
||||||
|
closing_tag = f"</{reasoning_tag}>"
|
||||||
|
if closing_tag in res:
|
||||||
|
# Split on the closing tag and keep everything after it
|
||||||
|
parts = res.split(closing_tag, 1)
|
||||||
|
res = parts[1].strip() if len(parts) > 1 else res
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def replace_reasoning_tags(text, tag_name):
|
||||||
|
"""
|
||||||
|
Replace opening and closing reasoning tags with standard formatting.
|
||||||
|
Ensures exactly one blank line before START and END markers.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text (str): The text containing the tags
|
||||||
|
tag_name (str): The name of the tag to replace
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Text with reasoning tags replaced with standard format
|
||||||
|
"""
|
||||||
|
if not text:
|
||||||
|
return text
|
||||||
|
|
||||||
|
# Replace opening tag with proper spacing
|
||||||
|
text = re.sub(f"\\s*<{tag_name}>\\s*", f"\n{REASONING_START}\n\n", text)
|
||||||
|
|
||||||
|
# Replace closing tag with proper spacing
|
||||||
|
text = re.sub(f"\\s*</{tag_name}>\\s*", f"\n\n{REASONING_END}\n\n", text)
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def format_reasoning_content(reasoning_content, tag_name):
|
||||||
|
"""
|
||||||
|
Format reasoning content with appropriate tags.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
reasoning_content (str): The content to format
|
||||||
|
tag_name (str): The tag name to use
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Formatted reasoning content with tags
|
||||||
|
"""
|
||||||
|
if not reasoning_content:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
formatted = f"<{tag_name}>\n\n{reasoning_content}\n\n</{tag_name}>"
|
||||||
|
return formatted
|
||||||
@@ -17,7 +17,6 @@ except ImportError:
|
|||||||
import pathspec
|
import pathspec
|
||||||
|
|
||||||
from aider import prompts, utils
|
from aider import prompts, utils
|
||||||
from aider.sendchat import simple_send_with_retries
|
|
||||||
|
|
||||||
from .dump import dump # noqa: F401
|
from .dump import dump # noqa: F401
|
||||||
|
|
||||||
@@ -29,6 +28,7 @@ ANY_GIT_ERROR += [
|
|||||||
ValueError,
|
ValueError,
|
||||||
AttributeError,
|
AttributeError,
|
||||||
AssertionError,
|
AssertionError,
|
||||||
|
TimeoutError,
|
||||||
]
|
]
|
||||||
ANY_GIT_ERROR = tuple(ANY_GIT_ERROR)
|
ANY_GIT_ERROR = tuple(ANY_GIT_ERROR)
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ class GitRepo:
|
|||||||
else:
|
else:
|
||||||
cmd += ["-a"]
|
cmd += ["-a"]
|
||||||
|
|
||||||
original_user_name = self.repo.config_reader().get_value("user", "name")
|
original_user_name = self.repo.git.config("--get", "user.name")
|
||||||
original_committer_name_env = os.environ.get("GIT_COMMITTER_NAME")
|
original_committer_name_env = os.environ.get("GIT_COMMITTER_NAME")
|
||||||
committer_name = f"{original_user_name} (aider)"
|
committer_name = f"{original_user_name} (aider)"
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ class GitRepo:
|
|||||||
os.environ["GIT_COMMITTER_NAME"] = committer_name
|
os.environ["GIT_COMMITTER_NAME"] = committer_name
|
||||||
|
|
||||||
if aider_edits and self.attribute_author:
|
if aider_edits and self.attribute_author:
|
||||||
original_auther_name_env = os.environ.get("GIT_AUTHOR_NAME")
|
original_author_name_env = os.environ.get("GIT_AUTHOR_NAME")
|
||||||
os.environ["GIT_AUTHOR_NAME"] = committer_name
|
os.environ["GIT_AUTHOR_NAME"] = committer_name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -173,8 +173,8 @@ class GitRepo:
|
|||||||
del os.environ["GIT_COMMITTER_NAME"]
|
del os.environ["GIT_COMMITTER_NAME"]
|
||||||
|
|
||||||
if aider_edits and self.attribute_author:
|
if aider_edits and self.attribute_author:
|
||||||
if original_auther_name_env is not None:
|
if original_author_name_env is not None:
|
||||||
os.environ["GIT_AUTHOR_NAME"] = original_auther_name_env
|
os.environ["GIT_AUTHOR_NAME"] = original_author_name_env
|
||||||
else:
|
else:
|
||||||
del os.environ["GIT_AUTHOR_NAME"]
|
del os.environ["GIT_AUTHOR_NAME"]
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ class GitRepo:
|
|||||||
max_tokens = model.info.get("max_input_tokens") or 0
|
max_tokens = model.info.get("max_input_tokens") or 0
|
||||||
if max_tokens and num_tokens > max_tokens:
|
if max_tokens and num_tokens > max_tokens:
|
||||||
continue
|
continue
|
||||||
commit_message = simple_send_with_retries(model, messages)
|
commit_message = model.simple_send_with_retries(messages)
|
||||||
if commit_message:
|
if commit_message:
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -309,8 +309,11 @@ class GitRepo:
|
|||||||
|
|
||||||
# Add staged files
|
# Add staged files
|
||||||
index = self.repo.index
|
index = self.repo.index
|
||||||
staged_files = [path for path, _ in index.entries.keys()]
|
try:
|
||||||
files.update(self.normalize_path(path) for path in staged_files)
|
staged_files = [path for path, _ in index.entries.keys()]
|
||||||
|
files.update(self.normalize_path(path) for path in staged_files)
|
||||||
|
except ANY_GIT_ERROR as err:
|
||||||
|
self.io.tool_error(f"Unable to read staged files: {err}")
|
||||||
|
|
||||||
res = [fname for fname in files if not self.ignored_file(fname)]
|
res = [fname for fname in files if not self.ignored_file(fname)]
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from aider.utils import Spinner
|
|||||||
|
|
||||||
# tree_sitter is throwing a FutureWarning
|
# tree_sitter is throwing a FutureWarning
|
||||||
warnings.simplefilter("ignore", category=FutureWarning)
|
warnings.simplefilter("ignore", category=FutureWarning)
|
||||||
from tree_sitter_languages import get_language, get_parser # noqa: E402
|
from grep_ast.tsl import USING_TSL_PACK, get_language, get_parser # noqa: E402
|
||||||
|
|
||||||
Tag = namedtuple("Tag", "rel_fname fname line name kind".split())
|
Tag = namedtuple("Tag", "rel_fname fname line name kind".split())
|
||||||
|
|
||||||
@@ -31,8 +31,12 @@ Tag = namedtuple("Tag", "rel_fname fname line name kind".split())
|
|||||||
SQLITE_ERRORS = (sqlite3.OperationalError, sqlite3.DatabaseError, OSError)
|
SQLITE_ERRORS = (sqlite3.OperationalError, sqlite3.DatabaseError, OSError)
|
||||||
|
|
||||||
|
|
||||||
|
CACHE_VERSION = 3
|
||||||
|
if USING_TSL_PACK:
|
||||||
|
CACHE_VERSION = 4
|
||||||
|
|
||||||
|
|
||||||
class RepoMap:
|
class RepoMap:
|
||||||
CACHE_VERSION = 3
|
|
||||||
TAGS_CACHE_DIR = f".aider.tags.cache.v{CACHE_VERSION}"
|
TAGS_CACHE_DIR = f".aider.tags.cache.v{CACHE_VERSION}"
|
||||||
|
|
||||||
warned_files = set()
|
warned_files = set()
|
||||||
@@ -282,10 +286,15 @@ class RepoMap:
|
|||||||
query = language.query(query_scm)
|
query = language.query(query_scm)
|
||||||
captures = query.captures(tree.root_node)
|
captures = query.captures(tree.root_node)
|
||||||
|
|
||||||
captures = list(captures)
|
|
||||||
|
|
||||||
saw = set()
|
saw = set()
|
||||||
for node, tag in captures:
|
if USING_TSL_PACK:
|
||||||
|
all_nodes = []
|
||||||
|
for tag, nodes in captures.items():
|
||||||
|
all_nodes += [(node, tag) for node in nodes]
|
||||||
|
else:
|
||||||
|
all_nodes = list(captures)
|
||||||
|
|
||||||
|
for node, tag in all_nodes:
|
||||||
if tag.startswith("name.definition."):
|
if tag.startswith("name.definition."):
|
||||||
kind = "def"
|
kind = "def"
|
||||||
elif tag.startswith("name.reference."):
|
elif tag.startswith("name.reference."):
|
||||||
@@ -422,6 +431,15 @@ class RepoMap:
|
|||||||
|
|
||||||
G = nx.MultiDiGraph()
|
G = nx.MultiDiGraph()
|
||||||
|
|
||||||
|
# Add a small self-edge for every definition that has no references
|
||||||
|
# Helps with tree-sitter 0.23.2 with ruby, where "def greet(name)"
|
||||||
|
# isn't counted as a def AND a ref. tree-sitter 0.24.0 does.
|
||||||
|
for ident in defines.keys():
|
||||||
|
if ident in references:
|
||||||
|
continue
|
||||||
|
for definer in defines[ident]:
|
||||||
|
G.add_edge(definer, definer, weight=0.1, ident=ident)
|
||||||
|
|
||||||
for ident in idents:
|
for ident in idents:
|
||||||
if progress:
|
if progress:
|
||||||
progress()
|
progress()
|
||||||
@@ -732,8 +750,27 @@ def get_random_color():
|
|||||||
|
|
||||||
def get_scm_fname(lang):
|
def get_scm_fname(lang):
|
||||||
# Load the tags queries
|
# Load the tags queries
|
||||||
|
if USING_TSL_PACK:
|
||||||
|
subdir = "tree-sitter-language-pack"
|
||||||
|
try:
|
||||||
|
path = resources.files(__package__).joinpath(
|
||||||
|
"queries",
|
||||||
|
subdir,
|
||||||
|
f"{lang}-tags.scm",
|
||||||
|
)
|
||||||
|
if path.exists():
|
||||||
|
return path
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Fall back to tree-sitter-languages
|
||||||
|
subdir = "tree-sitter-languages"
|
||||||
try:
|
try:
|
||||||
return resources.files(__package__).joinpath("queries", f"tree-sitter-{lang}-tags.scm")
|
return resources.files(__package__).joinpath(
|
||||||
|
"queries",
|
||||||
|
subdir,
|
||||||
|
f"{lang}-tags.scm",
|
||||||
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,22 @@
|
|||||||
//"supports_tool_choice": true,
|
//"supports_tool_choice": true,
|
||||||
"supports_prompt_caching": true
|
"supports_prompt_caching": true
|
||||||
},
|
},
|
||||||
|
"openrouter/deepseek/deepseek-chat:free": {
|
||||||
|
"max_tokens": 8192,
|
||||||
|
"max_input_tokens": 64000,
|
||||||
|
"max_output_tokens": 8192,
|
||||||
|
"input_cost_per_token": 0.0,
|
||||||
|
"input_cost_per_token_cache_hit": 0.0,
|
||||||
|
"cache_read_input_token_cost": 0.00,
|
||||||
|
"cache_creation_input_token_cost": 0.0,
|
||||||
|
"output_cost_per_token": 0.0,
|
||||||
|
"litellm_provider": "openrouter",
|
||||||
|
"mode": "chat",
|
||||||
|
//"supports_function_calling": true,
|
||||||
|
"supports_assistant_prefill": true,
|
||||||
|
//"supports_tool_choice": true,
|
||||||
|
"supports_prompt_caching": true
|
||||||
|
},
|
||||||
"fireworks_ai/accounts/fireworks/models/deepseek-r1": {
|
"fireworks_ai/accounts/fireworks/models/deepseek-r1": {
|
||||||
"max_tokens": 160000,
|
"max_tokens": 160000,
|
||||||
"max_input_tokens": 128000,
|
"max_input_tokens": 128000,
|
||||||
@@ -81,4 +97,148 @@
|
|||||||
"supports_system_messages": true,
|
"supports_system_messages": true,
|
||||||
"supports_response_schema": true
|
"supports_response_schema": true
|
||||||
},
|
},
|
||||||
|
"openrouter/openai/o3-mini": {
|
||||||
|
"max_tokens": 100000,
|
||||||
|
"max_input_tokens": 200000,
|
||||||
|
"max_output_tokens": 100000,
|
||||||
|
"input_cost_per_token": 0.0000011,
|
||||||
|
"output_cost_per_token": 0.0000044,
|
||||||
|
"cache_read_input_token_cost": 0.00000055,
|
||||||
|
"litellm_provider": "openrouter",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_parallel_function_calling": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_system_messages": true,
|
||||||
|
"supports_response_schema": true
|
||||||
|
},
|
||||||
|
"openrouter/openai/o3-mini-high": {
|
||||||
|
"max_tokens": 100000,
|
||||||
|
"max_input_tokens": 200000,
|
||||||
|
"max_output_tokens": 100000,
|
||||||
|
"input_cost_per_token": 0.0000011,
|
||||||
|
"output_cost_per_token": 0.0000044,
|
||||||
|
"cache_read_input_token_cost": 0.00000055,
|
||||||
|
"litellm_provider": "openrouter",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_parallel_function_calling": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_system_messages": true,
|
||||||
|
"supports_response_schema": true
|
||||||
|
},
|
||||||
|
"openrouter/openai/gpt-4o-mini": {
|
||||||
|
"max_tokens": 16384,
|
||||||
|
"max_input_tokens": 128000,
|
||||||
|
"max_output_tokens": 16384,
|
||||||
|
"input_cost_per_token": 0.00000015,
|
||||||
|
"output_cost_per_token": 0.00000060,
|
||||||
|
"input_cost_per_token_batches": 0.000000075,
|
||||||
|
"output_cost_per_token_batches": 0.00000030,
|
||||||
|
"cache_read_input_token_cost": 0.000000075,
|
||||||
|
"litellm_provider": "openrouter",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_parallel_function_calling": true,
|
||||||
|
"supports_response_schema": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_system_messages": true
|
||||||
|
},
|
||||||
|
"claude-3-7-sonnet-20250219": {
|
||||||
|
"max_tokens": 8192,
|
||||||
|
"max_input_tokens": 200000,
|
||||||
|
"max_output_tokens": 8192,
|
||||||
|
"input_cost_per_token": 0.000003,
|
||||||
|
"output_cost_per_token": 0.000015,
|
||||||
|
"cache_creation_input_token_cost": 0.00000375,
|
||||||
|
"cache_read_input_token_cost": 0.0000003,
|
||||||
|
"litellm_provider": "anthropic",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"tool_use_system_prompt_tokens": 159,
|
||||||
|
"supports_assistant_prefill": true,
|
||||||
|
"supports_pdf_input": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_response_schema": true,
|
||||||
|
"deprecation_date": "2025-10-01",
|
||||||
|
"supports_tool_choice": true
|
||||||
|
},
|
||||||
|
"anthropic/claude-3-7-sonnet-20250219": {
|
||||||
|
"max_tokens": 8192,
|
||||||
|
"max_input_tokens": 200000,
|
||||||
|
"max_output_tokens": 8192,
|
||||||
|
"input_cost_per_token": 0.000003,
|
||||||
|
"output_cost_per_token": 0.000015,
|
||||||
|
"cache_creation_input_token_cost": 0.00000375,
|
||||||
|
"cache_read_input_token_cost": 0.0000003,
|
||||||
|
"litellm_provider": "anthropic",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"tool_use_system_prompt_tokens": 159,
|
||||||
|
"supports_assistant_prefill": true,
|
||||||
|
"supports_pdf_input": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_response_schema": true,
|
||||||
|
"deprecation_date": "2025-10-01",
|
||||||
|
"supports_tool_choice": true
|
||||||
|
},
|
||||||
|
"openrouter/anthropic/claude-3.7-sonnet": {
|
||||||
|
"max_tokens": 8192,
|
||||||
|
"max_input_tokens": 200000,
|
||||||
|
"max_output_tokens": 8192,
|
||||||
|
"input_cost_per_token": 0.000003,
|
||||||
|
"output_cost_per_token": 0.000015,
|
||||||
|
"cache_creation_input_token_cost": 0.00000375,
|
||||||
|
"cache_read_input_token_cost": 0.0000003,
|
||||||
|
"litellm_provider": "openrouter",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"tool_use_system_prompt_tokens": 159,
|
||||||
|
"supports_assistant_prefill": true,
|
||||||
|
"supports_pdf_input": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_response_schema": true,
|
||||||
|
"deprecation_date": "2025-10-01",
|
||||||
|
"supports_tool_choice": true
|
||||||
|
},
|
||||||
|
"gpt-4.5-preview": {
|
||||||
|
"max_tokens": 16384,
|
||||||
|
"max_input_tokens": 128000,
|
||||||
|
"max_output_tokens": 16384,
|
||||||
|
"input_cost_per_token": 0.000075,
|
||||||
|
"output_cost_per_token": 0.00015,
|
||||||
|
"cache_read_input_token_cost": 0.0000375,
|
||||||
|
"litellm_provider": "openai",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_parallel_function_calling": true,
|
||||||
|
"supports_response_schema": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_system_messages": true,
|
||||||
|
"supports_tool_choice": true
|
||||||
|
},
|
||||||
|
"openai/gpt-4.5-preview": {
|
||||||
|
"max_tokens": 16384,
|
||||||
|
"max_input_tokens": 128000,
|
||||||
|
"max_output_tokens": 16384,
|
||||||
|
"input_cost_per_token": 0.000075,
|
||||||
|
"output_cost_per_token": 0.00015,
|
||||||
|
"cache_read_input_token_cost": 0.0000375,
|
||||||
|
"litellm_provider": "openai",
|
||||||
|
"mode": "chat",
|
||||||
|
"supports_function_calling": true,
|
||||||
|
"supports_parallel_function_calling": true,
|
||||||
|
"supports_response_schema": true,
|
||||||
|
"supports_vision": true,
|
||||||
|
"supports_prompt_caching": true,
|
||||||
|
"supports_system_messages": true,
|
||||||
|
"supports_tool_choice": true
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,156 @@
|
|||||||
editor_model_name: anthropic/claude-3-5-sonnet-20241022
|
editor_model_name: anthropic/claude-3-5-sonnet-20241022
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: anthropic/claude-3-7-sonnet-20250219
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: anthropic/claude-3-5-haiku-20241022
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: anthropic/claude-3-7-sonnet-20250219
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: anthropic/claude-3-7-sonnet-latest
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: anthropic/claude-3-5-haiku-20241022
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: anthropic/claude-3-7-sonnet-latest
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: claude-3-7-sonnet-20250219
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: claude-3-5-haiku-20241022
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: claude-3-7-sonnet-20250219
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: claude-3-7-sonnet-latest
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: claude-3-5-haiku-20241022
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: claude-3-7-sonnet-latest
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: bedrock_converse/anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: bedrock_converse/anthropic.claude-3-5-haiku-20241022-v1:0
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: bedrock_converse/anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: bedrock_converse/us.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: bedrock_converse/us.anthropic.claude-3-5-haiku-20241022-v1:0
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: bedrock_converse/us.anthropic.claude-3-7-sonnet-20250219-v1:0
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: vertex_ai/claude-3-7-sonnet@20250219
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
max_tokens: 64000
|
||||||
|
editor_model_name: vertex_ai/claude-3-7-sonnet@20250219
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: vertex_ai-anthropic_models/vertex_ai/claude-3-7-sonnet@20250219
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: vertex_ai/claude-3-5-haiku@20241022
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
max_tokens: 64000
|
||||||
|
editor_model_name: vertex_ai-anthropic_models/vertex_ai/claude-3-7-sonnet@20250219
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: openrouter/anthropic/claude-3.7-sonnet
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: openrouter/anthropic/claude-3-5-haiku
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: openrouter/anthropic/claude-3.7-sonnet
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: openrouter/anthropic/claude-3.7-sonnet:beta
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: openrouter/anthropic/claude-3-5-haiku
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
extra_headers:
|
||||||
|
anthropic-beta: prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
|
||||||
|
max_tokens: 64000
|
||||||
|
cache_control: true
|
||||||
|
editor_model_name: openrouter/anthropic/claude-3.7-sonnet
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
- name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0
|
- name: bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
|
weak_model_name: bedrock/anthropic.claude-3-5-haiku-20241022-v1:0
|
||||||
@@ -386,6 +536,10 @@
|
|||||||
edit_format: diff
|
edit_format: diff
|
||||||
use_repo_map: true
|
use_repo_map: true
|
||||||
|
|
||||||
|
- name: gemini/gemini-2.0-flash
|
||||||
|
edit_format: diff
|
||||||
|
use_repo_map: true
|
||||||
|
|
||||||
- name: openrouter/deepseek/deepseek-r1
|
- name: openrouter/deepseek/deepseek-r1
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
weak_model_name: openrouter/deepseek/deepseek-chat
|
weak_model_name: openrouter/deepseek/deepseek-chat
|
||||||
@@ -393,21 +547,21 @@
|
|||||||
examples_as_sys_msg: true
|
examples_as_sys_msg: true
|
||||||
extra_params:
|
extra_params:
|
||||||
max_tokens: 8192
|
max_tokens: 8192
|
||||||
|
include_reasoning: true
|
||||||
caches_by_default: true
|
caches_by_default: true
|
||||||
use_temperature: false
|
|
||||||
editor_model_name: openrouter/deepseek/deepseek-chat
|
editor_model_name: openrouter/deepseek/deepseek-chat
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
- name: openrouter/deepseek/deepseek-r1:free
|
- name: openrouter/deepseek/deepseek-r1:free
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
weak_model_name: openrouter/deepseek/deepseek-chat:free
|
weak_model_name: openrouter/deepseek/deepseek-r1:free
|
||||||
use_repo_map: true
|
use_repo_map: true
|
||||||
examples_as_sys_msg: true
|
examples_as_sys_msg: true
|
||||||
extra_params:
|
extra_params:
|
||||||
max_tokens: 8192
|
max_tokens: 8192
|
||||||
caches_by_default: true
|
caches_by_default: true
|
||||||
use_temperature: false
|
use_temperature: false
|
||||||
editor_model_name: openrouter/deepseek/deepseek-chat:free
|
editor_model_name: openrouter/deepseek/deepseek-r1:free
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
- name: deepseek/deepseek-reasoner
|
- name: deepseek/deepseek-reasoner
|
||||||
@@ -431,6 +585,18 @@
|
|||||||
max_tokens: 8192
|
max_tokens: 8192
|
||||||
caches_by_default: true
|
caches_by_default: true
|
||||||
|
|
||||||
|
- name: openrouter/deepseek/deepseek-chat:free
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: openrouter/deepseek/deepseek-chat:free
|
||||||
|
use_repo_map: true
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
extra_params:
|
||||||
|
max_tokens: 8192
|
||||||
|
caches_by_default: true
|
||||||
|
use_temperature: false
|
||||||
|
editor_model_name: openrouter/deepseek/deepseek-chat:free
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
- name: deepseek/deepseek-coder
|
- name: deepseek/deepseek-coder
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
use_repo_map: true
|
use_repo_map: true
|
||||||
@@ -565,6 +731,7 @@
|
|||||||
streaming: false
|
streaming: false
|
||||||
editor_model_name: openrouter/openai/gpt-4o
|
editor_model_name: openrouter/openai/gpt-4o
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
- name: openai/o1
|
- name: openai/o1
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
@@ -574,6 +741,7 @@
|
|||||||
streaming: false
|
streaming: false
|
||||||
editor_model_name: openai/gpt-4o
|
editor_model_name: openai/gpt-4o
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
- name: o1
|
- name: o1
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
@@ -583,6 +751,7 @@
|
|||||||
streaming: false
|
streaming: false
|
||||||
editor_model_name: gpt-4o
|
editor_model_name: gpt-4o
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
- name: openrouter/qwen/qwen-2.5-coder-32b-instruct
|
- name: openrouter/qwen/qwen-2.5-coder-32b-instruct
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
@@ -611,7 +780,7 @@
|
|||||||
streaming: true
|
streaming: true
|
||||||
editor_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3
|
editor_model_name: fireworks_ai/accounts/fireworks/models/deepseek-v3
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
remove_reasoning: think
|
reasoning_tag: think
|
||||||
extra_params:
|
extra_params:
|
||||||
max_tokens: 160000
|
max_tokens: 160000
|
||||||
|
|
||||||
@@ -630,6 +799,7 @@
|
|||||||
use_temperature: false
|
use_temperature: false
|
||||||
editor_model_name: gpt-4o
|
editor_model_name: gpt-4o
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
- name: o3-mini
|
- name: o3-mini
|
||||||
edit_format: diff
|
edit_format: diff
|
||||||
@@ -638,4 +808,93 @@
|
|||||||
use_temperature: false
|
use_temperature: false
|
||||||
editor_model_name: gpt-4o
|
editor_model_name: gpt-4o
|
||||||
editor_edit_format: editor-diff
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
|
- name: openrouter/openai/o3-mini
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: openrouter/openai/gpt-4o-mini
|
||||||
|
use_repo_map: true
|
||||||
|
use_temperature: false
|
||||||
|
editor_model_name: openrouter/openai/gpt-4o
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
|
- name: openrouter/openai/o3-mini-high
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: openrouter/openai/gpt-4o-mini
|
||||||
|
use_repo_map: true
|
||||||
|
use_temperature: false
|
||||||
|
editor_model_name: openrouter/openai/gpt-4o
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
|
- name: azure/o3-mini
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: azure/gpt-4o-mini
|
||||||
|
use_repo_map: true
|
||||||
|
use_temperature: false
|
||||||
|
editor_model_name: azure/gpt-4o
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
system_prompt_prefix: "Formatting re-enabled. "
|
||||||
|
|
||||||
|
- name: gpt-4.5-preview
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: gpt-4o-mini
|
||||||
|
use_repo_map: true
|
||||||
|
lazy: true
|
||||||
|
reminder: sys
|
||||||
|
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
|
||||||
|
use_repo_map: true
|
||||||
|
lazy: true
|
||||||
|
reminder: sys
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
editor_model_name: openai/gpt-4o
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
|
||||||
|
- name: fireworks_ai/accounts/fireworks/models/qwq-32b
|
||||||
|
reasoning_tag: think
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct
|
||||||
|
use_repo_map: true
|
||||||
|
editor_model_name: fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
reminder: user
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
use_temperature: 0.6
|
||||||
|
extra_params:
|
||||||
|
max_tokens: 32000
|
||||||
|
top_p: 0.95
|
||||||
|
|
||||||
|
- name: groq/qwen-qwq-32b
|
||||||
|
reasoning_tag: think
|
||||||
|
edit_format: diff
|
||||||
|
weak_model_name: groq/qwen-2.5-coder-32b
|
||||||
|
use_repo_map: true
|
||||||
|
editor_model_name: groq/qwen-2.5-coder-32b
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
use_temperature: 0.6
|
||||||
|
extra_params:
|
||||||
|
max_tokens: 128000
|
||||||
|
top_p: 0.95
|
||||||
|
|
||||||
|
- name: cohere_chat/command-a-03-2025
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
|
||||||
|
- name: openrouter/cohere/command-a-03-2025
|
||||||
|
examples_as_sys_msg: true
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
@@ -1,22 +1,6 @@
|
|||||||
import hashlib
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
|
|
||||||
from aider.dump import dump # noqa: F401
|
from aider.dump import dump # noqa: F401
|
||||||
from aider.exceptions import LiteLLMExceptions
|
|
||||||
from aider.llm import litellm
|
|
||||||
from aider.utils import format_messages
|
from aider.utils import format_messages
|
||||||
|
|
||||||
# from diskcache import Cache
|
|
||||||
|
|
||||||
|
|
||||||
CACHE_PATH = "~/.aider.send.cache.v1"
|
|
||||||
CACHE = None
|
|
||||||
# CACHE = Cache(CACHE_PATH)
|
|
||||||
|
|
||||||
RETRY_TIMEOUT = 60
|
|
||||||
|
|
||||||
|
|
||||||
def sanity_check_messages(messages):
|
def sanity_check_messages(messages):
|
||||||
"""Check if messages alternate between user and assistant roles.
|
"""Check if messages alternate between user and assistant roles.
|
||||||
@@ -75,99 +59,3 @@ def ensure_alternating_roles(messages):
|
|||||||
prev_role = current_role
|
prev_role = current_role
|
||||||
|
|
||||||
return fixed_messages
|
return fixed_messages
|
||||||
|
|
||||||
|
|
||||||
def send_completion(
|
|
||||||
model_name,
|
|
||||||
messages,
|
|
||||||
functions,
|
|
||||||
stream,
|
|
||||||
temperature=0,
|
|
||||||
extra_params=None,
|
|
||||||
):
|
|
||||||
#
|
|
||||||
#
|
|
||||||
if os.environ.get("AIDER_SANITY_CHECK_TURNS"):
|
|
||||||
sanity_check_messages(messages)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
if "deepseek-reasoner" in model_name:
|
|
||||||
messages = ensure_alternating_roles(messages)
|
|
||||||
|
|
||||||
kwargs = dict(
|
|
||||||
model=model_name,
|
|
||||||
messages=messages,
|
|
||||||
stream=stream,
|
|
||||||
)
|
|
||||||
if temperature is not None:
|
|
||||||
kwargs["temperature"] = temperature
|
|
||||||
|
|
||||||
if functions is not None:
|
|
||||||
function = functions[0]
|
|
||||||
kwargs["tools"] = [dict(type="function", function=function)]
|
|
||||||
kwargs["tool_choice"] = {"type": "function", "function": {"name": function["name"]}}
|
|
||||||
|
|
||||||
if extra_params is not None:
|
|
||||||
kwargs.update(extra_params)
|
|
||||||
|
|
||||||
key = json.dumps(kwargs, sort_keys=True).encode()
|
|
||||||
# dump(kwargs)
|
|
||||||
|
|
||||||
# Generate SHA1 hash of kwargs and append it to chat_completion_call_hashes
|
|
||||||
hash_object = hashlib.sha1(key)
|
|
||||||
|
|
||||||
if not stream and CACHE is not None and key in CACHE:
|
|
||||||
return hash_object, CACHE[key]
|
|
||||||
|
|
||||||
res = litellm.completion(**kwargs)
|
|
||||||
|
|
||||||
if not stream and CACHE is not None:
|
|
||||||
CACHE[key] = res
|
|
||||||
|
|
||||||
return hash_object, res
|
|
||||||
|
|
||||||
|
|
||||||
def simple_send_with_retries(model, messages):
|
|
||||||
litellm_ex = LiteLLMExceptions()
|
|
||||||
|
|
||||||
if "deepseek-reasoner" in model.name:
|
|
||||||
messages = ensure_alternating_roles(messages)
|
|
||||||
|
|
||||||
retry_delay = 0.125
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
kwargs = {
|
|
||||||
"model_name": model.name,
|
|
||||||
"messages": messages,
|
|
||||||
"functions": None,
|
|
||||||
"stream": False,
|
|
||||||
"temperature": None if not model.use_temperature else 0,
|
|
||||||
"extra_params": model.extra_params,
|
|
||||||
}
|
|
||||||
|
|
||||||
_hash, response = send_completion(**kwargs)
|
|
||||||
if not response or not hasattr(response, "choices") or not response.choices:
|
|
||||||
return None
|
|
||||||
return response.choices[0].message.content
|
|
||||||
except litellm_ex.exceptions_tuple() as err:
|
|
||||||
ex_info = litellm_ex.get_ex_info(err)
|
|
||||||
|
|
||||||
print(str(err))
|
|
||||||
if ex_info.description:
|
|
||||||
print(ex_info.description)
|
|
||||||
|
|
||||||
should_retry = ex_info.retry
|
|
||||||
if should_retry:
|
|
||||||
retry_delay *= 2
|
|
||||||
if retry_delay > RETRY_TIMEOUT:
|
|
||||||
should_retry = False
|
|
||||||
|
|
||||||
if not should_retry:
|
|
||||||
return None
|
|
||||||
|
|
||||||
print(f"Retrying in {retry_delay:.1f} seconds...")
|
|
||||||
time.sleep(retry_delay)
|
|
||||||
continue
|
|
||||||
except AttributeError:
|
|
||||||
return None
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ ROOT_IMPORTANT_FILES = [
|
|||||||
"composer.lock",
|
"composer.lock",
|
||||||
"pom.xml",
|
"pom.xml",
|
||||||
"build.gradle",
|
"build.gradle",
|
||||||
|
"build.gradle.kts",
|
||||||
"build.sbt",
|
"build.sbt",
|
||||||
"go.mod",
|
"go.mod",
|
||||||
"go.sum",
|
"go.sum",
|
||||||
|
|||||||
@@ -95,7 +95,9 @@ class FileWatcher:
|
|||||||
if self.verbose:
|
if self.verbose:
|
||||||
dump(rel_path)
|
dump(rel_path)
|
||||||
|
|
||||||
if self.gitignore_spec and self.gitignore_spec.match_file(str(rel_path)):
|
if self.gitignore_spec and self.gitignore_spec.match_file(
|
||||||
|
rel_path.as_posix() + ("/" if path_abs.is_dir() else "")
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.verbose:
|
if self.verbose:
|
||||||
@@ -108,28 +110,55 @@ class FileWatcher:
|
|||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def get_roots_to_watch(self):
|
||||||
|
"""Determine which root paths to watch based on gitignore rules"""
|
||||||
|
if self.gitignore_spec:
|
||||||
|
roots = [
|
||||||
|
str(path)
|
||||||
|
for path in self.root.iterdir()
|
||||||
|
if not self.gitignore_spec.match_file(
|
||||||
|
path.relative_to(self.root).as_posix() + ("/" if path.is_dir() else "")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
# Fallback to watching root if all top-level items are filtered out
|
||||||
|
return roots if roots else [str(self.root)]
|
||||||
|
return [str(self.root)]
|
||||||
|
|
||||||
|
def handle_changes(self, changes):
|
||||||
|
"""Process the detected changes and update state"""
|
||||||
|
if not changes:
|
||||||
|
return False
|
||||||
|
|
||||||
|
changed_files = {str(Path(change[1])) for change in changes}
|
||||||
|
self.changed_files.update(changed_files)
|
||||||
|
self.io.interrupt_input()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def watch_files(self):
|
||||||
|
"""Watch for file changes and process them"""
|
||||||
|
try:
|
||||||
|
roots_to_watch = self.get_roots_to_watch()
|
||||||
|
|
||||||
|
for changes in watch(
|
||||||
|
*roots_to_watch,
|
||||||
|
watch_filter=self.filter_func,
|
||||||
|
stop_event=self.stop_event,
|
||||||
|
ignore_permission_denied=True,
|
||||||
|
):
|
||||||
|
if self.handle_changes(changes):
|
||||||
|
return
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if self.verbose:
|
||||||
|
dump(f"File watcher error: {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Start watching for file changes"""
|
"""Start watching for file changes"""
|
||||||
self.stop_event = threading.Event()
|
self.stop_event = threading.Event()
|
||||||
self.changed_files = set()
|
self.changed_files = set()
|
||||||
|
|
||||||
def watch_files():
|
self.watcher_thread = threading.Thread(target=self.watch_files, daemon=True)
|
||||||
try:
|
|
||||||
for changes in watch(
|
|
||||||
str(self.root), watch_filter=self.filter_func, stop_event=self.stop_event
|
|
||||||
):
|
|
||||||
if not changes:
|
|
||||||
continue
|
|
||||||
changed_files = {str(Path(change[1])) for change in changes}
|
|
||||||
self.changed_files.update(changed_files)
|
|
||||||
self.io.interrupt_input()
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
if self.verbose:
|
|
||||||
dump(f"File watcher error: {e}")
|
|
||||||
raise e
|
|
||||||
|
|
||||||
self.watcher_thread = threading.Thread(target=watch_files, daemon=True)
|
|
||||||
self.watcher_thread.start()
|
self.watcher_thread.start()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
|||||||
@@ -23,6 +23,124 @@ cog.out(text)
|
|||||||
]]]-->
|
]]]-->
|
||||||
|
|
||||||
|
|
||||||
|
### main branch
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
### Aider v0.77.0
|
||||||
|
|
||||||
|
- Big upgrade in [programming languages supported](https://aider.chat/docs/languages.html) by adopting [tree-sitter-language-pack](https://github.com/Goldziher/tree-sitter-language-pack/).
|
||||||
|
- 130 new languages with linter support.
|
||||||
|
- 20 new languages with repo-map support.
|
||||||
|
- Added `/think-tokens` command to set thinking token budget with support for human-readable formats (8k, 10.5k, 0.5M).
|
||||||
|
- Added `/reasoning-effort` command to control model reasoning level.
|
||||||
|
- The `/think-tokens` and `/reasoning-effort` commands display current settings when called without arguments.
|
||||||
|
- Display of thinking token budget and reasoning effort in model information.
|
||||||
|
- Changed `--thinking-tokens` argument to accept string values with human-readable formats.
|
||||||
|
- Added `--auto-accept-architect` flag (default: true) to automatically accept changes from architect coder format without confirmation.
|
||||||
|
- Added support for `cohere_chat/command-a-03-2025` and `gemini/gemma-3-27b-it`
|
||||||
|
- The bare `/drop` command now preserves original read-only files provided via args.read.
|
||||||
|
- Fixed a bug where default model would be set by deprecated `--shortcut` switches even when already specified in the command line.
|
||||||
|
- Improved AutoCompleter to require 3 characters for autocompletion to reduce noise.
|
||||||
|
- Aider wrote 72% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.76.2
|
||||||
|
|
||||||
|
- Fixed handling of JSONDecodeError when loading model cache file.
|
||||||
|
- Fixed handling of GitCommandError when retrieving git user configuration.
|
||||||
|
- Aider wrote 75% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.76.1
|
||||||
|
|
||||||
|
- Added ignore_permission_denied option to file watcher to prevent errors when accessing restricted files, by Yutaka Matsubara.
|
||||||
|
- Aider wrote 0% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.76.0
|
||||||
|
|
||||||
|
- Improved support for thinking/reasoningmodels:
|
||||||
|
- Added `--thinking-tokens` CLI option to control token budget for models that support thinking.
|
||||||
|
- Display thinking/reasoning content from LLMs which return it.
|
||||||
|
- Enhanced handling of reasoning tags to better clean up model responses.
|
||||||
|
- Added deprecation warning for `remove_reasoning` setting, now replaced by `reasoning_tag`.
|
||||||
|
- Aider will notify you when it's completed the last request and needs your input:
|
||||||
|
- Added [notifications when LLM responses are ready](https://aider.chat/docs/usage/notifications.html) with `--notifications` flag.
|
||||||
|
- Specify desktop notification command with `--notifications-command`.
|
||||||
|
- Added support for QWQ 32B.
|
||||||
|
- Switch to `tree-sitter-language-pack` for tree sitter support.
|
||||||
|
- Improved error handling for EOF (Ctrl+D) in user input prompts.
|
||||||
|
- Added helper function to ensure hex color values have a # prefix.
|
||||||
|
- Fixed handling of Git errors when reading staged files.
|
||||||
|
- Improved SSL verification control for model information requests.
|
||||||
|
- Improved empty LLM response handling with clearer warning messages.
|
||||||
|
- Fixed Git identity retrieval to respect global configuration, by Akira Komamura.
|
||||||
|
- Offer to install dependencies for Bedrock and Vertex AI models.
|
||||||
|
- Deprecated model shortcut args (like --4o, --opus) in favor of the --model flag.
|
||||||
|
- Aider wrote 85% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.75.3
|
||||||
|
|
||||||
|
- Support for V3 free on OpenRouter: `--model openrouter/deepseek/deepseek-chat:free`.
|
||||||
|
|
||||||
|
### Aider v0.75.2
|
||||||
|
|
||||||
|
- Added support for Claude 3.7 Sonnet models on OpenRouter, Bedrock and Vertex AI.
|
||||||
|
- Updated default model to Claude 3.7 Sonnet on OpenRouter.
|
||||||
|
- Added support for GPT-4.5-preview model.
|
||||||
|
- Added support for Claude 3.7 Sonnet:beta on OpenRouter.
|
||||||
|
- Fixed weak_model_name patterns to match main model name patterns for some models.
|
||||||
|
|
||||||
|
### Aider v0.75.1
|
||||||
|
|
||||||
|
- Added support for `openrouter/anthropic/claude-3.7-sonnet`
|
||||||
|
|
||||||
|
### Aider v0.75.0
|
||||||
|
|
||||||
|
- Basic support for Claude 3.7 Sonnet
|
||||||
|
- Use `--model sonnet` to use the new 3.7
|
||||||
|
- Thinking support coming soon.
|
||||||
|
- Bugfix to `/editor` command.
|
||||||
|
- Aider wrote 46% of the code in this release.
|
||||||
|
|
||||||
|
### Aider v0.74.3
|
||||||
|
|
||||||
|
- Downgrade streamlit dependency to avoid threading bug.
|
||||||
|
- Added support for tree-sitter language pack.
|
||||||
|
- Added openrouter/o3-mini-high model configuration.
|
||||||
|
- Added build.gradle.kts to special files for Kotlin project support, by Lucas Shadler.
|
||||||
|
|
||||||
|
### Aider v0.74.2
|
||||||
|
|
||||||
|
- Prevent more than one cache warming thread from becoming active.
|
||||||
|
- Fixed continuation prompt ". " for multiline input.
|
||||||
|
- Added HCL (Terraform) syntax support, by Warren Krewenki.
|
||||||
|
|
||||||
|
### Aider v0.74.1
|
||||||
|
|
||||||
|
- Have o1 & o3-mini generate markdown by sending the magic "Formatting re-enabled." string.
|
||||||
|
- Bugfix for multi-line inputs, which should not include the ". " continuation prompt.
|
||||||
|
|
||||||
|
### Aider v0.74.0
|
||||||
|
|
||||||
|
- Dynamically changes the Ollama context window to hold the current chat.
|
||||||
|
- Better support for o3-mini, DeepSeek V3 & R1, o1-mini, o1 especially via third-party API providers.
|
||||||
|
- Remove `<think>` tags from R1 responses for commit messages (and other weak model uses).
|
||||||
|
- Can now specify `use_temperature: <float>` in model settings, not just true/false.
|
||||||
|
- The full docker container now includes `boto3` for Bedrock.
|
||||||
|
- Docker containers now set `HOME=/app` which is the normal project mount-point, to persist `~/.aider`.
|
||||||
|
- Bugfix to prevent creating incorrect filenames like `python`, `php`, etc.
|
||||||
|
- Bugfix for `--timeout`
|
||||||
|
- Bugfix so that `/model` now correctly reports that the weak model is not changed.
|
||||||
|
- Bugfix so that multi-line mode persists through ^C at confirmation prompts.
|
||||||
|
- Watch files now fully ignores top-level directories named in ignore files, to reduce the chance of hitting OS watch limits. Helpful to ignore giant subtrees like `node_modules`.
|
||||||
|
- Fast startup with more providers and when model metadata provided in local files.
|
||||||
|
- Improved .gitignore handling:
|
||||||
|
- Honor ignores already in effect regardless of how they've been configured.
|
||||||
|
- Check for .env only when the file exists.
|
||||||
|
- Yes/No prompts now accept All/Skip as alias for Y/N even when not processing a group of confirmations.
|
||||||
|
- Aider wrote 77% of the code in this release.
|
||||||
|
|
||||||
### Aider v0.73.0
|
### Aider v0.73.0
|
||||||
|
|
||||||
- Full support for o3-mini: `aider --model o3-mini`
|
- Full support for o3-mini: `aider --model o3-mini`
|
||||||
@@ -31,7 +149,7 @@ cog.out(text)
|
|||||||
- Added support for removing model-specific reasoning tags from responses with `remove_reasoning: tagname` model setting.
|
- Added support for removing model-specific reasoning tags from responses with `remove_reasoning: tagname` model setting.
|
||||||
- Auto-create parent directories when creating new files, by xqyz.
|
- Auto-create parent directories when creating new files, by xqyz.
|
||||||
- Support for R1 free on OpenRouter: `--model openrouter/deepseek/deepseek-r1:free`
|
- Support for R1 free on OpenRouter: `--model openrouter/deepseek/deepseek-r1:free`
|
||||||
- Aider wrote 70% of the code in this release.
|
- Aider wrote 69% of the code in this release.
|
||||||
|
|
||||||
### Aider v0.72.3
|
### Aider v0.72.3
|
||||||
|
|
||||||
|
|||||||
@@ -3167,8 +3167,8 @@
|
|||||||
malkoG: 83
|
malkoG: 83
|
||||||
start_tag: v0.64.0
|
start_tag: v0.64.0
|
||||||
total_lines: 670
|
total_lines: 670
|
||||||
- aider_percentage: 81.65
|
- aider_percentage: 86.17
|
||||||
aider_total: 574
|
aider_total: 841
|
||||||
end_date: '2024-12-01'
|
end_date: '2024-12-01'
|
||||||
end_tag: v0.66.0
|
end_tag: v0.66.0
|
||||||
file_counts:
|
file_counts:
|
||||||
@@ -3240,18 +3240,52 @@
|
|||||||
Paul Gauthier (aider): 103
|
Paul Gauthier (aider): 103
|
||||||
tests/browser/test_browser.py:
|
tests/browser/test_browser.py:
|
||||||
Paul Gauthier: 1
|
Paul Gauthier: 1
|
||||||
|
tests/fixtures/languages/c/test.c:
|
||||||
|
Paul Gauthier (aider): 6
|
||||||
|
tests/fixtures/languages/cpp/test.cpp:
|
||||||
|
Paul Gauthier (aider): 6
|
||||||
|
tests/fixtures/languages/csharp/test.cs:
|
||||||
|
Paul Gauthier (aider): 39
|
||||||
|
tests/fixtures/languages/elisp/test.el:
|
||||||
|
Paul Gauthier (aider): 25
|
||||||
|
tests/fixtures/languages/elixir/test.ex:
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
tests/fixtures/languages/elm/test.elm:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
Paul Gauthier (aider): 37
|
||||||
|
tests/fixtures/languages/go/test.go:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
Paul Gauthier (aider): 41
|
||||||
|
tests/fixtures/languages/java/test.java:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
Paul Gauthier (aider): 14
|
||||||
tests/fixtures/languages/javascript/test.js:
|
tests/fixtures/languages/javascript/test.js:
|
||||||
Paul Gauthier: 1
|
Paul Gauthier: 1
|
||||||
Paul Gauthier (aider): 25
|
Paul Gauthier (aider): 25
|
||||||
|
tests/fixtures/languages/ocaml/test.ml:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
Paul Gauthier (aider): 17
|
||||||
|
tests/fixtures/languages/php/test.php:
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
tests/fixtures/languages/python/test.py:
|
tests/fixtures/languages/python/test.py:
|
||||||
Paul Gauthier: 2
|
Paul Gauthier: 2
|
||||||
Paul Gauthier (aider): 26
|
Paul Gauthier (aider): 26
|
||||||
|
tests/fixtures/languages/ql/test.ql:
|
||||||
|
Paul Gauthier (aider): 3
|
||||||
|
tests/fixtures/languages/ruby/test.rb:
|
||||||
|
Paul Gauthier (aider): 3
|
||||||
|
tests/fixtures/languages/rust/test.rs:
|
||||||
|
Paul Gauthier (aider): 33
|
||||||
|
tests/fixtures/languages/tsx/test.tsx:
|
||||||
|
Paul Gauthier (aider): 30
|
||||||
|
tests/fixtures/languages/typescript/test.ts:
|
||||||
|
Paul Gauthier (aider): 3
|
||||||
grand_total:
|
grand_total:
|
||||||
Paul Gauthier: 99
|
Paul Gauthier: 105
|
||||||
Paul Gauthier (aider): 574
|
Paul Gauthier (aider): 841
|
||||||
Philippe de Reynal: 30
|
Philippe de Reynal: 30
|
||||||
start_tag: v0.65.0
|
start_tag: v0.65.0
|
||||||
total_lines: 703
|
total_lines: 976
|
||||||
- aider_percentage: 67.86
|
- aider_percentage: 67.86
|
||||||
aider_total: 437
|
aider_total: 437
|
||||||
end_date: '2024-12-06'
|
end_date: '2024-12-06'
|
||||||
@@ -3619,7 +3653,7 @@
|
|||||||
apaz-cli: 18
|
apaz-cli: 18
|
||||||
start_tag: v0.70.0
|
start_tag: v0.70.0
|
||||||
total_lines: 391
|
total_lines: 391
|
||||||
- aider_percentage: 51.69
|
- aider_percentage: 48.76
|
||||||
aider_total: 138
|
aider_total: 138
|
||||||
end_date: '2025-01-20'
|
end_date: '2025-01-20'
|
||||||
end_tag: v0.72.0
|
end_tag: v0.72.0
|
||||||
@@ -3680,10 +3714,464 @@
|
|||||||
Paul Gauthier (aider): 39
|
Paul Gauthier (aider): 39
|
||||||
tests/basic/test_repomap.py:
|
tests/basic/test_repomap.py:
|
||||||
Paul Walker: 1
|
Paul Walker: 1
|
||||||
|
tests/fixtures/languages/kotlin/test.kt:
|
||||||
|
Paul Walker: 16
|
||||||
grand_total:
|
grand_total:
|
||||||
Paul Gauthier: 92
|
Paul Gauthier: 92
|
||||||
Paul Gauthier (aider): 138
|
Paul Gauthier (aider): 138
|
||||||
Paul Walker: 28
|
Paul Walker: 44
|
||||||
Titusz Pan: 9
|
Titusz Pan: 9
|
||||||
start_tag: v0.71.0
|
start_tag: v0.71.0
|
||||||
total_lines: 267
|
total_lines: 283
|
||||||
|
- aider_percentage: 37.47
|
||||||
|
aider_total: 284
|
||||||
|
end_date: '2025-01-31'
|
||||||
|
end_tag: v0.73.0
|
||||||
|
file_counts:
|
||||||
|
aider/__init__.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/args.py:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
aider/coders/base_coder.py:
|
||||||
|
Paul Gauthier: 37
|
||||||
|
Paul Gauthier (aider): 26
|
||||||
|
aider/commands.py:
|
||||||
|
xqyz: 1
|
||||||
|
aider/io.py:
|
||||||
|
Paul Gauthier: 7
|
||||||
|
aider/main.py:
|
||||||
|
Paul Gauthier: 13
|
||||||
|
Paul Gauthier (aider): 15
|
||||||
|
aider/models.py:
|
||||||
|
Paul Gauthier: 8
|
||||||
|
Paul Gauthier (aider): 33
|
||||||
|
aider/resources/model-settings.yml:
|
||||||
|
Paul Gauthier: 334
|
||||||
|
kennyfrc: 11
|
||||||
|
xqyz: 4
|
||||||
|
aider/sendchat.py:
|
||||||
|
Mir Adnan ALI: 28
|
||||||
|
Paul Gauthier: 11
|
||||||
|
Paul Gauthier (aider): 6
|
||||||
|
aider/urls.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/website/_includes/leaderboard.js:
|
||||||
|
Paul Gauthier (aider): 1
|
||||||
|
aider/website/docs/leaderboards/index.md:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
benchmark/benchmark.py:
|
||||||
|
Paul Gauthier (aider): 21
|
||||||
|
benchmark/rsync.sh:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
tests/basic/test_coder.py:
|
||||||
|
Paul Gauthier: 10
|
||||||
|
Paul Gauthier (aider): 39
|
||||||
|
tests/basic/test_main.py:
|
||||||
|
Paul Gauthier (aider): 62
|
||||||
|
tests/basic/test_sendchat.py:
|
||||||
|
Paul Gauthier (aider): 77
|
||||||
|
grand_total:
|
||||||
|
Mir Adnan ALI: 28
|
||||||
|
Paul Gauthier: 430
|
||||||
|
Paul Gauthier (aider): 284
|
||||||
|
kennyfrc: 11
|
||||||
|
xqyz: 5
|
||||||
|
start_tag: v0.72.0
|
||||||
|
total_lines: 758
|
||||||
|
- aider_percentage: 76.07
|
||||||
|
aider_total: 604
|
||||||
|
end_date: '2025-02-06'
|
||||||
|
end_tag: v0.74.0
|
||||||
|
file_counts:
|
||||||
|
aider/__init__.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/args.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/coders/base_coder.py:
|
||||||
|
Paul Gauthier: 24
|
||||||
|
Paul Gauthier (aider): 9
|
||||||
|
aider/coders/editblock_coder.py:
|
||||||
|
Paul Gauthier: 5
|
||||||
|
aider/coders/wholefile_coder.py:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
aider/commands.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/exceptions.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 6
|
||||||
|
aider/history.py:
|
||||||
|
Paul Gauthier (aider): 1
|
||||||
|
aider/io.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 18
|
||||||
|
aider/llm.py:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
aider/main.py:
|
||||||
|
Paul Gauthier: 21
|
||||||
|
Paul Gauthier (aider): 25
|
||||||
|
aider/models.py:
|
||||||
|
Paul Gauthier: 83
|
||||||
|
Paul Gauthier (aider): 77
|
||||||
|
aider/repo.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
"Viktor Sz\xE9pe": 3
|
||||||
|
aider/resources/model-settings.yml:
|
||||||
|
Paul Gauthier: 11
|
||||||
|
aider/watch.py:
|
||||||
|
Paul Gauthier (aider): 45
|
||||||
|
benchmark/docker.sh:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
docker/Dockerfile:
|
||||||
|
Paul Gauthier: 5
|
||||||
|
Paul Gauthier (aider): 4
|
||||||
|
tests/basic/test_editblock.py:
|
||||||
|
Paul Gauthier: 7
|
||||||
|
tests/basic/test_history.py:
|
||||||
|
Paul Gauthier (aider): 13
|
||||||
|
tests/basic/test_io.py:
|
||||||
|
Paul Gauthier (aider): 46
|
||||||
|
tests/basic/test_main.py:
|
||||||
|
Paul Gauthier: 8
|
||||||
|
Paul Gauthier (aider): 1
|
||||||
|
tests/basic/test_models.py:
|
||||||
|
Paul Gauthier (aider): 297
|
||||||
|
tests/basic/test_repo.py:
|
||||||
|
Paul Gauthier (aider): 11
|
||||||
|
tests/basic/test_sendchat.py:
|
||||||
|
Paul Gauthier (aider): 7
|
||||||
|
tests/basic/test_watch.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 42
|
||||||
|
grand_total:
|
||||||
|
Paul Gauthier: 187
|
||||||
|
Paul Gauthier (aider): 604
|
||||||
|
"Viktor Sz\xE9pe": 3
|
||||||
|
start_tag: v0.73.0
|
||||||
|
total_lines: 794
|
||||||
|
- aider_percentage: 44.78
|
||||||
|
aider_total: 163
|
||||||
|
end_date: '2025-02-24'
|
||||||
|
end_tag: v0.75.0
|
||||||
|
file_counts:
|
||||||
|
aider/__init__.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/args.py:
|
||||||
|
Paul Gauthier: 7
|
||||||
|
aider/coders/base_coder.py:
|
||||||
|
Paul Gauthier: 12
|
||||||
|
Paul Gauthier (aider): 4
|
||||||
|
aider/commands.py:
|
||||||
|
FeepingCreature (aider): 6
|
||||||
|
aider/editor.py:
|
||||||
|
Paul Gauthier: 7
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
aider/io.py:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
Paul Gauthier (aider): 4
|
||||||
|
aider/linter.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/main.py:
|
||||||
|
Paul Gauthier: 16
|
||||||
|
aider/models.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
aider/queries/tree-sitter-language-pack/javascript-tags.scm:
|
||||||
|
Paul Gauthier: 5
|
||||||
|
aider/queries/tree-sitter-languages/hcl-tags.scm:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
Warren Krewenki: 74
|
||||||
|
aider/queries/tree-sitter-languages/javascript-tags.scm:
|
||||||
|
Paul Gauthier: 5
|
||||||
|
aider/repomap.py:
|
||||||
|
Paul Gauthier: 43
|
||||||
|
Paul Gauthier (aider): 11
|
||||||
|
aider/resources/model-settings.yml:
|
||||||
|
Paul Gauthier: 12
|
||||||
|
aider/special.py:
|
||||||
|
Lucas Shadler: 1
|
||||||
|
aider/website/docs/leaderboards/index.md:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
benchmark/Dockerfile:
|
||||||
|
Paul Gauthier (aider): 1
|
||||||
|
benchmark/benchmark.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
benchmark/cpp-test.sh:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
scripts/blame.py:
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
scripts/issues.py:
|
||||||
|
Paul Gauthier (aider): 17
|
||||||
|
tests/basic/test_coder.py:
|
||||||
|
Paul Gauthier (aider): 18
|
||||||
|
tests/basic/test_editor.py:
|
||||||
|
Antti Kaihola: 1
|
||||||
|
Paul Gauthier (aider): 41
|
||||||
|
tests/basic/test_models.py:
|
||||||
|
Paul Gauthier (aider): 1
|
||||||
|
tests/basic/test_repomap.py:
|
||||||
|
Paul Gauthier (aider): 1
|
||||||
|
tests/fixtures/languages/hcl/test.tf:
|
||||||
|
Paul Gauthier (aider): 52
|
||||||
|
grand_total:
|
||||||
|
Antti Kaihola: 1
|
||||||
|
FeepingCreature (aider): 6
|
||||||
|
Lucas Shadler: 1
|
||||||
|
Paul Gauthier: 125
|
||||||
|
Paul Gauthier (aider): 157
|
||||||
|
Warren Krewenki: 74
|
||||||
|
start_tag: v0.74.0
|
||||||
|
total_lines: 364
|
||||||
|
- aider_percentage: 84.75
|
||||||
|
aider_total: 1589
|
||||||
|
end_date: '2025-03-10'
|
||||||
|
end_tag: v0.76.0
|
||||||
|
file_counts:
|
||||||
|
aider/__init__.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/args.py:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
Paul Gauthier (aider): 25
|
||||||
|
aider/args_formatter.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 3
|
||||||
|
aider/coders/base_coder.py:
|
||||||
|
Paul Gauthier: 54
|
||||||
|
Paul Gauthier (aider): 29
|
||||||
|
aider/deprecated.py:
|
||||||
|
Paul Gauthier (aider): 107
|
||||||
|
aider/io.py:
|
||||||
|
Paul Gauthier: 7
|
||||||
|
Paul Gauthier (aider): 127
|
||||||
|
aider/main.py:
|
||||||
|
Akira Komamura: 2
|
||||||
|
Mattias: 1
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 16
|
||||||
|
aider/models.py:
|
||||||
|
Paul Gauthier: 6
|
||||||
|
Paul Gauthier (aider): 68
|
||||||
|
aider/queries/tree-sitter-language-pack/csharp-tags.scm:
|
||||||
|
Paul Gauthier: 14
|
||||||
|
Paul Gauthier (aider): 12
|
||||||
|
aider/reasoning_tags.py:
|
||||||
|
Paul Gauthier: 14
|
||||||
|
Paul Gauthier (aider): 68
|
||||||
|
aider/repo.py:
|
||||||
|
Akira Komamura: 1
|
||||||
|
Paul Gauthier (aider): 4
|
||||||
|
aider/repomap.py:
|
||||||
|
Paul Gauthier: 9
|
||||||
|
aider/resources/model-settings.yml:
|
||||||
|
Paul Gauthier: 61
|
||||||
|
Paul Gauthier (aider): 32
|
||||||
|
gmoz22: 4
|
||||||
|
aider/website/_includes/leaderboard.js:
|
||||||
|
Paul Gauthier (aider): 48
|
||||||
|
aider/website/docs/leaderboards/index.md:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
benchmark/benchmark.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
benchmark/problem_stats.py:
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
docker/Dockerfile:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
scripts/blame.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
scripts/pip-compile.sh:
|
||||||
|
Claudia Pellegrino: 10
|
||||||
|
Paul Gauthier: 6
|
||||||
|
Paul Gauthier (aider): 11
|
||||||
|
scripts/update-history.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
scripts/versionbump.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 64
|
||||||
|
tests/basic/test_deprecated.py:
|
||||||
|
Paul Gauthier: 10
|
||||||
|
Paul Gauthier (aider): 130
|
||||||
|
tests/basic/test_io.py:
|
||||||
|
Paul Gauthier (aider): 54
|
||||||
|
tests/basic/test_main.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
Paul Gauthier (aider): 93
|
||||||
|
tests/basic/test_model_info_manager.py:
|
||||||
|
Paul Gauthier (aider): 72
|
||||||
|
tests/basic/test_models.py:
|
||||||
|
Paul Gauthier: 27
|
||||||
|
Paul Gauthier (aider): 34
|
||||||
|
tests/basic/test_reasoning.py:
|
||||||
|
Paul Gauthier: 36
|
||||||
|
Paul Gauthier (aider): 525
|
||||||
|
tests/basic/test_repomap.py:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
tests/basic/test_ssl_verification.py:
|
||||||
|
Paul Gauthier (aider): 65
|
||||||
|
grand_total:
|
||||||
|
Akira Komamura: 3
|
||||||
|
Claudia Pellegrino: 10
|
||||||
|
Mattias: 1
|
||||||
|
Paul Gauthier: 268
|
||||||
|
Paul Gauthier (aider): 1589
|
||||||
|
gmoz22: 4
|
||||||
|
start_tag: v0.75.0
|
||||||
|
total_lines: 1875
|
||||||
|
- aider_percentage: 71.93
|
||||||
|
aider_total: 1399
|
||||||
|
end_date: '2025-03-13'
|
||||||
|
end_tag: v0.77.0
|
||||||
|
file_counts:
|
||||||
|
aider/__init__.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
aider/args.py:
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
aider/coders/architect_coder.py:
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
aider/coders/base_coder.py:
|
||||||
|
Paul Gauthier (aider): 14
|
||||||
|
aider/commands.py:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 71
|
||||||
|
aider/deprecated.py:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
aider/io.py:
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
aider/main.py:
|
||||||
|
Paul Gauthier (aider): 12
|
||||||
|
aider/models.py:
|
||||||
|
Paul Gauthier (aider): 83
|
||||||
|
aider/queries/tree-sitter-language-pack/arduino-tags.scm:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
aider/queries/tree-sitter-language-pack/c-tags.scm:
|
||||||
|
Paul Gauthier: 4
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
aider/queries/tree-sitter-language-pack/chatito-tags.scm:
|
||||||
|
Paul Gauthier: 11
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
aider/queries/tree-sitter-language-pack/commonlisp-tags.scm:
|
||||||
|
Paul Gauthier: 116
|
||||||
|
Paul Gauthier (aider): 6
|
||||||
|
aider/queries/tree-sitter-language-pack/cpp-tags.scm:
|
||||||
|
Paul Gauthier: 7
|
||||||
|
Paul Gauthier (aider): 8
|
||||||
|
aider/queries/tree-sitter-language-pack/d-tags.scm:
|
||||||
|
Paul Gauthier: 9
|
||||||
|
Paul Gauthier (aider): 17
|
||||||
|
aider/queries/tree-sitter-language-pack/dart-tags.scm:
|
||||||
|
Paul Gauthier: 42
|
||||||
|
Paul Gauthier (aider): 19
|
||||||
|
aider/queries/tree-sitter-language-pack/elisp-tags.scm:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
aider/queries/tree-sitter-language-pack/elixir-tags.scm:
|
||||||
|
Paul Gauthier: 10
|
||||||
|
Paul Gauthier (aider): 8
|
||||||
|
aider/queries/tree-sitter-language-pack/elm-tags.scm:
|
||||||
|
Paul Gauthier: 8
|
||||||
|
Paul Gauthier (aider): 11
|
||||||
|
aider/queries/tree-sitter-language-pack/gleam-tags.scm:
|
||||||
|
Paul Gauthier: 26
|
||||||
|
Paul Gauthier (aider): 15
|
||||||
|
aider/queries/tree-sitter-language-pack/go-tags.scm:
|
||||||
|
Paul Gauthier: 14
|
||||||
|
Paul Gauthier (aider): 14
|
||||||
|
aider/queries/tree-sitter-language-pack/java-tags.scm:
|
||||||
|
Paul Gauthier: 10
|
||||||
|
Paul Gauthier (aider): 7
|
||||||
|
aider/queries/tree-sitter-language-pack/lua-tags.scm:
|
||||||
|
Paul Gauthier: 25
|
||||||
|
Paul Gauthier (aider): 9
|
||||||
|
aider/queries/tree-sitter-language-pack/pony-tags.scm:
|
||||||
|
Paul Gauthier: 20
|
||||||
|
Paul Gauthier (aider): 19
|
||||||
|
aider/queries/tree-sitter-language-pack/properties-tags.scm:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
aider/queries/tree-sitter-language-pack/python-tags.scm:
|
||||||
|
Paul Gauthier: 9
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
aider/queries/tree-sitter-language-pack/r-tags.scm:
|
||||||
|
Paul Gauthier: 17
|
||||||
|
Paul Gauthier (aider): 4
|
||||||
|
aider/queries/tree-sitter-language-pack/racket-tags.scm:
|
||||||
|
Paul Gauthier: 10
|
||||||
|
Paul Gauthier (aider): 2
|
||||||
|
aider/queries/tree-sitter-language-pack/ruby-tags.scm:
|
||||||
|
Paul Gauthier: 23
|
||||||
|
Paul Gauthier (aider): 12
|
||||||
|
aider/queries/tree-sitter-language-pack/rust-tags.scm:
|
||||||
|
Paul Gauthier: 41
|
||||||
|
Paul Gauthier (aider): 14
|
||||||
|
aider/queries/tree-sitter-language-pack/solidity-tags.scm:
|
||||||
|
Paul Gauthier: 30
|
||||||
|
Paul Gauthier (aider): 13
|
||||||
|
aider/queries/tree-sitter-language-pack/swift-tags.scm:
|
||||||
|
Paul Gauthier: 39
|
||||||
|
Paul Gauthier (aider): 12
|
||||||
|
aider/queries/tree-sitter-language-pack/udev-tags.scm:
|
||||||
|
Paul Gauthier: 15
|
||||||
|
Paul Gauthier (aider): 5
|
||||||
|
aider/resources/model-settings.yml:
|
||||||
|
Paul Gauthier: 9
|
||||||
|
aider/watch.py:
|
||||||
|
Yutaka Matsubara: 4
|
||||||
|
aider/website/docs/leaderboards/index.md:
|
||||||
|
Paul Gauthier: 3
|
||||||
|
Paul Gauthier (aider): 8
|
||||||
|
scripts/redact-cast.py:
|
||||||
|
Paul Gauthier: 27
|
||||||
|
Paul Gauthier (aider): 98
|
||||||
|
scripts/tsl_pack_langs.py:
|
||||||
|
Paul Gauthier (aider): 145
|
||||||
|
scripts/versionbump.py:
|
||||||
|
Paul Gauthier (aider): 1
|
||||||
|
tests/basic/test_coder.py:
|
||||||
|
Paul Gauthier (aider): 104
|
||||||
|
tests/basic/test_commands.py:
|
||||||
|
Paul Gauthier: 2
|
||||||
|
Paul Gauthier (aider): 190
|
||||||
|
tests/basic/test_models.py:
|
||||||
|
Paul Gauthier (aider): 44
|
||||||
|
tests/basic/test_repomap.py:
|
||||||
|
Paul Gauthier: 1
|
||||||
|
Paul Gauthier (aider): 125
|
||||||
|
tests/fixtures/languages/arduino/test.ino:
|
||||||
|
Paul Gauthier (aider): 21
|
||||||
|
tests/fixtures/languages/c/test.c:
|
||||||
|
Paul Gauthier (aider): 12
|
||||||
|
tests/fixtures/languages/chatito/test.chatito:
|
||||||
|
Paul Gauthier (aider): 20
|
||||||
|
tests/fixtures/languages/commonlisp/test.lisp:
|
||||||
|
Paul Gauthier (aider): 17
|
||||||
|
tests/fixtures/languages/d/test.d:
|
||||||
|
Paul Gauthier (aider): 26
|
||||||
|
tests/fixtures/languages/dart/test.dart:
|
||||||
|
Paul Gauthier (aider): 21
|
||||||
|
tests/fixtures/languages/elm/test.elm:
|
||||||
|
Paul Gauthier (aider): 16
|
||||||
|
tests/fixtures/languages/gleam/test.gleam:
|
||||||
|
Paul Gauthier (aider): 10
|
||||||
|
tests/fixtures/languages/lua/test.lua:
|
||||||
|
Paul Gauthier (aider): 25
|
||||||
|
tests/fixtures/languages/pony/test.pony:
|
||||||
|
Paul Gauthier (aider): 8
|
||||||
|
tests/fixtures/languages/properties/test.properties:
|
||||||
|
Paul Gauthier (aider): 14
|
||||||
|
tests/fixtures/languages/r/test.r:
|
||||||
|
Paul Gauthier (aider): 17
|
||||||
|
tests/fixtures/languages/racket/test.rkt:
|
||||||
|
Paul Gauthier (aider): 8
|
||||||
|
tests/fixtures/languages/solidity/test.sol:
|
||||||
|
Paul Gauthier (aider): 21
|
||||||
|
tests/fixtures/languages/swift/test.swift:
|
||||||
|
Paul Gauthier (aider): 18
|
||||||
|
tests/fixtures/languages/udev/test.rules:
|
||||||
|
Paul Gauthier (aider): 22
|
||||||
|
grand_total:
|
||||||
|
Paul Gauthier: 542
|
||||||
|
Paul Gauthier (aider): 1399
|
||||||
|
Yutaka Matsubara: 4
|
||||||
|
start_tag: v0.76.0
|
||||||
|
total_lines: 1945
|
||||||
|
|||||||
@@ -1,3 +1,29 @@
|
|||||||
|
- dirname: 2025-02-25-20-23-07--gemini-pro
|
||||||
|
test_cases: 225
|
||||||
|
model: gemini/gemini-2.0-pro-exp-02-05
|
||||||
|
edit_format: whole
|
||||||
|
commit_hash: 2fccd47
|
||||||
|
pass_rate_1: 20.4
|
||||||
|
pass_rate_2: 35.6
|
||||||
|
pass_num_1: 46
|
||||||
|
pass_num_2: 80
|
||||||
|
percent_cases_well_formed: 100.0
|
||||||
|
error_outputs: 430
|
||||||
|
num_malformed_responses: 0
|
||||||
|
num_with_malformed_responses: 0
|
||||||
|
user_asks: 13
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 0
|
||||||
|
test_timeouts: 5
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model gemini/gemini-2.0-pro-exp-02-05
|
||||||
|
date: 2025-02-25
|
||||||
|
versions: 0.75.2.dev
|
||||||
|
seconds_per_case: 34.8
|
||||||
|
total_cost: 0.0000
|
||||||
|
|
||||||
- dirname: 2024-12-21-18-41-18--polyglot-gpt-4o-mini
|
- dirname: 2024-12-21-18-41-18--polyglot-gpt-4o-mini
|
||||||
test_cases: 225
|
test_cases: 225
|
||||||
model: gpt-4o-mini-2024-07-18
|
model: gpt-4o-mini-2024-07-18
|
||||||
@@ -518,3 +544,239 @@
|
|||||||
versions: 0.72.4.dev
|
versions: 0.72.4.dev
|
||||||
seconds_per_case: 124.6
|
seconds_per_case: 124.6
|
||||||
total_cost: 18.1584
|
total_cost: 18.1584
|
||||||
|
|
||||||
|
- dirname: 2025-01-21-22-51-49--gemini-2.0-flash-thinking-exp-01-21-polyglot-diff
|
||||||
|
test_cases: 225
|
||||||
|
model: gemini-2.0-flash-thinking-exp-01-21
|
||||||
|
edit_format: diff
|
||||||
|
commit_hash: 843720a
|
||||||
|
pass_rate_1: 5.8
|
||||||
|
pass_rate_2: 18.2
|
||||||
|
pass_num_1: 13
|
||||||
|
pass_num_2: 41
|
||||||
|
percent_cases_well_formed: 77.8
|
||||||
|
error_outputs: 182
|
||||||
|
num_malformed_responses: 180
|
||||||
|
num_with_malformed_responses: 50
|
||||||
|
user_asks: 26
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 2
|
||||||
|
test_timeouts: 7
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model gemini/gemini-2.0-flash-thinking-exp-01-21
|
||||||
|
date: 2025-01-21
|
||||||
|
versions: 0.72.2.dev
|
||||||
|
seconds_per_case: 24.2
|
||||||
|
total_cost: 0.0000
|
||||||
|
|
||||||
|
- dirname: 2025-02-15-19-51-22--chatgpt4o-feb15-diff
|
||||||
|
test_cases: 223
|
||||||
|
model: chatgpt-4o-latest (2025-02-15)
|
||||||
|
edit_format: diff
|
||||||
|
commit_hash: 108ce18-dirty
|
||||||
|
pass_rate_1: 9.0
|
||||||
|
pass_rate_2: 27.1
|
||||||
|
pass_num_1: 20
|
||||||
|
pass_num_2: 61
|
||||||
|
percent_cases_well_formed: 93.3
|
||||||
|
error_outputs: 66
|
||||||
|
num_malformed_responses: 21
|
||||||
|
num_with_malformed_responses: 15
|
||||||
|
user_asks: 57
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 0
|
||||||
|
test_timeouts: 2
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model chatgpt-4o-latest
|
||||||
|
date: 2025-02-15
|
||||||
|
versions: 0.74.3.dev
|
||||||
|
seconds_per_case: 12.4
|
||||||
|
total_cost: 14.3703
|
||||||
|
|
||||||
|
- dirname: 2025-02-24-19-54-07--sonnet37-diff
|
||||||
|
test_cases: 225
|
||||||
|
model: claude-3-7-sonnet-20250219 (no thinking)
|
||||||
|
edit_format: diff
|
||||||
|
commit_hash: 75e9ee6
|
||||||
|
pass_rate_1: 24.4
|
||||||
|
pass_rate_2: 60.4
|
||||||
|
pass_num_1: 55
|
||||||
|
pass_num_2: 136
|
||||||
|
percent_cases_well_formed: 93.3
|
||||||
|
error_outputs: 16
|
||||||
|
num_malformed_responses: 16
|
||||||
|
num_with_malformed_responses: 15
|
||||||
|
user_asks: 12
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 0
|
||||||
|
test_timeouts: 0
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model sonnet
|
||||||
|
date: 2025-02-24
|
||||||
|
versions: 0.74.4.dev
|
||||||
|
seconds_per_case: 28.3
|
||||||
|
total_cost: 17.7191
|
||||||
|
|
||||||
|
- dirname: 2025-02-24-21-47-23--sonnet37-diff-think-32k-64k
|
||||||
|
test_cases: 225
|
||||||
|
model: claude-3-7-sonnet-20250219 (32k thinking tokens)
|
||||||
|
edit_format: diff
|
||||||
|
commit_hash: 60d11a6, 93edbda
|
||||||
|
pass_rate_1: 29.3
|
||||||
|
pass_rate_2: 64.9
|
||||||
|
pass_num_1: 66
|
||||||
|
pass_num_2: 146
|
||||||
|
percent_cases_well_formed: 97.8
|
||||||
|
error_outputs: 66
|
||||||
|
num_malformed_responses: 5
|
||||||
|
num_with_malformed_responses: 5
|
||||||
|
user_asks: 5
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 0
|
||||||
|
test_timeouts: 1
|
||||||
|
total_tests: 225
|
||||||
|
command: "aider --model anthropic/claude-3-7-sonnet-20250219 # plus yml config"
|
||||||
|
date: 2025-02-24
|
||||||
|
versions: 0.75.1.dev
|
||||||
|
seconds_per_case: 105.2
|
||||||
|
total_cost: 36.8343
|
||||||
|
|
||||||
|
- dirname: 2025-02-27-20-26-15--gpt45-diff3
|
||||||
|
test_cases: 224
|
||||||
|
model: gpt-4.5-preview
|
||||||
|
edit_format: diff
|
||||||
|
commit_hash: b462e55-dirty
|
||||||
|
pass_rate_1: 22.3
|
||||||
|
pass_rate_2: 44.9
|
||||||
|
pass_num_1: 50
|
||||||
|
pass_num_2: 101
|
||||||
|
percent_cases_well_formed: 97.3
|
||||||
|
error_outputs: 10
|
||||||
|
num_malformed_responses: 8
|
||||||
|
num_with_malformed_responses: 6
|
||||||
|
user_asks: 15
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 1
|
||||||
|
test_timeouts: 2
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model openai/gpt-4.5-preview
|
||||||
|
date: 2025-02-27
|
||||||
|
versions: 0.75.2.dev
|
||||||
|
seconds_per_case: 113.5
|
||||||
|
total_cost: 183.1802
|
||||||
|
|
||||||
|
- dirname: 2025-03-06-17-40-24--qwq32b-diff-temp-topp-ex-sys-remind-user-for-real
|
||||||
|
test_cases: 225
|
||||||
|
model: QwQ-32B
|
||||||
|
edit_format: diff
|
||||||
|
commit_hash: 51d118f-dirty
|
||||||
|
pass_rate_1: 8.0
|
||||||
|
pass_rate_2: 20.9
|
||||||
|
pass_num_1: 18
|
||||||
|
pass_num_2: 47
|
||||||
|
percent_cases_well_formed: 67.6
|
||||||
|
error_outputs: 145
|
||||||
|
num_malformed_responses: 143
|
||||||
|
num_with_malformed_responses: 73
|
||||||
|
user_asks: 17
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 1
|
||||||
|
test_timeouts: 4
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model fireworks_ai/accounts/fireworks/models/qwq-32b
|
||||||
|
date: 2025-03-06
|
||||||
|
versions: 0.75.3.dev
|
||||||
|
seconds_per_case: 228.6
|
||||||
|
total_cost: 0.0000
|
||||||
|
|
||||||
|
- dirname: 2025-03-07-15-11-27--qwq32b-arch-temp-topp-again
|
||||||
|
test_cases: 225
|
||||||
|
model: QwQ-32B + Qwen 2.5 Coder Instruct
|
||||||
|
edit_format: architect
|
||||||
|
commit_hash: 52162a5
|
||||||
|
editor_model: fireworks_ai/accounts/fireworks/models/qwen2p5-coder-32b-instruct
|
||||||
|
editor_edit_format: editor-diff
|
||||||
|
pass_rate_1: 9.8
|
||||||
|
pass_rate_2: 26.2
|
||||||
|
pass_num_1: 22
|
||||||
|
pass_num_2: 59
|
||||||
|
percent_cases_well_formed: 100.0
|
||||||
|
error_outputs: 122
|
||||||
|
num_malformed_responses: 0
|
||||||
|
num_with_malformed_responses: 0
|
||||||
|
user_asks: 489
|
||||||
|
lazy_comments: 8
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 1
|
||||||
|
test_timeouts: 2
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model fireworks_ai/accounts/fireworks/models/qwq-32b --architect
|
||||||
|
date: 2025-03-07
|
||||||
|
versions: 0.75.3.dev
|
||||||
|
seconds_per_case: 137.4
|
||||||
|
total_cost: 0
|
||||||
|
|
||||||
|
- dirname: 2025-03-14-23-40-00--cmda-quality-whole2
|
||||||
|
test_cases: 225
|
||||||
|
model: command-a-03-2025-quality
|
||||||
|
edit_format: whole
|
||||||
|
commit_hash: a1aa63f
|
||||||
|
pass_rate_1: 2.2
|
||||||
|
pass_rate_2: 12.0
|
||||||
|
pass_num_1: 5
|
||||||
|
pass_num_2: 27
|
||||||
|
percent_cases_well_formed: 99.6
|
||||||
|
error_outputs: 2
|
||||||
|
num_malformed_responses: 1
|
||||||
|
num_with_malformed_responses: 1
|
||||||
|
user_asks: 215
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 1
|
||||||
|
test_timeouts: 4
|
||||||
|
total_tests: 225
|
||||||
|
command: OPENAI_API_BASE=https://api.cohere.ai/compatibility/v1 aider --model openai/command-a-03-2025-quality
|
||||||
|
date: 2025-03-14
|
||||||
|
versions: 0.77.1.dev
|
||||||
|
seconds_per_case: 85.1
|
||||||
|
total_cost: 0.0000
|
||||||
|
|
||||||
|
- dirname: 2025-03-15-01-21-24--gemma3-27b-or
|
||||||
|
test_cases: 225
|
||||||
|
model: gemma-3-27b-it
|
||||||
|
edit_format: whole
|
||||||
|
commit_hash: fd21f51-dirty
|
||||||
|
pass_rate_1: 1.8
|
||||||
|
pass_rate_2: 4.9
|
||||||
|
pass_num_1: 4
|
||||||
|
pass_num_2: 11
|
||||||
|
percent_cases_well_formed: 100.0
|
||||||
|
error_outputs: 3
|
||||||
|
num_malformed_responses: 0
|
||||||
|
num_with_malformed_responses: 0
|
||||||
|
user_asks: 181
|
||||||
|
lazy_comments: 0
|
||||||
|
syntax_errors: 0
|
||||||
|
indentation_errors: 0
|
||||||
|
exhausted_context_windows: 1
|
||||||
|
test_timeouts: 3
|
||||||
|
total_tests: 225
|
||||||
|
command: aider --model openrouter/google/gemma-3-27b-it
|
||||||
|
date: 2025-03-15
|
||||||
|
versions: 0.77.1.dev
|
||||||
|
seconds_per_case: 79.7
|
||||||
|
total_cost: 0.0000
|
||||||
@@ -11,14 +11,14 @@ cd /to/your/project
|
|||||||
# Work with DeepSeek via DeepSeek's API
|
# Work with DeepSeek via DeepSeek's API
|
||||||
aider --model deepseek --api-key deepseek=your-key-goes-here
|
aider --model deepseek --api-key deepseek=your-key-goes-here
|
||||||
|
|
||||||
# Work with Claude 3.5 Sonnet via Anthropic's API
|
# Work with Claude 3.7 Sonnet via Anthropic's API
|
||||||
aider --model sonnet --api-key anthropic=your-key-goes-here
|
aider --model sonnet --api-key anthropic=your-key-goes-here
|
||||||
|
|
||||||
# Work with GPT-4o via OpenAI's API
|
# Work with GPT-4o via OpenAI's API
|
||||||
aider --model gpt-4o --api-key openai=your-key-goes-here
|
aider --model gpt-4o --api-key openai=your-key-goes-here
|
||||||
|
|
||||||
# Work with Sonnet via OpenRouter's API
|
# Work with Sonnet via OpenRouter's API
|
||||||
aider --model openrouter/anthropic/claude-3.5-sonnet --api-key openrouter=your-key-goes-here
|
aider --model openrouter/anthropic/claude-3.7-sonnet --api-key openrouter=your-key-goes-here
|
||||||
|
|
||||||
# Work with DeepSeek via OpenRouter's API
|
# Work with DeepSeek via OpenRouter's API
|
||||||
aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here
|
aider --model openrouter/deepseek/deepseek-chat --api-key openrouter=your-key-goes-here
|
||||||
|
|||||||
@@ -23,6 +23,16 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
return (label && label.includes(HIGHLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)';
|
return (label && label.includes(HIGHLIGHT_MODEL)) ? 'rgba(255, 99, 132, 1)' : 'rgba(54, 162, 235, 1)';
|
||||||
},
|
},
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
|
}, {
|
||||||
|
label: 'Total Cost ($)',
|
||||||
|
data: [],
|
||||||
|
type: 'scatter',
|
||||||
|
yAxisID: 'y1',
|
||||||
|
backgroundColor: 'rgba(153, 102, 255, 1)',
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 1,
|
||||||
|
pointRadius: 5,
|
||||||
|
pointHoverRadius: 7
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,7 +42,8 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
model: '{{ row.model }}',
|
model: '{{ row.model }}',
|
||||||
pass_rate: {{ row[pass_rate_field] }},
|
pass_rate: {{ row[pass_rate_field] }},
|
||||||
percent_cases_well_formed: {{ row.percent_cases_well_formed }},
|
percent_cases_well_formed: {{ row.percent_cases_well_formed }},
|
||||||
edit_format: '{{ row.edit_format | default: "diff" }}'
|
edit_format: '{{ row.edit_format | default: "diff" }}',
|
||||||
|
total_cost: {{ row.total_cost | default: 0 }}
|
||||||
});
|
});
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
@@ -43,6 +54,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
displayedData = [];
|
displayedData = [];
|
||||||
leaderboardData.labels = [];
|
leaderboardData.labels = [];
|
||||||
leaderboardData.datasets[0].data = [];
|
leaderboardData.datasets[0].data = [];
|
||||||
|
leaderboardData.datasets[1].data = [];
|
||||||
|
|
||||||
allData.forEach(function(row, index) {
|
allData.forEach(function(row, index) {
|
||||||
var rowElement = document.getElementById('edit-row-' + index);
|
var rowElement = document.getElementById('edit-row-' + index);
|
||||||
@@ -53,6 +65,8 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
displayedData.push(row);
|
displayedData.push(row);
|
||||||
leaderboardData.labels.push(row.model);
|
leaderboardData.labels.push(row.model);
|
||||||
leaderboardData.datasets[0].data.push(row.pass_rate);
|
leaderboardData.datasets[0].data.push(row.pass_rate);
|
||||||
|
// Only include cost if it's not zero (placeholder for unknown)
|
||||||
|
leaderboardData.datasets[1].data.push(row.total_cost > 0 ? row.total_cost : null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -111,10 +125,29 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
fillStyle: blueDiagonalPattern,
|
fillStyle: blueDiagonalPattern,
|
||||||
strokeStyle: 'rgba(54, 162, 235, 1)',
|
strokeStyle: 'rgba(54, 162, 235, 1)',
|
||||||
lineWidth: 1
|
lineWidth: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Total Cost ($)',
|
||||||
|
fillStyle: 'rgba(153, 102, 255, 1)',
|
||||||
|
strokeStyle: '#fff',
|
||||||
|
lineWidth: 1,
|
||||||
|
pointStyle: 'circle'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
callbacks: {
|
||||||
|
label: function(context) {
|
||||||
|
const datasetLabel = context.dataset.label || '';
|
||||||
|
const value = context.parsed.y;
|
||||||
|
if (datasetLabel === 'Total Cost ($)') {
|
||||||
|
return datasetLabel + ': $' + value.toFixed(2);
|
||||||
|
}
|
||||||
|
return datasetLabel + ': ' + value.toFixed(1) + '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
@@ -125,6 +158,17 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
text: 'Percent completed correctly'
|
text: 'Percent completed correctly'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
y1: {
|
||||||
|
beginAtZero: true,
|
||||||
|
position: 'right',
|
||||||
|
grid: {
|
||||||
|
drawOnChartArea: false
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: 'Total Cost ($)'
|
||||||
|
}
|
||||||
|
},
|
||||||
x: {
|
x: {
|
||||||
ticks: {
|
ticks: {
|
||||||
callback: function(value, index) {
|
callback: function(value, index) {
|
||||||
@@ -173,6 +217,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
displayedData = [];
|
displayedData = [];
|
||||||
leaderboardData.labels = [];
|
leaderboardData.labels = [];
|
||||||
leaderboardData.datasets[0].data = [];
|
leaderboardData.datasets[0].data = [];
|
||||||
|
leaderboardData.datasets[1].data = [];
|
||||||
|
|
||||||
for (var i = 0; i < rows.length; i++) {
|
for (var i = 0; i < rows.length; i++) {
|
||||||
var rowText = rows[i].textContent;
|
var rowText = rows[i].textContent;
|
||||||
@@ -181,6 +226,8 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
displayedData.push(allData[i]);
|
displayedData.push(allData[i]);
|
||||||
leaderboardData.labels.push(allData[i].model);
|
leaderboardData.labels.push(allData[i].model);
|
||||||
leaderboardData.datasets[0].data.push(allData[i].pass_rate);
|
leaderboardData.datasets[0].data.push(allData[i].pass_rate);
|
||||||
|
// Only include cost if it's not zero (placeholder for unknown)
|
||||||
|
leaderboardData.datasets[1].data.push(allData[i].total_cost > 0 ? allData[i].total_cost : null);
|
||||||
} else {
|
} else {
|
||||||
rows[i].style.display = 'none';
|
rows[i].style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|||||||
183
aider/website/_includes/recording.css
Normal file
183
aider/website/_includes/recording.css
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/* Terminal header styling */
|
||||||
|
.terminal-header {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
border-top-left-radius: 6px;
|
||||||
|
border-top-right-radius: 6px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #c0c0c0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-button {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-close {
|
||||||
|
background-color: #ff5f56;
|
||||||
|
border: 1px solid #e0443e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-minimize {
|
||||||
|
background-color: #ffbd2e;
|
||||||
|
border: 1px solid #dea123;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-expand {
|
||||||
|
background-color: #27c93f;
|
||||||
|
border: 1px solid #1aab29;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-title {
|
||||||
|
flex-grow: 1;
|
||||||
|
text-align: center;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toast notification styling */
|
||||||
|
.toast-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 9999;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-notification {
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
color: white;
|
||||||
|
padding: 12px 25px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Page container styling */
|
||||||
|
.page-container {
|
||||||
|
max-width: 900px;
|
||||||
|
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;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Timestamp link styling */
|
||||||
|
.timestamp-link {
|
||||||
|
color: #0366d6;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timestamp-link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Active timestamp styling */
|
||||||
|
.timestamp-active {
|
||||||
|
background-color: #f0f8ff; /* Light blue background */
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
margin: -2px -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Highlight the list item containing the active timestamp */
|
||||||
|
li.active-marker {
|
||||||
|
background-color: #f6f8fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make list items clickable */
|
||||||
|
.transcript-item {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
padding: 4px 8px;
|
||||||
|
margin-left: -8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transcript-item:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keyboard shortcuts styling */
|
||||||
|
.keyboard-shortcuts {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide keyboard shortcuts on devices likely without physical keyboards */
|
||||||
|
.no-physical-keyboard .keyboard-shortcuts {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyboard-shortcuts kbd {
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 1px 0 rgba(0,0,0,0.2);
|
||||||
|
color: #333;
|
||||||
|
display: inline-block;
|
||||||
|
font-family: monospace;
|
||||||
|
line-height: 1;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.asciinema-player-theme-aider {
|
||||||
|
/* Foreground (default text) color */
|
||||||
|
--term-color-foreground: #444444; /* colour238 */
|
||||||
|
|
||||||
|
/* Background color */
|
||||||
|
--term-color-background: #dadada; /* colour253 */
|
||||||
|
|
||||||
|
/* Palette of 16 standard ANSI colors */
|
||||||
|
--term-color-0: #21222c;
|
||||||
|
--term-color-1: #ff5555;
|
||||||
|
--term-color-2: #50fa7b;
|
||||||
|
--term-color-3: #f1fa8c;
|
||||||
|
--term-color-4: #bd93f9;
|
||||||
|
--term-color-5: #ff79c6;
|
||||||
|
--term-color-6: #8be9fd;
|
||||||
|
--term-color-7: #f8f8f2;
|
||||||
|
--term-color-8: #6272a4;
|
||||||
|
--term-color-9: #ff6e6e;
|
||||||
|
--term-color-10: #69ff94;
|
||||||
|
--term-color-11: #ffffa5;
|
||||||
|
--term-color-12: #d6acff;
|
||||||
|
--term-color-13: #ff92df;
|
||||||
|
--term-color-14: #a4ffff;
|
||||||
|
--term-color-15: #ffffff;
|
||||||
|
}
|
||||||
349
aider/website/_includes/recording.js
Normal file
349
aider/website/_includes/recording.js
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
let player; // Store player reference to make it accessible to click handlers
|
||||||
|
let globalAudio; // Global audio element to be reused
|
||||||
|
|
||||||
|
// Detect if device likely has no physical keyboard
|
||||||
|
function detectNoKeyboard() {
|
||||||
|
// Check if it's a touch device (most mobile devices)
|
||||||
|
const isTouchDevice = ('ontouchstart' in window) ||
|
||||||
|
(navigator.maxTouchPoints > 0) ||
|
||||||
|
(navigator.msMaxTouchPoints > 0);
|
||||||
|
|
||||||
|
// Check common mobile user agents as additional signal
|
||||||
|
const isMobileUA = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||||
|
|
||||||
|
// If it's a touch device and has a mobile user agent, likely has no physical keyboard
|
||||||
|
if (isTouchDevice && isMobileUA) {
|
||||||
|
document.body.classList.add('no-physical-keyboard');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run detection
|
||||||
|
detectNoKeyboard();
|
||||||
|
|
||||||
|
// Parse the transcript section to create markers and convert timestamps to links
|
||||||
|
function parseTranscript() {
|
||||||
|
const markers = [];
|
||||||
|
// Find the Commentary heading
|
||||||
|
const transcriptHeading = Array.from(document.querySelectorAll('h2')).find(el => el.textContent.trim() === 'Commentary');
|
||||||
|
|
||||||
|
if (transcriptHeading) {
|
||||||
|
// Get all list items after the transcript heading
|
||||||
|
let currentElement = transcriptHeading.nextElementSibling;
|
||||||
|
|
||||||
|
while (currentElement && currentElement.tagName === 'UL') {
|
||||||
|
const listItems = currentElement.querySelectorAll('li');
|
||||||
|
|
||||||
|
listItems.forEach(item => {
|
||||||
|
const text = item.textContent.trim();
|
||||||
|
const match = text.match(/(\d+):(\d+)\s+(.*)/);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const minutes = parseInt(match[1], 10);
|
||||||
|
const seconds = parseInt(match[2], 10);
|
||||||
|
const timeInSeconds = minutes * 60 + seconds;
|
||||||
|
const formattedTime = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||||
|
const message = match[3].trim();
|
||||||
|
|
||||||
|
// Create link for the timestamp
|
||||||
|
const timeLink = document.createElement('a');
|
||||||
|
timeLink.href = '#';
|
||||||
|
timeLink.textContent = formattedTime;
|
||||||
|
timeLink.className = 'timestamp-link';
|
||||||
|
timeLink.dataset.time = timeInSeconds;
|
||||||
|
timeLink.dataset.message = message;
|
||||||
|
|
||||||
|
// Add click event to seek the player
|
||||||
|
timeLink.addEventListener('click', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (player && typeof player.seek === 'function') {
|
||||||
|
player.seek(timeInSeconds);
|
||||||
|
player.play();
|
||||||
|
|
||||||
|
// Also trigger toast and speech
|
||||||
|
showToast(message);
|
||||||
|
speakText(message, timeInSeconds);
|
||||||
|
|
||||||
|
// Highlight this timestamp
|
||||||
|
highlightTimestamp(timeInSeconds);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Replace text with the link + message
|
||||||
|
item.textContent = '';
|
||||||
|
item.appendChild(timeLink);
|
||||||
|
item.appendChild(document.createTextNode(' ' + message));
|
||||||
|
|
||||||
|
// Add class and click handler to the entire list item
|
||||||
|
item.classList.add('transcript-item');
|
||||||
|
item.dataset.time = timeInSeconds;
|
||||||
|
item.dataset.message = message;
|
||||||
|
|
||||||
|
item.addEventListener('click', function(e) {
|
||||||
|
// Prevent click event if the user clicked directly on the timestamp link
|
||||||
|
// This prevents double-firing of the event
|
||||||
|
if (e.target !== timeLink) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (player && typeof player.seek === 'function') {
|
||||||
|
player.seek(timeInSeconds);
|
||||||
|
player.play();
|
||||||
|
|
||||||
|
// Also trigger toast and speech
|
||||||
|
showToast(message);
|
||||||
|
speakText(message, timeInSeconds);
|
||||||
|
|
||||||
|
// Highlight this timestamp
|
||||||
|
highlightTimestamp(timeInSeconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
markers.push([timeInSeconds, message]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
currentElement = currentElement.nextElementSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return markers;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse transcript and create markers
|
||||||
|
const markers = parseTranscript();
|
||||||
|
|
||||||
|
// Create player with a single call
|
||||||
|
player = AsciinemaPlayer.create(
|
||||||
|
recording_url,
|
||||||
|
document.getElementById('demo'),
|
||||||
|
{
|
||||||
|
speed: 1.25,
|
||||||
|
idleTimeLimit: 1,
|
||||||
|
theme: "aider",
|
||||||
|
poster: "npt:0:01",
|
||||||
|
markers: markers
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Focus on the player element so keyboard shortcuts work immediately
|
||||||
|
setTimeout(() => {
|
||||||
|
// Use setTimeout to ensure the player is fully initialized
|
||||||
|
if (player && typeof player.focus === 'function') {
|
||||||
|
player.focus();
|
||||||
|
} else {
|
||||||
|
// If player doesn't have a focus method, try to find and focus the terminal element
|
||||||
|
const playerElement = document.querySelector('.asciinema-terminal');
|
||||||
|
if (playerElement) {
|
||||||
|
playerElement.focus();
|
||||||
|
} else {
|
||||||
|
// Last resort - try to find element with tabindex
|
||||||
|
const tabbableElement = document.querySelector('[tabindex]');
|
||||||
|
if (tabbableElement) {
|
||||||
|
tabbableElement.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
// Function to display toast notification
|
||||||
|
function showToast(text) {
|
||||||
|
// Get the appropriate container based on fullscreen state
|
||||||
|
let container = document.getElementById('toast-container');
|
||||||
|
const isFullscreen = document.fullscreenElement ||
|
||||||
|
document.webkitFullscreenElement ||
|
||||||
|
document.mozFullScreenElement ||
|
||||||
|
document.msFullscreenElement;
|
||||||
|
|
||||||
|
// If in fullscreen, check if we need to create a fullscreen toast container
|
||||||
|
if (isFullscreen) {
|
||||||
|
// Target the fullscreen element as the container parent
|
||||||
|
const fullscreenElement = document.fullscreenElement ||
|
||||||
|
document.webkitFullscreenElement ||
|
||||||
|
document.mozFullScreenElement ||
|
||||||
|
document.msFullscreenElement;
|
||||||
|
|
||||||
|
// Look for an existing fullscreen toast container
|
||||||
|
let fsContainer = fullscreenElement.querySelector('.fs-toast-container');
|
||||||
|
|
||||||
|
if (!fsContainer) {
|
||||||
|
// Create a new container for fullscreen mode
|
||||||
|
fsContainer = document.createElement('div');
|
||||||
|
fsContainer.className = 'toast-container fs-toast-container';
|
||||||
|
fsContainer.id = 'fs-toast-container';
|
||||||
|
fullscreenElement.appendChild(fsContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
container = fsContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create toast element
|
||||||
|
const toast = document.createElement('div');
|
||||||
|
toast.className = 'toast-notification';
|
||||||
|
toast.textContent = text;
|
||||||
|
|
||||||
|
// Add to container
|
||||||
|
container.appendChild(toast);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Improved browser TTS function
|
||||||
|
function useBrowserTTS(text) {
|
||||||
|
if ('speechSynthesis' in window) {
|
||||||
|
console.log('Using browser TTS fallback');
|
||||||
|
|
||||||
|
// Cancel any ongoing speech
|
||||||
|
window.speechSynthesis.cancel();
|
||||||
|
|
||||||
|
const utterance = new SpeechSynthesisUtterance(text);
|
||||||
|
utterance.rate = 1.0;
|
||||||
|
utterance.pitch = 1.0;
|
||||||
|
utterance.volume = 1.0;
|
||||||
|
|
||||||
|
// For iOS, use a shorter utterance if possible
|
||||||
|
if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) {
|
||||||
|
utterance.text = text.length > 100 ? text.substring(0, 100) + '...' : text;
|
||||||
|
}
|
||||||
|
|
||||||
|
utterance.onstart = () => console.log('Speech started');
|
||||||
|
utterance.onend = () => console.log('Speech ended');
|
||||||
|
utterance.onerror = (e) => console.warn('Speech error:', e);
|
||||||
|
|
||||||
|
window.speechSynthesis.speak(utterance);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
console.warn('SpeechSynthesis not supported');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to play pre-generated TTS audio files
|
||||||
|
function speakText(text, timeInSeconds) {
|
||||||
|
// Format time for filename (MM-SS)
|
||||||
|
const minutes = Math.floor(timeInSeconds / 60);
|
||||||
|
const seconds = timeInSeconds % 60;
|
||||||
|
const formattedTime = `${minutes.toString().padStart(2, '0')}-${seconds.toString().padStart(2, '0')}`;
|
||||||
|
|
||||||
|
// Get recording_id from the page or use default from the URL
|
||||||
|
const recordingId = typeof recording_id !== 'undefined' ? recording_id :
|
||||||
|
window.location.pathname.split('/').pop().replace('.html', '');
|
||||||
|
|
||||||
|
// Construct audio file path
|
||||||
|
const audioPath = `/assets/audio/${recordingId}/${formattedTime}.mp3`;
|
||||||
|
|
||||||
|
// Log for debugging
|
||||||
|
console.log(`Attempting to play audio: ${audioPath}`);
|
||||||
|
|
||||||
|
// Detect iOS
|
||||||
|
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||||
|
console.log(`Device is iOS: ${isIOS}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create or reuse audio element
|
||||||
|
if (!globalAudio) {
|
||||||
|
globalAudio = new Audio();
|
||||||
|
console.log("Created new global Audio element");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up event handlers
|
||||||
|
globalAudio.onerror = (e) => {
|
||||||
|
console.warn(`Audio error: ${e.type}`, e);
|
||||||
|
useBrowserTTS(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
// For iOS, preload might help with subsequent plays
|
||||||
|
if (isIOS) {
|
||||||
|
globalAudio.preload = "auto";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new source
|
||||||
|
globalAudio.src = audioPath;
|
||||||
|
|
||||||
|
// Play with proper error handling
|
||||||
|
const playPromise = globalAudio.play();
|
||||||
|
|
||||||
|
if (playPromise !== undefined) {
|
||||||
|
playPromise.catch(error => {
|
||||||
|
console.warn(`Play error: ${error.message}`);
|
||||||
|
|
||||||
|
// On iOS, a user gesture might be required
|
||||||
|
if (isIOS) {
|
||||||
|
console.log("iOS playback failed, trying SpeechSynthesis");
|
||||||
|
}
|
||||||
|
|
||||||
|
useBrowserTTS(text);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Exception in audio playback: ${e.message}`);
|
||||||
|
useBrowserTTS(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to highlight the active timestamp in the transcript
|
||||||
|
function highlightTimestamp(timeInSeconds) {
|
||||||
|
// Remove previous highlights
|
||||||
|
document.querySelectorAll('.timestamp-active').forEach(el => {
|
||||||
|
el.classList.remove('timestamp-active');
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('.active-marker').forEach(el => {
|
||||||
|
el.classList.remove('active-marker');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find the timestamp link with matching time
|
||||||
|
const timestampLinks = document.querySelectorAll('.timestamp-link');
|
||||||
|
let activeLink = null;
|
||||||
|
|
||||||
|
for (const link of timestampLinks) {
|
||||||
|
if (parseInt(link.dataset.time) === timeInSeconds) {
|
||||||
|
activeLink = link;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeLink) {
|
||||||
|
// Add highlight class to the link
|
||||||
|
activeLink.classList.add('timestamp-active');
|
||||||
|
|
||||||
|
// Also highlight the parent list item
|
||||||
|
const listItem = activeLink.closest('li');
|
||||||
|
if (listItem) {
|
||||||
|
listItem.classList.add('active-marker');
|
||||||
|
|
||||||
|
// No longer scrolling into view to avoid shifting focus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listener with safety checks
|
||||||
|
if (player && typeof player.addEventListener === 'function') {
|
||||||
|
player.addEventListener('marker', function(event) {
|
||||||
|
try {
|
||||||
|
const { index, time, label } = event;
|
||||||
|
console.log(`marker! ${index} - ${time} - ${label}`);
|
||||||
|
|
||||||
|
// Speak the marker label and show toast
|
||||||
|
speakText(label, time);
|
||||||
|
showToast(label);
|
||||||
|
|
||||||
|
// Highlight the corresponding timestamp in the transcript
|
||||||
|
highlightTimestamp(time);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in marker event handler:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
32
aider/website/_includes/recording.md
Normal file
32
aider/website/_includes/recording.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<link rel="stylesheet" type="text/css" href="/assets/asciinema/asciinema-player.css" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
{% include recording.css %}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script src="/assets/asciinema/asciinema-player.min.js"></script>
|
||||||
|
<script>
|
||||||
|
{% include recording.js %}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<div class="terminal-title">aider</div>
|
||||||
|
</div>
|
||||||
|
<div id="demo"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="keyboard-shortcuts">
|
||||||
|
<kbd>Space</kbd> Play/pause —
|
||||||
|
<kbd>f</kbd> Fullscreen —
|
||||||
|
<kbd>←</kbd><kbd>→</kbd> ±5s
|
||||||
|
</div>
|
||||||
@@ -1 +1 @@
|
|||||||
Aider works best with Claude 3.5 Sonnet, DeepSeek V3, o1 & GPT-4o and can [connect to almost any LLM](https://aider.chat/docs/llms.html).
|
Aider works best with Claude 3.5 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).
|
||||||
|
|||||||
@@ -39,9 +39,7 @@ Aider will directly edit the code in your local source files,
|
|||||||
and [git commit the changes](https://aider.chat/docs/git.html)
|
and [git commit the changes](https://aider.chat/docs/git.html)
|
||||||
with sensible commit messages.
|
with sensible commit messages.
|
||||||
You can start a new project or work with an existing git repo.
|
You can start a new project or work with an existing git repo.
|
||||||
Aider works well with GPT 3.5, GPT-4, GPT-4 Turbo with Vision,
|
{% include works-best.md %}
|
||||||
and Claude 3 Opus.
|
|
||||||
It also supports [connecting to almost any LLM](https://aider.chat/docs/llms.html).
|
|
||||||
|
|
||||||
Use the `--browser` switch to launch the browser version of aider:
|
Use the `--browser` switch to launch the browser version of aider:
|
||||||
|
|
||||||
|
|||||||
2366
aider/website/assets/asciinema/asciinema-player.css
Normal file
2366
aider/website/assets/asciinema/asciinema-player.css
Normal file
File diff suppressed because it is too large
Load Diff
1
aider/website/assets/asciinema/asciinema-player.min.js
vendored
Normal file
1
aider/website/assets/asciinema/asciinema-player.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
aider/website/assets/audio/auto-accept-architect/00-01.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/00-01.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/00-11.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/00-11.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/00-40.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/00-40.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/00-48.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/00-48.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/01-00.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/01-00.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/01-28.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/01-28.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/01-42.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/01-42.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/02-00.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/02-00.mp3
Normal file
Binary file not shown.
BIN
aider/website/assets/audio/auto-accept-architect/02-05.mp3
Normal file
BIN
aider/website/assets/audio/auto-accept-architect/02-05.mp3
Normal file
Binary file not shown.
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"00-01": "We're going to add a new feature to automatically accept edits proposed by the architect model.",
|
||||||
|
"00-11": "First, let's add the new switch.",
|
||||||
|
"00-40": "Aider figured out that it should be passed to the Coder class.",
|
||||||
|
"00-48": "Now we need to implement the functionality.",
|
||||||
|
"01-00": "Let's do some manual testing.",
|
||||||
|
"01-28": "That worked. Let's make sure we can turn it off too.",
|
||||||
|
"02-00": "Let's quickly tidy up the changes to HISTORY.",
|
||||||
|
"02-05": "All done!",
|
||||||
|
"01-42": "That worked too. Let's have aider update the HISTORY file to document the new feature."
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user