Compare commits

...

313 Commits

Author SHA1 Message Date
Paul Gauthier
305b4fee87 set version to 0.61.1.dev 2024-11-01 09:40:02 -07:00
Paul Gauthier
9e18fc55d3 version bump to 0.61.0 2024-11-01 09:38:46 -07:00
Paul Gauthier
ebc9a30cc6 copy 2024-11-01 09:23:37 -07:00
Paul Gauthier
f53f5927df Show friendly API error messages 2024-11-01 09:20:31 -07:00
Paul Gauthier (aider)
78a8d19ac5 fix: pass exception objects directly to check_and_open_urls 2024-11-01 09:12:50 -07:00
Paul Gauthier
bfa9dce1e0 refactor: improve API error messages and display format 2024-11-01 09:12:49 -07:00
Paul Gauthier (aider)
3b2f1f1e66 style: format long error messages with line breaks 2024-11-01 09:09:03 -07:00
Paul Gauthier (aider)
b2bcca967f refactor: update check_and_open_urls to handle exceptions with friendly messages 2024-11-01 09:08:57 -07:00
Paul Gauthier
929aeb22bf refactor: Update check_and_open_urls to handle exceptions with user-friendly messages 2024-11-01 09:08:56 -07:00
Paul Gauthier
66ad186edd start /save commands with /drop 2024-11-01 09:04:55 -07:00
Paul Gauthier
c098354a67 copy 2024-11-01 09:03:44 -07:00
Paul Gauthier (aider)
d67d319b31 style: fix whitespace and line spacing issues 2024-11-01 08:12:17 -07:00
Paul Gauthier (aider)
93639039d4 feat: disable spinner when stdout is not a tty 2024-11-01 08:12:13 -07:00
Paul Gauthier
789535cb85 feat: disable spinner animation when stdout is not a tty 2024-11-01 08:12:11 -07:00
Paul Gauthier
d8e1e823e7 update deps with chained constraints 2024-10-31 16:04:37 -07:00
Paul Gauthier (aider)
5b9fe6fee0 refactor: convert pip-compile script to use loop for requirements compilation 2024-10-31 16:03:12 -07:00
Paul Gauthier (aider)
91bc8cddf3 fix: add dependency constraints between requirements files 2024-10-31 16:02:33 -07:00
Paul Gauthier
392162ae84 copy 2024-10-31 15:33:17 -07:00
Paul Gauthier
0c4e4a123a pin pillow<11 to avoid regressing streamlit to ancient 1.22 2024-10-31 15:31:58 -07:00
Paul Gauthier (aider)
27711010a0 refactor: update --gui/--browser to use BooleanOptionalAction 2024-10-31 15:01:29 -07:00
Paul Gauthier
401967c27f refactor: convert browser flag to boolean argument 2024-10-31 15:01:26 -07:00
Paul Gauthier (aider)
d1b25b9a72 fix: remove duplicate test_cmd_read_only_with_image_file method 2024-10-31 15:00:21 -07:00
Paul Gauthier
df478e1f8f copy 2024-10-31 14:59:52 -07:00
Paul Gauthier (aider)
a459f0e130 test: add test for read-only command with image files 2024-10-31 14:59:46 -07:00
Paul Gauthier (aider)
66b6788990 test: add test for image file handling in read command 2024-10-31 14:59:22 -07:00
Paul Gauthier (aider)
624f9122ab style: fix whitespace in commands.py 2024-10-31 14:58:29 -07:00
Paul Gauthier (aider)
704350286c feat: allow /read command to work with images for vision models 2024-10-31 14:58:23 -07:00
Paul Gauthier (aider)
ec40ff5987 feat: prevent adding image files with /read command 2024-10-31 14:57:44 -07:00
Paul Gauthier
af7aaad903 fix: handle RecursionError during tree traversal in linter 2024-10-31 14:55:54 -07:00
Paul Gauthier
3794cf941f feat: add support for claude-3-5-sonnet-latest model 2024-10-31 14:53:50 -07:00
Paul Gauthier
72c1f25005 refactor: Move StringIO import to top of file 2024-10-31 14:49:16 -07:00
Paul Gauthier (aider)
c13536e641 style: move rich.columns import to top of file 2024-10-31 14:48:12 -07:00
Paul Gauthier (aider)
7a9988c060 style: fix linting issues in io.py 2024-10-31 14:45:35 -07:00
Paul Gauthier (aider)
b9939d4bd9 refactor: improve file list display with section headers 2024-10-31 14:45:31 -07:00
Paul Gauthier (aider)
b71a3148cf style: fix import order in io.py 2024-10-31 14:43:29 -07:00
Paul Gauthier (aider)
42abdb0a41 feat: add compact file listing using rich Columns when pretty=True 2024-10-31 14:43:25 -07:00
Paul Gauthier
4c39e92773 copy 2024-10-31 14:39:27 -07:00
Paul Gauthier
b7f7204c4e copy 2024-10-31 14:29:53 -07:00
Paul Gauthier (aider)
8f73c15f48 feat: skip analytics update in check mode 2024-10-31 14:16:34 -07:00
Paul Gauthier
17330e53c3 refactor: Improve error handling and URL processing in chat functionality 2024-10-31 14:13:36 -07:00
Paul Gauthier (aider)
3fcd79e165 style: fix line length and comment formatting 2024-10-31 14:03:33 -07:00
Paul Gauthier (aider)
750b12282f refactor: strip trailing punctuation from URLs before displaying 2024-10-31 14:03:27 -07:00
Paul Gauthier
94c5ff2fd2 refactor: simplify URL pattern matching and cleanup commented code 2024-10-31 14:03:26 -07:00
Paul Gauthier
85ad2826da test: add debug dump of URL pattern regex 2024-10-31 14:02:05 -07:00
Paul Gauthier
15c62e3e43 fix: improve URL pattern to handle trailing commas in links 2024-10-31 14:01:41 -07:00
Paul Gauthier (aider)
fea7134064 style: fix comment spacing and remove commented code 2024-10-31 14:01:28 -07:00
Paul Gauthier (aider)
da706d9eb8 fix: update URL regex to strip trailing punctuation 2024-10-31 14:01:21 -07:00
Paul Gauthier
9a37c0491d refactor: improve URL handling and error reporting in base coder 2024-10-31 14:01:20 -07:00
Paul Gauthier (aider)
1d3d6a589f style: remove unused Optional import 2024-10-31 13:52:50 -07:00
Paul Gauthier (aider)
c5a439e4e8 style: sort imports alphabetically in base_coder.py 2024-10-31 13:52:41 -07:00
Paul Gauthier (aider)
2b7584b651 refactor: extract URL checking logic into separate method 2024-10-31 13:52:37 -07:00
Paul Gauthier (aider)
1ef60b5a40 refactor: add URL checking function with browser open option 2024-10-31 13:52:24 -07:00
Paul Gauthier
b79321da51 chore: add TODO comments for URL handling refactoring 2024-10-31 13:52:22 -07:00
Paul Gauthier (aider)
6829b29ef4 feat: add error base class hierarchy to retry exception messages 2024-10-31 13:50:12 -07:00
Paul Gauthier
a9c0d20347 chore: add comment about error base class inspection 2024-10-31 13:50:11 -07:00
Paul Gauthier (aider)
25a906950c refactor: move webbrowser import to top of file 2024-10-31 13:48:28 -07:00
Paul Gauthier
740534dcff refactor: Move webbrowser import to top of file 2024-10-31 13:48:27 -07:00
Paul Gauthier (aider)
de65d86122 style: fix string quotes and line wrapping in error URL handling 2024-10-31 13:48:08 -07:00
Paul Gauthier (aider)
98bf9bd26d feat: add URL detection and viewer for error messages 2024-10-31 13:48:01 -07:00
Paul Gauthier
ade615c445 chore: Add TODO comment for URL handling in error messages 2024-10-31 13:48:00 -07:00
Paul Gauthier
d959e1c60d test: fix analytics disable test assertion for better clarity 2024-10-31 13:31:43 -07:00
Paul Gauthier (aider)
8d2f66fe34 test: add temp_data_dir fixture to all analytics tests 2024-10-31 13:28:31 -07:00
Paul Gauthier (aider)
66dc8dbccd style: remove unused MagicMock import 2024-10-31 13:22:59 -07:00
Paul Gauthier (aider)
b228bcab8c style: Fix linting issues in test_analytics.py 2024-10-31 13:22:50 -07:00
Paul Gauthier (aider)
ccbf1482c1 test: add comprehensive test suite for Analytics class 2024-10-31 13:22:47 -07:00
Paul Gauthier
f9a0946472 test: add basic analytics test suite 2024-10-31 13:22:45 -07:00
Paul Gauthier
faa80b7699 updated deps 2024-10-31 13:21:56 -07:00
Paul Gauthier
1eb2c724a5 copy 2024-10-31 13:15:33 -07:00
Paul Gauthier
c43e7f998e copy 2024-10-31 13:11:00 -07:00
Paul Gauthier
3e2454b84b cleanup 2024-10-31 11:49:17 -07:00
Paul Gauthier
2817766cf5 cleanup 2024-10-31 11:44:24 -07:00
Paul Gauthier
ba7656bc1c cleanup 2024-10-31 11:37:18 -07:00
Paul Gauthier
c14392a35a copy 2024-10-31 11:33:27 -07:00
Paul Gauthier
6bfb258473 copy 2024-10-31 11:31:32 -07:00
Paul Gauthier
1e872599fd copy 2024-10-31 11:02:04 -07:00
Paul Gauthier
c08b7f9c22 Merge branch 'main' into mixpanel 2024-10-31 10:09:36 -07:00
Paul Gauthier
6e4ccf8715 copy 2024-10-31 10:09:33 -07:00
Paul Gauthier (aider)
e4913669d4 refactor: simplify event method to use main_model attributes 2024-10-31 10:08:43 -07:00
Paul Gauthier
8e098752bd refactor: Use main_model attributes for weak and editor models in analytics 2024-10-31 10:08:41 -07:00
Paul Gauthier (aider)
6867dab89c style: remove trailing whitespace in analytics.py 2024-10-31 10:06:52 -07:00
Paul Gauthier (aider)
09a9fac91e refactor: extract model redaction logic and add model params 2024-10-31 10:05:10 -07:00
Paul Gauthier
2fd1681fab refactor: add weak_model and editor_model args to analytics event method 2024-10-31 10:05:08 -07:00
Paul Gauthier
ece91dc724 copy 2024-10-31 09:57:22 -07:00
Paul Gauthier
01bf154151 copy 2024-10-31 09:53:04 -07:00
Paul Gauthier
b5916981b3 copy 2024-10-30 20:19:47 -07:00
Paul Gauthier
a68b87272b copy 2024-10-30 20:19:08 -07:00
Paul Gauthier (aider)
88b55df1c6 chore: add privacy policy to update-docs script 2024-10-30 20:18:41 -07:00
Paul Gauthier (aider)
676c017eb1 feat: add git-based last updated date to privacy policy 2024-10-30 20:17:53 -07:00
Paul Gauthier
139b8a2d4a docs: add privacy policy document 2024-10-30 20:17:15 -07:00
Paul Gauthier
24c68928d6 feat: Add analytics tracking for model warnings 2024-10-30 14:34:27 -07:00
Paul Gauthier
f957111141 feat: Add model info manager import to analytics module 2024-10-30 14:30:14 -07:00
Paul Gauthier
e94e60b1d2 refactor: improve model name redaction in analytics and model info handling 2024-10-30 14:29:29 -07:00
Paul Gauthier (aider)
a565a63436 style: Fix import formatting in test_models.py 2024-10-30 13:21:47 -07:00
Paul Gauthier (aider)
a045bda171 refactor: update test to use ModelInfoManager instead of get_model_info 2024-10-30 13:21:43 -07:00
Paul Gauthier (aider)
a3d78e0944 style: split long URL string constant into multiple lines 2024-10-30 13:21:21 -07:00
Paul Gauthier
8082cbed98 refactor: rename get_model_flexible to get_model_from_cached_json_db 2024-10-30 13:21:19 -07:00
Paul Gauthier (aider)
aba8b5d00a style: fix linting issues and whitespace in models.py 2024-10-30 13:17:54 -07:00
Paul Gauthier (aider)
3d5a4d9303 refactor: encapsulate model info functionality into ModelInfoManager class 2024-10-30 13:17:49 -07:00
Paul Gauthier
a899b0e27e refactor: Extract model info handling into a dedicated class 2024-10-30 13:17:47 -07:00
Paul Gauthier
267872b7e4 feat: add opt-in analytics collection with privacy notice 2024-10-30 13:15:57 -07:00
Paul Gauthier (aider)
bd59a8debf refactor: extract analytics disable logic into dedicated method 2024-10-30 12:25:18 -07:00
Paul Gauthier
c0e137889c style: Update analytics refactoring comment with method name 2024-10-30 12:25:17 -07:00
Paul Gauthier
5b84b901b2 chore: add TODO comment for analytics refactoring 2024-10-30 12:24:39 -07:00
Paul Gauthier (aider)
059883abf7 feat: add asked_opt_in tracking to analytics 2024-10-30 12:17:17 -07:00
Paul Gauthier
0b622a6fd7 chore: add comment for analytics opt-in tracking implementation 2024-10-30 12:17:15 -07:00
Paul Gauthier
97989dd51a Merge branch 'main' into mixpanel 2024-10-30 12:06:38 -07:00
Paul Gauthier (aider)
d81c421bfe test: mock webbrowser.open in test setup 2024-10-30 12:04:43 -07:00
Paul Gauthier (aider)
bce586f510 fix: remove unused webbrowser import in test file 2024-10-30 12:00:12 -07:00
Paul Gauthier (aider)
a70b364842 style: fix import order and quote style in test file 2024-10-30 11:59:52 -07:00
Paul Gauthier (aider)
920e8da57c test: mock webbrowser.open in git index version test 2024-10-30 11:59:48 -07:00
Paul Gauthier (aider)
71a8b286dc style: fix linting issues in test_sanity_check_repo.py 2024-10-30 11:59:25 -07:00
Paul Gauthier (aider)
ee4decc50b fix: add missing urls import in test_sanity_check_repo.py 2024-10-30 11:59:21 -07:00
Paul Gauthier (aider)
63330aa833 style: fix line wrapping in test file 2024-10-30 11:59:08 -07:00
Paul Gauthier (aider)
15a0eb976f test: update git index version test to check confirm_ask call 2024-10-30 11:59:04 -07:00
Paul Gauthier
4f52ad385a copy 2024-10-30 11:52:09 -07:00
Paul Gauthier
cd1496f91b copy 2024-10-30 11:51:49 -07:00
Paul Gauthier (aider)
31babf39cd style: fix comment spacing in sanity_check_repo function 2024-10-30 11:42:50 -07:00
Paul Gauthier (aider)
fe3dbba1d9 feat: add browser URL launch with user confirmation prompt 2024-10-30 11:42:46 -07:00
Paul Gauthier
763724ed4e docs: add comment about prompting user for URL opening 2024-10-30 11:42:44 -07:00
Paul Gauthier
9e0e68caf9 copy 2024-10-30 11:41:39 -07:00
Paul Gauthier
52f697e513 style: remove extra blank line before main block 2024-10-30 11:41:11 -07:00
Paul Gauthier (aider)
aeca62bcf6 fix: remove unused import of urls module 2024-10-30 11:41:04 -07:00
Paul Gauthier
7e574bc214 refactor: improve documentation URL handling and error messages 2024-10-30 11:40:56 -07:00
Paul Gauthier (aider)
e9beb1336c style: fix line length in model warnings confirmation prompt 2024-10-30 11:34:24 -07:00
Paul Gauthier (aider)
4ac8386313 feat: add browser launch for model warnings documentation 2024-10-30 11:34:19 -07:00
Paul Gauthier
f0233455d2 feat: update model warning prompt to offer documentation link 2024-10-30 11:34:18 -07:00
Paul Gauthier
5c28dd039c pip compile 2024-10-30 09:41:57 -07:00
Paul Gauthier
26d1ab7a5f copy 2024-10-30 09:40:54 -07:00
Paul Gauthier
068fb38a5d Merge branch 'main' into mixpanel 2024-10-30 09:40:01 -07:00
Paul Gauthier
53e7eba00b copy 2024-10-30 06:39:48 -07:00
Paul Gauthier
854d908fe0 refactor: improve chat history file error handling and messaging 2024-10-30 06:37:59 -07:00
Paul Gauthier
ea3359fb4b test: adjust warning count assertion in model test 2024-10-30 06:33:31 -07:00
Paul Gauthier (aider)
55a2ba4bd6 style: Fix comment formatting in test_models.py 2024-10-30 06:32:22 -07:00
Paul Gauthier (aider)
20ca9c84c7 test: add warning message debug print in model test 2024-10-30 06:32:18 -07:00
Paul Gauthier
0d86124b15 test: add comment about tool warning args inspection 2024-10-30 06:32:17 -07:00
Paul Gauthier
554fa98c48 fix: simplify version check for dev mode 2024-10-30 06:30:11 -07:00
Paul Gauthier (aider)
eb92fa4f88 fix: handle TypeError when checking __version__ for dev mode 2024-10-30 06:26:50 -07:00
Paul Gauthier
0424e4b00a refactor: improve SQLite error handling and logging in tags cache 2024-10-29 15:09:22 -07:00
Paul Gauthier (aider)
adca062081 feat: improve SQLite error handling with original exception details 2024-10-29 15:05:16 -07:00
Paul Gauthier
ef0fcb8f38 refactor: Improve SQLite cache error handling and import organization 2024-10-29 15:04:00 -07:00
Paul Gauthier (aider)
0feed0047c style: fix whitespace and formatting in repomap.py 2024-10-29 14:59:55 -07:00
Paul Gauthier (aider)
7f027ff6e5 feat: add auto-recovery for corrupted tags cache 2024-10-29 14:59:50 -07:00
Paul Gauthier (aider)
e25a46c892 fix: wrap TAGS_CACHE length check in try/except block for SQLite errors 2024-10-29 14:58:00 -07:00
Paul Gauthier (aider)
68916b1186 feat: add error handling for SQLite tags cache operations 2024-10-29 14:55:43 -07:00
Paul Gauthier
e9771588e4 copy 2024-10-29 14:48:39 -07:00
Paul Gauthier
e1d55c82b1 refactor: Improve edit handling with dry run and path resolution 2024-10-29 14:31:12 -07:00
Paul Gauthier (aider)
5b6be29c1c chore: remove obsolete comment about path variable 2024-10-29 14:28:39 -07:00
Paul Gauthier
28d9f6f8da refactor: add dry run mode to apply_edits method 2024-10-29 14:28:38 -07:00
Paul Gauthier (aider)
3ccae4eff7 style: fix line length in test_commands.py 2024-10-29 14:19:53 -07:00
Paul Gauthier (aider)
3ad240a10e fix: normalize path separators in save/load tests for Windows compatibility 2024-10-29 14:19:47 -07:00
Paul Gauthier
87a31a583a refactor: remove unused comment in EditBlockCoder 2024-10-29 14:11:13 -07:00
Paul Gauthier (aider)
7553104433 refactor: handle updated edits array returned from apply_edits 2024-10-29 14:10:21 -07:00
Paul Gauthier
f9604633e6 fix: handle updated edits array in apply_edits return value 2024-10-29 14:10:19 -07:00
Paul Gauthier (aider)
eb9a73bdb0 fix: strip whitespace from file paths before resolving in test commands 2024-10-29 14:04:19 -07:00
Paul Gauthier (aider)
d75e75190d style: Fix regex string formatting in test commands 2024-10-29 14:03:46 -07:00
Paul Gauthier (aider)
94a49e601c refactor: use regex to normalize /add command spaces in tests 2024-10-29 14:03:40 -07:00
Paul Gauthier (aider)
3df3d86295 style: fix linting issues in test_commands.py 2024-10-29 14:02:43 -07:00
Paul Gauthier (aider)
63f8979f2b fix: normalize whitespace in command text assertions 2024-10-29 14:02:37 -07:00
Paul Gauthier
ad94e49ef5 test: fix failing test cases for save and load commands 2024-10-29 14:02:35 -07:00
Paul Gauthier
b40ff2a601 fix: improve o1 model detection with startswith check 2024-10-29 14:00:56 -07:00
Paul Gauthier
a4be01b474 refactor: move --load command execution before message processing 2024-10-29 13:59:41 -07:00
Paul Gauthier
c5dc44a73f style: simplify command execution output message 2024-10-29 13:59:04 -07:00
Paul Gauthier (aider)
358cbc9388 feat: add filename autocompletion to /load and /save commands 2024-10-29 13:58:25 -07:00
Paul Gauthier
2e5fa9dea4 style: align /add commands in history file for better readability 2024-10-29 13:58:23 -07:00
Paul Gauthier
717592463e feat: add --load option to execute commands from file on launch 2024-10-29 13:54:42 -07:00
Paul Gauthier (aider)
347a9f2a6d feat: add --load argument to execute commands from file 2024-10-29 13:53:19 -07:00
Paul Gauthier
d288122fab chore: add comment for load command implementation 2024-10-29 13:53:17 -07:00
Paul Gauthier (aider)
d1cf3d4600 refactor: conditionally set cursor shape only in vi mode 2024-10-29 13:50:40 -07:00
Paul Gauthier
5188872791 style: add comment about vi mode cursor config 2024-10-29 13:50:38 -07:00
Paul Gauthier
a57a06e8c7 Merge branch 'main' of github.com:Aider-AI/aider 2024-10-29 13:49:50 -07:00
Paul Gauthier (aider)
347ad34038 fix: update file path comparison in commands test to handle macOS prefix 2024-10-29 13:48:16 -07:00
Paul Gauthier (aider)
ccdd333ba3 fix: update test to use os.path.samefile for path comparison 2024-10-29 13:45:03 -07:00
Paul Gauthier (aider)
56f3220d4c fix: handle macOS /private/ prefix in file path tests 2024-10-29 13:21:31 -07:00
Paul Gauthier (aider)
26a85c2047 style: fix line length in test_commands.py 2024-10-29 13:20:49 -07:00
Paul Gauthier (aider)
f800ce1e5a test: use os.path.samefile for file path comparison in save/load test 2024-10-29 13:20:44 -07:00
Paul Gauthier
d4103cc271 chore: Remove unused comment in test file 2024-10-29 13:20:42 -07:00
Paul Gauthier (aider)
c3ba3b6f48 style: fix whitespace and comment formatting in test_commands.py 2024-10-29 13:19:15 -07:00
Paul Gauthier (aider)
be54df4084 refactor: improve path comparison in command tests using os.path.samefile 2024-10-29 13:19:09 -07:00
Paul Gauthier
d06c6f8557 style: improve clarity of comment in test_commands.py 2024-10-29 13:18:53 -07:00
Paul Gauthier
a876561ea0 test: add comment about parsing text in session file test 2024-10-29 13:17:50 -07:00
Paul Gauthier (aider)
6dc0b8d853 fix: use absolute paths for read-only files outside repo root 2024-10-29 13:14:37 -07:00
Paul Gauthier (aider)
460311d49e style: fix line continuation formatting in test file 2024-10-29 13:11:50 -07:00
Paul Gauthier (aider)
94396070e8 test: add test for saving and loading multiple external files 2024-10-29 13:11:44 -07:00
Paul Gauthier (aider)
4a3cb8dc95 fix: use platform-agnostic paths in test_commands.py 2024-10-29 13:11:00 -07:00
Paul Gauthier
f9005451fa test: add comment about Windows path separator issue in test_commands.py 2024-10-29 13:10:58 -07:00
paul-gauthier
16e292b1fd Merge pull request #2180 from kAIto47802/fix-o1-system-prompt 2024-10-29 13:03:35 -07:00
Paul Gauthier (aider)
7d37793765 style: fix linting issues by removing extra blank line 2024-10-29 12:54:12 -07:00
Paul Gauthier (aider)
9e9c162a16 style: fix indentation in test_cmd_save_and_load_with_external_file 2024-10-29 12:54:05 -07:00
Paul Gauthier (aider)
8d6db81a40 style: fix linting issues in test_commands.py 2024-10-29 12:53:27 -07:00
Paul Gauthier (aider)
425bd8932b test: add save/load test with external read-only file 2024-10-29 12:53:22 -07:00
Paul Gauthier
38820701be test: add comment for read-only file test case 2024-10-29 12:53:20 -07:00
Paul Gauthier
1bc74676ff copy 2024-10-29 12:49:16 -07:00
Paul Gauthier (aider)
0c37f002c9 style: remove extra newlines and fix trailing comma 2024-10-29 12:48:21 -07:00
Paul Gauthier (aider)
18c41b6128 refactor: move test_cmd_save_and_load to test_commands.py 2024-10-29 12:48:11 -07:00
Paul Gauthier
5876af4e94 test: add test for cmd_save and cmd_load functionality 2024-10-29 12:48:08 -07:00
Paul Gauthier (aider)
e1d145013a style: remove trailing newline in test_commands.py 2024-10-29 12:46:37 -07:00
Paul Gauthier (aider)
143eeff4da test: add tests for cmd_save and cmd_load commands 2024-10-29 12:46:31 -07:00
Paul Gauthier
3a7e4bac34 test: add TODO comment for cmd_save and cmd_load test coverage 2024-10-29 12:46:29 -07:00
Paul Gauthier (aider)
f5ca162576 style: fix whitespace and comment formatting 2024-10-29 12:43:56 -07:00
Paul Gauthier (aider)
dbefa6b010 feat: add /save command to store chat session file list 2024-10-29 12:43:51 -07:00
Paul Gauthier
79cdff6163 feat: add /save command to persist added files for /load 2024-10-29 12:43:49 -07:00
Paul Gauthier (aider)
b111fc357c fix: use IO encoding and handle decode errors in cmd_load 2024-10-29 12:42:33 -07:00
Paul Gauthier
2af48e159c feat: add encoding hint for file loading in commands 2024-10-29 12:42:31 -07:00
Paul Gauthier (aider)
6cec44e402 style: fix string quotes and whitespace in commands.py 2024-10-29 12:41:10 -07:00
Paul Gauthier (aider)
fc6c01a9a5 feat: add command to load and execute commands from file 2024-10-29 12:41:01 -07:00
Paul Gauthier
01439875af feat: add comment for future cmd_load implementation 2024-10-29 12:40:57 -07:00
kAIto47802
fcdf998fac Fix o1 settings 2024-10-29 08:47:24 +09:00
Paul Gauthier
ed4ad45e3d copy 2024-10-28 15:12:06 -07:00
Paul Gauthier
907c1dbe2b refactor: split error and retry messages in simple_send_with_retries 2024-10-28 15:10:27 -07:00
Paul Gauthier (aider)
3baad86afd refactor: consolidate error and retry messages into single print statement 2024-10-28 15:09:22 -07:00
Paul Gauthier (aider)
0351924628 test: update print call count assertions in sendchat tests 2024-10-28 15:09:11 -07:00
Paul Gauthier
29250f82ed test: fix print call count assertions in sendchat tests 2024-10-28 15:07:50 -07:00
Paul Gauthier
a819bf1d64 test: fix assertion errors in sendchat retry tests 2024-10-28 15:07:11 -07:00
Paul Gauthier (aider)
bc515cf74a refactor: add retry loop to simple_send_with_retries function 2024-10-28 15:05:07 -07:00
Paul Gauthier
f9c45432e6 refactor: Move retry logic from base_coder to sendchat module 2024-10-28 15:05:06 -07:00
Paul Gauthier
54d55c857b refactor: update retry exceptions to use openai instead of litellm 2024-10-28 14:40:42 -07:00
Paul Gauthier
8e2a4b47d6 fix: update litellm exception imports and error handling 2024-10-28 14:29:42 -07:00
Paul Gauthier (aider)
513f06be46 refactor: move retry_exceptions import to top of test file 2024-10-28 14:28:49 -07:00
Paul Gauthier
0fb79917ff test: add test for retry_exceptions function call 2024-10-28 14:28:48 -07:00
Paul Gauthier (aider)
cd133f95ee style: fix linting issues with whitespace and line breaks 2024-10-28 14:27:26 -07:00
Paul Gauthier (aider)
3d66b53791 test: add basic test for retry_exceptions function 2024-10-28 14:27:20 -07:00
Paul Gauthier
bf63e7045b refactor: simplify litellm exception imports 2024-10-28 14:27:19 -07:00
Paul Gauthier
e2dff0a74b #2120 2024-10-25 15:47:30 -07:00
Paul Gauthier (aider)
bf60e58d5b fix: use os.path.join for cross-platform path handling in tests 2024-10-25 10:57:04 -07:00
Paul Gauthier
e3a3a55dd5 fix: make file paths portable for Windows compatibility in tests 2024-10-25 10:57:03 -07:00
Paul Gauthier
1ed2eefff4 copy 2024-10-25 09:38:10 -07:00
Paul Gauthier
df65e87ef3 test: update InputOutput initialization with fancy_input param in tests 2024-10-25 09:24:52 -07:00
Paul Gauthier
ddb876d2fe only glob, not rglob for /read 2024-10-25 09:22:50 -07:00
Paul Gauthier
a080581329 refactor: improve file path handling with glob and rglob 2024-10-25 07:49:19 -07:00
Paul Gauthier (aider)
f70a82791b fix: handle absolute paths and globs in cmd_read_only 2024-10-25 07:43:31 -07:00
Paul Gauthier
5d3a60228c fix: use Path.rglob instead of glob.glob for recursive file matching 2024-10-25 07:43:29 -07:00
Paul Gauthier
fd820dbfe2 Merge branch 'main' of github.com:Aider-AI/aider 2024-10-25 07:41:02 -07:00
paul-gauthier
b911ceaa61 Merge pull request #2126 from webkonstantin/fix-read-only-from-working-dir
fix: Impossible to /read-only from another working directory
2024-10-25 07:40:57 -07:00
Paul Gauthier
9edf9b4186 refactor: extract get_rel_fname function for path resolution 2024-10-25 07:36:29 -07:00
Paul Gauthier
be74259df6 fix: add missing AnthropicError exception to retry list 2024-10-25 07:31:39 -07:00
Paul Gauthier
29293cc8ac fix: update import path for AnthropicError in retry_exceptions 2024-10-25 07:07:36 -07:00
Paul Gauthier
9e7995b730 bump deps 2024-10-25 06:55:47 -07:00
Konstantin L
ba9fdaa755 fix: Impossible to /read-only from another working directory 2024-10-25 10:59:23 +02:00
Paul Gauthier
dde2dee304 fix last test 2024-10-24 14:31:41 -07:00
Paul Gauthier (aider)
55a99143c2 test: set fancy_input=False in all InputOutput() test instances 2024-10-24 14:31:11 -07:00
Paul Gauthier
ba2bee61de test: fix confirm_ask_yes_no test by disabling fancy input 2024-10-24 14:31:09 -07:00
Paul Gauthier (aider)
5fd8fb15b9 fix: add fancy_input=False to all InputOutput test initializations 2024-10-24 14:27:53 -07:00
Paul Gauthier
8908a48b68 copy 2024-10-24 14:25:08 -07:00
Paul Gauthier (aider)
43fbda0faf feat: add --fancy-input flag to control input history and completion 2024-10-24 14:24:09 -07:00
Paul Gauthier (aider)
97a9c65125 feat: add fancy_input parameter to InputOutput class initialization 2024-10-24 14:23:24 -07:00
Paul Gauthier
8a63b1b3ce refactor: rename pretty flag to fancy_input for clarity 2024-10-24 14:23:22 -07:00
Paul Gauthier
3c658ac66f feat: set default reminder to "user" for gpt-4-1106-preview model 2024-10-24 14:08:51 -07:00
Paul Gauthier
055d529947 remove accepts_images 2024-10-24 14:08:06 -07:00
Paul Gauthier (aider)
9507f3c008 refactor: use main_model.info["supports_vision"] instead of accepts_images 2024-10-24 14:05:17 -07:00
Paul Gauthier
e0a1eefe0a copy 2024-10-24 14:01:00 -07:00
Paul Gauthier
0aad7b46f6 cleaner logic for load/save analytics.json 2024-08-16 11:28:13 -07:00
Paul Gauthier
62d8190733 copy 2024-08-16 11:04:54 -07:00
Paul Gauthier
4759297b67 disabled -> permanently_disabled 2024-08-16 11:03:14 -07:00
Paul Gauthier
607a9a8c86 track -> enable 2024-08-16 10:59:44 -07:00
Paul Gauthier
96b67ab26c copy 2024-08-16 10:45:14 -07:00
Paul Gauthier
93b8cb9cec Merge branch 'main' into mixpanel 2024-08-16 10:42:55 -07:00
Paul Gauthier (aider)
7b6ad16fdb fix: Preserve existing UUID when marking analytics as disabled 2024-08-13 14:22:39 -07:00
Paul Gauthier (aider)
b722572a28 style: format analytics.py file 2024-08-13 13:03:54 -07:00
Paul Gauthier (aider)
46489f1a46 feat: Add PostHog analytics integration 2024-08-13 13:03:51 -07:00
Paul Gauthier
d7a29c42b7 Merge branch 'main' into mixpanel 2024-08-13 13:01:43 -07:00
Paul Gauthier (aider)
1ebe5f8bd5 feat: add edit_format to event() call 2024-08-13 10:04:28 -07:00
Paul Gauthier
26fe63b7ac cleanup 2024-08-13 10:04:05 -07:00
Paul Gauthier
d2435c2e00 copy 2024-08-13 10:02:54 -07:00
Paul Gauthier
4d04a35e73 Merge branch 'main' into mixpanel 2024-08-13 09:52:50 -07:00
Paul Gauthier
cabad84521 tweak 2024-08-13 08:12:23 -07:00
Paul Gauthier
aeadf2f139 fix: Disable analytics by default and provide option to enable 2024-08-13 08:08:05 -07:00
Paul Gauthier
4ebbfa01b7 share last 1k analytics logs 2024-08-13 07:50:28 -07:00
Paul Gauthier
960b456e70 cleanup 2024-08-13 07:50:06 -07:00
Paul Gauthier (aider)
329514289d fix: Initialize Analytics instance with track=False if analytics is None 2024-08-13 07:45:35 -07:00
Paul Gauthier (aider)
03f14dfe47 feat: Create Analytics instance with track=False if analytics is None 2024-08-13 07:45:19 -07:00
Paul Gauthier (aider)
1c321df457 feat: Move analytics arguments to their own section 2024-08-13 07:23:46 -07:00
Paul Gauthier
8a21eb7804 handle new vars that accumulate tokens/costs for infinite output 2024-08-13 07:23:01 -07:00
Paul Gauthier
c1d4adbebf added mixpanel dep 2024-08-13 07:18:26 -07:00
Paul Gauthier
ef933c207b Merge branch 'main' into mixpanel 2024-08-13 07:17:13 -07:00
Paul Gauthier
08aaae4d36 initial 2024-08-13 07:16:35 -07:00
Paul Gauthier
f52265362f Merge branch 'main' into mixpanel 2024-08-13 07:09:34 -07:00
Paul Gauthier (aider)
00aa43d964 fix: Move imports to the top of the file in aider/analytics.py 2024-08-12 20:44:56 -07:00
Paul Gauthier (aider)
84489f16b5 refactor: Refactor data file name and mkdir operations 2024-08-12 20:44:42 -07:00
Paul Gauthier
e07194bbeb fix: Rename uuid_file to data_file for consistency 2024-08-12 20:44:41 -07:00
Paul Gauthier (aider)
1567d3e3d1 fix: Remove duplicate get_or_create_uuid method 2024-08-12 20:41:59 -07:00
Paul Gauthier (aider)
eca7a57138 style: Format code with linter 2024-08-12 20:41:17 -07:00
Paul Gauthier (aider)
64df0ad590 feat: Add --analytics-disable option to disable analytics tracking 2024-08-12 20:41:10 -07:00
Paul Gauthier
5a28d499a8 fix: Update the path for the Mixpanel UUID file 2024-08-12 20:41:09 -07:00
Paul Gauthier
4bad876f66 fix: Add event tracking for interactive help command 2024-08-12 20:36:51 -07:00
Paul Gauthier (aider)
1a8763d989 feat: Add --analytics-log argument and pass it to Analytics 2024-08-12 18:27:40 -07:00
Paul Gauthier (aider)
13eaf5e5ce style: Fix formatting in analytics.py 2024-08-12 18:26:11 -07:00
Paul Gauthier (aider)
82250db8af feat: Add logfile support to Analytics class 2024-08-12 18:26:08 -07:00
Paul Gauthier
85fa78f5a6 fix: Correct command execution logic 2024-08-12 18:23:51 -07:00
Paul Gauthier (aider)
9ed732959e fix: Remove unnecessary slice from event name in Commands.run 2024-08-12 18:22:51 -07:00
Paul Gauthier (aider)
860a36fe6c refactor: Extract command name from matching_commands[0][1:] 2024-08-12 18:22:36 -07:00
Paul Gauthier (aider)
01a9a8ffc4 feat: add event logging for command usage 2024-08-12 18:22:05 -07:00
Paul Gauthier
aa840f0e28 be careful logging main_models that are not in the model db 2024-08-12 18:20:35 -07:00
Paul Gauthier (aider)
a7a626423c fix: Remove properties argument from event method in Analytics class 2024-08-12 18:08:02 -07:00
Paul Gauthier
c2c9b60ea6 feat: Add main_model parameter to event method in analytics.py 2024-08-12 18:08:01 -07:00
Paul Gauthier (aider)
a6282818db fix: Add early return if self.mp is not set 2024-08-12 16:23:12 -07:00
Paul Gauthier (aider)
f563544761 style: Fix linter issues in analytics.py 2024-08-12 16:21:49 -07:00
Paul Gauthier (aider)
48a344bc6d feat: Add system information to all events 2024-08-12 16:21:46 -07:00
Paul Gauthier
f110e8c8db fix: Update Mixpanel project token 2024-08-12 16:21:45 -07:00
Paul Gauthier (aider)
65c0608d5c style: format code 2024-08-12 16:17:17 -07:00
Paul Gauthier (aider)
57ce0dca67 feat: add self.event() to calculate_and_show_tokens_and_cost 2024-08-12 16:17:11 -07:00
Paul Gauthier
4129065d6c fix: Add event attribute to Coder class 2024-08-12 16:17:10 -07:00
Paul Gauthier (aider)
d59fd508c2 style: Apply linter formatting to analytics.py 2024-08-12 16:16:42 -07:00
Paul Gauthier (aider)
62a5cf8dee feat: Handle numeric values in event properties 2024-08-12 16:16:39 -07:00
Paul Gauthier (aider)
6ec4e60058 feat: Add kwargs support to event() method 2024-08-12 16:14:11 -07:00
Paul Gauthier
087b3d4ffb feat: Rename track_event to event in aider/analytics.py 2024-08-12 16:14:10 -07:00
Paul Gauthier (aider)
7d3585bafe style: Fix formatting and linting issues in analytics.py 2024-08-12 16:11:23 -07:00
Paul Gauthier (aider)
1a49974f98 feat: add aider version number to all events 2024-08-12 16:11:20 -07:00
Paul Gauthier
b11c17dbd4 feat: Add optional analytics tracking 2024-08-12 16:10:20 -07:00
Paul Gauthier
474ac62391 feat: Add analytics field to Coder class 2024-08-12 16:08:58 -07:00
Paul Gauthier (aider)
6ee8a74d47 style: format code with linter 2024-08-12 16:07:15 -07:00
Paul Gauthier (aider)
121dd908a6 feat: Add Mixpanel project token to Analytics class 2024-08-12 16:07:12 -07:00
Paul Gauthier
2e1ac25ce2 feat: Add analytics module with Mixpanel integration 2024-08-12 16:07:11 -07:00
Paul Gauthier
b49ee06f23 feat: Add analytics.py module 2024-08-12 16:05:06 -07:00
49 changed files with 2312 additions and 454 deletions

View File

@@ -1,7 +1,32 @@
# Release history
### v0.60.0
### main branch
- Load and save aider slash-commands to files:
- `/save <fname>` command will make a file of `/add` and `/read-only` commands that recreate the current file context in the chat.
- `/load <fname>` will replay the commands in the file.
- You can use `/load` to run any arbitrary set of slash-commands, not just `/add` and `/read-only`.
- Use `--load <fname>` to run a list of commands on launch, before the interactive chat begins.
- Anonymous, opt-in [analytics](https://aider.chat/docs/more/analytics.html) with no personal data sharing.
- Aider follows litellm's `supports_vision` attribute to enable image support for models.
- Bugfix for when diff mode flexibly handles the model using the wrong filename.
- Displays filenames in sorted order for `/add` and `/read-only`.
- New `--no-fancy-input` switch disables prompt toolkit input, now still available with `--no-pretty`.
- Override browser config with `--no-browser` or `--no-gui`.
- Offer to open documentation URLs when errors occur.
- Properly support all o1 models, regardless of provider.
- Improved layout of filenames above input prompt.
- Better handle corrupted repomap tags cache.
- Improved handling of API errors, especially when accessing the weak model.
- Aider wrote 68% of the code in this release.
### Aider v0.60.1
- Enable image support for Sonnet 10/22.
- Display filenames in sorted order.
### Aider v0.60.0
- Full support for Sonnet 10/22, the new SOTA model on aider's code editing benchmark.
- Aider uses Sonnet 10/22 by default.
@@ -15,12 +40,12 @@
- Bugfix to properly include URLs in `/help` RAG results.
- Aider wrote 49% of the code in this release.
### v0.59.1
### Aider v0.59.1
- Check for obsolete `yes: true` in yaml config, show helpful error.
- Model settings for openrouter/anthropic/claude-3.5-sonnet:beta
### v0.59.0
### Aider v0.59.0
- Improvements to `/read-only`:
- Now supports shell-style auto-complete of the full file system.

View File

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

164
aider/analytics.py Normal file
View File

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

View File

@@ -550,6 +550,25 @@ def get_parser(default_config_files, git_root):
)
##########
group = parser.add_argument_group("Analytics")
group.add_argument(
"--analytics",
action=argparse.BooleanOptionalAction,
default=False,
help="Enable/disable analytics for one session (default: False)",
)
group.add_argument(
"--analytics-log",
metavar="ANALYTICS_LOG_FILE",
help="Specify a file to log analytics events",
)
group.add_argument(
"--analytics-disable",
action="store_true",
help="Permanently disable analytics",
default=False,
)
group = parser.add_argument_group("Other Settings")
group.add_argument(
"--file",
@@ -660,6 +679,11 @@ def get_parser(default_config_files, git_root):
" (disables chat mode)"
),
)
group.add_argument(
"--load",
metavar="LOAD_FILE",
help="Load and execute /commands from a file on launch",
)
group.add_argument(
"--encoding",
default="utf-8",
@@ -678,8 +702,8 @@ def get_parser(default_config_files, git_root):
group.add_argument(
"--gui",
"--browser",
action="store_true",
help="Run aider in your browser",
action=argparse.BooleanOptionalAction,
help="Run aider in your browser (default: False)",
default=False,
)
group.add_argument(
@@ -688,6 +712,12 @@ def get_parser(default_config_files, git_root):
default=True,
help="Enable/disable suggesting shell commands (default: True)",
)
group.add_argument(
"--fancy-input",
action=argparse.BooleanOptionalAction,
default=True,
help="Enable/disable fancy input with history and completion (default: True)",
)
##########
group = parser.add_argument_group("Voice Settings")

View File

@@ -13,12 +13,15 @@ import sys
import threading
import time
import traceback
import webbrowser
from collections import defaultdict
from datetime import datetime
from json.decoder import JSONDecodeError
from pathlib import Path
from typing import List
from aider import __version__, models, prompts, urls, utils
from aider.analytics import Analytics
from aider.commands import Commands
from aider.history import ChatSummary
from aider.io import ConfirmGroup, InputOutput
@@ -258,12 +261,17 @@ class Coder:
commands=None,
summarizer=None,
total_cost=0.0,
analytics=None,
map_refresh="auto",
cache_prompts=False,
num_cache_warming_pings=0,
suggest_shell_commands=True,
chat_language=None,
):
# Fill in a dummy Analytics if needed, but it is never .enable()'d
self.analytics = analytics if analytics is not None else Analytics()
self.event = self.analytics.event
self.chat_language = chat_language
self.commit_before_message = []
self.aider_commit_hashes = set()
@@ -679,7 +687,7 @@ class Coder:
return chat_files_messages
def get_images_message(self):
if not self.main_model.accepts_images:
if not self.main_model.info.get("supports_vision"):
return None
image_messages = []
@@ -782,13 +790,58 @@ class Coder:
self.num_reflections += 1
message = self.reflected_message
def check_for_urls(self, inp):
def check_and_open_urls(self, exc: Exception) -> List[str]:
import openai
"""Check exception for URLs, offer to open in a browser, with user-friendly error msgs."""
text = str(exc)
friendly_msg = None
if isinstance(exc, (openai.APITimeoutError, openai.APIConnectionError)):
friendly_msg = (
"There is a problem connecting to the API provider. Please try again later or check"
" your model settings."
)
elif isinstance(exc, openai.RateLimitError):
friendly_msg = (
"The API provider's rate limits have been exceeded. Check with your provider or"
" wait awhile and retry."
)
elif isinstance(exc, openai.InternalServerError):
friendly_msg = (
"The API provider seems to be down or overloaded. Please try again later."
)
elif isinstance(exc, openai.BadRequestError):
friendly_msg = "The API provider refused the request as invalid?"
elif isinstance(exc, openai.AuthenticationError):
friendly_msg = (
"The API provider refused your authentication. Please check that you are using a"
" valid API key."
)
if friendly_msg:
self.io.tool_warning(text)
self.io.tool_error(f"{friendly_msg}")
else:
self.io.tool_error(text)
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*)")
urls = list(set(url_pattern.findall(text))) # Use set to remove duplicates
for url in urls:
url = url.rstrip(".',\"")
if self.io.confirm_ask("Open URL for more info about this error?", subject=url):
webbrowser.open(url)
return urls
def check_for_urls(self, inp: str) -> List[str]:
"""Check input for URLs and offer to add them to the chat."""
url_pattern = re.compile(r"(https?://[^\s/$.?#].[^\s]*[^\s,.])")
urls = list(set(url_pattern.findall(inp))) # Use set to remove duplicates
added_urls = []
group = ConfirmGroup(urls)
for url in urls:
if url not in self.rejected_urls:
url = url.rstrip(".',\"")
if self.io.confirm_ask(
"Add URL to the chat?", subject=url, group=group, allow_never=True
):
@@ -1101,6 +1154,8 @@ class Coder:
return chunks
def send_message(self, inp):
import openai # for error codes below
self.cur_messages += [
dict(role="user", content=inp),
]
@@ -1129,10 +1184,16 @@ class Coder:
yield from self.send(messages, functions=self.functions)
break
except retry_exceptions() as err:
self.io.tool_warning(str(err))
# Print the error and its base classes
# for cls in err.__class__.__mro__: dump(cls.__name__)
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
self.mdstream = None
self.check_and_open_urls(err)
break
err_msg = str(err)
self.io.tool_error(err_msg)
self.io.tool_output(f"Retrying in {retry_delay:.1f} seconds...")
time.sleep(retry_delay)
continue
@@ -1160,10 +1221,15 @@ class Coder:
messages.append(
dict(role="assistant", content=self.multi_response_content, prefix=True)
)
except (openai.APIError, openai.APIStatusError) as err:
# for cls in err.__class__.__mro__: dump(cls.__name__)
self.mdstream = None
self.check_and_open_urls(err)
break
except Exception as err:
self.io.tool_error(f"Unexpected error: {err}")
lines = traceback.format_exception(type(err), err, err.__traceback__)
self.io.tool_error("".join(lines))
self.io.tool_warning("".join(lines))
self.io.tool_error(str(err))
return
finally:
if self.mdstream:
@@ -1638,11 +1704,27 @@ class Coder:
self.usage_report = tokens_report + sep + cost_report
def show_usage_report(self):
if self.usage_report:
self.io.tool_output(self.usage_report)
self.message_cost = 0.0
self.message_tokens_sent = 0
self.message_tokens_received = 0
if not self.usage_report:
return
self.io.tool_output(self.usage_report)
prompt_tokens = self.message_tokens_sent
completion_tokens = self.message_tokens_received
self.event(
"message_send",
main_model=self.main_model,
edit_format=self.edit_format,
prompt_tokens=prompt_tokens,
completion_tokens=completion_tokens,
total_tokens=prompt_tokens + completion_tokens,
cost=self.message_cost,
total_cost=self.total_cost,
)
self.message_cost = 0.0
self.message_tokens_sent = 0
self.message_tokens_received = 0
def get_multi_response_content(self, final=False):
cur = self.multi_response_content or ""
@@ -1811,8 +1893,10 @@ class Coder:
edited = set()
try:
edits = self.get_edits()
edits = self.apply_edits_dry_run(edits)
edits = self.prepare_to_edit(edits)
edited = set(edit[0] for edit in edits)
self.apply_edits(edits)
except ValueError as err:
self.num_malformed_responses += 1
@@ -1940,6 +2024,9 @@ class Coder:
def apply_edits(self, edits):
return
def apply_edits_dry_run(self, edits):
return edits
def run_shell_commands(self):
if not self.suggest_shell_commands:
return ""

View File

@@ -35,9 +35,13 @@ class EditBlockCoder(Coder):
return edits
def apply_edits(self, edits):
def apply_edits_dry_run(self, edits):
return self.apply_edits(edits, dry_run=True)
def apply_edits(self, edits, dry_run=False):
failed = []
passed = []
updated_edits = []
for edit in edits:
path, original, updated = edit
@@ -50,14 +54,21 @@ class EditBlockCoder(Coder):
content = self.io.read_text(full_path)
new_content = do_replace(full_path, content, original, updated, self.fence)
if new_content:
path = self.get_rel_fname(full_path)
break
updated_edits.append((path, original, updated))
if new_content:
self.io.write_text(full_path, new_content)
if not dry_run:
self.io.write_text(full_path, new_content)
passed.append(edit)
else:
failed.append(edit)
if dry_run:
return updated_edits
if not failed:
return

View File

@@ -223,6 +223,7 @@ class Commands:
def run(self, inp):
if inp.startswith("!"):
self.coder.event("command_run")
return self.do_run("run", inp[1:])
res = self.matching_commands(inp)
@@ -230,9 +231,13 @@ class Commands:
return
matching_commands, first_word, rest_inp = res
if len(matching_commands) == 1:
return self.do_run(matching_commands[0][1:], rest_inp)
command = matching_commands[0][1:]
self.coder.event(f"command_{command}")
return self.do_run(command, rest_inp)
elif first_word in matching_commands:
return self.do_run(first_word[1:], rest_inp)
command = first_word[1:]
self.coder.event(f"command_{command}")
return self.do_run(command, rest_inp)
elif len(matching_commands) > 1:
self.io.tool_error(f"Ambiguous command: {', '.join(matching_commands)}")
else:
@@ -748,7 +753,9 @@ class Commands:
f"Cannot add {matched_file} as it's not part of the repository"
)
else:
if is_image_file(matched_file) and not self.coder.main_model.accepts_images:
if is_image_file(matched_file) and not self.coder.main_model.info.get(
"supports_vision"
):
self.io.tool_error(
f"Cannot add image file {matched_file} as the"
f" {self.coder.main_model.name} does not support images."
@@ -961,6 +968,7 @@ class Commands:
self.basic_help()
return
self.coder.event("interactive help")
from aider.coders import Coder
if not self.help:
@@ -1168,11 +1176,17 @@ class Commands:
# First collect all expanded paths
for pattern in filenames:
expanded_pattern = expanduser(pattern)
expanded_paths = glob.glob(expanded_pattern, recursive=True)
if not expanded_paths:
if os.path.isabs(expanded_pattern):
# For absolute paths, glob it
matches = list(glob.glob(expanded_pattern))
else:
# For relative paths and globs, use glob from the root directory
matches = list(Path(self.coder.root).glob(expanded_pattern))
if not matches:
self.io.tool_error(f"No matches found for: {pattern}")
else:
all_paths.extend(expanded_paths)
all_paths.extend(matches)
# Then process them in sorted order
for path in sorted(all_paths):
@@ -1185,6 +1199,13 @@ class Commands:
self.io.tool_error(f"Not a file or directory: {abs_path}")
def _add_read_only_file(self, abs_path, original_name):
if is_image_file(original_name) and not self.coder.main_model.info.get("supports_vision"):
self.io.tool_error(
f"Cannot add image file {original_name} as the"
f" {self.coder.main_model.name} does not support images."
)
return
if abs_path in self.coder.abs_read_only_fnames:
self.io.tool_error(f"{original_name} is already in the chat as a read-only file")
return
@@ -1238,6 +1259,63 @@ class Commands:
output = f"{announcements}\n{settings}"
self.io.tool_output(output)
def completions_raw_load(self, document, complete_event):
return self.completions_raw_read_only(document, complete_event)
def cmd_load(self, args):
"Load and execute commands from a file"
if not args.strip():
self.io.tool_error("Please provide a filename containing commands to load.")
return
try:
with open(args.strip(), "r", encoding=self.io.encoding, errors="replace") as f:
commands = f.readlines()
except FileNotFoundError:
self.io.tool_error(f"File not found: {args}")
return
except Exception as e:
self.io.tool_error(f"Error reading file: {e}")
return
for cmd in commands:
cmd = cmd.strip()
if not cmd or cmd.startswith("#"):
continue
self.io.tool_output(f"\nExecuting: {cmd}")
self.run(cmd)
def completions_raw_save(self, document, complete_event):
return self.completions_raw_read_only(document, complete_event)
def cmd_save(self, args):
"Save commands to a file that can reconstruct the current chat session's files"
if not args.strip():
self.io.tool_error("Please provide a filename to save the commands to.")
return
try:
with open(args.strip(), "w", encoding=self.io.encoding) as f:
f.write("/drop\n")
# Write commands to add editable files
for fname in sorted(self.coder.abs_fnames):
rel_fname = self.coder.get_rel_fname(fname)
f.write(f"/add {rel_fname}\n")
# Write commands to add read-only files
for fname in sorted(self.coder.abs_read_only_fnames):
# Use absolute path for files outside repo root, relative path for files inside
if Path(fname).is_relative_to(self.coder.root):
rel_fname = self.coder.get_rel_fname(fname)
f.write(f"/read-only {rel_fname}\n")
else:
f.write(f"/read-only {fname}\n")
self.io.tool_output(f"Saved commands to {args.strip()}")
except Exception as e:
self.io.tool_error(f"Error saving commands to file: {e}")
def cmd_copy(self, args):
"Copy the last assistant message to the clipboard"
all_messages = self.coder.done_messages + self.coder.cur_messages

View File

@@ -3,6 +3,7 @@ import os
from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime
from io import StringIO
from pathlib import Path
from prompt_toolkit.completion import Completer, Completion, ThreadedCompleter
@@ -15,6 +16,7 @@ from prompt_toolkit.shortcuts import CompleteStyle, PromptSession
from prompt_toolkit.styles import Style
from pygments.lexers import MarkdownLexer, guess_lexer_for_filename
from pygments.token import Token
from rich.columns import Columns
from rich.console import Console
from rich.markdown import Markdown
from rich.style import Style as RichStyle
@@ -192,6 +194,7 @@ class InputOutput:
dry_run=False,
llm_history_file=None,
editingmode=EditingMode.EMACS,
fancy_input=True,
):
self.never_prompts = set()
self.editingmode = editingmode
@@ -234,15 +237,16 @@ class InputOutput:
self.append_chat_history(f"\n# aider chat started at {current_time}\n\n")
self.prompt_session = None
if self.pretty:
if fancy_input:
# Initialize PromptSession
session_kwargs = {
"input": self.input,
"output": self.output,
"lexer": PygmentsLexer(MarkdownLexer),
"editing_mode": self.editingmode,
"cursor": ModalCursorShapeConfig(),
}
if self.editingmode == EditingMode.VI:
session_kwargs["cursor"] = ModalCursorShapeConfig()
if self.input_history_file is not None:
session_kwargs["history"] = FileHistory(self.input_history_file)
try:
@@ -359,7 +363,7 @@ class InputOutput:
show = ""
if rel_fnames:
rel_read_only_fnames = [
os.path.relpath(fname, root) for fname in (abs_read_only_fnames or [])
get_rel_fname(fname, root) for fname in (abs_read_only_fnames or [])
]
show = self.format_files_for_input(rel_fnames, rel_read_only_fnames)
if edit_format:
@@ -692,22 +696,45 @@ class InputOutput:
try:
with self.chat_history_file.open("a", encoding=self.encoding, errors="ignore") as f:
f.write(text)
except (PermissionError, OSError):
self.tool_error(
f"Warning: Unable to write to chat history file {self.chat_history_file}."
" Permission denied."
)
except (PermissionError, OSError) as err:
print(f"Warning: Unable to write to chat history file {self.chat_history_file}.")
print(err)
self.chat_history_file = None # Disable further attempts to write
def format_files_for_input(self, rel_fnames, rel_read_only_fnames):
read_only_files = []
for full_path in sorted(rel_read_only_fnames or []):
read_only_files.append(f"{full_path} (read only)")
if not self.pretty:
read_only_files = []
for full_path in sorted(rel_read_only_fnames or []):
read_only_files.append(f"{full_path} (read only)")
editable_files = []
for full_path in sorted(rel_fnames):
if full_path in rel_read_only_fnames:
continue
editable_files.append(f"{full_path}")
editable_files = []
for full_path in sorted(rel_fnames):
if full_path in rel_read_only_fnames:
continue
editable_files.append(f"{full_path}")
return "\n".join(read_only_files + editable_files) + "\n"
return "\n".join(read_only_files + editable_files) + "\n"
output = StringIO()
console = Console(file=output, force_terminal=False)
read_only_files = sorted(rel_read_only_fnames or [])
editable_files = [f for f in sorted(rel_fnames) if f not in rel_read_only_fnames]
if read_only_files:
console.print("Read only files:", style="bold")
console.print(Columns(read_only_files))
if editable_files:
if read_only_files:
console.print()
console.print("Editable files:", style="bold")
console.print(Columns(editable_files))
return output.getvalue()
def get_rel_fname(fname, root):
try:
return os.path.relpath(fname, root)
except ValueError:
return fname

View File

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

View File

@@ -5,6 +5,7 @@ import re
import sys
import threading
import traceback
import webbrowser
from pathlib import Path
import git
@@ -13,6 +14,7 @@ from dotenv import load_dotenv
from prompt_toolkit.enums import EditingMode
from aider import __version__, models, urls, utils
from aider.analytics import Analytics
from aider.args import get_parser
from aider.coders import Coder
from aider.commands import Commands, SwitchCoder
@@ -194,7 +196,10 @@ def launch_gui(args):
"--server.runOnSave=false",
]
if "-dev" in __version__:
# https://github.com/Aider-AI/aider/issues/2193
is_dev = "-dev" in str(__version__)
if is_dev:
print("Watching for file changes.")
else:
st_args += [
@@ -362,7 +367,8 @@ def sanity_check_repo(repo, io):
io.tool_error("Aider only works with git repos with version number 1 or 2.")
io.tool_output("You may be able to convert your repo: git update-index --index-version=2")
io.tool_output("Or run aider --no-git to proceed without using git.")
io.tool_output(urls.git_index_version)
if io.confirm_ask("Open documentation url for more info?", subject=urls.git_index_version):
webbrowser.open(urls.git_index_version)
return False
io.tool_error("Unable to read git repository, it may be corrupt?")
@@ -423,6 +429,11 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
# Parse again to include any arguments that might have been defined in .env
args = parser.parse_args(argv)
if args.analytics_disable:
analytics = Analytics(permanently_disable=True)
print("Analytics have been permanently disabled.")
return
if not args.verify_ssl:
import httpx
@@ -472,6 +483,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
encoding=args.encoding,
llm_history_file=args.llm_history_file,
editingmode=editing_mode,
fancy_input=args.fancy_input,
)
io = get_io(args.pretty)
@@ -483,9 +495,35 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io = get_io(False)
io.tool_warning("Terminal does not support pretty output (UnicodeDecodeError)")
analytics = Analytics(logfile=args.analytics_log, permanently_disable=args.analytics_disable)
if args.analytics:
if analytics.need_to_ask():
io.tool_output(
"Aider respects your privacy and never collects your code, chat messages, keys or"
" personal info."
)
io.tool_output(f"For more info: {urls.analytics}")
disable = not io.confirm_ask(
"Allow collection of anonymous analytics to help improve aider?"
)
analytics.asked_opt_in = True
if disable:
analytics.disable(permanently=True)
io.tool_output("Analytics have been permanently disabled.")
analytics.save_data()
io.tool_output()
# This is a no-op if the user has opted out
analytics.enable()
analytics.event("launched")
if args.gui and not return_coder:
if not check_streamlit_install(io):
return
analytics.event("gui session")
launch_gui(argv)
return
@@ -600,11 +638,15 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.show_model_warnings:
problem = models.sanity_check_models(io, main_model)
if problem:
analytics.event("model warning", main_model=main_model)
io.tool_output("You can skip this check with --no-show-model-warnings")
io.tool_output()
try:
if not io.confirm_ask("Proceed anyway?"):
return 1
if io.confirm_ask(
"Open documentation url for more info?", subject=urls.model_warnings
):
webbrowser.open(urls.model_warnings)
io.tool_output()
except KeyboardInterrupt:
return 1
@@ -673,6 +715,7 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
test_cmd=args.test_cmd,
commands=commands,
summarizer=summarizer,
analytics=analytics,
map_refresh=args.map_refresh,
cache_prompts=args.cache_prompts,
map_mul_no_files=args.map_multiplier_no_files,
@@ -746,6 +789,9 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
io.tool_output(f"Cur working dir: {Path.cwd()}")
io.tool_output(f"Git working dir: {git_root}")
if args.load:
commands.cmd_load(args.load)
if args.message:
io.add_to_input_history(args.message)
io.tool_output()
@@ -771,6 +817,8 @@ def main(argv=None, input=None, output=None, force_git_root=None, return_coder=F
if args.exit:
return
analytics.event("cli session", main_model=main_model, edit_format=main_model.edit_format)
while True:
try:
coder.run()
@@ -818,7 +866,11 @@ def check_and_load_imports(io, verbose=False):
except Exception as err:
io.tool_error(str(err))
io.tool_output("Error loading required imports. Did you install aider properly?")
io.tool_output("https://aider.chat/docs/install/install.html")
if io.confirm_ask(
"Open documentation url for more info?", subject=urls.install_properly
):
webbrowser.open(urls.install_properly)
sys.exit(1)
installs[str(key)] = True

View File

@@ -13,7 +13,6 @@ import json5
import yaml
from PIL import Image
from aider import urls
from aider.dump import dump # noqa: F401
from aider.llm import litellm
@@ -70,7 +69,6 @@ class ModelSettings:
weak_model_name: Optional[str] = None
use_repo_map: bool = False
send_undo_reply: bool = False
accepts_images: bool = False
lazy: bool = False
reminder: str = "user"
examples_as_sys_msg: bool = False
@@ -126,7 +124,6 @@ MODEL_SETTINGS = [
"udiff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -135,7 +132,6 @@ MODEL_SETTINGS = [
"udiff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -144,7 +140,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
@@ -154,7 +149,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -163,7 +157,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -172,7 +165,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
@@ -181,7 +173,6 @@ MODEL_SETTINGS = [
"gpt-4o-mini",
"whole",
weak_model_name="gpt-4o-mini",
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -189,7 +180,6 @@ MODEL_SETTINGS = [
"openai/gpt-4o-mini",
"whole",
weak_model_name="openai/gpt-4o-mini",
accepts_images=True,
lazy=True,
reminder="sys",
),
@@ -215,7 +205,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
reminder="sys",
),
ModelSettings(
@@ -266,7 +255,6 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
@@ -284,7 +272,6 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
@@ -302,7 +289,23 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
},
"max_tokens": 8192,
},
cache_control=True,
reminder="user",
),
ModelSettings(
"anthropic/claude-3-5-sonnet-latest",
"diff",
weak_model_name="anthropic/claude-3-haiku-20240307",
editor_model_name="anthropic/claude-3-5-sonnet-20241022",
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
@@ -320,7 +323,6 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"extra_headers": {
"anthropic-beta": ANTHROPIC_BETA_HEADER,
@@ -362,7 +364,6 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"max_tokens": 8192,
},
@@ -377,7 +378,6 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"max_tokens": 8192,
},
@@ -394,7 +394,6 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"max_tokens": 8192,
},
@@ -408,7 +407,6 @@ MODEL_SETTINGS = [
editor_edit_format="editor-diff",
use_repo_map=True,
examples_as_sys_msg=True,
accepts_images=True,
extra_params={
"max_tokens": 8192,
},
@@ -548,7 +546,6 @@ MODEL_SETTINGS = [
"diff",
weak_model_name="openrouter/openai/gpt-4o-mini",
use_repo_map=True,
accepts_images=True,
lazy=True,
reminder="sys",
editor_edit_format="editor-diff",
@@ -652,77 +649,77 @@ MODEL_SETTINGS = [
]
model_info_url = (
"https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"
)
class ModelInfoManager:
MODEL_INFO_URL = (
"https://raw.githubusercontent.com/BerriAI/litellm/main/"
"model_prices_and_context_window.json"
)
CACHE_TTL = 60 * 60 * 24 # 24 hours
def __init__(self):
self.cache_dir = Path.home() / ".aider" / "caches"
self.cache_file = self.cache_dir / "model_prices_and_context_window.json"
self.content = None
self._load_cache()
def get_model_flexible(model, content):
info = content.get(model, dict())
if info:
return info
pieces = model.split("/")
if len(pieces) == 2:
info = content.get(pieces[1])
if info and info.get("litellm_provider") == pieces[0]:
return info
return dict()
def get_model_info(model):
if not litellm._lazy_module:
cache_dir = Path.home() / ".aider" / "caches"
cache_file = cache_dir / "model_prices_and_context_window.json"
def _load_cache(self):
try:
cache_dir.mkdir(parents=True, exist_ok=True)
use_cache = True
self.cache_dir.mkdir(parents=True, exist_ok=True)
if self.cache_file.exists():
cache_age = time.time() - self.cache_file.stat().st_mtime
if cache_age < self.CACHE_TTL:
self.content = json.loads(self.cache_file.read_text())
except OSError:
# If we can't create the cache directory, we'll skip using the cache
use_cache = False
if use_cache:
current_time = time.time()
cache_age = (
current_time - cache_file.stat().st_mtime if cache_file.exists() else float("inf")
)
if cache_age < 60 * 60 * 24:
try:
content = json.loads(cache_file.read_text())
res = get_model_flexible(model, content)
if res:
return res
except Exception as ex:
print(str(ex))
import requests
pass
def _update_cache(self):
try:
response = requests.get(model_info_url, timeout=5)
import requests
response = requests.get(self.MODEL_INFO_URL, timeout=5)
if response.status_code == 200:
content = response.json()
if use_cache:
try:
cache_file.write_text(json.dumps(content, indent=4))
except OSError:
# If we can't write to the cache file, we'll just skip caching
pass
res = get_model_flexible(model, content)
if res:
return res
self.content = response.json()
try:
self.cache_file.write_text(json.dumps(self.content, indent=4))
except OSError:
pass
except Exception as ex:
print(str(ex))
# If all else fails, do it the slow way...
try:
info = litellm.get_model_info(model)
return info
except Exception:
def get_model_from_cached_json_db(self, model):
if not self.content:
self._update_cache()
if not self.content:
return dict()
info = self.content.get(model, dict())
if info:
return info
pieces = model.split("/")
if len(pieces) == 2:
info = self.content.get(pieces[1])
if info and info.get("litellm_provider") == pieces[0]:
return info
return dict()
def get_model_info(self, model):
if not litellm._lazy_module:
info = self.get_model_from_cached_json_db(model)
if info:
return info
# If all else fails, do it the slow way...
try:
return litellm.get_model_info(model)
except Exception:
return dict()
model_info_manager = ModelInfoManager()
class Model(ModelSettings):
def __init__(self, model, weak_model=None, editor_model=None, editor_edit_format=None):
@@ -756,7 +753,7 @@ class Model(ModelSettings):
self.get_editor_model(editor_model, editor_edit_format)
def get_model_info(self, model):
return get_model_info(model)
return model_info_manager.get_model_info(model)
def configure_model_settings(self, model):
for ms in MODEL_SETTINGS:
@@ -795,8 +792,12 @@ class Model(ModelSettings):
self.edit_format = "diff"
self.use_repo_map = True
self.examples_as_sys_msg = True
self.reminder = None
self.accepts_images = True
self.reminder = "user"
if model.startswith("o1-") or "/o1-" in model:
self.use_system_prompt = False
self.use_temperature = False
self.streaming = False
# use the defaults
if self.edit_format == "diff":
@@ -1057,9 +1058,6 @@ def sanity_check_model(io, model):
for match in possible_matches:
io.tool_output(f"- {match}")
if show:
io.tool_output(f"For more info, see: {urls.model_warnings}")
return show

View File

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

View File

@@ -1,5 +1,6 @@
import hashlib
import json
import time
import backoff
@@ -18,18 +19,32 @@ RETRY_TIMEOUT = 60
def retry_exceptions():
import httpx
import openai
return (
# httpx
httpx.ConnectError,
httpx.RemoteProtocolError,
httpx.ReadTimeout,
litellm.exceptions.APIConnectionError,
litellm.exceptions.APIError,
litellm.exceptions.RateLimitError,
litellm.exceptions.ServiceUnavailableError,
litellm.exceptions.Timeout,
litellm.exceptions.InternalServerError,
litellm.llms.anthropic.chat.AnthropicError,
#
# litellm exceptions inherit from openai exceptions
# https://docs.litellm.ai/docs/exception_mapping
#
# openai.BadRequestError,
# litellm.ContextWindowExceededError,
# litellm.ContentPolicyViolationError,
#
# openai.AuthenticationError,
# openai.PermissionDeniedError,
# openai.NotFoundError,
#
openai.APITimeoutError,
openai.UnprocessableEntityError,
openai.RateLimitError,
openai.APIConnectionError,
# openai.APIError,
# openai.APIStatusError,
openai.InternalServerError,
)
@@ -56,8 +71,6 @@ def send_completion(
temperature=0,
extra_params=None,
):
from aider.llm import litellm
kwargs = dict(
model=model_name,
messages=messages,
@@ -90,18 +103,27 @@ def send_completion(
return hash_object, res
@lazy_litellm_retry_decorator
def simple_send_with_retries(model_name, messages, extra_params=None):
try:
kwargs = {
"model_name": model_name,
"messages": messages,
"functions": None,
"stream": False,
"extra_params": extra_params,
}
retry_delay = 0.125
while True:
try:
kwargs = {
"model_name": model_name,
"messages": messages,
"functions": None,
"stream": False,
"extra_params": extra_params,
}
_hash, response = send_completion(**kwargs)
return response.choices[0].message.content
except (AttributeError, litellm.exceptions.BadRequestError):
return
_hash, response = send_completion(**kwargs)
return response.choices[0].message.content
except retry_exceptions() as err:
print(str(err))
retry_delay *= 2
if retry_delay > RETRY_TIMEOUT:
break
print(f"Retrying in {retry_delay:.1f} seconds...")
time.sleep(retry_delay)
continue
except AttributeError:
return

View File

@@ -10,3 +10,5 @@ llms = "https://aider.chat/docs/llms.html"
large_repos = "https://aider.chat/docs/faq.html#can-i-use-aider-in-a-large-mono-repo"
github_issues = "https://github.com/Aider-AI/aider/issues/new"
git_index_version = "https://github.com/Aider-AI/aider/issues/211"
install_properly = "https://aider.chat/docs/troubleshooting/imports.html"
analytics = "https://aider.chat/docs/more/analytics.html"

View File

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

View File

@@ -1,7 +1,7 @@
---
title: Release history
parent: More info
nav_order: 999
nav_order: 900
highlight_image: /assets/blame.jpg
description: Release notes and stats on aider writing its own code.
---
@@ -19,7 +19,32 @@ cog.out(text)
### v0.60.0
### main branch
- Load and save aider slash-commands to files:
- `/save <fname>` command will make a file of `/add` and `/read-only` commands that recreate the current file context in the chat.
- `/load <fname>` will replay the commands in the file.
- You can use `/load` to run any arbitrary set of slash-commands, not just `/add` and `/read-only`.
- Use `--load <fname>` to run a list of commands on launch, before the interactive chat begins.
- Anonymous, opt-in [analytics](https://aider.chat/docs/more/analytics.html) with no personal data sharing.
- Aider follows litellm's `supports_vision` attribute to enable image support for models.
- Bugfix for when diff mode flexibly handles the model using the wrong filename.
- Displays filenames in sorted order for `/add` and `/read-only`.
- New `--no-fancy-input` switch disables prompt toolkit input, now still available with `--no-pretty`.
- Override browser config with `--no-browser` or `--no-gui`.
- Offer to open documentation URLs when errors occur.
- Properly support all o1 models, regardless of provider.
- Improved layout of filenames above input prompt.
- Better handle corrupted repomap tags cache.
- Improved handling of API errors, especially when accessing the weak model.
- Aider wrote 68% of the code in this release.
### Aider v0.60.1
- Enable image support for Sonnet 10/22.
- Display filenames in sorted order.
### Aider v0.60.0
- Full support for Sonnet 10/22, the new SOTA model on aider's code editing benchmark.
- Aider uses Sonnet 10/22 by default.
@@ -33,12 +58,12 @@ cog.out(text)
- Bugfix to properly include URLs in `/help` RAG results.
- Aider wrote 49% of the code in this release.
### v0.59.1
### Aider v0.59.1
- Check for obsolete `yes: true` in yaml config, show helpful error.
- Model settings for openrouter/anthropic/claude-3.5-sonnet:beta
### v0.59.0
### Aider v0.59.0
- Improvements to `/read-only`:
- Now supports shell-style auto-complete of the full file system.

View File

@@ -0,0 +1,349 @@
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560031}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560032}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560039}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560039}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "prompt_tokens": 638, "completion_tokens": 25, "total_tokens": 663, "cost": 0.0001107, "total_cost": 0.0001107, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560043}
{"event": "command_exit", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560044}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560239}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560239}
{"event": "command_add", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560263}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20240620", "prompt_tokens": 15025, "completion_tokens": 462, "total_tokens": 15487, "cost": 0.052005, "total_cost": 0.052005, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560308}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20240620", "prompt_tokens": 16242, "completion_tokens": 269, "total_tokens": 16511, "cost": 0.052761, "total_cost": 0.104766, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560334}
{"event": "command_exit", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560339}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560733}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560733}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "prompt_tokens": 638, "completion_tokens": 25, "total_tokens": 663, "cost": 0.0001107, "total_cost": 0.0001107, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560737}
{"event": "command_exit", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "52b5cc12-f16d-45f3-b30c-95ab4ae904ee", "time": 1723560765}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723560805}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723560805}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "prompt_tokens": 638, "completion_tokens": 25, "total_tokens": 663, "cost": 0.0001107, "total_cost": 0.0001107, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723560812}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "8f9e4550-33c4-4417-b152-e35ace897f13", "time": 1723560903}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "8f9e4550-33c4-4417-b152-e35ace897f13", "time": 1723560903}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "bc3e1ea0-29a7-43ef-85fd-94694f8acebb", "time": 1723560920}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "bc3e1ea0-29a7-43ef-85fd-94694f8acebb", "time": 1723560920}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723560994}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723560994}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561016}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561017}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561046}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561046}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561049}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561049}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "6547b0bb-4248-4d40-8269-dc59e9624e0f", "time": 1723561234}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "6547b0bb-4248-4d40-8269-dc59e9624e0f", "time": 1723561235}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "prompt_tokens": 638, "completion_tokens": 25, "total_tokens": 663, "cost": 0.0001107, "total_cost": 0.0001107, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": "6547b0bb-4248-4d40-8269-dc59e9624e0f", "time": 1723561241}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561304}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561304}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "prompt_tokens": 638, "completion_tokens": 25, "total_tokens": 663, "cost": 0.0001107, "total_cost": 0.0001107, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561307}
{"event": "command_exit", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561665}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561679}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561841}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561841}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20240620", "prompt_tokens": 12148, "completion_tokens": 269, "total_tokens": 12417, "cost": 0.040479, "total_cost": 0.040479, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561858}
{"event": "command_undo", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723561925}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723568624}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723568624}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20240620", "prompt_tokens": 14217, "completion_tokens": 217, "total_tokens": 14434, "cost": 0.045906, "total_cost": 0.045906, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.49.2-dev"}, "user_id": null, "time": 1723568667}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev"}, "user_id": null, "time": 1723579444}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev"}, "user_id": null, "time": 1723579445}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev"}, "user_id": null, "time": 1723579738}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev"}, "user_id": null, "time": 1723579738}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579757}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579757}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579779}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579940}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579940}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 638, "completion_tokens": 25, "total_tokens": 663, "cost": 0.0001107, "total_cost": 0.0001107, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579944}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 673, "completion_tokens": 28, "total_tokens": 701, "cost": 0.00011775, "total_cost": 0.00022845, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579948}
{"event": "command_exit", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723579952}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723584128}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723584128}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20240620", "edit_format": "diff", "prompt_tokens": 3461, "completion_tokens": 289, "total_tokens": 3750, "cost": 0.014718, "total_cost": 0.014718, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723584158}
{"event": "command_diff", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723584162}
{"event": "command_exit", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723584173}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723593477}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723593477}
{"event": "command_chat-mode", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723593516}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20240620", "edit_format": "ask", "prompt_tokens": 9262, "completion_tokens": 223, "total_tokens": 9485, "cost": 0.031131000000000002, "total_cost": 0.031131000000000002, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723593580}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723593593}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723593593}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20240620", "edit_format": "ask", "prompt_tokens": 2054, "completion_tokens": 370, "total_tokens": 2424, "cost": 0.011712, "total_cost": 0.011712, "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.1-dev", "$lib": "posthog-python", "$lib_version": "3.5.0", "$geoip_disable": true}, "user_id": "5218a941-50b3-405f-9f75-1bf42b282b6b", "time": 1723593607}
{"event": "launched", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.2-dev"}, "user_id": "cbbee83e-62da-4629-9a3c-04d37a26f7a7", "time": 1723832819}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20240620", "python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.2-dev"}, "user_id": "cbbee83e-62da-4629-9a3c-04d37a26f7a7", "time": 1723832821}
{"event": "command_exit", "properties": {"python_version": "3.12.4", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.50.2-dev"}, "user_id": "cbbee83e-62da-4629-9a3c-04d37a26f7a7", "time": 1723832823}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316502}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316502}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316583}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316586}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316586}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316589}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316644}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316645}
{"event": "command_settings", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "1f30456a-1f79-4f19-9720-fb0b8a304b0a", "time": 1730316661}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317188}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317189}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317192}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317294}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317294}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317302}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317724}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317725}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "3645b476-b3d5-46d6-aa89-864bf75dfb5b", "time": 1730317726}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317730}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317730}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317731}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317749}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317749}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317751}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317753}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317753}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730317754}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730318254}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "092dd9f6-5445-42cd-b90c-a9e456b37a74", "time": 1730318254}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318258}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318259}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318260}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318328}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318328}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7", "$lib": "posthog-python", "$lib_version": "3.7.0", "$geoip_disable": true}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318331}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318336}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318337}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318367}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318367}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318371}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318373}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318373}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318398}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318398}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318403}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318404}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318407}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318451}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318451}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730318455}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730319350}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730319838}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730319839}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323755}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323810}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323820}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323821}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323824}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323831}
{"event": "cli session", "properties": {"main_model": "some/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323851}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323974}
{"event": "model warning", "properties": {"main_model": "some/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323975}
{"event": "cli session", "properties": {"main_model": "some/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730323985}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730324000}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730324063}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730337491}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "5e16241e-8c66-479e-9954-1fbee80560a3", "time": 1730337491}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "cd4d7b34-79ca-4ffe-9fba-7557dbeb8a88", "time": 1730394556}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "cd4d7b34-79ca-4ffe-9fba-7557dbeb8a88", "time": 1730394556}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "cd4d7b34-79ca-4ffe-9fba-7557dbeb8a88", "time": 1730394558}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "feeaed68-f237-48ad-ac13-807e1692cc40", "time": 1730400360}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "feeaed68-f237-48ad-ac13-807e1692cc40", "time": 1730400360}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "feeaed68-f237-48ad-ac13-807e1692cc40", "time": 1730405507}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "feeaed68-f237-48ad-ac13-807e1692cc40", "time": 1730405508}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730405785}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730405786}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730406699}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730406754}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730406756}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407580}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407592}
{"event": "model warning", "properties": {"main_model": "anthropic/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "anthropic/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407593}
{"event": "cli session", "properties": {"main_model": "anthropic/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "anthropic/REDACTED", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407596}
{"event": "message_send", "properties": {"main_model": "anthropic/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "anthropic/REDACTED", "edit_format": "whole", "prompt_tokens": 1218, "completion_tokens": 0, "total_tokens": 1218, "cost": 0.0, "total_cost": 0.0, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407601}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407713}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407713}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407784}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407784}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407812}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407812}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407847}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407848}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407963}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730407963}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408020}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408020}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408030}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408030}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408070}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408070}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408244}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c22c476e-18e6-4a09-9b57-1002c91be450", "time": 1730408244}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408426}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408426}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408493}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408493}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408525}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408526}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408549}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408549}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408583}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408583}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408615}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408615}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408687}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408689}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408703}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408704}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408729}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408729}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408833}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408834}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408850}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408851}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408987}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730408987}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409038}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409038}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409073}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409073}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409129}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409129}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409149}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409149}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409207}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409368}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409368}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 3647, "completion_tokens": 211, "total_tokens": 3858, "cost": 0.014106, "total_cost": 0.014106, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409393}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409453}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409455}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409582}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409582}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409714}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409714}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409722}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409724}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409725}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409766}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409766}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730409782}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410248}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410250}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410851}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410852}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410896}
{"event": "command_chat-mode", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410902}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 6309, "completion_tokens": 904, "total_tokens": 7213, "cost": 0.032487, "total_cost": 0.032487, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410958}
{"event": "command_code", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730410990}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 9288, "completion_tokens": 448, "total_tokens": 9736, "cost": 0.034584000000000004, "total_cost": 0.067071, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411002}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411007}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411007}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411013}
{"event": "command_read-only", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411019}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 7880, "completion_tokens": 325, "total_tokens": 8205, "cost": 0.028515000000000002, "total_cost": 0.095586, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411067}
{"event": "command_code", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411120}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 10269, "completion_tokens": 375, "total_tokens": 10644, "cost": 0.036432, "total_cost": 0.132018, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411129}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411166}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411167}
{"event": "command_read-only", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411172}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411220}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411220}
{"event": "command_read-only", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411222}
{"event": "command_chat-mode", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411276}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 10770, "completion_tokens": 174, "total_tokens": 10944, "cost": 0.03492, "total_cost": 0.166938, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411291}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411314}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411351}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411422}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411423}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411552}
{"event": "model warning", "properties": {"main_model": "anthropic/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "anthropic/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411554}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411577}
{"event": "model warning", "properties": {"main_model": "anthropic/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "anthropic/REDACTED", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411578}
{"event": "cli session", "properties": {"main_model": "anthropic/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "anthropic/REDACTED", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411580}
{"event": "message_send", "properties": {"main_model": "anthropic/REDACTED", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "anthropic/REDACTED", "edit_format": "diff", "prompt_tokens": 2749, "completion_tokens": 52, "total_tokens": 2801, "cost": 0.0, "total_cost": 0.0, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411584}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411627}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411751}
{"event": "command_reset", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411839}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411842}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 14351, "completion_tokens": 440, "total_tokens": 14791, "cost": 0.049653, "total_cost": 0.216591, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411862}
{"event": "command_undo", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411880}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 14896, "completion_tokens": 266, "total_tokens": 15162, "cost": 0.048678, "total_cost": 0.265269, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411902}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411941}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 27430, "completion_tokens": 608, "total_tokens": 28038, "cost": 0.09141, "total_cost": 0.35667899999999997, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411960}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 27414, "completion_tokens": 506, "total_tokens": 27920, "cost": 0.089832, "total_cost": 0.446511, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730411984}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 28297, "completion_tokens": 343, "total_tokens": 28640, "cost": 0.090036, "total_cost": 0.536547, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412019}
{"event": "command_reset", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412065}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412068}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412073}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412073}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412074}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 9491, "completion_tokens": 158, "total_tokens": 9649, "cost": 0.030843000000000002, "total_cost": 0.56739, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412084}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412095}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412095}
{"event": "command_exit", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412096}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412186}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412187}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412189}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412300}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412301}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412302}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412321}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412321}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730412322}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413528}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413531}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413534}
{"event": "command_chat-mode", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413538}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 8811, "completion_tokens": 309, "total_tokens": 9120, "cost": 0.031068000000000002, "total_cost": 0.031068000000000002, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413585}
{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413632}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 15950, "completion_tokens": 330, "total_tokens": 16280, "cost": 0.05280000000000001, "total_cost": 0.08386800000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413669}
{"event": "command_run", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413704}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "ask", "prompt_tokens": 18174, "completion_tokens": 292, "total_tokens": 18466, "cost": 0.058902, "total_cost": 0.14277, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413719}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413935}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413935}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730413937}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730414047}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730414048}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730414048}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730414048}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730414050}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730415697}
{"event": "cli session", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730415697}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 3293, "completion_tokens": 439, "total_tokens": 3732, "cost": 0.016464, "total_cost": 0.016464, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730415752}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 3960, "completion_tokens": 517, "total_tokens": 4477, "cost": 0.019635, "total_cost": 0.036099, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730415790}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730415930}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730415931}
{"event": "command_drop", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730473870}
{"event": "command_reset", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730473873}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 4607, "completion_tokens": 97, "total_tokens": 4704, "cost": 0.015276, "total_cost": 0.5826659999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730473888}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730473908}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730473916}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 5842, "completion_tokens": 604, "total_tokens": 6446, "cost": 0.026586, "total_cost": 0.6092519999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730473929}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730474024}
{"event": "gui session", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730474025}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730474027}
{"event": "command_reset", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477197}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477206}
{"event": "command_add", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477229}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 18098, "completion_tokens": 632, "total_tokens": 18730, "cost": 0.063774, "total_cost": 0.6730259999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477334}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 18968, "completion_tokens": 219, "total_tokens": 19187, "cost": 0.060189000000000006, "total_cost": 0.733215, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477568}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477576}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477576}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 19375, "completion_tokens": 91, "total_tokens": 19466, "cost": 0.05949, "total_cost": 0.792705, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477578}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 19587, "completion_tokens": 158, "total_tokens": 19745, "cost": 0.061131, "total_cost": 0.853836, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477585}
{"event": "message_send", "properties": {"main_model": "claude-3-5-sonnet-20241022", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "claude-3-5-sonnet-20241022", "edit_format": "diff", "prompt_tokens": 20082, "completion_tokens": 294, "total_tokens": 20376, "cost": 0.064656, "total_cost": 0.9184920000000001, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477595}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477605}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477606}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477636}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477636}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477655}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477656}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 37070, "completion_tokens": 0, "total_tokens": 37070, "cost": 0.005560499999999993, "total_cost": 0.005560499999999993, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477731}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477733}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477733}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 2022, "completion_tokens": 0, "total_tokens": 2022, "cost": 0.00030329999999999995, "total_cost": 0.00030329999999999995, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477738}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477767}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477767}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 674, "completion_tokens": 0, "total_tokens": 674, "cost": 0.00010109999999999999, "total_cost": 0.00010109999999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477770}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477789}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477789}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 674, "completion_tokens": 0, "total_tokens": 674, "cost": 0.00010109999999999999, "total_cost": 0.00010109999999999999, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477792}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477822}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477822}
{"event": "launched", "properties": {"python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477834}
{"event": "cli session", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477835}
{"event": "message_send", "properties": {"main_model": "gpt-4o-mini", "weak_model": "claude-3-5-sonnet-20241022", "editor_model": "gpt-4o-mini", "edit_format": "whole", "prompt_tokens": 4044, "completion_tokens": 0, "total_tokens": 4044, "cost": 0.0006066, "total_cost": 0.0006066, "python_version": "3.12.6", "os_platform": "Darwin", "os_release": "23.6.0", "machine": "x86_64", "aider_version": "0.60.2.dev13+g9e7995b7"}, "user_id": "c42c4e6b-f054-44d7-ae1f-6726cc41da88", "time": 1730477852}

View File

@@ -265,6 +265,18 @@
## Run tests and fix problems found
#test: false
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#analytics: false
## Specify a file to log analytics events
#analytics-log: xxx
## Permanently disable analytics
#analytics-disable: false
#################
# Other Settings:
@@ -329,18 +341,24 @@
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Load and execute /commands from a file on launch
#load: xxx
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx
## Run aider in your browser
## Run aider in your browser (default: False)
#gui: false
## Enable/disable suggesting shell commands (default: True)
#suggest-shell-commands: true
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
#################
# Voice Settings:

View File

@@ -264,6 +264,18 @@
## Run tests and fix problems found
#AIDER_TEST=false
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#AIDER_ANALYTICS=false
## Specify a file to log analytics events
#AIDER_ANALYTICS_LOG=
## Permanently disable analytics
#AIDER_ANALYTICS_DISABLE=false
#################
# Other Settings:
@@ -315,15 +327,21 @@
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser
## Run aider in your browser (default: False)
#AIDER_GUI=false
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
#################
# Voice Settings:

View File

@@ -81,8 +81,7 @@ cog.out(get_model_settings_as_yaml())
cog.out("```\n")
]]]-->
```yaml
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -98,8 +97,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -115,8 +113,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -132,8 +129,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -149,8 +145,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -166,8 +161,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -183,8 +177,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -200,8 +193,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -217,8 +209,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -234,8 +225,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -251,8 +241,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -268,8 +257,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -285,8 +273,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -302,8 +289,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -319,8 +305,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: udiff
editor_edit_format: null
@@ -336,8 +321,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -353,8 +337,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -370,8 +353,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -387,8 +369,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -404,8 +385,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -421,8 +401,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -438,8 +417,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -455,8 +433,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: true
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -475,8 +452,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: true
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -495,8 +471,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
- accepts_images: true
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -515,8 +490,26 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
- accepts_images: true
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
editor_model_name: anthropic/claude-3-5-sonnet-20241022
examples_as_sys_msg: true
extra_params:
extra_headers:
anthropic-beta: prompt-caching-2024-07-31
max_tokens: 8192
lazy: false
name: anthropic/claude-3-5-sonnet-latest
reminder: user
send_undo_reply: false
streaming: true
use_repo_map: true
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -535,8 +528,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: false
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -554,8 +546,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: anthropic/claude-3-haiku-20240307
- accepts_images: false
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -573,8 +564,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: claude-3-haiku-20240307
- accepts_images: true
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -591,8 +581,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku
- accepts_images: true
cache_control: true
- cache_control: true
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -609,8 +598,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/anthropic/claude-3-haiku:beta
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -627,8 +615,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -645,8 +632,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -662,8 +648,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -679,8 +664,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: vertex_ai/claude-3-haiku@20240307
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -696,8 +680,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: command-r-plus
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -713,8 +696,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: command-r-08-2024
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -730,8 +712,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: command-r-plus-08-2024
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -747,8 +728,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: groq/llama3-8b-8192
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -764,8 +744,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/meta-llama/llama-3-70b-instruct
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -781,8 +760,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -798,8 +776,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
@@ -815,8 +792,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
@@ -832,8 +808,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff-fenced
editor_edit_format: null
@@ -849,8 +824,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: null
@@ -866,8 +840,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -884,8 +857,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: true
edit_format: diff
editor_edit_format: null
@@ -902,8 +874,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -920,8 +891,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: true
edit_format: diff
editor_edit_format: null
@@ -938,8 +908,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: null
@@ -955,8 +924,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: null
- accepts_images: true
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -972,8 +940,7 @@ cog.out("```\n")
use_system_prompt: true
use_temperature: true
weak_model_name: openrouter/openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
@@ -989,8 +956,7 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
@@ -1006,8 +972,7 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: azure/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
@@ -1023,8 +988,7 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -1040,8 +1004,7 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff
@@ -1057,8 +1020,7 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: azure/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: architect
editor_edit_format: editor-diff
@@ -1074,8 +1036,7 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: whole
editor_edit_format: editor-diff
@@ -1091,8 +1052,7 @@ cog.out("```\n")
use_system_prompt: false
use_temperature: false
weak_model_name: openrouter/openai/gpt-4o-mini
- accepts_images: false
cache_control: false
- cache_control: false
caches_by_default: false
edit_format: diff
editor_edit_format: editor-diff

View File

@@ -321,6 +321,18 @@ cog.outl("```")
## Run tests and fix problems found
#test: false
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#analytics: false
## Specify a file to log analytics events
#analytics-log: xxx
## Permanently disable analytics
#analytics-disable: false
#################
# Other Settings:
@@ -385,18 +397,24 @@ cog.outl("```")
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Load and execute /commands from a file on launch
#load: xxx
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx
## Run aider in your browser
## Run aider in your browser (default: False)
#gui: false
## Enable/disable suggesting shell commands (default: True)
#suggest-shell-commands: true
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
#################
# Voice Settings:

View File

@@ -306,6 +306,18 @@ cog.outl("```")
## Run tests and fix problems found
#AIDER_TEST=false
############
# Analytics:
## Enable/disable analytics for one session (default: False)
#AIDER_ANALYTICS=false
## Specify a file to log analytics events
#AIDER_ANALYTICS_LOG=
## Permanently disable analytics
#AIDER_ANALYTICS_DISABLE=false
#################
# Other Settings:
@@ -357,15 +369,21 @@ cog.outl("```")
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#AIDER_MESSAGE_FILE=
## Load and execute /commands from a file on launch
#AIDER_LOAD=
## Specify the encoding for input and output (default: utf-8)
#AIDER_ENCODING=utf-8
## Run aider in your browser
## Run aider in your browser (default: False)
#AIDER_GUI=false
## Enable/disable suggesting shell commands (default: True)
#AIDER_SUGGEST_SHELL_COMMANDS=true
## Enable/disable fancy input with history and completion (default: True)
#AIDER_FANCY_INPUT=true
#################
# Voice Settings:

View File

@@ -61,16 +61,19 @@ usage: aider [-h] [--openai-api-key] [--anthropic-api-key] [--model]
[--commit] [--commit-prompt] [--dry-run | --no-dry-run]
[--skip-sanity-check-repo] [--lint] [--lint-cmd]
[--auto-lint | --no-auto-lint] [--test-cmd]
[--auto-test | --no-auto-test] [--test] [--file]
[--read] [--vim] [--chat-language] [--version]
[--just-check-update]
[--auto-test | --no-auto-test] [--test]
[--analytics | --no-analytics] [--analytics-log]
[--analytics-disable] [--file] [--read] [--vim]
[--chat-language] [--version] [--just-check-update]
[--check-update | --no-check-update]
[--install-main-branch] [--upgrade] [--apply]
[--yes-always] [-v] [--show-repo-map] [--show-prompts]
[--exit] [--message] [--message-file] [--encoding] [-c]
[--gui]
[--exit] [--message] [--message-file] [--load]
[--encoding] [-c]
[--gui | --no-gui | --browser | --no-browser]
[--suggest-shell-commands | --no-suggest-shell-commands]
[--voice-format] [--voice-language]
[--fancy-input | --no-fancy-input] [--voice-format]
[--voice-language]
```
@@ -500,6 +503,25 @@ Run tests and fix problems found
Default: False
Environment variable: `AIDER_TEST`
## Analytics:
### `--analytics`
Enable/disable analytics for one session (default: False)
Default: False
Environment variable: `AIDER_ANALYTICS`
Aliases:
- `--analytics`
- `--no-analytics`
### `--analytics-log ANALYTICS_LOG_FILE`
Specify a file to log analytics events
Environment variable: `AIDER_ANALYTICS_LOG`
### `--analytics-disable`
Permanently disable analytics
Default: False
Environment variable: `AIDER_ANALYTICS_DISABLE`
## Other Settings:
### `--file FILE`
@@ -594,6 +616,10 @@ Aliases:
- `--message-file MESSAGE_FILE`
- `-f MESSAGE_FILE`
### `--load LOAD_FILE`
Load and execute /commands from a file on launch
Environment variable: `AIDER_LOAD`
### `--encoding VALUE`
Specify the encoding for input and output (default: utf-8)
Default: utf-8
@@ -606,12 +632,14 @@ Aliases:
- `--config CONFIG_FILE`
### `--gui`
Run aider in your browser
Run aider in your browser (default: False)
Default: False
Environment variable: `AIDER_GUI`
Aliases:
- `--gui`
- `--no-gui`
- `--browser`
- `--no-browser`
### `--suggest-shell-commands`
Enable/disable suggesting shell commands (default: True)
@@ -621,6 +649,14 @@ Aliases:
- `--suggest-shell-commands`
- `--no-suggest-shell-commands`
### `--fancy-input`
Enable/disable fancy input with history and completion (default: True)
Default: True
Environment variable: `AIDER_FANCY_INPUT`
Aliases:
- `--fancy-input`
- `--no-fancy-input`
## Voice Settings:
### `--voice-format VOICE_FORMAT`

View File

@@ -220,3 +220,13 @@ Aider is
[open source and available on GitHub](https://github.com/Aider-AI/aider)
under an
[Apache 2.0 license](https://github.com/Aider-AI/aider/blob/main/LICENSE.txt).
## Can I edit files myself while aider is running?
Yes. Aider always reads the latest copy of files from the file
system when you send each message.
While you're waiting for aider's reply to complete, it's probably unwise to
edit files that you've added to the chat.
Your edits and aider's edits might conflict.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
---
parent: More info
nav_order: 900
nav_order: 400
description: You can script aider via the command line or python.
---

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -32,6 +32,8 @@ class TestMain(TestCase):
os.environ["HOME"] = self.homedir_obj.name
self.input_patcher = patch("builtins.input", return_value=None)
self.mock_input = self.input_patcher.start()
self.webbrowser_patcher = patch("webbrowser.open")
self.mock_webbrowser = self.webbrowser_patcher.start()
def tearDown(self):
os.chdir(self.original_cwd)
@@ -40,6 +42,7 @@ class TestMain(TestCase):
os.environ.clear()
os.environ.update(self.original_env)
self.input_patcher.stop()
self.webbrowser_patcher.stop()
def test_main_with_empty_dir_no_files_on_command(self):
main(["--no-git", "--exit"], input=DummyInput(), output=DummyOutput())

View File

@@ -1,12 +1,18 @@
import unittest
from unittest.mock import ANY, MagicMock, patch
from aider.models import Model, get_model_info, sanity_check_model, sanity_check_models
from aider.models import (
Model,
ModelInfoManager,
sanity_check_model,
sanity_check_models,
)
class TestModels(unittest.TestCase):
def test_get_model_info_nonexistent(self):
info = get_model_info("non-existent-model")
manager = ModelInfoManager()
info = manager.get_model_info("non-existent-model")
self.assertEqual(info, {})
def test_max_context_tokens(self):
@@ -73,8 +79,11 @@ class TestModels(unittest.TestCase):
result
) # Should return True because there's a problem with the editor model
mock_io.tool_warning.assert_called_with(ANY) # Ensure a warning was issued
self.assertGreaterEqual(mock_io.tool_warning.call_count, 2) # Expect two warnings
warning_messages = [call.args[0] for call in mock_io.tool_warning.call_args_list]
print("Warning messages:", warning_messages) # Add this line
self.assertGreaterEqual(mock_io.tool_warning.call_count, 1) # Expect two warnings
self.assertTrue(
any("bogus-model" in msg for msg in warning_messages)
) # Check that one of the warnings mentions the bogus model

View File

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

View File

@@ -4,7 +4,7 @@ from unittest.mock import MagicMock, patch
import httpx
from aider.llm import litellm
from aider.sendchat import simple_send_with_retries
from aider.sendchat import retry_exceptions, simple_send_with_retries
class PrintCalled(Exception):
@@ -12,6 +12,10 @@ class PrintCalled(Exception):
class TestSendChat(unittest.TestCase):
def test_retry_exceptions(self):
"""Test that retry_exceptions() can be called without raising errors"""
retry_exceptions() # Should not raise any exceptions
@patch("litellm.completion")
@patch("builtins.print")
def test_simple_send_with_retries_rate_limit_error(self, mock_print, mock_completion):
@@ -31,7 +35,7 @@ class TestSendChat(unittest.TestCase):
# Call the simple_send_with_retries method
simple_send_with_retries("model", ["message"])
mock_print.assert_called_once()
assert mock_print.call_count == 2
@patch("litellm.completion")
@patch("builtins.print")
@@ -44,4 +48,4 @@ class TestSendChat(unittest.TestCase):
# Call the simple_send_with_retries method
simple_send_with_retries("model", ["message"])
mock_print.assert_called_once()
assert mock_print.call_count == 2